[Python-checkins] r59373 - in doctools/trunk/sphinx: builder.py environment.py latexwriter.py texinputs texinputs/fancyhdr.sty texinputs/fncychap.sty texinputs/howto.cls texinputs/manual.cls texinputs/python.ist texinputs/python.sty texinputs/underscore.sty

georg.brandl python-checkins at python.org
Wed Dec 5 22:11:37 CET 2007


Author: georg.brandl
Date: Wed Dec  5 22:11:36 2007
New Revision: 59373

Added:
   doctools/trunk/sphinx/latexwriter.py
   doctools/trunk/sphinx/texinputs/
   doctools/trunk/sphinx/texinputs/fancyhdr.sty
   doctools/trunk/sphinx/texinputs/fncychap.sty
   doctools/trunk/sphinx/texinputs/howto.cls
   doctools/trunk/sphinx/texinputs/manual.cls
   doctools/trunk/sphinx/texinputs/python.ist
   doctools/trunk/sphinx/texinputs/python.sty
   doctools/trunk/sphinx/texinputs/underscore.sty
Modified:
   doctools/trunk/sphinx/builder.py
   doctools/trunk/sphinx/environment.py
Log:
Add beginnings of a LaTeX writer. This is in no way usable code yet.


Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py	(original)
+++ doctools/trunk/sphinx/builder.py	Wed Dec  5 22:11:36 2007
@@ -20,7 +20,7 @@
 import cStringIO as StringIO
 from os import path
 
-from docutils.io import StringOutput, DocTreeInput
+from docutils.io import StringOutput, FileOutput, DocTreeInput
 from docutils.core import publish_parts
 from docutils.utils import new_document
 from docutils.readers import doctree
@@ -32,11 +32,12 @@
 from .htmlhelp import build_hhx
 from .patchlevel import get_version_info, get_sys_version_info
 from .htmlwriter import HTMLWriter
-#from .latexwriter import LaTeXWriter
-from .environment import BuildEnvironment
+from .latexwriter import LaTeXWriter
+from .environment import BuildEnvironment, NoUri
 from .highlighting import pygments, get_stylesheet
 from .util.console import bold, purple, green
 
+from . import addnodes
 # side effect: registers roles and directives
 from . import roles
 from . import directives
@@ -225,6 +226,16 @@
         self.msg('creating index...')
         self.env.create_index(self)
 
+        # another indirection to support methods which don't build files
+        # individually
+        self.write(filenames)
+
+        # finish (write style files etc.)
+        self.msg('finishing...')
+        self.finish()
+        self.msg('done!')
+
+    def write(self, filenames):
         if filenames:
             # add all TOC files that may have changed
             filenames_set = set(filenames)
@@ -246,11 +257,6 @@
                 doctree = self.env.get_and_resolve_doctree(filename, self)
                 self.write_file(filename, doctree)
 
-        # finish (write style files etc.)
-        self.msg('finishing...')
-        self.finish()
-        self.msg('done!')
-
     def prepare_writing(self, filenames):
         raise NotImplementedError
 
@@ -641,36 +647,85 @@
     name = 'latex'
 
     def init(self):
-        pass
+        self.filenames = []
 
     def get_outdated_files(self):
         # always rebuild everything for now
         return self.env.all_files
 
     def get_target_uri(self, source_filename):
-        # XXX: returns nothing for now
-        return ''
+        if source_filename not in self.filenames:
+            raise NoUri
+        else:
+            return ''
 
-    def prepare_writing(self, filenames):
-        self.docwriter = LaTeXWriter(self.config, self.name)
-        self.docsettings = OptionParser(
+    def write(self, filenames):
+        # "filenames" is ignored here...
+
+        # first, assemble the "special" docs that are in every PDF
+        specials = []
+        for fname in ["license", "copyright", "about", "glossary"]:
+            specials.extend(self.env.get_doctree(fname+".rst").children)
+
+        docwriter = LaTeXWriter(self.config, self.name)
+        docsettings = OptionParser(
             defaults=self.env.settings,
-            components=(self.docwriter,)).get_default_values()
-        
+            components=(docwriter,)).get_default_values()
 
-    def write_file(self, filename, doctree):
-        destination = StringOutput(encoding='utf-8')
-        doctree.settings = self.docsettings
-        output = self.docwriter.write(doctree, destination)
-        print output
+        # XXX get names of toplevels automatically?
+        for docname in ["c-api"]:#, "distutils", "documenting", "extending",
+                        #"howto", "install", "library", "reference",
+                        #"tutorial", "using"]:
+            # XXX whatsnew missing
+            destination = FileOutput(
+                destination_path=path.join(self.outdir, docname+".tex"),
+                encoding='utf-8')
+            doctree = self.assemble_doctree(path.join(docname, "index.rst"))
+            doctree.extend(specials)
+            print "Writing..."
+            doctree.settings = docsettings
+            doctree.settings.filename = docname
+            output = docwriter.write(doctree, destination)
+            print "Done!"
+
+    def assemble_doctree(self, indexfile):
+        self.filenames = [indexfile]
+        print "Processing", indexfile
+        def process_tree(tree):
+            tree = tree.deepcopy()
+            for toctreenode in tree.traverse(addnodes.toctree):
+                index = toctreenode.parent.index(toctreenode)
+                includefiles = map(str, toctreenode['includefiles'])
+                for includefile in includefiles:
+                    try:
+                        print "Including", includefile
+                        subtree = process_tree(self.env.get_doctree(includefile))
+                        self.filenames.append(includefile)
+                    except:
+                        print >>self.warning_stream, 'WARNING: %s: toctree contains ' \
+                              'ref to nonexisting file %r' % (filename, includefile)
+                    else:
+                        toctreenode.parent[index:index] = subtree.children
+                toctreenode.parent.remove(toctreenode)
+            return tree
+        largetree = process_tree(self.env.get_doctree(indexfile))
+        print "Resolving references..."
+        self.env.resolve_references(largetree, indexfile, self)
+        #print largetree
+        return largetree
 
     def finish(self):
-        pass
+        self.msg('copying TeX support files...')
+        styledirname = path.join(path.dirname(__file__), 'texinputs')
+        for filename in os.listdir(styledirname):
+            if not filename.startswith('.'):
+                shutil.copyfile(path.join(styledirname, filename),
+                                path.join(self.outdir, filename))
 
 
 builders = {
     'html': StandaloneHTMLBuilder,
     'web': WebHTMLBuilder,
     'htmlhelp': HTMLHelpBuilder,
-#    'latex': LaTeXBuilder,
+    'latex': LaTeXBuilder,
 }

Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py	(original)
+++ doctools/trunk/sphinx/environment.py	Wed Dec  5 22:11:36 2007
@@ -74,6 +74,11 @@
 ])
 
 
+class NoUri(Exception):
+    """Raised by get_relative_uri if there is no URI available."""
+    pass
+
+
 class DefaultSubstitutions(Transform):
     """
     Replace some substitutions if they aren't defined in the document.
@@ -582,73 +587,75 @@
             typ = node['reftype']
             target = node['reftarget']
 
-            if typ == 'ref':
-                filename, labelid, sectname = self.labels.get(target, ('','',''))
-                if not filename:
-                    newnode = doctree.reporter.system_message(
-                        2, 'undefined label: %s' % target)
-                    print >>self.warning_stream, \
-                          '%s: undefined label: %s' % (docfilename, target)
-                else:
-                    newnode = nodes.reference('', '')
-                    if filename == docfilename:
-                        newnode['refid'] = labelid
-                    else:
-                        newnode['refuri'] = builder.get_relative_uri(
-                            docfilename, filename) + '#' + labelid
-                    newnode.append(nodes.emphasis(sectname, sectname))
-            elif typ in ('token', 'term', 'envvar', 'option'):
-                filename, labelid = self.reftargets.get((typ, target), ('', ''))
-                if not filename:
-                    if typ == 'term':
+            try:
+                if typ == 'ref':
+                    filename, labelid, sectname = self.labels.get(target, ('','',''))
+                    if not filename:
+                        newnode = doctree.reporter.system_message(
+                            2, 'undefined label: %s' % target)
                         print >>self.warning_stream, \
-                              '%s: term not in glossary: %s' % (docfilename, target)
-                    newnode = contnode
-                else:
-                    newnode = nodes.reference('', '')
-                    if filename == docfilename:
-                        newnode['refid'] = labelid
+                              '%s: undefined label: %s' % (docfilename, target)
                     else:
-                        newnode['refuri'] = builder.get_relative_uri(
-                            docfilename, filename) + '#' + labelid
-                    newnode.append(contnode)
-            elif typ == 'mod':
-                filename, synopsis, platform, deprecated = \
-                    self.modules.get(target, ('','','', ''))
-                # just link to an anchor if there are multiple modules in one file
-                # because the anchor is generally below the heading which is ugly
-                # but can't be helped easily
-                anchor = ''
-                if not filename or filename == docfilename:
-                    # don't link to self
-                    newnode = contnode
-                else:
-                    if len(self.filemodules[filename]) > 1:
-                        anchor = '#' + 'module-' + target
-                    newnode = nodes.reference('', '')
-                    newnode['refuri'] = (
-                        builder.get_relative_uri(docfilename, filename) + anchor)
-                    newnode['reftitle'] = '%s%s%s' % (
-                        ('(%s) ' % platform if platform else ''),
-                        synopsis, (' (deprecated)' if deprecated else ''))
-                    newnode.append(contnode)
-            else:
-                modname = node['modname']
-                clsname = node['classname']
-                searchorder = 1 if node.hasattr('refspecific') else 0
-                name, desc = self.find_desc(modname, clsname, target, typ, searchorder)
-                if not desc:
-                    newnode = contnode
-                else:
-                    newnode = nodes.reference('', '')
-                    if desc[0] == docfilename:
-                        newnode['refid'] = name
+                        newnode = nodes.reference('', '')
+                        if filename == docfilename:
+                            newnode['refid'] = labelid
+                        else:
+                            newnode['refuri'] = builder.get_relative_uri(
+                                docfilename, filename) + '#' + labelid
+                        newnode.append(nodes.emphasis(sectname, sectname))
+                elif typ in ('token', 'term', 'envvar', 'option'):
+                    filename, labelid = self.reftargets.get((typ, target), ('', ''))
+                    if not filename:
+                        if typ == 'term':
+                            print >>self.warning_stream, \
+                                  '%s: term not in glossary: %s' % (docfilename, target)
+                        newnode = contnode
                     else:
+                        newnode = nodes.reference('', '')
+                        if filename == docfilename:
+                            newnode['refid'] = labelid
+                        else:
+                            newnode['refuri'] = builder.get_relative_uri(
+                                docfilename, filename) + '#' + labelid
+                        newnode.append(contnode)
+                elif typ == 'mod':
+                    filename, synopsis, platform, deprecated = \
+                        self.modules.get(target, ('','','', ''))
+                    # just link to an anchor if there are multiple modules in one file
+                    # because the anchor is generally below the heading which is ugly
+                    # but can't be helped easily
+                    anchor = ''
+                    if not filename or filename == docfilename:
+                        # don't link to self
+                        newnode = contnode
+                    else:
+                        if len(self.filemodules[filename]) > 1:
+                            anchor = '#' + 'module-' + target
+                        newnode = nodes.reference('', '')
                         newnode['refuri'] = (
-                            builder.get_relative_uri(docfilename, desc[0])
-                            + '#' + name)
-                    newnode.append(contnode)
-
+                            builder.get_relative_uri(docfilename, filename) + anchor)
+                        newnode['reftitle'] = '%s%s%s' % (
+                            ('(%s) ' % platform if platform else ''),
+                            synopsis, (' (deprecated)' if deprecated else ''))
+                        newnode.append(contnode)
+                else:
+                    modname = node['modname']
+                    clsname = node['classname']
+                    searchorder = 1 if node.hasattr('refspecific') else 0
+                    name, desc = self.find_desc(modname, clsname, target, typ, searchorder)
+                    if not desc:
+                        newnode = contnode
+                    else:
+                        newnode = nodes.reference('', '')
+                        if desc[0] == docfilename:
+                            newnode['refid'] = name
+                        else:
+                            newnode['refuri'] = (
+                                builder.get_relative_uri(docfilename, desc[0])
+                                + '#' + name)
+                        newnode.append(contnode)
+            except NoUri:
+                newnode = contnode
             if newnode:
                 node.replace_self(newnode)
 
@@ -663,8 +670,11 @@
             if subword:
                 add_entry(subword, '', dic=entry[1])
             else:
-                entry[0].append(builder.get_relative_uri('genindex.rst', fn)
-                                + '#' + tid)
+                try:
+                    entry[0].append(builder.get_relative_uri('genindex.rst', fn)
+                                    + '#' + tid)
+                except NoUri:
+                    pass
 
         for fn, entries in self.indexentries.iteritems():
             # new entry types must be listed in directives.py!

Added: doctools/trunk/sphinx/latexwriter.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/latexwriter.py	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,448 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.latexwriter
+    ~~~~~~~~~~~~~~~~~~
+
+    Custom docutils writer for LaTeX.
+
+    Much of this code is adapted from Dave Kuhlman's "docpy" writer from his
+    docutils sandbox.
+
+    :copyright: 2007 by Georg Brandl, Dave Kuhlman.
+    :license: Python license.
+"""
+
+import re
+import time
+
+from docutils import frontend, nodes, languages, writers, utils
+
+
+HEADER = r'''%% Generated by Sphinx.
+\documentclass[%(papersize)s,%(pointsize)s]{manual}
+\usepackage{hyperref}
+\title{%(title)s}
+\date{%(date)s}
+\release{%(release)s}
+\author{Guido van Rossum\\
+  Fred L. Drake, Jr., editor}
+\authoraddress{
+  \strong{Python Software Foundation}\\
+  Email: \email{docs at python.org}
+}
+\makeindex
+
+'''
+
+FOOTER = r''''
+\printindex
+\end{document}
+'''
+
+
+class LaTeXWriter(writers.Writer):
+
+    supported = ('sphinxlatex',)
+
+    settings_spec = ('No options here.', '', ())
+    settings_defaults = {}
+
+    output = None
+
+    def __init__(self, config, buildername):
+        writers.Writer.__init__(self)
+        self.config = config
+
+    def translate(self):
+        try:
+            visitor = LaTeXTranslator(self.document, self.config)
+            self.document.walkabout(visitor)
+            self.output = visitor.astext()
+        except:
+            import pdb, sys, traceback
+            traceback.print_exc()
+            tb = sys.exc_info()[2]
+            pdb.post_mortem(tb)
+
+
+TABLE_MODE_NONE = 0
+TABLE_MODE_HEAD = 1
+TABLE_MODE_BODY = 2
+
+class TableSpec:
+    def __init__(self):
+        self.columnCount = 0
+        self.mode = TABLE_MODE_NONE
+    def getColumnCount(self): return self.columnCount
+    def setColumnCount(self, columnCount): self.columnCount = columnCount
+    def getMode(self): return self.mode
+    def setMode(self, mode): self.mode = mode
+
+
+class LaTeXTranslator(nodes.NodeVisitor):
+    sectionnames = ["chapter", "chapter", "section", "subsection",
+                    "subsubsection", "paragraph", "subparagraph"]
+
+    def __init__(self, document, config):
+        nodes.NodeVisitor.__init__(self, document)
+        self.body = []
+        self.options = {'papersize': 'a4paper', # XXX
+                        'pointsize': '12pt',
+                        'filename': document.settings.filename,
+                        'title': '',
+                        'release': config['release'],
+                        'date': time.strftime(config.get('today_fmt', '%B %d, %Y')),
+                        }
+        self.context = []
+        self.verbatim = 0
+        self.this_is_the_title = 1
+        self.sectionlevel = 0 # XXX starts with chapter now
+        self.highlightlang = 'python'
+
+    def astext(self):
+        return (HEADER % self.options) + \
+               u''.join(self.body) + \
+               (FOOTER % self.options)
+
+    def visit_document(self, node):
+        self.body.append('\\begin{document}\n\\maketitle\n')
+    def depart_document(self, node):
+        pass
+
+    def visit_highlightlang(self, node):
+        self.highlightlang = node['lang']
+        raise nodes.SkipNode
+
+    def visit_comment(self, node):
+        raise nodes.SkipNode
+
+    def visit_section(self, node):
+        if not self.this_is_the_title:
+            self.sectionlevel += 1
+    def depart_section(self, node):
+        self.sectionlevel -= 1
+
+    def visit_glossary(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_transition(self, node):
+        self.body.append('\n\n\\hrule{}\n\n')
+
+    def depart_transition(self, node):
+        pass
+
+    def visit_title(self, node):
+        if self.this_is_the_title:
+            if len(node.children) != 1 and not isinstance(node.children[0], Text):
+                raise RuntimeError("title is not a Text node")
+            self.options['title'] = node.children[0].astext()
+            self.this_is_the_title = 0
+            raise nodes.SkipNode
+        elif isinstance(node.parent, nodes.section):
+            self.body.append('\n\n')
+            self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
+            self.context.append('}\n')
+        else:
+            raise RuntimeError("XXX title without section")
+    def depart_title(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_field_list(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_desc(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_seealso(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_rubric(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_footnote(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_table(self, node):
+        self.tableSpec = TableSpec()
+    def depart_table(self, node):
+        self.tableSpec = None
+
+    def visit_colspec(self, node):
+        pass
+    def depart_colspec(self, node):
+        pass
+
+    def visit_tgroup(self, node):
+        columnCount = int(node.get('cols', 0))
+        self.tableSpec.setColumnCount(columnCount)
+        if columnCount == 2:
+            self.body.append('\\begin{tableii}{l|l}{textrm}')
+        elif columnCount == 3:
+            self.body.append('\\begin{tableiii}{l|l|l}{textrm}')
+        elif columnCount == 4:
+            self.body.append('\\begin{tableiv}{l|l|l|l}{textrm}')
+        elif columnCount == 5:
+            self.body.append('\\begin{tablev}{l|l|l|l|l}{textrm}')
+    def depart_tgroup(self, node):
+        if self.tableSpec.getColumnCount() == 2:
+            self.body.append('\n\\end{tableii}\n')
+        elif self.tableSpec.getColumnCount() == 3:
+            self.body.append('\n\\end{tableiii}\n')
+        elif self.tableSpec.getColumnCount() == 4:
+            self.body.append('\n\\end{tableiv}\n')
+        elif self.tableSpec.getColumnCount() == 5:
+            self.body.append('\n\\end{tablev}\n')
+
+    def visit_thead(self, node):
+        self.tableSpec.setMode(TABLE_MODE_HEAD)
+    def depart_thead(self, node):
+        self.tableSpec.setMode(TABLE_MODE_NONE)
+
+    def visit_tbody(self, node):
+        self.tableSpec.setMode(TABLE_MODE_BODY)
+    def depart_tbody(self, node):
+        self.tableSpec.setMode(TABLE_MODE_NONE)
+
+    def visit_row(self, node):
+        if self.tableSpec.getMode() == TABLE_MODE_HEAD:
+            pass
+        elif self.tableSpec.getMode() == TABLE_MODE_BODY:
+            if self.tableSpec.getColumnCount() == 2:
+                self.body.append('\n\\lineii')
+            elif self.tableSpec.getColumnCount() == 3:
+                self.body.append('\n\\lineiii')
+            elif self.tableSpec.getColumnCount() == 4:
+                self.body.append('\n\\lineiv')
+            elif self.tableSpec.getColumnCount() == 5:
+                self.body.append('\n\\linev')
+    def depart_row(self, node):
+        if self.tableSpec.getMode() == TABLE_MODE_HEAD:
+            pass
+        elif self.tableSpec.getMode() == TABLE_MODE_BODY:
+            pass
+
+    def visit_entry(self, node):
+        if self.tableSpec.getMode() == TABLE_MODE_HEAD:
+            #self.body.append('%% [(visit_entry) text: +%s+]' % node.astext())
+            self.body.append('{%s}' % node.astext().strip(' '))
+            raise nodes.SkipNode
+        elif self.tableSpec.getMode() == TABLE_MODE_BODY:
+            #self.body.append('%% [(visit_entry) text: +%s+]' % node.astext())
+            self.body.append('{%s}' % node.astext().strip(' '))
+            raise nodes.SkipNode
+    def depart_entry(self, node):
+        pass
+##         if self.tableSpec.getMode() == TABLE_MODE_HEAD:
+##             self.body.append('}')
+##         elif self.tableSpec.getMode() == TABLE_MODE_BODY:
+##             self.body.append('}')
+
+    def visit_bullet_list(self, node):
+        self.body.append('\\begin{itemize}\n' )
+    def depart_bullet_list(self, node):
+        self.body.append('\\end{itemize}\n' )
+
+    def visit_enumerated_list(self, node):
+        self.body.append('\\begin{enumerate}\n' )
+    def depart_enumerated_list(self, node):
+        self.body.append('\\end{enumerate}\n' )
+
+    def visit_list_item(self, node):
+        # Append "{}" in case the next character is "[", which would break
+        # LaTeX's list environment (no numbering and the "[" is not printed).
+        self.body.append(r'\item {} ')
+    def depart_list_item(self, node):
+        self.body.append('\n')
+
+    def visit_definition_list(self, node):
+        self.body.append('\\begin{description}\n')
+    def depart_definition_list(self, node):
+        self.body.append('\\end{description}\n')
+
+    def visit_definition_list_item(self, node):
+        pass
+    def depart_definition_list_item(self, node):
+        pass
+
+    def visit_term(self, node):
+        self.body.append('\\item[')
+    def depart_term(self, node):
+        # definition list term.
+        self.body.append(':]\n')
+
+    def visit_classifier(self, node):
+        pass # XXX
+    def depart_classifier(self, node):
+        pass
+
+    def visit_definition(self, node):
+        pass
+    def depart_definition(self, node):
+        self.body.append('\n')
+
+    def visit_paragraph(self, node):
+        self.body.append('\n')
+    def depart_paragraph(self, node):
+        self.body.append('\n')
+
+    def visit_centered(self, node):
+        self.body.append('\n\\begin{centering}')
+    def depart_centered(self, node):
+        self.body.append('\n\\end{centering}')
+
+    def visit_note(self, node):
+        self.body.append('\n\\note{')
+    def depart_note(self, node):
+        self.body.append('}\n')
+
+    def visit_warning(self, node):
+        self.body.append('\n\\warning{')
+    def depart_warning(self, node):
+        self.body.append('}\n')
+
+    def visit_versionmodified(self, node):
+        #self.body.append('\n\\vmod{')
+        pass
+    def depart_versionmodified(self, node):
+        #self.body.append('}\n')
+        pass
+
+    def visit_target(self, node):
+        if not (node.has_key('refuri') or node.has_key('refid')
+                or node.has_key('refname')):
+            for id in node['ids']:
+                self.body.append(r'\hypertarget{%s}{' % id)
+            self.context.append('}' * len(node['ids']))
+        else:
+            self.context.append('')
+    def depart_target(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_index(self, node):
+        raise nodes.SkipNode # XXX
+
+    def visit_reference(self, node):
+        pass # XXX
+    def depart_reference(self, node):
+        pass
+
+    def visit_pending_xref(self, node):
+        pass
+    def depart_pending_xref(self, node):
+        pass
+
+    def visit_emphasis(self, node):
+        self.body.append(r'\emph{')
+    def depart_emphasis(self, node):
+        self.body.append('}')
+
+    def visit_literal_emphasis(self, node):
+        self.body.append(r'\emph{') # XXX
+    def depart_literal_emphasis(self, node):
+        self.body.append('}')
+
+    def visit_strong(self, node):
+        self.body.append(r'\textbf{')
+    def depart_strong(self, node):
+        self.body.append('}')
+
+    def visit_literal(self, node):
+        content = self.encode(node.astext().strip())
+        if re.search('[ \t\n]', content):
+            self.body.append(r'\samp{%s}' % content)
+        else:
+            self.body.append(r'\code{%s}' % content)
+        raise nodes.SkipNode
+
+    def visit_footnote_reference(self, node):
+        pass #XXX
+    def depart_footnote_reference(self, node):
+        pass
+
+    def visit_literal_block(self, node):
+        self.body.append('\n\\begin{verbatim}')
+        self.verbatim = 1
+    def depart_literal_block(self, node):
+        self.body.append('\\end{verbatim}\n')
+        self.verbatim = 0
+
+    def visit_line_block(self, node):
+        """line-block:
+        * whitespace (including linebreaks) is significant
+        * inline markup is supported.
+        * serif typeface
+        """
+        self.body.append('\\begin{flushleft}\n')
+        #self.insert_none_breaking_blanks = 1
+        #self.line_block_without_mbox = 1
+        #if self.line_block_without_mbox:
+        #    self.insert_newline = 1
+        #else:
+        #    self.mbox_newline = 1
+        #    self.body.append('\\mbox{')
+    def depart_line_block(self, node):
+        #if self.line_block_without_mbox:
+        #    self.insert_newline = 0
+        #else:
+        #    self.body.append('}')
+        #    self.mbox_newline = 0
+        #self.insert_none_breaking_blanks = 0
+        self.body.append('\n\\end{flushleft}\n')
+
+    def visit_line(self, node):
+        pass
+    def depart_line(self, node):
+        pass
+
+    def visit_block_quote(self, node):
+        # If the block quote contains a single object and that object
+        # is a list, then generate a list not a block quote.
+        # This lets us indent lists.
+        done = 0
+        if len(node.children) == 1:
+            child = node.children[0]
+            if isinstance(child, nodes.bullet_list) or \
+                    isinstance(child, nodes.enumerated_list):
+                done = 1
+        if not done:
+            self.body.append('\\begin{quote}\n')
+    def depart_block_quote(self, node):
+        done = 0
+        if len(node.children) == 1:
+            child = node.children[0]
+            if isinstance(child, nodes.bullet_list) or \
+                    isinstance(child, nodes.enumerated_list):
+                done = 1
+        if not done:
+            self.body.append('\\end{quote}\n')
+
+    replacements = [
+        (u"\\", ur"\textbackslash{}"),
+        (u"$", ur"\$"),
+        (u"&", ur"\&"),
+        (u"#", ur"\#"),
+        (u"_", ur"\_"),
+        (u"{", ur"\{"),
+        (u"}", ur"\}"),
+        (u"¶", ur"\P{}"),
+        (u"§", ur"\S{}"),
+        (u"~", ur"\textasciitilde{}"),
+        (u"<", ur"\textless{}"),
+        (u">", ur"\textgreater{}"),
+        (u"^", ur"\textasciicircum{}"),
+    ]
+
+    def encode(self, text):
+        if self.verbatim:
+            return text
+        for x, y in self.replacements:
+            text = text.replace(x, y)
+        return text
+
+    def visit_Text(self, node):
+        self.body.append(self.encode(node.astext()))
+    def depart_Text(self, node):
+        pass
+
+    def unknown_visit(self, node):
+        raise NotImplementedError("Unknown node: " + node.__class__.__name__)

Added: doctools/trunk/sphinx/texinputs/fancyhdr.sty
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/fancyhdr.sty	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,329 @@
+% fancyhdr.sty version 1.99d
+% Fancy headers and footers for LaTeX.
+% Piet van Oostrum, Dept of Computer Science, University of Utrecht
+% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
+% Telephone: +31 30 2532180. Email: piet at cs.ruu.nl
+% ========================================================================
+% LICENCE: This is free software. You are allowed to use and distribute
+% this software in any way you like. You are also allowed to make modified
+% versions of it, but you can distribute a modified version only if you
+% clearly indicate that it is a modified version and the person(s) who
+% modified it. This indication should be in a prominent place, e.g. in the
+% top of the file. If possible a contact address, preferably by email,
+% should be given for these persons. If that is feasible the modifications
+% should be indicated in the source code.
+% ========================================================================
+% MODIFICATION HISTORY:
+% Sep 16, 1994
+% version 1.4: Correction for use with \reversemargin
+% Sep 29, 1994:
+% version 1.5: Added the \iftopfloat, \ifbotfloat and \iffloatpage commands
+% Oct 4, 1994:
+% version 1.6: Reset single spacing in headers/footers for use with
+% setspace.sty or doublespace.sty
+% Oct 4, 1994:
+% version 1.7: changed \let\@mkboth\markboth to
+% \def\@mkboth{\protect\markboth} to make it more robust
+% Dec 5, 1994:
+% version 1.8: corrections for amsbook/amsart: define \@chapapp and (more
+% importantly) use the \chapter/sectionmark definitions from ps at headings if
+% they exist (which should be true for all standard classes).
+% May 31, 1995:
+% version 1.9: The proposed \renewcommand{\headrulewidth}{\iffloatpage...
+% construction in the doc did not work properly with the fancyplain style. 
+% June 1, 1995:
+% version 1.91: The definition of \@mkboth wasn't restored on subsequent
+% \pagestyle{fancy}'s.
+% June 1, 1995:
+% version 1.92: The sequence \pagestyle{fancyplain} \pagestyle{plain}
+% \pagestyle{fancy} would erroneously select the plain version.
+% June 1, 1995:
+% version 1.93: \fancypagestyle command added.
+% Dec 11, 1995:
+% version 1.94: suggested by Conrad Hughes <chughes at maths.tcd.ie>
+% CJCH, Dec 11, 1995: added \footruleskip to allow control over footrule
+% position (old hardcoded value of .3\normalbaselineskip is far too high
+% when used with very small footer fonts).
+% Jan 31, 1996:
+% version 1.95: call \@normalsize in the reset code if that is defined,
+% otherwise \normalsize.
+% this is to solve a problem with ucthesis.cls, as this doesn't
+% define \@currsize. Unfortunately for latex209 calling \normalsize doesn't
+% work as this is optimized to do very little, so there \@normalsize should
+% be called. Hopefully this code works for all versions of LaTeX known to
+% mankind.  
+% April 25, 1996:
+% version 1.96: initialize \headwidth to a magic (negative) value to catch
+% most common cases that people change it before calling \pagestyle{fancy}.
+% Note it can't be initialized when reading in this file, because
+% \textwidth could be changed afterwards. This is quite probable.
+% We also switch to \MakeUppercase rather than \uppercase and introduce a
+% \nouppercase command for use in headers. and footers.
+% May 3, 1996:
+% version 1.97: Two changes:
+% 1. Undo the change in version 1.8 (using the pagestyle{headings} defaults
+% for the chapter and section marks. The current version of amsbook and
+% amsart classes don't seem to need them anymore. Moreover the standard
+% latex classes don't use \markboth if twoside isn't selected, and this is
+% confusing as \leftmark doesn't work as expected.
+% 2. include a call to \ps at empty in ps@@fancy. This is to solve a problem
+% in the amsbook and amsart classes, that make global changes to \topskip,
+% which are reset in \ps at empty. Hopefully this doesn't break other things.
+% May 7, 1996:
+% version 1.98:
+% Added % after the line  \def\nouppercase
+% May 7, 1996:
+% version 1.99: This is the alpha version of fancyhdr 2.0
+% Introduced the new commands \fancyhead, \fancyfoot, and \fancyhf.
+% Changed \headrulewidth, \footrulewidth, \footruleskip to
+% macros rather than length parameters, In this way they can be
+% conditionalized and they don't consume length registers. There is no need
+% to have them as length registers unless you want to do calculations with
+% them, which is unlikely. Note that this may make some uses of them
+% incompatible (i.e. if you have a file that uses \setlength or \xxxx=)
+% May 10, 1996:
+% version 1.99a:
+% Added a few more % signs
+% May 10, 1996:
+% version 1.99b:
+% Changed the syntax of \f at nfor to be resistent to catcode changes of :=
+% Removed the [1] from the defs of \lhead etc. because the parameter is
+% consumed by the \@[xy]lhead etc. macros.
+% June 24, 1997:
+% version 1.99c:
+% corrected \nouppercase to also include the protected form of \MakeUppercase
+% \global added to manipulation of \headwidth.
+% \iffootnote command added.
+% Some comments added about \@fancyhead and \@fancyfoot.
+% Aug 24, 1998
+% version 1.99d
+% Changed the default \ps at empty to \ps@@empty in order to allow
+% \fancypagestyle{empty} redefinition.
+
+\let\fancy at def\gdef
+
+\def\if at mpty#1#2#3{\def\temp at ty{#1}\ifx\@empty\temp at ty #2\else#3\fi}
+
+% Usage: \@forc \var{charstring}{command to be executed for each char}
+% This is similar to LaTeX's \@tfor, but expands the charstring.
+
+\def\@forc#1#2#3{\expandafter\f at rc\expandafter#1\expandafter{#2}{#3}}
+\def\f at rc#1#2#3{\def\temp at ty{#2}\ifx\@empty\temp at ty\else
+                                    \f@@rc#1#2\f@@rc{#3}\fi}
+\def\f@@rc#1#2#3\f@@rc#4{\def#1{#2}#4\f at rc#1{#3}{#4}}
+
+% Usage: \f at nfor\name:=list\do{body}
+% Like LaTeX's \@for but an empty list is treated as a list with an empty
+% element
+
+\newcommand{\f at nfor}[3]{\edef\@fortmp{#2}%
+    \expandafter\@forloop#2,\@nil,\@nil\@@#1{#3}}
+
+% Usage: \def at ult \cs{defaults}{argument}
+% sets \cs to the characters from defaults appearing in argument
+% or defaults if it would be empty. All characters are lowercased.
+
+\newcommand\def at ult[3]{%
+    \edef\temp at a{\lowercase{\edef\noexpand\temp at a{#3}}}\temp at a
+    \def#1{}%
+    \@forc\tmpf at ra{#2}%
+        {\expandafter\if at in\tmpf at ra\temp at a{\edef#1{#1\tmpf at ra}}{}}%
+    \ifx\@empty#1\def#1{#2}\fi}
+% 
+% \if at in <char><set><truecase><falsecase>
+%
+\newcommand{\if at in}[4]{%
+    \edef\temp at a{#2}\def\temp at b##1#1##2\temp at b{\def\temp at b{##1}}%
+    \expandafter\temp at b#2#1\temp at b\ifx\temp at a\temp at b #4\else #3\fi}
+
+\newcommand{\fancyhead}{\@ifnextchar[{\f at ncyhf h}{\f at ncyhf h[]}}
+\newcommand{\fancyfoot}{\@ifnextchar[{\f at ncyhf f}{\f at ncyhf f[]}}
+\newcommand{\fancyhf}{\@ifnextchar[{\f at ncyhf {}}{\f at ncyhf {}[]}}
+
+% The header and footer fields are stored in command sequences with
+% names of the form: \f at ncy<x><y><z> with <x> for [eo], <y> form [lcr]
+% and <z> from [hf].
+
+\def\f at ncyhf#1[#2]#3{%
+    \def\temp at c{}%
+    \@forc\tmpf at ra{#2}%
+        {\expandafter\if at in\tmpf at ra{eolcrhf,EOLCRHF}%
+            {}{\edef\temp at c{\temp at c\tmpf at ra}}}%
+    \ifx\@empty\temp at c\else
+        \ifx\PackageError\undefined
+        \errmessage{Illegal char `\temp at c' in fancyhdr argument:
+          [#2]}\else
+        \PackageError{Fancyhdr}{Illegal char `\temp at c' in fancyhdr argument:
+          [#2]}{}\fi
+    \fi
+    \f at nfor\temp at c{#2}%
+        {\def at ult\f@@@eo{eo}\temp at c
+         \def at ult\f@@@lcr{lcr}\temp at c
+         \def at ult\f@@@hf{hf}{#1\temp at c}%
+         \@forc\f@@eo\f@@@eo
+             {\@forc\f@@lcr\f@@@lcr
+                 {\@forc\f@@hf\f@@@hf
+                     {\expandafter\fancy at def\csname
+                      f at ncy\f@@eo\f@@lcr\f@@hf\endcsname
+                      {#3}}}}}}
+
+% Fancyheadings version 1 commands. These are more or less deprecated,
+% but they continue to work.
+
+\newcommand{\lhead}{\@ifnextchar[{\@xlhead}{\@ylhead}}
+\def\@xlhead[#1]#2{\fancy at def\f at ncyelh{#1}\fancy at def\f at ncyolh{#2}}
+\def\@ylhead#1{\fancy at def\f at ncyelh{#1}\fancy at def\f at ncyolh{#1}}
+
+\newcommand{\chead}{\@ifnextchar[{\@xchead}{\@ychead}}
+\def\@xchead[#1]#2{\fancy at def\f at ncyech{#1}\fancy at def\f at ncyoch{#2}}
+\def\@ychead#1{\fancy at def\f at ncyech{#1}\fancy at def\f at ncyoch{#1}}
+
+\newcommand{\rhead}{\@ifnextchar[{\@xrhead}{\@yrhead}}
+\def\@xrhead[#1]#2{\fancy at def\f at ncyerh{#1}\fancy at def\f at ncyorh{#2}}
+\def\@yrhead#1{\fancy at def\f at ncyerh{#1}\fancy at def\f at ncyorh{#1}}
+
+\newcommand{\lfoot}{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
+\def\@xlfoot[#1]#2{\fancy at def\f at ncyelf{#1}\fancy at def\f at ncyolf{#2}}
+\def\@ylfoot#1{\fancy at def\f at ncyelf{#1}\fancy at def\f at ncyolf{#1}}
+
+\newcommand{\cfoot}{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
+\def\@xcfoot[#1]#2{\fancy at def\f at ncyecf{#1}\fancy at def\f at ncyocf{#2}}
+\def\@ycfoot#1{\fancy at def\f at ncyecf{#1}\fancy at def\f at ncyocf{#1}}
+
+\newcommand{\rfoot}{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
+\def\@xrfoot[#1]#2{\fancy at def\f at ncyerf{#1}\fancy at def\f at ncyorf{#2}}
+\def\@yrfoot#1{\fancy at def\f at ncyerf{#1}\fancy at def\f at ncyorf{#1}}
+
+\newdimen\headwidth
+\newcommand{\headrulewidth}{0.4pt}
+\newcommand{\footrulewidth}{\z at skip}
+\newcommand{\footruleskip}{.3\normalbaselineskip}
+
+% Fancyplain stuff shouldn't be used anymore (rather
+% \fancypagestyle{plain} should be used), but it must be present for
+% compatibility reasons.
+
+\newcommand{\plainheadrulewidth}{\z at skip}
+\newcommand{\plainfootrulewidth}{\z at skip}
+\newif\if at fancyplain \@fancyplainfalse
+\def\fancyplain#1#2{\if at fancyplain#1\else#2\fi}
+
+\headwidth=-123456789sp %magic constant
+
+% Command to reset various things in the headers:
+% a.o.  single spacing (taken from setspace.sty)
+% and the catcode of ^^M (so that epsf files in the header work if a
+% verbatim crosses a page boundary)
+% It also defines a \nouppercase command that disables \uppercase and
+% \Makeuppercase. It can only be used in the headers and footers.
+\def\fancy at reset{\restorecr
+ \def\baselinestretch{1}%
+ \def\nouppercase##1{{\let\uppercase\relax\let\MakeUppercase\relax
+     \expandafter\let\csname MakeUppercase \endcsname\relax##1}}%
+ \ifx\undefined\@newbaseline% NFSS not present; 2.09 or 2e
+   \ifx\@normalsize\undefined \normalsize % for ucthesis.cls
+   \else \@normalsize \fi
+ \else% NFSS (2.09) present
+  \@newbaseline%
+ \fi}
+
+% Initialization of the head and foot text.
+
+% The default values still contain \fancyplain for compatibility.
+\fancyhf{} % clear all
+% lefthead empty on ``plain'' pages, \rightmark on even, \leftmark on odd pages
+% evenhead empty on ``plain'' pages, \leftmark on even, \rightmark on odd pages
+\fancyhead[el,or]{\fancyplain{}{\sl\rightmark}}
+\fancyhead[er,ol]{\fancyplain{}{\sl\leftmark}}
+\fancyfoot[c]{\rm\thepage} % page number
+
+% Put together a header or footer given the left, center and
+% right text, fillers at left and right and a rule.
+% The \lap commands put the text into an hbox of zero size,
+% so overlapping text does not generate an errormessage.
+% These macros have 5 parameters:
+% 1. \@lodd or \@rodd % This determines at which side the header will stick
+%    out.
+% 2. \f at ncyolh, \f at ncyelh, \f at ncyolf or \f at ncyelf. This is the left component.
+% 3. \f at ncyoch, \f at ncyech, \f at ncyocf or \f at ncyecf. This is the middle comp.
+% 4. \f at ncyorh, \f at ncyerh, \f at ncyorf or \f at ncyerf. This is the right component.
+% 5. \@lodd or \@rodd % This determines at which side the header will stick
+%    out. This is the reverse of parameter nr. 1. One of them is always
+%    \relax and the other one is \hss (after expansion).
+
+\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\fancy at reset\vbox{\hbox
+{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill
+\parbox[b]{\headwidth}{\centering#3\strut}\hfill
+\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5}
+
+\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\fancy at reset\vbox{\footrule
+\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill
+\parbox[t]{\headwidth}{\centering#3\strut}\hfill
+\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5}
+
+\def\headrule{{\if at fancyplain\let\headrulewidth\plainheadrulewidth\fi
+\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}}
+
+\def\footrule{{\if at fancyplain\let\footrulewidth\plainfootrulewidth\fi
+\vskip-\footruleskip\vskip-\footrulewidth
+\hrule\@width\headwidth\@height\footrulewidth\vskip\footruleskip}}
+
+\def\ps at fancy{%
+\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}%for amsbook
+%
+% Define \MakeUppercase for old LaTeXen.
+% Note: we used \def rather than \let, so that \let\uppercase\relax (from
+% the version 1 documentation) will still work.
+%
+\@ifundefined{MakeUppercase}{\def\MakeUppercase{\uppercase}}{}%
+\@ifundefined{chapter}{\def\sectionmark##1{\markboth
+{\MakeUppercase{\ifnum \c at secnumdepth>\z@
+ \thesection\hskip 1em\relax \fi ##1}}{}}%
+\def\subsectionmark##1{\markright {\ifnum \c at secnumdepth >\@ne
+ \thesubsection\hskip 1em\relax \fi ##1}}}%
+{\def\chaptermark##1{\markboth {\MakeUppercase{\ifnum \c at secnumdepth>\m at ne
+ \@chapapp\ \thechapter. \ \fi ##1}}{}}%
+\def\sectionmark##1{\markright{\MakeUppercase{\ifnum \c at secnumdepth >\z@
+ \thesection. \ \fi ##1}}}}%
+%\csname ps at headings\endcsname % use \ps at headings defaults if they exist
+\ps@@fancy
+\gdef\ps at fancy{\@fancyplainfalse\ps@@fancy}%
+% Initialize \headwidth if the user didn't
+%
+\ifdim\headwidth<0sp
+%
+% This catches the case that \headwidth hasn't been initialized and the
+% case that the user added something to \headwidth in the expectation that
+% it was initialized to \textwidth. We compensate this now. This loses if
+% the user intended to multiply it by a factor. But that case is more
+% likely done by saying something like \headwidth=1.2\textwidth. 
+% The doc says you have to change \headwidth after the first call to
+% \pagestyle{fancy}. This code is just to catch the most common cases were
+% that requirement is violated.
+%
+    \global\advance\headwidth123456789sp\global\advance\headwidth\textwidth
+\fi}
+\def\ps at fancyplain{\ps at fancy \let\ps at plain\ps at plain@fancy}
+\def\ps at plain@fancy{\@fancyplaintrue\ps@@fancy}
+\let\ps@@empty\ps at empty
+\def\ps@@fancy{%
+\ps@@empty % This is for amsbook/amsart, which do strange things with \topskip
+\def\@mkboth{\protect\markboth}%
+\def\@oddhead{\@fancyhead\@lodd\f at ncyolh\f at ncyoch\f at ncyorh\@rodd}%
+\def\@oddfoot{\@fancyfoot\@lodd\f at ncyolf\f at ncyocf\f at ncyorf\@rodd}%
+\def\@evenhead{\@fancyhead\@rodd\f at ncyelh\f at ncyech\f at ncyerh\@lodd}%
+\def\@evenfoot{\@fancyfoot\@rodd\f at ncyelf\f at ncyecf\f at ncyerf\@lodd}%
+}
+\def\@lodd{\if at reversemargin\hss\else\relax\fi}
+\def\@rodd{\if at reversemargin\relax\else\hss\fi}
+
+\newif\iffootnote
+\let\latex at makecol\@makecol
+\def\@makecol{\ifvoid\footins\footnotetrue\else\footnotefalse\fi
+\let\topfloat\@toplist\let\botfloat\@botlist\latex at makecol}
+\def\iftopfloat#1#2{\ifx\topfloat\empty #2\else #1\fi}
+\def\ifbotfloat#1#2{\ifx\botfloat\empty #2\else #1\fi}
+\def\iffloatpage#1#2{\if at fcolmade #1\else #2\fi}
+
+\newcommand{\fancypagestyle}[2]{%
+  \@namedef{ps@#1}{\let\fancy at def\def#2\relax\ps at fancy}}

Added: doctools/trunk/sphinx/texinputs/fncychap.sty
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/fncychap.sty	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,433 @@
+%%% Derived from the original fncychap.sty,
+%%% but changed ``TWELV'' to ``TWELVE''.
+
+%%% Copyright   Ulf A. Lindgren
+%%%             Department of Applied Electronics
+%%%             Chalmers University of Technology
+%%%             S-412 96 Gothenburg, Sweden
+%%%             E-mail lindgren at ae.chalmers.se
+%%%
+%%% Note        Permission is granted to modify this file under
+%%%             the condition that it is saved using another
+%%%             file and package name.
+%%%
+%%% Revision    1.1
+%%%
+%%%             Jan. 8th Modified package name base date option
+%%%             Jan. 22th Modified FmN and FmTi for error in book.cls
+%%%                  \MakeUppercase{#}->{\MakeUppercase#}
+%%%             Apr. 6th Modified Lenny option to prevent undesired 
+%%%                  skip of line.
+%%%             Nov. 8th Fixed \@chapapp for AMS
+%%%             Feb. 11th Fixed appendix problem related to Bjarne
+%%% Last modified    Feb. 11th 1998
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesPackage{fncychap}
+             [1997/04/06 v1.11
+                 LaTeX package (Revised chapters)]
+
+%%%% DEFINITION OF Chapapp variables
+\newcommand{\CNV}{\huge\bfseries}
+\newcommand{\ChNameVar}[1]{\renewcommand{\CNV}{#1}}
+
+
+%%%% DEFINITION OF TheChapter variables
+\newcommand{\CNoV}{\huge\bfseries}
+\newcommand{\ChNumVar}[1]{\renewcommand{\CNoV}{#1}}
+
+\newif\ifUCN
+\UCNfalse
+\newif\ifLCN
+\LCNfalse
+\def\ChNameLowerCase{\LCNtrue\UCNfalse}
+\def\ChNameUpperCase{\UCNtrue\LCNfalse}
+\def\ChNameAsIs{\UCNfalse\LCNfalse}
+
+%%%%% Fix for AMSBook 971008
+
+\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}
+
+
+%%%%% Fix for Bjarne and appendix 980211
+
+\newif\ifinapp
+\inappfalse
+\renewcommand\appendix{\par
+  \setcounter{chapter}{0}%
+  \setcounter{section}{0}%
+  \inapptrue%
+  \renewcommand\@chapapp{\appendixname}%
+  \renewcommand\thechapter{\@Alph\c at chapter}}
+
+%%%%%
+
+\newcommand{\FmN}[1]{%
+\ifUCN
+   {\MakeUppercase#1}\LCNfalse
+\else
+   \ifLCN
+      {\MakeLowercase#1}\UCNfalse
+   \else #1
+   \fi
+\fi}
+
+
+%%%% DEFINITION OF Title variables
+\newcommand{\CTV}{\Huge\bfseries}
+\newcommand{\ChTitleVar}[1]{\renewcommand{\CTV}{#1}}
+
+%%%% DEFINITION OF the basic rule width
+\newlength{\RW}
+\setlength{\RW}{1pt}
+\newcommand{\ChRuleWidth}[1]{\setlength{\RW}{#1}}
+
+\newif\ifUCT
+\UCTfalse
+\newif\ifLCT
+\LCTfalse
+\def\ChTitleLowerCase{\LCTtrue\UCTfalse}
+\def\ChTitleUpperCase{\UCTtrue\LCTfalse}
+\def\ChTitleAsIs{\UCTfalse\LCTfalse}
+\newcommand{\FmTi}[1]{%
+\ifUCT
+
+   {\MakeUppercase#1}\LCTfalse
+\else
+   \ifLCT
+      {\MakeLowercase#1}\UCTfalse
+   \else #1
+   \fi
+\fi}
+
+
+
+\newlength{\mylen}
+\newlength{\myhi}
+\newlength{\px}
+\newlength{\py}
+\newlength{\pyy}
+\newlength{\pxx}
+
+
+\def\mghrulefill#1{\leavevmode\leaders\hrule\@height #1\hfill\kern\z@}
+
+\newcommand{\DOCH}{%
+  \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+  \par\nobreak
+  \vskip 20\p@
+  }
+\newcommand{\DOTI}[1]{%
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@
+    }
+\newcommand{\DOTIS}[1]{%
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@
+    }
+
+%%%%%% SONNY DEF
+
+\DeclareOption{Sonny}{%
+  \ChNameVar{\Large\sf}
+  \ChNumVar{\Huge}
+  \ChTitleVar{\Large\sf}
+  \ChRuleWidth{0.5pt}
+  \ChNameUpperCase
+  \renewcommand{\DOCH}{%
+    \raggedleft
+    \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+    \par\nobreak
+    \vskip 40\p@}
+  \renewcommand{\DOTI}[1]{%
+    \CTV\raggedleft\mghrulefill{\RW}\par\nobreak
+    \vskip 5\p@
+    \CTV\FmTi{#1}\par\nobreak
+    \mghrulefill{\RW}\par\nobreak
+    \vskip 40\p@}
+  \renewcommand{\DOTIS}[1]{%
+    \CTV\raggedleft\mghrulefill{\RW}\par\nobreak
+    \vskip 5\p@
+    \CTV\FmTi{#1}\par\nobreak
+    \mghrulefill{\RW}\par\nobreak
+    \vskip 40\p@}
+}
+
+%%%%%% LENNY DEF
+
+\DeclareOption{Lenny}{%
+
+  \ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont}
+  \ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont}
+  \ChTitleVar{\Huge\bfseries\rm}
+  \ChRuleWidth{1pt}
+  \renewcommand{\DOCH}{%
+    \settowidth{\px}{\CNV\FmN{\@chapapp}}
+    \addtolength{\px}{2pt}
+    \settoheight{\py}{\CNV\FmN{\@chapapp}}
+    \addtolength{\py}{1pt}
+
+    \settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter}
+    \addtolength{\mylen}{1pt}
+    \settowidth{\pxx}{\CNoV\thechapter}
+    \addtolength{\pxx}{-1pt}
+
+    \settoheight{\pyy}{\CNoV\thechapter}
+    \addtolength{\pyy}{-2pt}
+    \setlength{\myhi}{\pyy}
+    \addtolength{\myhi}{-1\py}
+    \par
+    \parbox[b]{\textwidth}{%
+    \rule[\py]{\RW}{\myhi}%
+    \hskip -\RW%
+    \rule[\pyy]{\px}{\RW}%
+    \hskip -\px%
+    \raggedright%
+    \CNV\FmN{\@chapapp}\space\CNoV\thechapter%
+    \hskip1pt%
+    \mghrulefill{\RW}%
+    \rule{\RW}{\pyy}\par\nobreak%
+    \vskip -\baselineskip%
+    \vskip -\pyy%
+    \hskip \mylen%
+    \mghrulefill{\RW}\par\nobreak%
+    \vskip \pyy}%
+    \vskip 20\p@}
+ 
+
+  \renewcommand{\DOTI}[1]{%
+    \raggedright
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@}
+
+  \renewcommand{\DOTIS}[1]{%
+    \raggedright
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@}
+ }
+
+
+%%%%%%% GLENN DEF
+
+
+\DeclareOption{Glenn}{%
+  \ChNameVar{\bfseries\Large\sf}
+  \ChNumVar{\Huge}
+  \ChTitleVar{\bfseries\Large\rm}
+  \ChRuleWidth{1pt}
+  \ChNameUpperCase
+  \ChTitleUpperCase
+  \renewcommand{\DOCH}{%
+    \settoheight{\myhi}{\CTV\FmTi{Test}}
+    \setlength{\py}{\baselineskip}
+    \addtolength{\py}{\RW}
+    \addtolength{\py}{\myhi}
+    \setlength{\pyy}{\py}
+    \addtolength{\pyy}{-1\RW}
+     
+    \raggedright
+    \CNV\FmN{\@chapapp}\space\CNoV\thechapter
+    \hskip 3pt\mghrulefill{\RW}\rule[-1\pyy]{2\RW}{\py}\par\nobreak}
+
+  \renewcommand{\DOTI}[1]{%
+    \addtolength{\pyy}{-4pt}
+    \settoheight{\myhi}{\CTV\FmTi{#1}}
+    \addtolength{\myhi}{\py}
+    \addtolength{\myhi}{-1\RW}
+    \vskip -1\pyy
+    \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
+    \raggedleft\CTV\FmTi{#1}\par\nobreak
+    \vskip 80\p@}
+
+  \renewcommand{\DOTIS}[1]{%
+    \setlength{\py}{10pt}
+    \setlength{\pyy}{\py}
+    \addtolength{\pyy}{\RW}
+    \setlength{\myhi}{\baselineskip}
+    \addtolength{\myhi}{\pyy}
+    \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak
+%    \addtolength{}{}
+\vskip -1\baselineskip
+    \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
+    \raggedleft\CTV\FmTi{#1}\par\nobreak
+    \vskip 60\p@}
+  }
+
+%%%%%%% CONNY DEF
+
+\DeclareOption{Conny}{%
+  \ChNameUpperCase
+  \ChTitleUpperCase  
+  \ChNameVar{\centering\Huge\rm\bfseries}
+  \ChNumVar{\Huge}
+  \ChTitleVar{\centering\Huge\rm}
+  \ChRuleWidth{2pt}
+
+  \renewcommand{\DOCH}{%
+    \mghrulefill{3\RW}\par\nobreak
+    \vskip -0.5\baselineskip
+    \mghrulefill{\RW}\par\nobreak
+    \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+    \par\nobreak
+    \vskip -0.5\baselineskip
+   }
+  \renewcommand{\DOTI}[1]{%
+    \mghrulefill{\RW}\par\nobreak
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 60\p@
+    }
+  \renewcommand{\DOTIS}[1]{%
+    \mghrulefill{\RW}\par\nobreak
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 60\p@
+    }
+  }
+
+%%%%%%% REJNE DEF
+
+\DeclareOption{Rejne}{%
+
+  \ChNameUpperCase
+  \ChTitleUpperCase  
+  \ChNameVar{\centering\Large\rm}
+  \ChNumVar{\Huge}
+  \ChTitleVar{\centering\Huge\rm}
+  \ChRuleWidth{1pt}
+  \renewcommand{\DOCH}{%
+    \settoheight{\py}{\CNoV\thechapter}
+    \addtolength{\py}{-1pt}
+    \CNV\FmN{\@chapapp}\par\nobreak
+    \vskip 20\p@
+    \setlength{\myhi}{2\baselineskip}
+    \setlength{\px}{\myhi}
+    \addtolength{\px}{-1\RW}
+    \rule[-1\px]{\RW}{\myhi}\mghrulefill{\RW}\hskip
+    10pt\raisebox{-0.5\py}{\CNoV\thechapter}\hskip
+10pt\mghrulefill{\RW}\rule[-1\px]{\RW}{\myhi}\par\nobreak
+     \vskip -1\p@
+    }
+  \renewcommand{\DOTI}[1]{%
+    \setlength{\mylen}{\textwidth}
+    \addtolength{\mylen}{-2\RW}
+    {\vrule width\RW}\parbox{\mylen}{\CTV\FmTi{#1}}{\vrule
+width\RW}\par\nobreak
+    \vskip
+-1pt\rule{\RW}{2\baselineskip}\mghrulefill{\RW}\rule{\RW}{2\baselineskip}
+    \vskip 60\p@
+    }
+  \renewcommand{\DOTIS}[1]{%
+    \setlength{\py}{\fboxrule}
+    \setlength{\fboxrule}{\RW}
+    \setlength{\mylen}{\textwidth}
+    \addtolength{\mylen}{-2\RW}
+    \fbox{\parbox{\mylen}{\vskip
+2\baselineskip\CTV\FmTi{#1}\par\nobreak\vskip \baselineskip}} 
+    \setlength{\fboxrule}{\py}
+    \vskip 60\p@
+    }
+  }
+
+
+%%%%%%% BJARNE DEF
+
+\DeclareOption{Bjarne}{%
+  \ChNameUpperCase
+  \ChTitleUpperCase  
+  \ChNameVar{\raggedleft\normalsize\rm}
+  \ChNumVar{\raggedleft \bfseries\Large}
+  \ChTitleVar{\raggedleft \Large\rm}
+  \ChRuleWidth{1pt}
+
+
+%% Note thechapter -> c at chapter fix appendix bug
+
+  \newcounter{AlphaCnt}
+  \newcounter{AlphaDecCnt}
+  \newcommand{\AlphaNo}{%
+    \ifcase\number\theAlphaCnt
+      \ifnum\c at chapter=0
+        ZERO\else{}\fi
+    \or ONE\or TWO\or THREE\or FOUR\or FIVE
+    \or SIX\or SEVEN\or EIGHT\or NINE\or TEN
+    \or ELEVEN\or TWELVE\or THIRTEEN\or FOURTEEN\or FIFTEEN
+    \or SIXTEEN\or SEVENTEEN\or EIGHTEEN\or NINETEEN\fi
+}
+
+  \newcommand{\AlphaDecNo}{%
+    \setcounter{AlphaDecCnt}{0}
+    \@whilenum\number\theAlphaCnt>0\do
+      {\addtocounter{AlphaCnt}{-10}
+       \addtocounter{AlphaDecCnt}{1}}
+     \ifnum\number\theAlphaCnt=0
+     \else
+       \addtocounter{AlphaDecCnt}{-1}
+       \addtocounter{AlphaCnt}{10}
+     \fi
+     
+     
+    \ifcase\number\theAlphaDecCnt\or TEN\or TWENTY\or THIRTY\or
+    FORTY\or FIFTY\or SIXTY\or SEVENTY\or EIGHTY\or NINETY\fi
+    }
+  \newcommand{\TheAlphaChapter}{%
+    
+    \ifinapp 
+      \thechapter
+    \else
+      \setcounter{AlphaCnt}{\c at chapter}
+      \ifnum\c at chapter<20
+        \AlphaNo
+      \else
+        \AlphaDecNo\AlphaNo
+      \fi
+    \fi
+    }  
+  \renewcommand{\DOCH}{%
+    \mghrulefill{\RW}\par\nobreak
+    \CNV\FmN{\@chapapp}\par\nobreak 
+    \CNoV\TheAlphaChapter\par\nobreak
+    \vskip -1\baselineskip\vskip 5pt\mghrulefill{\RW}\par\nobreak
+    \vskip 20\p@
+    }
+  \renewcommand{\DOTI}[1]{%
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@
+    }
+  \renewcommand{\DOTIS}[1]{%
+    \CTV\FmTi{#1}\par\nobreak
+    \vskip 40\p@
+    }
+}
+
+\DeclareOption*{%
+  \PackageWarning{fancychapter}{unknown style option}
+  }
+
+\ProcessOptions* \relax
+
+\def\@makechapterhead#1{%
+  \vspace*{50\p@}%
+  {\parindent \z@ \raggedright \normalfont
+    \ifnum \c at secnumdepth >\m at ne
+      \DOCH
+    \fi
+    \interlinepenalty\@M
+    \DOTI{#1}
+  }}
+\def\@schapter#1{\if at twocolumn
+                   \@topnewpage[\@makeschapterhead{#1}]%
+                 \else
+                   \@makeschapterhead{#1}%
+                   \@afterheading
+                 \fi}
+\def\@makeschapterhead#1{%
+  \vspace*{50\p@}%
+  {\parindent \z@ \raggedright
+    \normalfont
+    \interlinepenalty\@M
+    \DOTIS{#1}
+    \vskip 40\p@
+  }}
+
+\endinput
+
+

Added: doctools/trunk/sphinx/texinputs/howto.cls
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/howto.cls	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,113 @@
+%
+% howto.cls for the Python documentation
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{howto}
+             [1998/02/25 Document class (Python HOWTO)]
+
+\RequirePackage{fancybox}
+
+% Change the options here to get a different set of basic options,  This
+% is where to add things like "a4paper" or "10pt".
+%
+\LoadClass[twoside]{article}
+
+\setcounter{secnumdepth}{1}
+
+% Optional packages:
+%
+% If processing of these documents fails at your TeX installation,
+% these may be commented out (independently) to make things work.
+% These are both supplied with the current version of the teTeX
+% distribution.
+%
+% The "fancyhdr" package makes nicer page footers reasonable to
+% implement, and is used to put the chapter and section information in 
+% the footers.
+%
+\RequirePackage{fancyhdr}\typeout{Using fancier footers than usual.}
+
+
+% Required package:
+%
+% This gives us all the Python-specific markup that we really want.
+% This should come last.  Do not change this.
+%
+\RequirePackage{python}
+
+% This comes after python.sty because it otherwise defines its own
+% "seealso" command.
+\RequirePackage{makeidx}
+
+
+% support for module synopsis sections:
+\newcommand{\py at ModSynopsisFilename}{\jobname.syn}
+
+
+% need to do one of these....
+\newcommand{\py at doHorizontalRule}{\rule{\textwidth}{1pt}}
+
+
+% Change the title page to look a bit better, and fit in with the
+% fncychap ``Bjarne'' style a bit better.
+%
+\renewcommand{\maketitle}{
+  \py at doHorizontalRule
+  \ifpdf
+    \begingroup
+    % This \def is required to deal with multi-line authors; it
+    % changes \\ to ', ' (comma-space), making it pass muster for
+    % generating document info in the PDF file.
+    \def\\{, }
+    \pdfinfo{
+      /Author (\@author)
+      /Title (\@title)
+    }
+    \endgroup
+  \fi
+  \begin{flushright}
+    {\rm\Huge\py at HeaderFamily \@title} \par
+    {\em\large\py at HeaderFamily \py at release\releaseinfo} \par
+    \vspace{25pt}
+    {\Large\py at HeaderFamily \@author} \par
+    \vspace{25pt}
+    \@date \par
+    \py at authoraddress \par
+  \end{flushright}
+  \@thanks
+  \setcounter{footnote}{0}
+  \let\thanks\relax\let\maketitle\relax
+  \gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+
+
+\let\py at OldTableofcontents=\tableofcontents
+\renewcommand{\tableofcontents}{
+  \begingroup
+    \parskip = 0mm
+    \py at OldTableofcontents
+  \endgroup
+  \py at doHorizontalRule
+  \vspace{12pt}
+  \py at doing@page at targetstrue
+}  
+
+% Fix the theindex environment to add an entry to the Table of
+% Contents; this is much nicer than just having to jump to the end of
+% the book and flip around, especially with multiple indexes.
+%
+\let\py at OldTheindex=\theindex
+\renewcommand{\theindex}{
+  \clearpage
+  \py at OldTheindex
+  \addcontentsline{toc}{section}{\indexname}
+}
+
+\@ifundefined{fancyhf}{
+  \pagestyle{plain}}{
+  \pagestyle{normal}}		% start this way; change for
+\pagenumbering{arabic}		% ToC & chapters
+\setcounter{secnumdepth}{2}
+
+\thispagestyle{empty}

Added: doctools/trunk/sphinx/texinputs/manual.cls
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/manual.cls	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,159 @@
+%
+% manual.cls for the Python documentation
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{manual}
+             [1998/03/03 Document class (Python manual)]
+
+\RequirePackage{fancybox}
+
+% Change the options here to get a different set of basic options, but only
+% if you have to.
+%
+\LoadClass[twoside,openright]{report}
+
+\setcounter{secnumdepth}{2}
+
+% Optional packages:
+%
+% If processing of these documents fails at your TeX installation,
+% these may be commented out (independently) to make things work.
+% These are both supplied with the current version of the teTeX
+% distribution.
+%
+% The "fancyhdr" package makes nicer page footers reasonable to
+% implement, and is used to put the chapter and section information in 
+% the footers.
+%
+\RequirePackage{fancyhdr}\typeout{Using fancier footers than usual.}
+
+
+% Required packages:
+%
+% The "fncychap" package is used to get the nice chapter headers.  The
+% .sty file is distributed with Python, so you should not need to disable
+% it.  You'd also end up with a mixed page style; uglier than stock LaTeX!
+%
+\RequirePackage[Bjarne]{fncychap}\typeout{Using fancy chapter headings.}
+% Do horizontal rules it this way to match:
+\newcommand{\py at doHorizontalRule}{\mghrulefill{\RW}}
+%
+%
+% This gives us all the Python-specific markup that we really want.
+% This should come last.  Do not change this.
+%
+\RequirePackage{python}
+
+% This comes after python.sty because it otherwise defines its own
+% "seealso" command.
+\RequirePackage{makeidx}
+
+
+% support for module synopsis sections:
+\newcommand{\py at ModSynopsisFilename}{\jobname\thechapter.syn}
+\let\py at OldChapter=\chapter
+\renewcommand{\chapter}{
+  \py at ProcessModSynopsis
+  \py at closeModSynopsisFile
+  \py at OldChapter
+}
+
+
+% Change the title page to look a bit better, and fit in with the
+% fncychap ``Bjarne'' style a bit better.
+%
+\renewcommand{\maketitle}{%
+  \begin{titlepage}%
+    \let\footnotesize\small
+    \let\footnoterule\relax
+    \py at doHorizontalRule%
+    \ifpdf
+      \begingroup
+      % This \def is required to deal with multi-line authors; it
+      % changes \\ to ', ' (comma-space), making it pass muster for
+      % generating document info in the PDF file.
+      \def\\{, }
+      \pdfinfo{
+        /Author (\@author)
+        /Title (\@title)
+      }
+      \endgroup
+    \fi
+    \begin{flushright}%
+      {\rm\Huge\py at HeaderFamily \@title \par}%
+      {\em\LARGE\py at HeaderFamily \py at release\releaseinfo \par}
+      \vfill
+      {\LARGE\py at HeaderFamily \@author \par}
+      \vfill\vfill
+      {\large
+       \@date \par
+       \vfill
+       \py at authoraddress \par
+      }%
+    \end{flushright}%\par
+    \@thanks
+  \end{titlepage}%
+  \setcounter{footnote}{0}%
+  \let\thanks\relax\let\maketitle\relax
+  \gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+
+
+% Catch the end of the {abstract} environment, but here make sure the
+% abstract is followed by a blank page if the 'openright' option is used.
+%
+\let\py at OldEndAbstract=\endabstract
+\renewcommand{\endabstract}{
+  \if at openright
+    \ifodd\value{page}
+      \typeout{Adding blank page after the abstract.}
+      \vfil\pagebreak
+    \fi
+  \fi
+  \py at OldEndAbstract
+}
+
+% This wraps the \tableofcontents macro with all the magic to get the
+% spacing right and have the right number of pages if the 'openright'
+% option has been used.  This eliminates a fair amount of crud in the
+% individual document files.
+%
+\let\py at OldTableofcontents=\tableofcontents
+\renewcommand{\tableofcontents}{%
+  \setcounter{page}{1}%
+  \pagebreak%
+  \pagestyle{plain}%
+  {%
+    \parskip = 0mm%
+    \py at OldTableofcontents%
+    \if at openright%
+      \ifodd\value{page}%
+        \typeout{Adding blank page after the table of contents.}%
+        \pagebreak\hspace{0pt}%
+      \fi%
+    \fi%
+    \cleardoublepage%
+  }%
+  \pagenumbering{arabic}%
+  \@ifundefined{fancyhf}{}{\pagestyle{normal}}%
+  \py at doing@page at targetstrue%
+}
+% This is needed to get the width of the section # area wide enough in the
+% library reference.  Doing it here keeps it the same for all the manuals.
+%
+\renewcommand*\l at section{\@dottedtocline{1}{1.5em}{2.6em}}
+\renewcommand*\l at subsection{\@dottedtocline{2}{4.1em}{3.5em}}
+\setcounter{tocdepth}{1}
+
+
+% Fix the theindex environment to add an entry to the Table of
+% Contents; this is much nicer than just having to jump to the end of
+% the book and flip around, especially with multiple indexes.
+%
+\let\py at OldTheindex=\theindex
+\renewcommand{\theindex}{
+  \cleardoublepage
+  \py at OldTheindex
+  \addcontentsline{toc}{chapter}{\indexname}
+}

Added: doctools/trunk/sphinx/texinputs/python.ist
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/python.ist	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,11 @@
+line_max 100
+headings_flag 1
+heading_prefix "  \\bigletter "
+
+preamble "\\begin{theindex}
+\\def\\bigletter#1{{\\Large\\sffamily#1}\\nopagebreak\\vspace{1mm}}
+
+"
+
+symhead_positive "{Symbols}"
+numhead_positive "{Numbers}"

Added: doctools/trunk/sphinx/texinputs/python.sty
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/python.sty	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,1328 @@
+%
+% python.sty for the Python docummentation  [works only with Latex2e]
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesPackage{python}
+             [1998/01/11 LaTeX package (Python markup)]
+
+\RequirePackage{longtable}
+\RequirePackage{underscore}
+\RequirePackage{times}
+
+% Uncomment these two lines to ignore the paper size and make the page 
+% size more like a typical published manual.
+%\renewcommand{\paperheight}{9in}
+%\renewcommand{\paperwidth}{8.5in}   % typical squarish manual
+%\renewcommand{\paperwidth}{7in}     % O'Reilly ``Programmming Python''
+
+% These packages can be used to add marginal annotations which indicate
+% index entries and labels; useful for reviewing this messy documentation!
+%
+%\RequirePackage{showkeys}
+%\RequirePackage{showidx}
+
+% If we ever want to indent paragraphs, this needs to be changed.
+% This is used inside the macros defined here instead of coding
+% \noindent directly.
+\let\py at parindent=\noindent
+
+% for PDF output, use maximal compression & a lot of other stuff
+% (test for PDF recommended by Tanmoy Bhattacharya <tanmoy at qcd.lanl.gov>)
+%
+\newif\ifpy at doing@page at targets
+\py at doing@page at targetsfalse
+
+\newif\ifpdf\pdffalse
+\ifx\pdfoutput\undefined\else\ifcase\pdfoutput
+\else
+  \pdftrue
+  \input{pdfcolor}
+  \let\py at LinkColor=\NavyBlue
+  \let\py at NormalColor=\Black
+  \pdfcompresslevel=9
+  \pdfpagewidth=\paperwidth    % page width of PDF output
+  \pdfpageheight=\paperheight  % page height of PDF output
+  %
+  % Pad the number with '0' to 3 digits wide so no page name is a prefix
+  % of any other.
+  %
+  \newcommand{\py at targetno}[1]{\ifnum#1<100 0\fi\ifnum#1<10 0\fi#1}
+  \newcommand{\py at pageno}{\py at targetno\thepage}
+  %
+  % This definition allows the entries in the page-view of the ToC to be
+  % active links.  Some work, some don't.
+  %
+  \let\py at OldContentsline=\contentsline
+  %
+  % Backward compatibility hack: pdfTeX 0.13 defined \pdfannotlink,
+  % but it changed to \pdfstartlink in 0.14.  This let's us use either
+  % version and still get useful behavior.
+  %
+  \@ifundefined{pdfstartlink}{
+    \let\pdfstartlink=\pdfannotlink
+  }{}
+  %
+  % The \py at parindent here is a hack -- we're forcing pdfTeX into
+  % horizontal mode since \pdfstartlink requires that.
+  \def\py at pdfstartlink{%
+    \ifvmode\py at parindent\fi%
+    \pdfstartlink%
+  }
+  %
+  % Macro that takes two args: the name to link to and the content of
+  % the link.  This takes care of the PDF magic, getting the colors
+  % the same for each link, and avoids having lots of garbage all over 
+  % this style file.
+  \newcommand{\py at linkToName}[2]{%
+    \py at pdfstartlink attr{/Border [0 0 0]} goto name{#1}%
+      \py at LinkColor#2\py at NormalColor%
+    \pdfendlink%
+  }
+  % Compute the padded page number separately since we end up with a pair of
+  % \relax tokens; this gets the right string computed and works.
+  \renewcommand{\contentsline}[3]{%
+    \def\my at pageno{\py at targetno{#3}}%
+    \py at OldContentsline{#1}{\py at linkToName{page\my at pageno}{#2}}{#3}%
+  }
+  \AtEndDocument{
+    \def\_{\string_}
+    \InputIfFileExists{\jobname.bkm}{\pdfcatalog{/PageMode /UseOutlines}}{}
+  }
+  \newcommand{\py at target}[1]{%
+    \ifpy at doing@page at targets%
+      {\pdfdest name{#1} xyz}%
+    \fi%
+  }
+  \let\py at OldLabel=\label
+  \renewcommand{\label}[1]{%
+    \py at OldLabel{#1}%
+    \py at target{label-#1}%
+  }
+  % This stuff adds a page# destination to every PDF page, where # is three
+  % digits wide, padded with leading zeros.  This doesn't really help with
+  % the frontmatter, but does fine with the body.
+  %
+  % This is *heavily* based on the hyperref package.
+  %
+  \def\@begindvi{%
+    \unvbox \@begindvibox
+    \@hyperfixhead
+  }
+  \def\@hyperfixhead{%
+   \let\H at old@thehead\@thehead
+       \global\def\@foo{\py at target{page\py at pageno}}%
+     \expandafter\ifx\expandafter\@empty\H at old@thehead
+       \def\H at old@thehead{\hfil}\fi
+    \def\@thehead{\@foo\relax\H at old@thehead}%
+  }
+\fi\fi
+
+% Increase printable page size (copied from fullpage.sty)
+\topmargin 0pt
+\advance \topmargin by -\headheight
+\advance \topmargin by -\headsep
+
+% attempt to work a little better for A4 users
+\textheight \paperheight
+\advance\textheight by -2in
+
+\oddsidemargin 0pt
+\evensidemargin 0pt
+%\evensidemargin -.25in  % for ``manual size'' documents
+\marginparwidth 0.5in
+
+\textwidth \paperwidth
+\advance\textwidth by -2in
+
+
+% Style parameters and macros used by most documents here
+\raggedbottom
+\sloppy
+\parindent = 0mm
+\parskip = 2mm
+\hbadness = 5000                % don't print trivial gripes
+
+\pagestyle{empty}               % start this way; change for
+\pagenumbering{roman}           % ToC & chapters
+
+% Use this to set the font family for headers and other decor:
+\newcommand{\py at HeaderFamily}{\sffamily}
+
+% Set up abstract ways to get the normal and smaller font sizes that
+% work even in footnote context.
+\newif\ifpy at infootnote \py at infootnotefalse
+\let\py at oldmakefntext\@makefntext
+\def\@makefntext#1{%
+  \bgroup%
+    \py at infootnotetrue
+    \py at oldmakefntext{#1}%
+  \egroup%
+}
+\def\py at defaultsize{%
+  \ifpy at infootnote\footnotesize\else\normalsize\fi%
+}
+\def\py at smallsize{%
+  \ifpy at infootnote\scriptsize\else\small\fi%
+}
+
+% Redefine the 'normal' header/footer style when using "fancyhdr" package:
+\@ifundefined{fancyhf}{}{
+  % Use \pagestyle{normal} as the primary pagestyle for text.
+  \fancypagestyle{normal}{
+    \fancyhf{}
+    \fancyfoot[LE,RO]{{\py at HeaderFamily\thepage}}
+    \fancyfoot[LO]{{\py at HeaderFamily\nouppercase{\rightmark}}}
+    \fancyfoot[RE]{{\py at HeaderFamily\nouppercase{\leftmark}}}
+    \renewcommand{\headrulewidth}{0pt}
+    \renewcommand{\footrulewidth}{0.4pt}
+  }
+  % Update the plain style so we get the page number & footer line,
+  % but not a chapter or section title.  This is to keep the first
+  % page of a chapter and the blank page between chapters `clean.'
+  \fancypagestyle{plain}{
+    \fancyhf{}
+    \fancyfoot[LE,RO]{{\py at HeaderFamily\thepage}}
+    \renewcommand{\headrulewidth}{0pt}
+    \renewcommand{\footrulewidth}{0.4pt}
+  }
+  % Redefine \cleardoublepage so that the blank page between chapters
+  % gets the plain style and not the fancy style.  This is described
+  % in the documentation for the fancyhdr package by Piet von Oostrum.
+  \@ifundefined{chapter}{}{
+    \renewcommand{\cleardoublepage}{
+      \clearpage\if at openright \ifodd\c at page\else
+      \hbox{}
+      \thispagestyle{plain}
+      \newpage
+      \if at twocolumn\hbox{}\newpage\fi\fi\fi
+    }
+  }
+}
+
+% This sets up the {verbatim} environment to be indented and a minipage,
+% and to have all the other mostly nice properties that we want for
+% code samples.
+
+\let\py at OldVerbatim=\verbatim
+\let\py at OldEndVerbatim=\endverbatim
+\RequirePackage{verbatim}
+\let\py at OldVerbatimInput=\verbatiminput
+
+% Variable used by begin code command
+\newlength{\py at codewidth}
+
+\renewcommand{\verbatim}{%
+  \setlength{\parindent}{1cm}%
+  % Calculate the text width for the minipage:
+  \setlength{\py at codewidth}{\linewidth}%
+  \addtolength{\py at codewidth}{-\parindent}%
+  %
+  \par\indent%
+  \begin{minipage}[t]{\py at codewidth}%
+    \small%
+    \py at OldVerbatim%
+}
+\renewcommand{\endverbatim}{%
+    \py at OldEndVerbatim%
+  \end{minipage}%
+}
+\renewcommand{\verbatiminput}[1]{%
+  {\setlength{\parindent}{1cm}%
+   % Calculate the text width for the minipage:
+   \setlength{\py at codewidth}{\linewidth}%
+   \addtolength{\py at codewidth}{-\parindent}%
+   %
+   \small%
+   \begin{list}{}{\setlength{\leftmargin}{1cm}}
+     \item%
+     \py at OldVerbatimInput{#1}%
+   \end{list}
+  }%
+}
+
+% This does a similar thing for the {alltt} environment:
+\RequirePackage{alltt}
+\let\py at OldAllTT=\alltt
+\let\py at OldEndAllTT=\endalltt
+
+\renewcommand{\alltt}{%
+  \setlength{\parindent}{1cm}%
+  % Calculate the text width for the minipage:
+  \setlength{\py at codewidth}{\linewidth}%
+  \addtolength{\py at codewidth}{-\parindent}%
+  \let\e=\textbackslash%
+  %
+  \par\indent%
+  \begin{minipage}[t]{\py at codewidth}%
+    \small%
+    \py at OldAllTT%
+}
+\renewcommand{\endalltt}{%
+    \py at OldEndAllTT%
+  \end{minipage}%
+}
+
+
+\newcommand{\py at modulebadkey}{{--just-some-junk--}}
+
+
+%%  Lots of index-entry generation support.
+
+% Command to wrap around stuff that refers to function / module /
+% attribute names  in the index.  Default behavior: like \code{}.  To
+% just keep the index entries in the roman font, uncomment the second
+% definition; it matches O'Reilly style more.
+%
+\newcommand{\py at idxcode}[1]{\texttt{#1}}
+%\renewcommand{\py at idxcode}[1]{#1}
+
+% Command to generate two index entries (using subentries)
+\newcommand{\indexii}[2]{\index{#1!#2}\index{#2!#1}}
+
+% And three entries (using only one level of subentries)
+\newcommand{\indexiii}[3]{\index{#1!#2 #3}\index{#2!#3, #1}\index{#3!#1 #2}}
+
+% And four (again, using only one level of subentries)
+\newcommand{\indexiv}[4]{
+\index{#1!#2 #3 #4}
+\index{#2!#3 #4, #1}
+\index{#3!#4, #1 #2}
+\index{#4!#1 #2 #3}
+}
+
+% Command to generate a reference to a function, statement, keyword,
+% operator.
+\newcommand{\kwindex}[1]{\indexii{keyword}{#1@{\py at idxcode{#1}}}}
+\newcommand{\stindex}[1]{\indexii{statement}{#1@{\py at idxcode{#1}}}}
+\newcommand{\opindex}[1]{\indexii{operator}{#1@{\py at idxcode{#1}}}}
+\newcommand{\exindex}[1]{\indexii{exception}{#1@{\py at idxcode{#1}}}}
+\newcommand{\obindex}[1]{\indexii{object}{#1}}
+\newcommand{\bifuncindex}[1]{%
+  \index{#1@{\py at idxcode{#1()}} (built-in function)}}
+
+% Add an index entry for a module
+\newcommand{\py at refmodule}[2]{\index{#1@{\py at idxcode{#1}} (#2module)}}
+\newcommand{\refmodindex}[1]{\py at refmodule{#1}{}}
+\newcommand{\refbimodindex}[1]{\py at refmodule{#1}{built-in }}
+\newcommand{\refexmodindex}[1]{\py at refmodule{#1}{extension }}
+\newcommand{\refstmodindex}[1]{\py at refmodule{#1}{standard }}
+
+% Refer to a module's documentation using a hyperlink of the module's
+% name, at least if we're building PDF:
+\ifpdf
+  \newcommand{\refmodule}[2][\py at modulebadkey]{%
+    \ifx\py at modulebadkey#1\def\py at modulekey{#2}\else\def\py at modulekey{#1}\fi%
+    \py at linkToName{label-module-\py at modulekey}{\module{#2}}%
+  }
+\else
+  \newcommand{\refmodule}[2][\py at modulebadkey]{\module{#2}}
+\fi
+
+% support for the module index
+\newif\ifpy at UseModuleIndex
+\py at UseModuleIndexfalse
+
+\newcommand{\makemodindex}{
+  \newwrite\modindexfile
+  \openout\modindexfile=mod\jobname.idx
+  \py at UseModuleIndextrue
+}
+
+% Add the defining entry for a module
+\newcommand{\py at modindex}[2]{%
+  \renewcommand{\py at thismodule}{#1}
+  \setindexsubitem{(in module #1)}%
+  \index{#1@{\py at idxcode{#1}} (#2module)|textbf}%
+  \ifpy at UseModuleIndex%
+    \@ifundefined{py at modplat@\py at thismodulekey}{
+      \write\modindexfile{\protect\indexentry{#1@{\texttt{#1}}}{\thepage}}%
+    }{\write\modindexfile{\protect\indexentry{#1@{\texttt{#1} %
+        \emph{(\py at platformof[\py at thismodulekey]{})}}}{\thepage}}%
+    }
+  \fi%
+}
+
+% *** XXX *** THE NEXT FOUR MACROS ARE NOW OBSOLETE !!! ***
+
+% built-in & Python modules in the main distribution
+\newcommand{\bimodindex}[1]{\py at modindex{#1}{built-in }%
+  \typeout{*** MACRO bimodindex IS OBSOLETE -- USE declaremodule INSTEAD!}}
+\newcommand{\stmodindex}[1]{\py at modindex{#1}{standard }%
+  \typeout{*** MACRO stmodindex IS OBSOLETE -- USE declaremodule INSTEAD!}}
+
+% Python & extension modules outside the main distribution
+\newcommand{\modindex}[1]{\py at modindex{#1}{}%
+  \typeout{*** MACRO modindex IS OBSOLETE -- USE declaremodule INSTEAD!}}
+\newcommand{\exmodindex}[1]{\py at modindex{#1}{extension }%
+  \typeout{*** MACRO exmodindex IS OBSOLETE -- USE declaremodule INSTEAD!}}
+
+% Additional string for an index entry
+\newif\ifpy at usingsubitem\py at usingsubitemfalse
+\newcommand{\py at indexsubitem}{}
+\newcommand{\setindexsubitem}[1]{\renewcommand{\py at indexsubitem}{ #1}%
+                                 \py at usingsubitemtrue}
+\newcommand{\ttindex}[1]{%
+  \ifpy at usingsubitem
+    \index{#1@{\py at idxcode{#1}}\py at indexsubitem}%
+  \else%
+    \index{#1@{\py at idxcode{#1}}}%
+  \fi%
+}
+\newcommand{\withsubitem}[2]{%
+  \begingroup%
+    \def\ttindex##1{\index{##1@{\py at idxcode{##1}} #1}}%
+    #2%
+  \endgroup%
+}
+
+
+% Module synopsis processing -----------------------------------------------
+%
+\newcommand{\py at thisclass}{}
+\newcommand{\py at thismodule}{}
+\newcommand{\py at thismodulekey}{}
+\newcommand{\py at thismoduletype}{}
+
+\newcommand{\py at standardIndexModule}[1]{\py at modindex{#1}{standard }}
+\newcommand{\py at builtinIndexModule}[1]{\py at modindex{#1}{built-in }}
+\newcommand{\py at extensionIndexModule}[1]{\py at modindex{#1}{extension }}
+\newcommand{\py at IndexModule}[1]{\py at modindex{#1}{}}
+
+\newif\ifpy at HaveModSynopsis       \py at HaveModSynopsisfalse
+\newif\ifpy at ModSynopsisFileIsOpen \py at ModSynopsisFileIsOpenfalse
+\newif\ifpy at HaveModPlatform       \py at HaveModPlatformfalse
+
+% \declaremodule[key]{type}{name}
+\newcommand{\declaremodule}[3][\py at modulebadkey]{
+  \py at openModSynopsisFile
+  \renewcommand{\py at thismoduletype}{#2}
+  \ifx\py at modulebadkey#1
+    \renewcommand{\py at thismodulekey}{#3}
+  \else
+    \renewcommand{\py at thismodulekey}{#1}
+  \fi
+  \@ifundefined{py@#2IndexModule}{%
+    \typeout{*** MACRO declaremodule called with unknown module type: `#2'}
+    \py at IndexModule{#3}%
+  }{%
+    \csname py@#2IndexModule\endcsname{#3}%
+  }
+  \label{module-\py at thismodulekey}
+}
+\newif\ifpy at ModPlatformFileIsOpen \py at ModPlatformFileIsOpenfalse
+\newcommand{\py at ModPlatformFilename}{\jobname.pla}
+\newcommand{\platform}[1]{
+  \ifpy at ModPlatformFileIsOpen\else
+    \newwrite\py at ModPlatformFile
+    \openout\py at ModPlatformFile=\py at ModPlatformFilename
+    \py at ModPlatformFileIsOpentrue
+  \fi
+}
+\InputIfFileExists{\jobname.pla}{}{}
+\newcommand{\py at platformof}[2][\py at modulebadkey]{%
+  \ifx\py at modulebadkey#1 \def\py at key{#2}%
+  \else \def\py at key{#1}%
+  \fi%
+  \csname py at modplat@\py at key\endcsname%
+}
+\newcommand{\ignorePlatformAnnotation}[1]{}
+
+% \moduleauthor{name}{email}
+\newcommand{\moduleauthor}[2]{}
+
+% \sectionauthor{name}{email}
+\newcommand{\sectionauthor}[2]{}
+
+
+\newcommand{\py at defsynopsis}{Module has no synopsis.}
+\newcommand{\py at modulesynopsis}{\py at defsynopsis}
+\newcommand{\modulesynopsis}[1]{
+  \py at HaveModSynopsistrue
+  \renewcommand{\py at modulesynopsis}{#1}
+}
+
+% define the file
+\newwrite\py at ModSynopsisFile
+
+% hacked from \addtocontents from latex.ltx:
+\long\def\py at writeModSynopsisFile#1{%
+  \protected at write\py at ModSynopsisFile%
+      {\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
+      {\string#1}%
+}
+\newcommand{\py at closeModSynopsisFile}{
+  \ifpy at ModSynopsisFileIsOpen
+    \closeout\py at ModSynopsisFile
+    \py at ModSynopsisFileIsOpenfalse
+  \fi
+}
+\newcommand{\py at openModSynopsisFile}{
+  \ifpy at ModSynopsisFileIsOpen\else
+    \openout\py at ModSynopsisFile=\py at ModSynopsisFilename
+    \py at ModSynopsisFileIsOpentrue
+  \fi
+}
+
+\newcommand{\py at ProcessModSynopsis}{
+  \ifpy at HaveModSynopsis
+    \py at writeModSynopsisFile{\modulesynopsis%
+      {\py at thismodulekey}{\py at thismodule}%
+      {\py at thismoduletype}{\py at modulesynopsis}}%
+    \py at HaveModSynopsisfalse
+  \fi
+  \renewcommand{\py at modulesynopsis}{\py at defsynopsis}
+}
+\AtEndDocument{\py at ProcessModSynopsis\py at closeModSynopsisFile}
+
+
+\long\def\py at writeModPlatformFile#1{%
+  \protected at write\py at ModPlatformFile%
+    {\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
+    {\string#1}%
+}
+
+
+\newcommand{\localmoduletable}{
+  \IfFileExists{\py at ModSynopsisFilename}{
+    \begin{synopsistable}
+      \input{\py at ModSynopsisFilename}
+    \end{synopsistable}
+  }{}
+}
+
+\ifpdf
+  \newcommand{\py at ModSynopsisSummary}[4]{%
+    \py at linkToName{label-module-#1}{\bfcode{#2}} & #4\\
+  }
+\else
+  \newcommand{\py at ModSynopsisSummary}[4]{\bfcode{#2} & #4\\}
+\fi
+\newenvironment{synopsistable}{
+  % key, name, type, synopsis
+  \let\modulesynopsis=\py at ModSynopsisSummary
+  \begin{tabular}{ll}
+}{
+  \end{tabular}
+}
+%
+% --------------------------------------------------------------------------
+
+
+\newcommand{\py at reset}{
+  \py at usingsubitemfalse
+  \py at ProcessModSynopsis
+  \renewcommand{\py at thisclass}{}
+  \renewcommand{\py at thismodule}{}
+  \renewcommand{\py at thismodulekey}{}
+  \renewcommand{\py at thismoduletype}{}
+}
+
+% Augment the sectioning commands used to get our own font family in place,
+% and reset some internal data items:
+\renewcommand{\section}{\py at reset%
+                        \@startsection{section}{1}{\z@}%
+                                    {-3.5ex \@plus -1ex \@minus -.2ex}%
+                                    {2.3ex \@plus.2ex}%
+                                    {\reset at font\Large\py at HeaderFamily}}
+\renewcommand{\subsection}{\@startsection{subsection}{2}{\z@}%
+                                    {-3.25ex\@plus -1ex \@minus -.2ex}%
+                                    {1.5ex \@plus .2ex}%
+                                    {\reset at font\large\py at HeaderFamily}}
+\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{\z@}%
+                                    {-3.25ex\@plus -1ex \@minus -.2ex}%
+                                    {1.5ex \@plus .2ex}%
+                                    {\reset at font\normalsize\py at HeaderFamily}}
+\renewcommand{\paragraph}{\@startsection{paragraph}{4}{\z@}%
+                                    {3.25ex \@plus1ex \@minus.2ex}%
+                                    {-1em}%
+                                    {\reset at font\normalsize\py at HeaderFamily}}
+\renewcommand{\subparagraph}{\@startsection{subparagraph}{5}{\parindent}%
+                                    {3.25ex \@plus1ex \@minus .2ex}%
+                                    {-1em}%
+                                    {\reset at font\normalsize\py at HeaderFamily}}
+
+
+% Now for a lot of semantically-loaded environments that do a ton of magical
+% things to get the right formatting and index entries for the stuff in
+% Python modules and C API.
+
+
+% {fulllineitems} is used in one place in libregex.tex, but is really for
+% internal use in this file.
+%
+\newcommand{\py at itemnewline}[1]{%
+  \@tempdima\linewidth%
+  \advance\@tempdima \leftmargin\makebox[\@tempdima][l]{#1}%
+}
+
+\newenvironment{fulllineitems}{
+  \begin{list}{}{\labelwidth \leftmargin \labelsep 0pt
+                 \rightmargin 0pt \topsep -\parskip \partopsep \parskip
+                 \itemsep -\parsep
+                 \let\makelabel=\py at itemnewline}
+}{\end{list}}
+
+% \optional is mostly for use in the arguments parameters to the various
+% {*desc} environments defined below, but may be used elsewhere.  Known to
+% be used in the debugger chapter.
+%
+% Typical usage:
+%
+%     \begin{funcdesc}{myfunc}{reqparm\optional{, optparm}}
+%                                    ^^^       ^^^
+%                          No space here       No space here
+%
+% When a function has multiple optional parameters, \optional should be
+% nested, not chained.  This is right:
+%
+%     \begin{funcdesc}{myfunc}{\optional{parm1\optional{, parm2}}}
+%
+\let\py at badkey=\@undefined
+
+\newcommand{\optional}[1]{%
+  {\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
+
+% This can be used when a function or method accepts an varying number 
+% of arguments, such as by using the *args syntax in the parameter list.
+\newcommand{\py at moreargs}{...}
+
+% This can be used when you don't want to document the parameters to a 
+% function or method, but simply state that it's an alias for
+% something else.
+\newcommand{\py at unspecified}{...}
+
+
+\newlength{\py at argswidth}
+\newcommand{\py at sigparams}[1]{%
+  \parbox[t]{\py at argswidth}{\py at varvars{#1}\code{)}}}
+\newcommand{\py at sigline}[2]{%
+  \settowidth{\py at argswidth}{#1\code{(}}%
+  \addtolength{\py at argswidth}{-2\py at argswidth}%
+  \addtolength{\py at argswidth}{\textwidth}%
+  \item[#1\code{(}\py at sigparams{#2}]}
+
+% C functions ------------------------------------------------------------
+% \begin{cfuncdesc}[refcount]{type}{name}{arglist}
+% Note that the [refcount] slot should only be filled in by
+% tools/anno-api.py; it pulls the value from the refcounts database.
+\newcommand{\cfuncline}[3]{
+  \py at sigline{\code{#1 \bfcode{#2}}}{#3}%
+  \index{#2@{\py at idxcode{#2()}}}
+}
+\newenvironment{cfuncdesc}[4][\py at badkey]{
+  \begin{fulllineitems}
+    \cfuncline{#2}{#3}{#4}
+    \ifx\@undefined#1\relax\else%
+      \emph{Return value: \textbf{#1}.}\\
+    \fi
+}{\end{fulllineitems}}
+
+% C variables ------------------------------------------------------------
+% \begin{cvardesc}{type}{name}
+\newenvironment{cvardesc}[2]{
+  \begin{fulllineitems}
+    \item[\code{#1 \bfcode{#2}}\index{#2@{\py at idxcode{#2}}}]
+}{\end{fulllineitems}}
+
+% C data types -----------------------------------------------------------
+% \begin{ctypedesc}[index name]{typedef name}
+\newenvironment{ctypedesc}[2][\py at badkey]{
+  \begin{fulllineitems}
+    \item[\bfcode{#2}%
+    \ifx\@undefined#1\relax%
+      \index{#2@{\py at idxcode{#2}} (C type)}
+    \else%
+      \index{#2@{\py at idxcode{#1}} (C type)}
+    \fi]
+}{\end{fulllineitems}}
+
+% C type fields ----------------------------------------------------------
+% \begin{cmemberdesc}{container type}{ctype}{membername}
+\newcommand{\cmemberline}[3]{
+  \item[\code{#2 \bfcode{#3}}]
+  \index{#3@{\py at idxcode{#3}} (#1 member)}
+}
+\newenvironment{cmemberdesc}[3]{
+  \begin{fulllineitems}
+    \cmemberline{#1}{#2}{#3}
+}{\end{fulllineitems}}
+
+% Funky macros -----------------------------------------------------------
+% \begin{csimplemacrodesc}{name}
+% -- "simple" because it has no args; NOT for constant definitions!
+\newenvironment{csimplemacrodesc}[1]{
+  \begin{fulllineitems}
+    \item[\bfcode{#1}\index{#1@{\py at idxcode{#1}} (macro)}]
+}{\end{fulllineitems}}
+
+% simple functions (not methods) -----------------------------------------
+% \begin{funcdesc}{name}{args}
+\newcommand{\funcline}[2]{%
+  \funclineni{#1}{#2}%
+  \index{#1@{\py at idxcode{#1()}} (in module \py at thismodule)}}
+\newenvironment{funcdesc}[2]{
+  \begin{fulllineitems}
+    \funcline{#1}{#2}
+}{\end{fulllineitems}}
+
+% similar to {funcdesc}, but doesn't add to the index
+\newcommand{\funclineni}[2]{%
+  \py at sigline{\bfcode{#1}}{#2}}
+\newenvironment{funcdescni}[2]{
+  \begin{fulllineitems}
+    \funclineni{#1}{#2}
+}{\end{fulllineitems}}
+
+% classes ----------------------------------------------------------------
+% \begin{classdesc}{name}{constructor args}
+\newenvironment{classdesc}[2]{
+  % Using \renewcommand doesn't work for this, for unknown reasons:
+  \global\def\py at thisclass{#1}
+  \begin{fulllineitems}
+    \py at sigline{\strong{class }\bfcode{#1}}{#2}%
+    \index{#1@{\py at idxcode{#1}} (class in \py at thismodule)}
+}{\end{fulllineitems}}
+
+% \begin{classdesc*}{name}
+\newenvironment{classdesc*}[1]{
+  % Using \renewcommand doesn't work for this, for unknown reasons:
+  \global\def\py at thisclass{#1}
+  \begin{fulllineitems}
+    \item[\strong{class }\code{\bfcode{#1}}%
+      \index{#1@{\py at idxcode{#1}} (class in \py at thismodule)}]
+}{\end{fulllineitems}}
+
+% \begin{excclassdesc}{name}{constructor args}
+% but indexes as an exception
+\newenvironment{excclassdesc}[2]{
+  % Using \renewcommand doesn't work for this, for unknown reasons:
+  \global\def\py at thisclass{#1}
+  \begin{fulllineitems}
+    \py at sigline{\strong{exception }\bfcode{#1}}{#2}%
+    \index{#1@{\py at idxcode{#1}} (exception in \py at thismodule)}
+}{\end{fulllineitems}}
+
+% There is no corresponding {excclassdesc*} environment.  To describe
+% a class exception without parameters, use the {excdesc} environment.
+
+
+\let\py at classbadkey=\@undefined
+
+% object method ----------------------------------------------------------
+% \begin{methoddesc}[classname]{methodname}{args}
+\newcommand{\methodline}[3][\@undefined]{
+  \methodlineni{#2}{#3}
+  \ifx\@undefined#1\relax
+    \index{#2@{\py at idxcode{#2()}} (\py at thisclass\ method)}
+  \else
+    \index{#2@{\py at idxcode{#2()}} (#1 method)}
+  \fi
+}
+\newenvironment{methoddesc}[3][\@undefined]{
+  \begin{fulllineitems}
+    \ifx\@undefined#1\relax
+      \methodline{#2}{#3}
+    \else
+      \def\py at thisclass{#1}
+      \methodline{#2}{#3}
+    \fi
+}{\end{fulllineitems}}
+
+% similar to {methoddesc}, but doesn't add to the index
+% (never actually uses the optional argument)
+\newcommand{\methodlineni}[3][\py at classbadkey]{%
+  \py at sigline{\bfcode{#2}}{#3}}
+\newenvironment{methoddescni}[3][\py at classbadkey]{
+  \begin{fulllineitems}
+    \methodlineni{#2}{#3}
+}{\end{fulllineitems}}
+
+% object data attribute --------------------------------------------------
+% \begin{memberdesc}[classname]{membername}
+\newcommand{\memberline}[2][\py at classbadkey]{%
+  \ifx\@undefined#1\relax
+    \memberlineni{#2}
+    \index{#2@{\py at idxcode{#2}} (\py at thisclass\ attribute)}
+  \else
+    \memberlineni{#2}
+    \index{#2@{\py at idxcode{#2}} (#1 attribute)}
+  \fi
+}
+\newenvironment{memberdesc}[2][\py at classbadkey]{
+  \begin{fulllineitems}
+    \ifx\@undefined#1\relax
+      \memberline{#2}
+    \else
+      \def\py at thisclass{#1}
+      \memberline{#2}
+    \fi
+}{\end{fulllineitems}}
+
+% similar to {memberdesc}, but doesn't add to the index
+% (never actually uses the optional argument)
+\newcommand{\memberlineni}[2][\py at classbadkey]{\item[\bfcode{#2}]}
+\newenvironment{memberdescni}[2][\py at classbadkey]{
+  \begin{fulllineitems}
+    \memberlineni{#2}
+}{\end{fulllineitems}}
+
+% For exceptions: --------------------------------------------------------
+% \begin{excdesc}{name}
+%  -- for constructor information, use excclassdesc instead
+\newenvironment{excdesc}[1]{
+  \begin{fulllineitems}
+    \item[\strong{exception }\bfcode{#1}%
+          \index{#1@{\py at idxcode{#1}} (exception in \py at thismodule)}]
+}{\end{fulllineitems}}
+
+% Module data or constants: ----------------------------------------------
+% \begin{datadesc}{name}
+\newcommand{\dataline}[1]{%
+  \datalineni{#1}\index{#1@{\py at idxcode{#1}} (data in \py at thismodule)}}
+\newenvironment{datadesc}[1]{
+  \begin{fulllineitems}
+    \dataline{#1}
+}{\end{fulllineitems}}
+
+% similar to {datadesc}, but doesn't add to the index
+\newcommand{\datalineni}[1]{\item[\bfcode{#1}]\nopagebreak}
+\newenvironment{datadescni}[1]{
+  \begin{fulllineitems}
+    \datalineni{#1}
+}{\end{fulllineitems}}
+
+% bytecode instruction ---------------------------------------------------
+% \begin{opcodedesc}{name}{var}
+% -- {var} may be {}
+\newenvironment{opcodedesc}[2]{
+  \begin{fulllineitems}
+    \item[\bfcode{#1}\quad\var{#2}]
+}{\end{fulllineitems}}
+
+
+\newcommand{\nodename}[1]{\label{#1}}
+
+% For these commands, use \command{} to get the typography right, not 
+% {\command}.  This works better with the texinfo translation.
+\newcommand{\ABC}{{\sc abc}}
+\newcommand{\UNIX}{{\sc Unix}}
+\newcommand{\POSIX}{POSIX}
+\newcommand{\ASCII}{{\sc ascii}}
+\newcommand{\Cpp}{C\protect\raisebox{.18ex}{++}}
+\newcommand{\C}{C}
+\newcommand{\EOF}{{\sc eof}}
+\newcommand{\NULL}{\constant{NULL}}
+\newcommand{\infinity}{\ensuremath{\infty}}
+\newcommand{\plusminus}{\ensuremath{\pm}}
+
+% \guilabel{Start}
+\newcommand{\guilabel}[1]{\textsf{#1}}
+% \menuselection{Start \sub Programs \sub Python}
+\newcommand{\menuselection}[1]{\guilabel{{\def\sub{ \ensuremath{>} }#1}}}
+
+% Also for consistency: spell Python "Python", not "python"!
+
+% code is the most difficult one...
+\newcommand{\code}[1]{\textrm{\@vobeyspaces\@noligs\def\{{\char`\{}\def\}{\char`\}}\def\~{\char`\~}\def\^{\char`\^}\def\e{\char`\\}\def\${\char`\$}\def\#{\char`\#}\def\&{\char`\&}\def\%{\char`\%}%
+\texttt{#1}}}
+
+\newcommand{\bfcode}[1]{\code{\bfseries#1}} % bold-faced code font
+\newcommand{\csimplemacro}[1]{\code{#1}}
+\newcommand{\kbd}[1]{\code{#1}}
+\newcommand{\samp}[1]{`\code{#1}'}
+\newcommand{\var}[1]{%
+  \ifmmode%
+    \hbox{\py at defaultsize\textrm{\textit{#1\/}}}%
+  \else%
+    \py at defaultsize\textrm{\textit{#1\/}}%
+  \fi%
+}
+\renewcommand{\emph}[1]{{\em #1}}
+\newcommand{\dfn}[1]{\emph{#1}}
+\newcommand{\strong}[1]{{\bf #1}}
+% let's experiment with a new font:
+\newcommand{\file}[1]{`\filenq{#1}'}
+\newcommand{\filenq}[1]{{\py at smallsize\textsf{\let\e=\textbackslash#1}}}
+
+% Use this def/redef approach for \url{} since hyperref defined this already,
+% but only if we actually used hyperref:
+\ifpdf
+  \newcommand{\url}[1]{{%
+    \py at pdfstartlink%
+    attr{ /Border [0 0 0] }%
+    user{%
+      /Subtype/Link%
+      /A<<%
+      /Type/Action%
+      /S/URI%
+      /URI(#1)%
+      >>%
+    }%
+    \py at LinkColor%                      color of the link text
+    \py at smallsize\sf #1%
+    \py at NormalColor%                    Turn it back off; these are declarative
+    \pdfendlink}%                       and don't appear bound to the current
+  }%                                    formatting "box".
+\else
+  \newcommand{\url}[1]{\mbox{\py at smallsize\textsf{#1}}}
+\fi
+\newcommand{\email}[1]{{\py at smallsize\textsf{#1}}}
+\newcommand{\newsgroup}[1]{{\py at smallsize\textsf{#1}}}
+
+\newcommand{\py at varvars}[1]{{%
+  {\let\unspecified=\py at unspecified%
+   \let\moreargs=\py at moreargs%
+   \var{#1}}}}
+
+% I'd really like to get rid of this!
+\newif\iftexi\texifalse
+
+% This is used to get l2h to put the copyright and abstract on
+% a separate HTML page.
+\newif\ifhtml\htmlfalse
+
+
+% These should be used for all references to identifiers which are
+% used to refer to instances of specific language constructs.  See the
+% names for specific semantic assignments.
+%
+% For now, don't do anything really fancy with them; just use them as
+% logical markup.  This might change in the future.
+%
+\newcommand{\module}[1]{\texttt{#1}}
+\newcommand{\keyword}[1]{\texttt{#1}}
+\newcommand{\exception}[1]{\texttt{#1}}
+\newcommand{\class}[1]{\texttt{#1}}
+\newcommand{\function}[1]{\texttt{#1}}
+\newcommand{\member}[1]{\texttt{#1}}
+\newcommand{\method}[1]{\texttt{#1}}
+
+\newcommand{\pytype}[1]{#1}             % built-in Python type
+
+\newcommand{\cfunction}[1]{\texttt{#1}}
+\newcommand{\ctype}[1]{\texttt{#1}}     % C struct or typedef name
+\newcommand{\cdata}[1]{\texttt{#1}}     % C variable, typically global
+
+\newcommand{\mailheader}[1]{{\py at smallsize\textsf{#1:}}}
+\newcommand{\mimetype}[1]{{\py at smallsize\textsf{#1}}}
+% The \! is a "negative thin space" in math mode.
+\newcommand{\regexp}[1]{%
+  {\tiny$^{^\lceil}\!\!$%
+   {\py at defaultsize\code{#1}}%
+   $\!\rfloor\!$%
+  }}
+\newcommand{\envvar}[1]{%
+  #1%
+  \index{#1}%
+  \index{environment variables!{#1}}%
+}
+\newcommand{\makevar}[1]{#1}            % variable in a Makefile
+\newcommand{\character}[1]{\samp{#1}}
+
+% constants defined in Python modules or C headers, not language constants:
+\newcommand{\constant}[1]{\code{#1}}    % manifest constant, not syntactic
+
+\newcommand{\manpage}[2]{{\emph{#1}(#2)}}
+\newcommand{\pep}[1]{PEP #1\index{Python Enhancement Proposals!PEP #1}}
+\newcommand{\rfc}[1]{RFC #1\index{RFC!RFC #1}}
+\newcommand{\program}[1]{\strong{#1}}
+\newcommand{\programopt}[1]{\strong{#1}}
+% Note that \longprogramopt provides the '--'!
+\newcommand{\longprogramopt}[1]{\strong{-{}-#1}}
+
+% \ulink{link text}{URL}
+\ifpdf
+  \newcommand{\ulink}[2]{{%
+    % For PDF, we *should* only generate a link when the URL is absolute.
+    \py at pdfstartlink%
+    attr{ /Border [0 0 0] }%
+    user{%
+      /Subtype/Link%
+      /A<<%
+      /Type/Action%
+      /S/URI%
+      /URI(#2)%
+      >>%
+    }%
+    \py at LinkColor%                              color of the link text
+    #1%
+    \py at NormalColor%                    Turn it back off; these are declarative
+    \pdfendlink}%                       and don't appear bound to the current
+  }%                                    formatting "box".
+\else
+  \newcommand{\ulink}[2]{#1}
+\fi
+
+% cited titles:  \citetitle{Title of Work}
+%       online:  \citetitle[url-to-resource]{Title of Work}
+\ifpdf
+  \newcommand{\citetitle}[2][\py at modulebadkey]{%
+    \ifx\py at modulebadkey#1\emph{#2}\else\ulink{\emph{#2}}{#1}\fi%
+  }
+\else
+  \newcommand{\citetitle}[2][URL]{\emph{#2}}
+\fi
+
+
+
+% This version is being checked in for the historical record; it shows
+% how I've managed to get some aspects of this to work.  It will not
+% be used in practice, so a subsequent revision will change things
+% again.  This version has problems, but shows how to do something
+% that proved more tedious than I'd expected, so I don't want to lose
+% the example completely.
+%
+\newcommand{\grammartoken}[1]{\texttt{#1}}
+\newenvironment{productionlist}[1][\py at badkey]{
+  \def\optional##1{{\Large[}##1{\Large]}}
+  \def\production##1##2{\code{##1}&::=&\code{##2}\\}
+  \def\productioncont##1{& &\code{##1}\\}
+  \def\token##1{##1}
+  \let\grammartoken=\token
+  \parindent=2em
+  \indent
+  \begin{tabular}{lcl}
+}{%
+  \end{tabular}
+}
+
+\newlength{\py at noticelength}
+
+\newcommand{\py at heavybox}{
+  \setlength{\fboxrule}{2pt}
+  \setlength{\fboxsep}{7pt}
+  \setlength{\py at noticelength}{\linewidth}
+  \addtolength{\py at noticelength}{-2\fboxsep}
+  \addtolength{\py at noticelength}{-2\fboxrule}
+  \setlength{\shadowsize}{3pt}
+  \Sbox
+  \minipage{\py at noticelength}
+}
+\newcommand{\py at endheavybox}{
+  \endminipage
+  \endSbox
+  \fbox{\TheSbox}
+}
+
+% a 'note' is as plain as it gets:
+\newcommand{\py at noticelabel@note}{Note:}
+\newcommand{\py at noticestart@note}{}
+\newcommand{\py at noticeend@note}{}
+
+% a 'warning' gets more visible distinction:
+\newcommand{\py at noticelabel@warning}{Warning:}
+\newcommand{\py at noticestart@warning}{\py at heavybox}
+\newcommand{\py at noticeend@warning}{\py at endheavybox}
+
+\newenvironment{notice}[1][note]{
+  \def\py at noticetype{#1}
+  \csname py at noticestart@#1\endcsname
+  \par\strong{\csname py at noticelabel@#1\endcsname}
+}{\csname py at noticeend@\py at noticetype\endcsname}
+\newcommand{\note}[1]{\strong{\py at noticelabel@note} #1}
+\newcommand{\warning}[1]{\strong{\py at noticelabel@warning} #1}
+
+% Deprecation stuff.
+% Should be extended to allow an index / list of deprecated stuff.  But
+% there's a lot of stuff that needs to be done to make that automatable.
+%
+% First parameter is the release number that deprecates the feature, the
+% second is the action the should be taken by users of the feature.
+%
+% Example:
+%  \deprecated{1.5.1}{Use \method{frobnicate()} instead.}
+%
+\newcommand{\deprecated}[2]{%
+  \strong{Deprecated since release #1.}  #2\par}
+
+% New stuff.
+% This should be used to mark things which have been added to the
+% development tree but that aren't in the release, but are documented.
+% This allows release of documentation that already includes updated
+% descriptions.  Place at end of descriptor environment.
+%
+% Example:
+%  \versionadded{1.5.2}
+%  \versionchanged[short explanation]{2.0}
+%
+\newcommand{\versionadded}[2][\py at badkey]{%
+  \ifx\@undefined#1\relax%
+    {  New in version #2.  }%
+  \else%
+    {  New in version #2:\ #1.  }%
+  \fi%
+}
+\newcommand{\versionchanged}[2][\py at badkey]{%
+  \ifx\@undefined#1\relax%
+    {  Changed in version #2.  }%
+  \else%
+    {  Changed in version #2:\ #1.  }%
+  \fi%
+}
+
+
+% Tables.
+%
+\newenvironment{tableii}[4]{%
+  \begin{center}%
+    \def\lineii##1##2{\csname#2\endcsname{##1}&##2\\}%
+    \begin{tabular}{#1}\strong{#3}&\strong{#4} \\* \hline%
+}{%
+    \end{tabular}%
+  \end{center}%
+}
+
+\newenvironment{longtableii}[4]{%
+  \begin{center}%
+    \def\lineii##1##2{\csname#2\endcsname{##1}&##2\\}%
+    \begin{longtable}[c]{#1}\strong{#3}&\strong{#4} \\* \hline\endhead%
+}{%
+    \end{longtable}%
+  \end{center}%
+}
+
+\newenvironment{tableiii}[5]{%
+  \begin{center}%
+    \def\lineiii##1##2##3{\csname#2\endcsname{##1}&##2&##3\\}%
+    \begin{tabular}{#1}\strong{#3}&\strong{#4}&\strong{#5} \\%
+      \hline%
+}{%
+    \end{tabular}%
+  \end{center}%
+}
+
+\newenvironment{longtableiii}[5]{%
+  \begin{center}%
+    \def\lineiii##1##2##3{\csname#2\endcsname{##1}&##2&##3\\}%
+    \begin{longtable}[c]{#1}\strong{#3}&\strong{#4}&\strong{#5} \\%
+      \hline\endhead%
+}{%
+    \end{longtable}%
+  \end{center}%
+}
+
+\newenvironment{tableiv}[6]{%
+  \begin{center}%
+    \def\lineiv##1##2##3##4{\csname#2\endcsname{##1}&##2&##3&##4\\}%
+    \begin{tabular}{#1}\strong{#3}&\strong{#4}&\strong{#5}&\strong{#6} \\%
+      \hline%
+}{%
+    \end{tabular}%
+  \end{center}%
+}
+
+\newenvironment{longtableiv}[6]{%
+  \begin{center}%
+    \def\lineiv##1##2##3##4{\csname#2\endcsname{##1}&##2&##3&##4\\}%
+    \begin{longtable}[c]{#1}\strong{#3}&\strong{#4}&\strong{#5}&\strong{#6}%
+      \\%
+      \hline\endhead%
+}{%
+    \end{longtable}%
+  \end{center}%
+}
+
+\newenvironment{tablev}[7]{%
+  \begin{center}%
+    \def\linev##1##2##3##4##5{\csname#2\endcsname{##1}&##2&##3&##4&##5\\}%
+    \begin{tabular}{#1}\strong{#3}&\strong{#4}&\strong{#5}&\strong{#6}&\strong{#7} \\%
+      \hline%
+}{%
+    \end{tabular}%
+  \end{center}%
+}
+
+\newenvironment{longtablev}[7]{%
+  \begin{center}%
+    \def\linev##1##2##3##4##5{\csname#2\endcsname{##1}&##2&##3&##4&##5\\}%
+    \begin{longtable}[c]{#1}\strong{#3}&\strong{#4}&\strong{#5}&\strong{#6}&\strong{#7}%
+      \\%
+      \hline\endhead%
+}{%
+    \end{longtable}%
+  \end{center}%
+}
+
+% XXX Don't think we can use this yet, though it cleans up some
+% tedious markup.  There's no equivalent for the HTML transform yet,
+% and that needs to exist.  I don't know how to write it.
+%
+% This should really have something that makes it easier to bind a
+% table's ``Notes'' column and an associated tablenotes environment,
+% and generates the right magic for getting the numbers right in the
+% table.
+%
+% So this is quite incomplete.
+%
+\newcounter{py at tablenotescounter}
+\newenvironment{tablenotes}{%
+  \noindent Notes:
+  \par
+  \setcounter{py at tablenotescounter}{0}
+  \begin{list}{(\arabic{py at tablenotescounter})}%
+              {\usecounter{py at tablenotescounter}}
+}{\end{list}}
+
+
+% Cross-referencing (AMK, new impl. FLD)
+% Sample usage:
+%  \begin{seealso}
+%    \seemodule{rand}{Uniform random number generator.}; % Module xref
+%    \seetext{\emph{Encyclopedia Britannica}}.           % Ref to a book
+% 
+%    % A funky case: module name contains '_'; have to supply an optional key
+%    \seemodule[copyreg]{copy_reg}{Interface constructor registration for
+%                                  \module{pickle}.}
+%  \end{seealso}
+%
+% Note that the last parameter for \seemodule and \seetext should be complete
+% sentences and be terminated with the proper punctuation.
+
+\ifpdf
+  \newcommand{\py at seemodule}[3][\py at modulebadkey]{%
+    \par%
+    \ifx\py at modulebadkey#1\def\py at modulekey{#2}\else\def\py at modulekey{#1}\fi%
+    \begin{fulllineitems}
+      \item[\py at linkToName{label-module-\py at modulekey}{Module \module{#2}}
+            (section \ref{module-\py at modulekey}):]
+      #3
+    \end{fulllineitems}
+  }
+\else
+  \newcommand{\py at seemodule}[3][\py at modulebadkey]{%
+    \par%
+    \ifx\py at modulebadkey#1\def\py at modulekey{#2}\else\def\py at modulekey{#1}\fi%
+    \begin{fulllineitems}
+      \item[Module \module{#2} (section \ref{module-\py at modulekey}):]
+      #3
+    \end{fulllineitems}
+  }
+\fi
+
+% \seelink{url}{link text}{why it's interesting}
+\newcommand{\py at seelink}[3]{%
+  \par
+  \begin{fulllineitems}
+    \item[\ulink{#2}{#1}]
+    #3
+  \end{fulllineitems}
+}
+% \seetitle[url]{title}{why it's interesting}
+\newcommand{\py at seetitle}[3][\py at modulebadkey]{%
+  \par
+  \begin{fulllineitems}
+    \item[\citetitle{#2}]
+    \ifx\py at modulebadkey#1\else
+      \item[{\small{(\url{#1})}}]
+    \fi
+    #3
+  \end{fulllineitems}
+}
+% \seepep{number}{title}{why it's interesting}
+\newcommand{\py at seepep}[3]{%
+  \par%
+  \begin{fulllineitems}
+    \item[\pep{#1}, ``\emph{#2}'']
+    #3
+  \end{fulllineitems}
+}
+% \seerfc{number}{title}{why it's interesting}
+\newcommand{\py at seerfc}[3]{%
+  \par%
+  \begin{fulllineitems}
+    \item[\rfc{#1}, ``\emph{#2}'']
+    #3
+  \end{fulllineitems}
+}
+% \seeurl{url}{why it's interesting}
+\newcommand{\py at seeurl}[2]{%
+  \par%
+  \begin{fulllineitems}
+    \item[\url{#1}]
+    #2
+  \end{fulllineitems}
+}
+
+\newenvironment{seealso*}{
+  \par
+  \def\seetext##1{\par{##1}}
+  \let\seemodule=\py at seemodule
+  \let\seepep=\py at seepep
+  \let\seerfc=\py at seerfc
+  \let\seetitle=\py at seetitle
+  \let\seeurl=\py at seeurl
+  \let\seelink=\py at seelink
+}{\par}
+\newenvironment{seealso}{
+  \par
+  \strong{See Also:}
+  \par
+  \def\seetext##1{\par{##1}}
+  \let\seemodule=\py at seemodule
+  \let\seepep=\py at seepep
+  \let\seerfc=\py at seerfc
+  \let\seetitle=\py at seetitle
+  \let\seeurl=\py at seeurl
+  \let\seelink=\py at seelink
+}{\par}
+
+% Allow the Python release number to be specified independently of the
+% \date{}.  This allows the date to reflect the document's date and
+% release to specify the Python release that is documented.
+%
+\newcommand{\py at release}{}
+\newcommand{\version}{}
+\newcommand{\shortversion}{}
+\newcommand{\releaseinfo}{}
+\newcommand{\releasename}{Release}
+\newcommand{\release}[1]{%
+  \renewcommand{\py at release}{\releasename\space\version}%
+  \renewcommand{\version}{#1}}
+\newcommand{\setshortversion}[1]{%
+  \renewcommand{\shortversion}{#1}}
+\newcommand{\setreleaseinfo}[1]{%
+  \renewcommand{\releaseinfo}{#1}}
+
+% Allow specification of the author's address separately from the
+% author's name.  This can be used to format them differently, which
+% is a good thing.
+%
+\newcommand{\py at authoraddress}{}
+\newcommand{\authoraddress}[1]{\renewcommand{\py at authoraddress}{#1}}
+\let\developersaddress=\authoraddress
+\let\developer=\author
+\let\developers=\author
+
+% This sets up the fancy chapter headings that make the documents look
+% at least a little better than the usual LaTeX output.
+%
+\@ifundefined{ChTitleVar}{}{
+  \ChNameVar{\raggedleft\normalsize\py at HeaderFamily}
+  \ChNumVar{\raggedleft \bfseries\Large\py at HeaderFamily}
+  \ChTitleVar{\raggedleft \rm\Huge\py at HeaderFamily}
+  % This creates chapter heads without the leading \vspace*{}:
+  \def\@makechapterhead#1{%
+    {\parindent \z@ \raggedright \normalfont
+      \ifnum \c at secnumdepth >\m at ne
+        \DOCH
+      \fi
+      \interlinepenalty\@M
+      \DOTI{#1}
+    }
+  }
+}
+
+
+% Definition lists; requested by AMK for HOWTO documents.  Probably useful
+% elsewhere as well, so keep in in the general style support.
+%
+\newenvironment{definitions}{%
+  \begin{description}%
+  \def\term##1{\item[##1]\mbox{}\\*[0mm]}
+}{%
+  \end{description}%
+}
+
+% Tell TeX about pathological hyphenation cases:
+\hyphenation{Base-HTTP-Re-quest-Hand-ler}

Added: doctools/trunk/sphinx/texinputs/underscore.sty
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/texinputs/underscore.sty	Wed Dec  5 22:11:36 2007
@@ -0,0 +1,232 @@
+% underscore.sty     12-Oct-2001   Donald Arseneau   asnd at triumf.ca
+% Make the "_" character print as "\textunderscore" in text.
+% Copyright 1998,2001 Donald Arseneau;  Distribute freely if unchanged.
+% Instructions follow after the definitions.
+
+\ProvidesPackage{underscore}[2001/10/12]
+
+\begingroup
+ \catcode`\_=\active
+ \gdef_{% \relax % No relax gives a small vulnerability in alignments
+   \ifx\if at safe@actives\iftrue % must be outermost test!
+      \string_%
+   \else
+      \ifx\protect\@typeset at protect
+         \ifmmode \sb \else \BreakableUnderscore \fi
+      \else
+         \ifx\protect\@unexpandable at protect \noexpand_%
+         \else \protect_%
+      \fi\fi
+    \fi}
+\endgroup
+
+% At begin: set catcode; fix \long \ttdefault so I can use it in comparisons; 
+\AtBeginDocument{%
+  {\immediate\write\@auxout{\catcode\number\string`\_ \string\active}}%
+  \catcode\string`\_\string=\active
+  \edef\ttdefault{\ttdefault}%
+}
+
+\newcommand{\BreakableUnderscore}{\leavevmode\nobreak\hskip\z at skip
+ \ifx\f at family\ttdefault \string_\else \textunderscore\fi
+ \usc at dischyph\nobreak\hskip\z at skip}
+
+\DeclareRobustCommand{\_}{%
+  \ifmmode \nfss at text{\textunderscore}\else \BreakableUnderscore \fi}
+
+\let\usc at dischyph\@dischyph
+\DeclareOption{nohyphen}{\def\usc at dischyph{\discretionary{}{}{}}}
+\DeclareOption{strings}{\catcode`\_=\active}
+
+\ProcessOptions
+\ifnum\catcode`\_=\active\else \endinput \fi
+
+%%%%%%%%   Redefine commands that use character strings   %%%%%%%%
+
+\@ifundefined{UnderscoreCommands}{\let\UnderscoreCommands\@empty}{}
+\expandafter\def\expandafter\UnderscoreCommands\expandafter{%
+  \UnderscoreCommands
+  \do\include \do\includeonly
+  \do\@input \do\@iinput \do\InputIfFileExists
+  \do\ref \do\pageref \do\newlabel
+  \do\bibitem \do\@bibitem \do\cite \do\nocite \do\bibcite
+}
+
+% Macro to redefine a macro to pre-process its string argument
+% with \protect -> \string.
+\def\do#1{% Avoid double processing if user includes command twice!
+ \@ifundefined{US\string_\expandafter\@gobble\string#1}{%
+   \edef\@tempb{\meaning#1}% Check if macro is just a protection shell...
+   \def\@tempc{\protect}%
+   \edef\@tempc{\meaning\@tempc\string#1\space\space}%
+   \ifx\@tempb\@tempc % just a shell: hook into the protected inner command
+     \expandafter\do
+       \csname \expandafter\@gobble\string#1 \expandafter\endcsname
+   \else % Check if macro takes an optional argument
+     \def\@tempc{\@ifnextchar[}%
+     \edef\@tempa{\def\noexpand\@tempa####1\meaning\@tempc}%
+     \@tempa##2##3\@tempa{##2\relax}%
+     \edef\@tempb{\meaning#1\meaning\@tempc}%
+     \edef\@tempc{\noexpand\@tempd \csname
+        US\string_\expandafter\@gobble\string#1\endcsname}%
+     \if \expandafter\@tempa\@tempb \relax 12\@tempa % then no optional arg
+       \@tempc #1\US at prot
+     \else  % There is optional arg
+       \@tempc #1\US at protopt
+     \fi
+   \fi
+ }{}}
+
+\def\@tempd#1#2#3{\let#1#2\def#2{#3#1}}
+
+\def\US at prot#1#2{\let\@@protect\protect \let\protect\string
+  \edef\US at temp##1{##1{#2}}\restore at protect\US at temp#1}
+\def\US at protopt#1{\@ifnextchar[{\US at protarg#1}{\US at prot#1}}
+\def\US at protarg #1[#2]{\US at prot{{#1[#2]}}}
+
+\UnderscoreCommands
+\let\do\relax \let\@tempd\relax  % un-do
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\endinput
+
+underscore.sty    12-Oct-2001  Donald Arseneau
+
+Features:
+~~~~~~~~~
+\_ prints an underscore so that the hyphenation of constituent words
+is not affected and hyphenation is permitted after the underscore.
+For example, "compound\_fracture" hyphenates as com- pound_- frac- ture.
+If you prefer the underscore to break without a hyphen (but still with 
+the same rules for explicit hyphen-breaks) then use the [nohyphen]
+package option.
+
+A simple _  acts just like \_ in text mode, but makes a subscript in 
+math mode: activation_energy $E_a$
+
+Both forms use an underscore character if the font encoding contains
+one (e.g., "\usepackage[T1]{fontenc}" or typewriter fonts in any encoding),
+but they use a rule if the there is no proper character.
+
+Deficiencies:
+~~~~~~~~~~~~~
+The skips and penalties ruin any kerning with the underscore character
+(when a character is used).  However, there doesn't seem to be much, if
+any, such kerning in the ec fonts, and there is never any kerning with
+a rule.
+
+You must avoid "_" in file names and in cite or ref tags, or you must use 
+the babel package, with its active-character controls, or you must give 
+the [strings] option, which attempts to redefine several commands (and 
+may not work perfectly).  Even without the [strings] option or babel, you 
+can use occasional underscores like: "\include{file\string_name}".
+
+Option: [strings]
+~~~~~~~~~~~~~~~~~
+The default operation is quite simple and needs no customization; but
+you must avoid using "_" in any place where LaTeX uses an argument as
+a string of characters for some control function or as a name.  These
+include the tags for \cite and \ref, file names for \input, \include,
+and \includegraphics, environment names, counter names, and placement
+parameters (like "[t]").  The problem with these contexts is that they
+are `moving arguments' but LaTeX does not `switch on' the \protect
+mechanism for them.
+
+If you need to use the underscore character in these places, the package
+option [strings] is provided to redefine commands taking a string argument
+so that the argument is protected (with \protect -> \string).  The list
+of commands is given in "\UnderscoreCommands", with "\do" before each,
+covering \cite, \ref, \input, and their variants.  Not included are many
+commands regarding font names, everything with counter names, environment
+names, page styles, and versions of \ref and \cite defined by external
+packages (e.g. \vref and \citeyear).
+
+You can add to the list of supported commands by defining \UnderscoreCommands
+before loading this package; e.g.
+
+   \usepackage{chicago}
+   \newcommand{\UnderscoreCommands}{%   (\cite already done)
+     \do\citeNP \do\citeA \do\citeANP \do\citeN \do\shortcite
+     \do\shortciteNP \do\shortciteA \do\shortciteANP \do\shortciteN
+     \do\citeyear \do\citeyearNP
+   }
+   \usepackage[strings]{underscore}
+
+Not all commands can be supported this way!  Only commands that take a
+string argument *first* can be protected.  One optional argument before
+the string argument is also permitted, as exemplified by \cite: both
+\cite{tags} and \cite[text]{tags} are allowed.  A command like
+\@addtoreset which takes two counter names as arguments could not
+be protected by adding it to \UnderscoreCommands.
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! When you use the [strings] option, you must load this package !!
+!! last (or nearly last).                                        !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+There are two reasons: 1) The redefinitions done for protection must come
+after other packages define their customized versions of those commands.
+2) The [strings] option requires the _ character to be activated immediately
+in order for the cite and ref tags to be read properly from the .aux file
+as plain strings, and this catcode setting might disrupt other packages.
+
+The babel package implements a protection mechanism for many commands,
+and will be a complete fix for most documents without the [strings] option.
+Many add-on packages are compatible with babel, so they will get the
+strings protection also.  However, there are several commands that are 
+not covered by babel, but can easily be supported by the [strings] and 
+\UnderscoreCommands mechanism.  Beware that using both [strings] and babel 
+may lead to conflicts, but does appear to work (load babel last).
+
+Implementation Notes:
+~~~~~~~~~~~~~~~~~~~~~
+The first setting of "_" to be an active character is performed in a local
+group so as to not interfere with other packages.  The catcode setting
+is repeated with \AtBeginDocument so the definition is in effect for the
+text.  However, the catcode setting is repeated immediately when the
+[strings] option is detected.
+
+The definition of the active "_" is essentially:
+       \ifmmode \sb \else \BreakableUnderscore \fi
+where "\sb" retains the normal subscript meaning of "_" and where
+"\BreakableUnderscore" is essentially "\_".  The rest of the definition
+handles the "\protect"ion without causing \relax to be inserted before
+the character.
+
+\BreakableUnderscore uses "\nobreak\hskip\z at skip" to separate the
+underscore from surrounding words, thus allowing TeX to hyphenate them,
+but preventing free breaks around the underscore. Next, it checks the
+current font family, and uses the underscore character from tt fonts or
+otherwise \textunderscore (which is a character or rule depending on
+the font encoding).  After the underscore, it inserts a discretionary
+hyphenation point as "\usc at dischyph", which is usually just "\-"
+except that it still works in the tabbing environment, although it
+will give "\discretionary{}{}{}" under the [nohyphen] option.  After
+that, another piece of non-breaking interword glue is inserted. 
+Ordinarily, the comparison "\ifx\f at family\ttdefault" will always fail 
+because \ttdefault is `long' where \f at family is not (boooo hisss), but 
+\ttdefault is redefined to be non-long by "\AtBeginDocument".
+
+The "\_" command is then defined to use "\BreakableUnderscore".
+
+If the [strings] option is not given, then that is all!
+
+Under the [strings] option, the list of special commands is processed to:
+- retain the original command as \US_command (\US_ref)
+- redefine the command as \US at prot\US_command for ordinary commands
+  (\ref -> \US at prot\US_ref) or as \US at protopt\US_command when an optional
+  argument is possible (\bibitem -> \US at protopt\US_bibitem).
+- self-protecting commands (\cite) retain their self-protection.
+Diagnosing the state of the pre-existing command is done by painful
+contortions involving \meaning.
+
+\US at prot and \US at protopt read the argument, process it with \protect
+enabled, then invoke the saved \US_command.
+
+Modifications:
+~~~~~~~~~~~~~~
+12-Oct-2001  Babel (safe at actives) compatibility and [nohyphen] option.
+
+Test file integrity:  ASCII 32-57, 58-126:  !"#$%&'()*+,-./0123456789
+:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~


More information about the Python-checkins mailing list