[Python-checkins] r60005 - in doctools/trunk/sphinx: __init__.py _jinja.py addnodes.py builder.py directives.py environment.py highlighting.py htmlhelp.py htmlwriter.py latexwriter.py patchlevel.py refcounting.py roles.py search.py style/default.css style/rightsidebar.css style/searchtools.js style/stickysidebar.css style/traditional.css templates/_commentform.html templates/admin templates/changes templates/changes/frameset.html templates/changes/rstsource.html templates/changes/versionchanges.html templates/commentform.html templates/comments.html templates/download.html templates/edit.html templates/index.html templates/inlinecomments.html templates/keyword_not_found.html templates/layout.html templates/not_found.html templates/rstsource.html templates/search.html templates/settings.html templates/show_source.html templates/sidebar.html templates/submitted.html templates/versionchanges.html templates/versionchanges_frameset.html templates/web templates/web/_commentform.html templates/web/admin templates/web/admin/moderate_comments.html templates/web/commentform.html templates/web/comments.html templates/web/edit.html templates/web/inlinecomments.html templates/web/keyword_not_found.html templates/web/not_found.html templates/web/settings.html templates/web/submitted.html util/__init__.py util/stemmer.py web/admin.py web/antispam.py web/application.py web/database.py web/markup.py web/oldurls.py web/serve.py web/userdb.py web/util.py web/webconf.py web/wsgiutil.py

georg.brandl python-checkins at python.org
Wed Jan 16 21:27:27 CET 2008


Author: georg.brandl
Date: Wed Jan 16 21:27:25 2008
New Revision: 60005

Added:
   doctools/trunk/sphinx/templates/changes/
   doctools/trunk/sphinx/templates/changes/frameset.html
      - copied, changed from r59608, doctools/trunk/sphinx/templates/versionchanges_frameset.html
   doctools/trunk/sphinx/templates/changes/rstsource.html
      - copied, changed from r59608, doctools/trunk/sphinx/templates/rstsource.html
   doctools/trunk/sphinx/templates/changes/versionchanges.html
      - copied, changed from r59608, doctools/trunk/sphinx/templates/versionchanges.html
   doctools/trunk/sphinx/templates/web/
   doctools/trunk/sphinx/templates/web/_commentform.html
      - copied unchanged from r57711, doctools/trunk/sphinx/templates/_commentform.html
   doctools/trunk/sphinx/templates/web/admin/
      - copied from r57711, doctools/trunk/sphinx/templates/admin/
   doctools/trunk/sphinx/templates/web/commentform.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/commentform.html
   doctools/trunk/sphinx/templates/web/comments.html
      - copied unchanged from r57711, doctools/trunk/sphinx/templates/comments.html
   doctools/trunk/sphinx/templates/web/edit.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/edit.html
   doctools/trunk/sphinx/templates/web/inlinecomments.html
      - copied unchanged from r57711, doctools/trunk/sphinx/templates/inlinecomments.html
   doctools/trunk/sphinx/templates/web/keyword_not_found.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/keyword_not_found.html
   doctools/trunk/sphinx/templates/web/not_found.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/not_found.html
   doctools/trunk/sphinx/templates/web/settings.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/settings.html
   doctools/trunk/sphinx/templates/web/submitted.html
      - copied, changed from r57711, doctools/trunk/sphinx/templates/submitted.html
Removed:
   doctools/trunk/sphinx/templates/_commentform.html
   doctools/trunk/sphinx/templates/admin/
   doctools/trunk/sphinx/templates/commentform.html
   doctools/trunk/sphinx/templates/comments.html
   doctools/trunk/sphinx/templates/download.html
   doctools/trunk/sphinx/templates/edit.html
   doctools/trunk/sphinx/templates/inlinecomments.html
   doctools/trunk/sphinx/templates/keyword_not_found.html
   doctools/trunk/sphinx/templates/not_found.html
   doctools/trunk/sphinx/templates/rstsource.html
   doctools/trunk/sphinx/templates/settings.html
   doctools/trunk/sphinx/templates/show_source.html
   doctools/trunk/sphinx/templates/sidebar.html
   doctools/trunk/sphinx/templates/submitted.html
   doctools/trunk/sphinx/templates/versionchanges.html
   doctools/trunk/sphinx/templates/versionchanges_frameset.html
Modified:
   doctools/trunk/sphinx/__init__.py
   doctools/trunk/sphinx/_jinja.py
   doctools/trunk/sphinx/addnodes.py
   doctools/trunk/sphinx/builder.py
   doctools/trunk/sphinx/directives.py
   doctools/trunk/sphinx/environment.py
   doctools/trunk/sphinx/highlighting.py
   doctools/trunk/sphinx/htmlhelp.py
   doctools/trunk/sphinx/htmlwriter.py
   doctools/trunk/sphinx/latexwriter.py
   doctools/trunk/sphinx/patchlevel.py
   doctools/trunk/sphinx/refcounting.py
   doctools/trunk/sphinx/roles.py
   doctools/trunk/sphinx/search.py
   doctools/trunk/sphinx/style/default.css
   doctools/trunk/sphinx/style/rightsidebar.css
   doctools/trunk/sphinx/style/searchtools.js
   doctools/trunk/sphinx/style/stickysidebar.css
   doctools/trunk/sphinx/style/traditional.css
   doctools/trunk/sphinx/templates/index.html
   doctools/trunk/sphinx/templates/layout.html
   doctools/trunk/sphinx/templates/search.html
   doctools/trunk/sphinx/templates/web/admin/moderate_comments.html
   doctools/trunk/sphinx/util/__init__.py
   doctools/trunk/sphinx/util/stemmer.py
   doctools/trunk/sphinx/web/admin.py
   doctools/trunk/sphinx/web/antispam.py
   doctools/trunk/sphinx/web/application.py
   doctools/trunk/sphinx/web/database.py
   doctools/trunk/sphinx/web/markup.py
   doctools/trunk/sphinx/web/oldurls.py
   doctools/trunk/sphinx/web/serve.py
   doctools/trunk/sphinx/web/userdb.py
   doctools/trunk/sphinx/web/util.py
   doctools/trunk/sphinx/web/webconf.py
   doctools/trunk/sphinx/web/wsgiutil.py
Log:
A few refactorings in Sphinx.


Modified: doctools/trunk/sphinx/__init__.py
==============================================================================
--- doctools/trunk/sphinx/__init__.py	(original)
+++ doctools/trunk/sphinx/__init__.py	Wed Jan 16 21:27:25 2008
@@ -3,7 +3,7 @@
     Sphinx
     ~~~~~~
 
-    The Python documentation toolchain.
+    The Sphinx documentation toolchain.
 
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
@@ -14,8 +14,8 @@
 from os import path
 from cStringIO import StringIO
 
-from .builder import builders
-from .util.console import nocolor
+from sphinx.builder import builders
+from sphinx.util.console import nocolor
 
 __version__ = '$Revision: 5369 $'
 
@@ -31,7 +31,6 @@
          -E        -- don't use a saved environment, always read all files
          -d <path> -- path for the cached environment and doctree files
                       (default outdir/.doctrees)
-         -O <option[=value]> -- give option to to the builder (-O help for list)
          -D <setting=value> -- override a setting in sourcedir/conf.py
          -N        -- do not do colored output
          -q        -- no output on stdout, just warnings on stderr
@@ -44,7 +43,7 @@
 
 def main(argv):
     try:
-        opts, args = getopt.getopt(argv[1:], 'ab:d:O:D:NEqP')
+        opts, args = getopt.getopt(argv[1:], 'ab:d:D:NEqP')
         srcdirname = path.abspath(args[0])
         if not path.isdir(srcdirname):
             print >>sys.stderr, 'Error: Cannot find source directory.'
@@ -70,9 +69,8 @@
         return 1
 
     builder = all_files = None
-    opt_help = freshenv = use_pdb = False
+    freshenv = use_pdb = False
     status = sys.stdout
-    options = {}
     confoverrides = {}
     doctreedir = path.join(outdirname, '.doctrees')
     for opt, val in opts:
@@ -88,18 +86,6 @@
             all_files = True
         elif opt == '-d':
             doctreedir = val
-        elif opt == '-O':
-            if val == 'help':
-                opt_help = True
-                continue
-            if '=' in val:
-                key, val = val.split('=')
-                try:
-                    val = int(val)
-                except: pass
-            else:
-                key, val = val, True
-            options[key] = val
         elif opt == '-D':
             key, val = val.split('=')
             try:
@@ -125,14 +111,8 @@
 
     builderobj = builders[builder]
 
-    if opt_help:
-        print 'Options recognized by the %s builder:' % builder
-        for optname, description in builderobj.option_spec.iteritems():
-            print ' * %s: %s' % (optname, description)
-        return 0
-
     try:
-        builderobj = builderobj(srcdirname, outdirname, doctreedir, options,
+        builderobj = builderobj(srcdirname, outdirname, doctreedir,
                                 status_stream=status,
                                 warning_stream=sys.stderr,
                                 confoverrides=confoverrides,
@@ -146,7 +126,8 @@
     except:
         if not use_pdb:
             raise
-        import pdb
+        import pdb, traceback
+        traceback.print_exc()
         pdb.post_mortem(sys.exc_info()[2])
 
 

Modified: doctools/trunk/sphinx/_jinja.py
==============================================================================
--- doctools/trunk/sphinx/_jinja.py	(original)
+++ doctools/trunk/sphinx/_jinja.py	Wed Jan 16 21:27:25 2008
@@ -8,11 +8,41 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import absolute_import
 
 import sys
+import codecs
 from os import path
 
 sys.path.insert(0, path.dirname(__file__))
 
-from jinja import Environment, FileSystemLoader
+from jinja import Environment
+from jinja.loaders import BaseLoader
+from jinja.exceptions import TemplateNotFound
+
+class SphinxFileSystemLoader(BaseLoader):
+    """
+    A loader that loads templates either relative to one of a list of given
+    paths, or from an absolute path.
+    """
+
+    def __init__(self, paths):
+        self.searchpaths = map(path.abspath, paths)
+
+    def get_source(self, environment, name, parent):
+        name = name.replace('/', path.sep)
+        if path.isabs(name):
+            if not path.exists(name):
+                raise TemplateNotFound(name)
+            filename = name
+        else:
+            for searchpath in self.searchpaths:
+                if path.exists(path.join(searchpath, name)):
+                    filename = path.join(searchpath, name)
+                    break
+            else:
+                raise TemplateNotFound(name)
+        f = codecs.open(filename, 'r', environment.template_charset)
+        try:
+            return f.read()
+        finally:
+            f.close()

Modified: doctools/trunk/sphinx/addnodes.py
==============================================================================
--- doctools/trunk/sphinx/addnodes.py	(original)
+++ doctools/trunk/sphinx/addnodes.py	Wed Jan 16 21:27:25 2008
@@ -3,6 +3,8 @@
     sphinx.addnodes
     ~~~~~~~~~~~~~~~
 
+    Additional docutils nodes.
+
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """

Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py	(original)
+++ doctools/trunk/sphinx/builder.py	Wed Jan 16 21:27:25 2008
@@ -8,7 +8,6 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import os
 import sys
@@ -21,26 +20,27 @@
 from os import path
 from cgi import escape
 
+from docutils import nodes
 from docutils.io import StringOutput, FileOutput, DocTreeInput
 from docutils.core import publish_parts
 from docutils.utils import new_document
 from docutils.readers import doctree
 from docutils.frontend import OptionParser
 
-from .util import (get_matching_files, attrdict, status_iterator, ensuredir,
-                   get_category, relative_uri, os_path, SEP)
-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, NoUri
-from .highlighting import pygments, highlight_block, get_stylesheet
-from .util.console import bold, purple, green
+from sphinx import addnodes
+from sphinx.util import (get_matching_files, attrdict, status_iterator,
+                         ensuredir, relative_uri, os_path, SEP)
+from sphinx.htmlhelp import build_hhx
+from sphinx.patchlevel import get_version_info, get_sys_version_info
+from sphinx.htmlwriter import HTMLWriter
+from sphinx.latexwriter import LaTeXWriter
+from sphinx.environment import BuildEnvironment, NoUri
+from sphinx.highlighting import pygments, highlight_block, get_stylesheet
+from sphinx.util.console import bold, purple, green
 
-from . import addnodes
 # side effect: registers roles and directives
-from . import roles
-from . import directives
+from sphinx import roles
+from sphinx import directives
 
 ENV_PICKLE_FILENAME = 'environment.pickle'
 LAST_BUILD_FILENAME = 'last_build'
@@ -53,33 +53,18 @@
         self.builder = builder
     def __call__(self, otheruri, resource=False):
         if not resource:
-            otheruri = self.builder.get_target_uri(otheruri)
+            otheruri = self.builder.get_target_uri(otheruri + '.rst')
         return relative_uri(self.baseuri, otheruri)
 
 
-class collect_env_warnings(object):
-    def __init__(self, builder):
-        self.builder = builder
-        self.warnings = []
-    def __enter__(self):
-        self.builder.env.set_warnfunc(self.warnings.append)
-    def __exit__(self, *args):
-        self.builder.env.set_warnfunc(self.builder.warn)
-        for warning in self.warnings:
-            self.builder.warn(warning)
-
-
 class Builder(object):
     """
     Builds target formats from the reST sources.
     """
 
-    option_spec = {}
-
     def __init__(self, srcdirname, outdirname, doctreedirname,
-                 options, confoverrides=None, env=None,
-                 status_stream=None, warning_stream=None,
-                 freshenv=False):
+                 confoverrides=None, env=None, freshenv=False,
+                 status_stream=None, warning_stream=None):
         self.srcdir = srcdirname
         self.outdir = outdirname
         self.doctreedir = doctreedirname
@@ -87,9 +72,6 @@
             os.mkdir(doctreedirname)
         self.freshenv = freshenv
 
-        self.options = attrdict(options)
-        self.validate_options()
-
         self.status_stream = status_stream or sys.stdout
         self.warning_stream = warning_stream or sys.stderr
 
@@ -97,7 +79,12 @@
         self.env = env
 
         self.config = {}
-        execfile(path.join(srcdirname, 'conf.py'), self.config)
+        olddir = os.getcwd()
+        try:
+            os.chdir(srcdirname)
+            execfile(path.join(srcdirname, 'conf.py'), self.config)
+        finally:
+            os.chdir(olddir)
         # remove potentially pickling-problematic values
         del self.config['__builtins__']
         for key, val in self.config.items():
@@ -105,31 +92,23 @@
                 del self.config[key]
         if confoverrides:
             self.config.update(confoverrides)
-        # replace version info if 'auto'
-        if self.config['version'] == 'auto' or self.config['release'] == 'auto':
+        # replace version info if '<auto>'
+        if self.config['version'] == '<auto>' or self.config['release'] == '<auto>':
             try:
                 version, release = get_version_info(srcdirname)
             except (IOError, OSError):
                 version, release = get_sys_version_info()
                 self.warn('Can\'t get version info from Include/patchlevel.h, '
                           'using version of this interpreter (%s).' % release)
-            if self.config['version'] == 'auto':
+            if self.config['version'] == '<auto>':
                 self.config['version'] = version
-            if self.config['release'] == 'auto':
+            if self.config['release'] == '<auto>':
                 self.config['release'] = release
 
         self.init()
 
     # helper methods
 
-    def validate_options(self):
-        for option in self.options:
-            if option not in self.option_spec:
-                raise ValueError('Got unexpected option %s' % option)
-        for option in self.option_spec:
-            if option not in self.options:
-                self.options[option] = False
-
     def msg(self, message='', nonl=False, nobold=False):
         if not nobold: message = bold(message)
         if nonl:
@@ -214,16 +193,20 @@
 
         updated_filenames = []
         # while reading, collect all warnings from docutils
-        with collect_env_warnings(self):
-            self.msg('reading, updating environment:', nonl=1)
-            iterator = self.env.update(self.config)
-            self.msg(iterator.next(), nonl=1, nobold=1)
-            for filename in iterator:
-                if not updated_filenames:
-                    self.msg('')
-                updated_filenames.append(filename)
-                self.msg(purple(filename), nonl=1, nobold=1)
-            self.msg()
+        warnings = []
+        self.env.set_warnfunc(warnings.append)
+        self.msg('reading, updating environment:', nonl=1)
+        iterator = self.env.update(self.config)
+        self.msg(iterator.next(), nonl=1, nobold=1)
+        for filename in iterator:
+            if not updated_filenames:
+                self.msg('')
+            updated_filenames.append(filename)
+            self.msg(purple(filename), nonl=1, nobold=1)
+        self.msg()
+        for warning in warnings:
+            self.warn(warning)
+        self.env.set_warnfunc(self.warn)
 
         if updated_filenames:
             # save the environment
@@ -260,12 +243,16 @@
         self.prepare_writing(filenames)
 
         # write target files
-        with collect_env_warnings(self):
-            self.msg('writing output...')
-            for filename in status_iterator(sorted(filenames), green,
-                                            stream=self.status_stream):
-                doctree = self.env.get_and_resolve_doctree(filename, self)
-                self.write_file(filename, doctree)
+        warnings = []
+        self.env.set_warnfunc(warnings.append)
+        self.msg('writing output...')
+        for filename in status_iterator(sorted(filenames), green,
+                                        stream=self.status_stream):
+            doctree = self.env.get_and_resolve_doctree(filename, self)
+            self.write_file(filename, doctree)
+        for warning in warnings:
+            self.warn(warning)
+        self.env.set_warnfunc(self.warn)
 
     def prepare_writing(self, filenames):
         raise NotImplementedError
@@ -288,22 +275,28 @@
     def init(self):
         """Load templates."""
         # lazily import this, maybe other builders won't need it
-        from ._jinja import Environment, FileSystemLoader
+        from sphinx._jinja import Environment, SphinxFileSystemLoader
 
         # load templates
         self.templates = {}
         templates_path = path.join(path.dirname(__file__), 'templates')
-        jinja_env = Environment(loader=FileSystemLoader(templates_path),
-                                # disable traceback, more likely that something in the
-                                # application is broken than in the templates
-                                friendly_traceback=False)
+        self.jinja_env = Environment(loader=SphinxFileSystemLoader([templates_path]),
+                                     # disable traceback, more likely that something
+                                     # in the application is broken than in the templates
+                                     friendly_traceback=False)
+        # pre-load built-in templates
         for fname in os.listdir(templates_path):
             if fname.endswith('.html'):
-                self.templates[fname[:-5]] = jinja_env.get_template(fname)
+                self.templates[fname] = self.jinja_env.get_template(fname)
+
+    def get_template(self, name):
+        if name in self.templates:
+            return self.templates[name]
+        return self.jinja_env.get_template(name)
 
     def render_partial(self, node):
         """Utility: Render a lone doctree node."""
-        doc = new_document('foo')
+        doc = new_document('<partial node>')
         doc.append(node)
         return publish_parts(
             doc,
@@ -314,7 +307,7 @@
         )
 
     def prepare_writing(self, filenames):
-        from .search import IndexBuilder
+        from sphinx.search import IndexBuilder
         self.indexer = IndexBuilder()
         self.load_indexer(filenames)
         self.docwriter = HTMLWriter(self)
@@ -331,13 +324,15 @@
             self.last_updated = None
 
         self.globalcontext = dict(
-            last_updated = self.last_updated,
-            builder = self.name,
+            project = self.config.get('project', 'Python'),
+            copyright = self.config.get('copyright', ''),
             release = self.config['release'],
             version = self.config['version'],
+            last_updated = self.last_updated,
+            builder = self.name,
             parents = [],
-            len = len,
             titles = {},
+            len = len, # the built-in
         )
 
     def write_file(self, filename, doctree):
@@ -375,7 +370,6 @@
         context = dict(
             title = title,
             sourcename = sourcename,
-            pathto = relpath_to(self, self.get_target_uri(filename)),
             body = self.docwriter.parts['fragment'],
             toc = self.render_partial(self.env.get_toc_for(filename))['fragment'],
             # only display a TOC if there's more than one item to show
@@ -386,7 +380,7 @@
         )
 
         self.index_file(filename, doctree, title)
-        self.handle_file(filename, context)
+        self.handle_page(filename[:-4], context)
 
     def finish(self):
         self.msg('writing additional files...')
@@ -402,10 +396,8 @@
         genindexcontext = dict(
             genindexentries = self.env.index,
             genindexcounts = indexcounts,
-            current_page_name = 'genindex',
-            pathto = relpath_to(self, self.get_target_uri('genindex.rst')),
         )
-        self.handle_file('genindex.rst', genindexcontext, 'genindex')
+        self.handle_page('genindex', genindexcontext, 'genindex.html')
 
         # the global module index
 
@@ -422,12 +414,12 @@
         cg = 0 # collapse group
         fl = '' # first letter
         for mn, (fn, sy, pl, dep) in modules:
-            pl = pl.split(', ') if pl else []
+            pl = pl and pl.split(', ') or []
             platforms.update(pl)
             if fl != mn[0].lower() and mn[0] != '_':
                 modindexentries.append(['', False, 0, False,
                                         mn[0].upper(), '', [], False])
-            tn = mn.partition('.')[0]
+            tn = mn.split('.')[0]
             if tn != mn:
                 # submodule
                 if pmn == tn:
@@ -447,32 +439,22 @@
         modindexcontext = dict(
             modindexentries = modindexentries,
             platforms = platforms,
-            current_page_name = 'modindex',
-            pathto = relpath_to(self, self.get_target_uri('modindex.rst')),
         )
-        self.handle_file('modindex.rst', modindexcontext, 'modindex')
+        self.handle_page('modindex', modindexcontext, 'modindex.html')
 
-        # the download page
-        downloadcontext = dict(
-            pathto = relpath_to(self, self.get_target_uri('download.rst')),
-            current_page_name = 'download',
-            download_base_url = self.config['html_download_base_url'],
-        )
-        self.handle_file('download.rst', downloadcontext, 'download')
+        # the search page
+        self.handle_page('search', {}, 'search.html')
 
-        # the index page
-        indexcontext = dict(
-            pathto = relpath_to(self, self.get_target_uri('index.rst')),
-            current_page_name = 'index',
-        )
-        self.handle_file('index.rst', indexcontext, 'index')
+        # additional pages from conf.py
+        for pagename, template in self.config.get('html_additional_pages', {}).items():
+            template = path.join(self.srcdir, template)
+            self.handle_page(pagename, {}, template)
 
-        # the search page
-        searchcontext = dict(
-            pathto = relpath_to(self, self.get_target_uri('search.rst')),
-            current_page_name = 'search',
-        )
-        self.handle_file('search.rst', searchcontext, 'search')
+        # the index page
+        indextemplate = self.config.get('html_index')
+        if indextemplate:
+            indextemplate = path.join(self.srcdir, indextemplate)
+        self.handle_page('index', {'indextemplate': indextemplate}, 'index.html')
 
         # copy style files
         self.msg('copying style files...')
@@ -512,8 +494,11 @@
 
     def load_indexer(self, filenames):
         try:
-            with open(path.join(self.outdir, 'searchindex.json'), 'r') as f:
+            f = open(path.join(self.outdir, 'searchindex.json'), 'r')
+            try:
                 self.indexer.load(f, 'json')
+            finally:
+                f.close()
         except (IOError, OSError):
             pass
         # delete all entries for files that will be rebuilt
@@ -522,32 +507,43 @@
     def index_file(self, filename, doctree, title):
         # only index pages with title
         if self.indexer is not None and title:
-            category = get_category(filename)
-            if category is not None:
-                self.indexer.feed(self.get_target_uri(filename)[:-5], # strip '.html'
-                                  category, title, doctree)
+            self.indexer.feed(self.get_target_uri(filename)[:-5], # strip '.html'
+                              title, doctree)
 
-    def handle_file(self, filename, context, templatename='page'):
+    def handle_page(self, pagename, context, templatename='page.html'):
         ctx = self.globalcontext.copy()
+        ctx['current_page_name'] = pagename
+        ctx['pathto'] = relpath_to(self, self.get_target_uri(pagename+'.rst'))
+        ctx['hasdoc'] = lambda name: name+'.rst' in self.env.all_files
+        sidebarfile = self.config.get('html_sidebars', {}).get(pagename)
+        if sidebarfile:
+            ctx['customsidebar'] = path.join(self.srcdir, sidebarfile)
         ctx.update(context)
-        output = self.templates[templatename].render(ctx)
-        outfilename = path.join(self.outdir, os_path(filename)[:-4] + '.html')
+
+        output = self.get_template(templatename).render(ctx)
+        outfilename = path.join(self.outdir, os_path(pagename) + '.html')
         ensuredir(path.dirname(outfilename)) # normally different from self.outdir
         try:
-            with codecs.open(outfilename, 'w', 'utf-8') as fp:
-                fp.write(output)
+            f = codecs.open(outfilename, 'w', 'utf-8')
+            try:
+                f.write(output)
+            finally:
+                f.close()
         except (IOError, OSError), err:
             self.warn("Error writing file %s: %s" % (outfilename, err))
         if self.copysource and context.get('sourcename'):
             # copy the source file for the "show source" link
-            shutil.copyfile(path.join(self.srcdir, os_path(filename)),
+            shutil.copyfile(path.join(self.srcdir, os_path(pagename+'.rst')),
                             path.join(self.outdir, os_path(context['sourcename'])))
 
     def handle_finish(self):
         self.msg('dumping search index...')
         self.indexer.prune([self.get_target_uri(fn)[:-5] for fn in self.env.all_files])
-        with open(path.join(self.outdir, 'searchindex.json'), 'w') as f:
+        f = open(path.join(self.outdir, 'searchindex.json'), 'w')
+        try:
             self.indexer.dump(f, 'json')
+        finally:
+            f.close()
 
 
 class WebHTMLBuilder(StandaloneHTMLBuilder):
@@ -581,44 +577,57 @@
 
     def load_indexer(self, filenames):
         try:
-            with open(path.join(self.outdir, 'searchindex.pickle'), 'r') as f:
+            f = open(path.join(self.outdir, 'searchindex.pickle'), 'r')
+            try:
                 self.indexer.load(f, 'pickle')
+            finally:
+                f.close()
         except (IOError, OSError):
             pass
         # delete all entries for files that will be rebuilt
         self.indexer.prune(set(self.env.all_files) - set(filenames))
 
     def index_file(self, filename, doctree, title):
-        # only index pages with title and category
+        # only index pages with title
         if self.indexer is not None and title:
-            category = get_category(filename)
-            if category is not None:
-                self.indexer.feed(filename, category, title, doctree)
+            self.indexer.feed(filename, title, doctree)
 
-    def handle_file(self, filename, context, templatename='page'):
-        outfilename = path.join(self.outdir, os_path(filename)[:-4] + '.fpickle')
+    def handle_page(self, pagename, context, templatename='page.html'):
+        context['current_page_name'] = pagename
+        sidebarfile = self.config.get('html_sidebars', {}).get(pagename, '')
+        if sidebarfile:
+            context['customsidebar'] = path.join(self.srcdir, sidebarfile)
+        outfilename = path.join(self.outdir, os_path(pagename) + '.fpickle')
         ensuredir(path.dirname(outfilename))
-        context.pop('pathto', None) # can't be pickled
-        with file(outfilename, 'wb') as fp:
-            pickle.dump(context, fp, 2)
+        f = open(outfilename, 'wb')
+        try:
+            pickle.dump(context, f, 2)
+        finally:
+            f.close()
 
         # if there is a source file, copy the source file for the "show source" link
         if context.get('sourcename'):
             source_name = path.join(self.outdir, 'sources',
                                     os_path(context['sourcename']))
             ensuredir(path.dirname(source_name))
-            shutil.copyfile(path.join(self.srcdir, os_path(filename)), source_name)
+            shutil.copyfile(path.join(self.srcdir, os_path(pagename)+'.rst'), source_name)
 
     def handle_finish(self):
         # dump the global context
         outfilename = path.join(self.outdir, 'globalcontext.pickle')
-        with file(outfilename, 'wb') as fp:
-            pickle.dump(self.globalcontext, fp, 2)
+        f = open(outfilename, 'wb')
+        try:
+            pickle.dump(self.globalcontext, f, 2)
+        finally:
+            f.close()
 
         self.msg('dumping search index...')
         self.indexer.prune(self.env.all_files)
-        with open(path.join(self.outdir, 'searchindex.pickle'), 'wb') as f:
+        f = open(path.join(self.outdir, 'searchindex.pickle'), 'wb')
+        try:
             self.indexer.dump(f, 'pickle')
+        finally:
+            f.close()
 
         # copy the environment file from the doctree dir to the output dir
         # as needed by the web app
@@ -641,15 +650,11 @@
     """
     name = 'htmlhelp'
 
-    option_spec = {
-        'outname': 'Output file base name (default "pydoc")'
-    }
-
     # don't copy the reST source
     copysource = False
 
     def handle_finish(self):
-        build_hhx(self, self.outdir, self.options.get('outname') or 'pydoc')
+        build_hhx(self, self.outdir, self.config.get('htmlhelp_basename', 'pydoc'))
 
 
 class LaTeXBuilder(Builder):
@@ -660,6 +665,17 @@
 
     def init(self):
         self.filenames = []
+        self.document_data = map(list, self.config.get('latex_documents', ()))
+
+        # assign subdirs to titles
+        self.titles = []
+        for entry in self.document_data:
+            # replace version with real version
+            entry[0] = entry[0].replace('<auto>', self.config['version'])
+            sourcename = entry[0]
+            if sourcename.endswith('/index.rst'):
+                sourcename = sourcename[:-9]
+            self.titles.append((sourcename, entry[2]))
 
     def get_outdated_files(self):
         return 'all documents' # for now
@@ -674,49 +690,42 @@
         else:
             return ''
 
-    def get_document_data(self):
-        # Python specific...
-        for toplevel in ["c-api", "distutils", "documenting", "extending",
-                         "install", "reference", "tutorial", "using", "library"]:
-            yield (toplevel + SEP + 'index.rst', toplevel+'.tex', 'manual')
-        yield ('whatsnew' + SEP + self.config['version'] + '.rst',
-               'whatsnew.tex', 'howto')
-        for howto in [fn for fn in self.env.all_files
-                      if fn.startswith('howto'+SEP)
-                         and not fn.endswith('index.rst')]:
-            yield (howto, 'howto-'+howto[6:-4]+'.tex', 'howto')
-
     def write(self, *ignored):
-        # first, assemble the "special" docs that are in every PDF
-        specials = []
-        for fname in ["glossary", "about", "license", "copyright"]:
-            specials.append(self.env.get_doctree(fname+".rst"))
+        # first, assemble the "appendix" docs that are in every PDF
+        appendices = []
+        for fname in self.config.get('latex_appendices', []):
+            appendices.append(self.env.get_doctree(fname))
 
         docwriter = LaTeXWriter(self)
         docsettings = OptionParser(
             defaults=self.env.settings,
             components=(docwriter,)).get_default_values()
 
-        for sourcename, targetname, docclass in self.get_document_data():
+        if not self.document_data:
+            self.warn('No "latex_documents" config setting found; no documents '
+                      'will be written.')
+
+        for sourcename, targetname, title, author, docclass in self.document_data:
             destination = FileOutput(
                 destination_path=path.join(self.outdir, targetname),
                 encoding='utf-8')
             print "processing", targetname + "...",
             doctree = self.assemble_doctree(
-                sourcename, specials=(docclass == 'manual') and specials or [])
+                sourcename, appendices=(docclass == 'manual') and appendices or [])
             print "writing...",
             doctree.settings = docsettings
+            doctree.settings.author = author
             doctree.settings.filename = sourcename
             doctree.settings.docclass = docclass
             output = docwriter.write(doctree, destination)
             print "done"
 
-    def assemble_doctree(self, indexfile, specials):
+    def assemble_doctree(self, indexfile, appendices):
         self.filenames = set([indexfile, 'glossary.rst', 'about.rst',
                               'license.rst', 'copyright.rst'])
         print green(indexfile),
         def process_tree(filename, tree):
-            #tree = tree.deepcopy() XXX
+            tree = tree.deepcopy()
             for toctreenode in tree.traverse(addnodes.toctree):
                 newnodes = []
                 includefiles = map(str, toctreenode['includefiles'])
@@ -734,11 +743,25 @@
                 toctreenode.parent.replace(toctreenode, newnodes)
             return tree
         largetree = process_tree(indexfile, self.env.get_doctree(indexfile))
-        largetree.extend(specials)
+        largetree.extend(appendices)
         print
         print "resolving references..."
-        # XXX problem here: :ref:s to distant tex files
         self.env.resolve_references(largetree, indexfile, self)
+        # resolve :ref:s to distant tex files -- we can't add a cross-reference,
+        # but append the document name
+        for pendingnode in largetree.traverse(addnodes.pending_xref):
+            filename = pendingnode['reffilename']
+            sectname = pendingnode['refsectname']
+            newnodes = [nodes.emphasis(sectname, sectname)]
+            for subdir, title in self.titles:
+                if filename.startswith(subdir):
+                    newnodes.append(nodes.Text(' (in ', ' (in '))
+                    newnodes.append(nodes.emphasis(title, title))
+                    newnodes.append(nodes.Text(')', ')'))
+                    break
+            else:
+                pass
+            pendingnode.replace_self(newnodes)
         return largetree
 
     def finish(self):
@@ -757,15 +780,15 @@
     name = 'changes'
 
     def init(self):
-        from ._jinja import Environment, FileSystemLoader
+        from sphinx._jinja import Environment, FileSystemLoader
         templates_path = path.join(path.dirname(__file__), 'templates')
-        jinja_env = Environment(loader=FileSystemLoader(templates_path),
+        jinja_env = Environment(loader=SphinxFileSystemLoader([templates_path]),
                                 # disable traceback, more likely that something in the
                                 # application is broken than in the templates
                                 friendly_traceback=False)
-        self.ftemplate = jinja_env.get_template('versionchanges_frameset.html')
-        self.vtemplate = jinja_env.get_template('versionchanges.html')
-        self.stemplate = jinja_env.get_template('rstsource.html')
+        self.ftemplate = jinja_env.get_template('changes/frameset.html')
+        self.vtemplate = jinja_env.get_template('changes/versionchanges.html')
+        self.stemplate = jinja_env.get_template('changes/rstsource.html')
 
     def get_outdated_files(self):
         return self.outdir
@@ -813,15 +836,22 @@
                     (entry, filename, lineno))
 
         ctx = {
+            'project': self.config.get('project', 'Python'),
             'version': ver,
             'libchanges': sorted(libchanges.iteritems()),
             'apichanges': sorted(apichanges),
             'otherchanges': sorted(otherchanges.iteritems()),
         }
-        with open(path.join(self.outdir, 'index.html'), 'w') as f:
+        f = open(path.join(self.outdir, 'index.html'), 'w')
+        try:
             f.write(self.ftemplate.render(ctx))
-        with open(path.join(self.outdir, 'changes.html'), 'w') as f:
+        finally:
+            f.close()
+        f = open(path.join(self.outdir, 'changes.html'), 'w')
+        try:
             f.write(self.vtemplate.render(ctx))
+        finally:
+            f.close()
 
         hltext = ['.. versionadded:: %s' % ver,
                   '.. versionchanged:: %s' % ver,
@@ -837,14 +867,17 @@
 
         self.msg('copying source files...')
         for filename in self.env.all_files:
-            with open(path.join(self.srcdir, os_path(filename))) as f:
-                lines = f.readlines()
+            f = open(path.join(self.srcdir, os_path(filename)))
+            lines = f.readlines()
             targetfn = path.join(self.outdir, 'rst', os_path(filename)) + '.html'
             ensuredir(path.dirname(targetfn))
-            with codecs.open(targetfn, 'w', 'utf8') as f:
+            f = codecs.open(targetfn, 'w', 'utf8')
+            try:
                 text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
                 ctx = {'filename': filename, 'text': text}
                 f.write(self.stemplate.render(ctx))
+            finally:
+                f.close()
         shutil.copyfile(path.join(path.dirname(__file__), 'style', 'default.css'),
                         path.join(self.outdir, 'default.css'))
 

Modified: doctools/trunk/sphinx/directives.py
==============================================================================
--- doctools/trunk/sphinx/directives.py	(original)
+++ doctools/trunk/sphinx/directives.py	Wed Jan 16 21:27:25 2008
@@ -8,7 +8,6 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import re
 import string
@@ -19,7 +18,7 @@
 from docutils.parsers.rst import directives, roles
 from docutils.parsers.rst.directives import admonitions
 
-from . import addnodes
+from sphinx import addnodes
 
 # ------ index markup --------------------------------------------------------------
 
@@ -142,7 +141,7 @@
         else:
             fullname = env.currclass + '.' + name
     else:
-        fullname = classname + name if classname else name
+        fullname = classname and classname + name or name
 
     if classname:
         signode += addnodes.desc_classname(classname, classname)
@@ -285,7 +284,7 @@
     if entry.result_refs is None:
         rc += "Always NULL."
     else:
-        rc += ("New" if entry.result_refs else "Borrowed") + " reference."
+        rc += (entry.result_refs and "New" or "Borrowed") + " reference."
     node += addnodes.refcount(rc, rc)
 
 
@@ -347,7 +346,7 @@
         # only add target and index entry if this is the first description of the
         # function name in this desc block
         if not noindex and name not in names:
-            fullname = (env.currmodule + '.' if env.currmodule else '') + name
+            fullname = (env.currmodule and env.currmodule + '.' or '') + name
             # note target
             if fullname not in state.document.ids:
                 signode['names'].append(fullname)
@@ -612,8 +611,9 @@
     fn = path.normpath(path.join(source_dir, fn))
 
     try:
-        with open(fn) as f:
-            text = f.read()
+        f = open(fn)
+        text = f.read()
+        f.close()
     except (IOError, OSError):
         retnode = state.document.reporter.warning(
             'Include file %r not found or reading it failed' % arguments[0], line=lineno)

Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py	(original)
+++ doctools/trunk/sphinx/environment.py	Wed Jan 16 21:27:25 2008
@@ -8,18 +8,22 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import re
 import os
 import time
 import heapq
-import hashlib
 import difflib
 import itertools
 import cPickle as pickle
 from os import path
 from string import uppercase
+try:
+    import hashlib
+    md5 = hashlib.md5
+except:
+    import md5
+    md5 = md5.new
 
 from docutils import nodes
 from docutils.io import FileInput
@@ -37,9 +41,9 @@
     Body.enum.converters['lowerroman'] = \
     Body.enum.converters['upperroman'] = lambda x: None
 
-from . import addnodes
-from .util import get_matching_files, os_path, SEP
-from .refcounting import Refcounts
+from sphinx import addnodes
+from sphinx.util import get_matching_files, os_path, SEP
+from sphinx.refcounting import Refcounts
 
 default_settings = {
     'embed_stylesheet': False,
@@ -156,8 +160,11 @@
 
     @staticmethod
     def frompickle(filename):
-        with open(filename, 'rb') as picklefile:
+        picklefile = open(filename, 'rb')
+        try:
             env = pickle.load(picklefile)
+        finally:
+            picklefile.close()
         if env.version != ENV_VERSION:
             raise IOError('env version not current')
         return env
@@ -166,8 +173,11 @@
         # remove unpicklable attributes
         warnfunc = self._warnfunc
         self.set_warnfunc(None)
-        with open(filename, 'wb') as picklefile:
+        picklefile = open(filename, 'wb')
+        try:
             pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
+        finally:
+            picklefile.close()
         # reset stream
         self.set_warnfunc(warnfunc)
 
@@ -178,9 +188,8 @@
         self.srcdir = srcdir
         self.config = {}
 
-        # read the refcounts file
-        self.refcounts = Refcounts.fromfile(
-            path.join(self.srcdir, 'data', 'refcounts.dat'))
+        # refcount data if present
+        self.refcounts = {}
 
         # the docutils settings for building
         self.settings = default_settings.copy()
@@ -194,7 +203,7 @@
 
         # Build times -- to determine changed files
         # Also use this as an inventory of all existing and built filenames.
-        self.all_files = {}         # filename -> (mtime, md5) at the time of build
+        self.all_files = {}         # filename -> (mtime, md5sum) at the time of build
 
         # File metadata
         self.metadata = {}          # filename -> dict of metadata items
@@ -291,21 +300,22 @@
                                                  os_path(filename)[:-3] + 'doctree')):
                         changed.append(filename)
                         continue
-                    mtime, md5 = self.all_files[filename]
+                    mtime, md5sum = self.all_files[filename]
                     newmtime = path.getmtime(path.join(self.srcdir, os_path(filename)))
                     if newmtime == mtime:
                         continue
                     # check the MD5
                     #with file(path.join(self.srcdir, filename), 'rb') as f:
-                    #    newmd5 = hashlib.md5(f.read()).digest()
-                    #if newmd5 != md5:
+                    #    newmd5sum = md5(f.read()).digest()
+                    #if newmd5sum != md5sum:
                     changed.append(filename)
 
         return added, changed, removed
 
     # If one of these config values changes, all files need to be re-read.
     influential_config_values = [
-        'version', 'release', 'today', 'today_fmt', 'unused_files'
+        'version', 'release', 'today', 'today_fmt', 'unused_files',
+        'project', 'refcount_file', 'add_function_parentheses', 'add_module_names'
     ]
 
     def update(self, config):
@@ -330,14 +340,15 @@
 
         self.config = config
 
+        # read the refcounts file
+        if self.config.get('refcount_file'):
+            self.refcounts = Refcounts.fromfile(
+                path.join(self.srcdir, self.config['refcount_file']))
+
         # clear all files no longer present
         for filename in removed:
             self.clear_file(filename)
 
-        # re-read the refcount file
-        self.refcounts = Refcounts.fromfile(
-            path.join(self.srcdir, 'data', 'refcounts.dat'))
-
         # read all new and changed files
         for filename in added + changed:
             yield filename
@@ -364,9 +375,12 @@
         self.build_toc_from(filename, doctree)
 
         # calculate the MD5 of the file at time of build
-        with file(src_path, 'rb') as f:
-            md5 = hashlib.md5(f.read()).digest()
-        self.all_files[filename] = (path.getmtime(src_path), md5)
+        f = open(src_path, 'rb')
+        try:
+            md5sum = md5(f.read()).digest()
+        finally:
+            f.close()
+        self.all_files[filename] = (path.getmtime(src_path), md5sum)
 
         # make it picklable
         doctree.reporter = None
@@ -388,8 +402,11 @@
             dirname = path.dirname(doctree_filename)
             if not path.isdir(dirname):
                 os.makedirs(dirname)
-            with file(doctree_filename, 'wb') as f:
+            f = open(doctree_filename, 'wb')
+            try:
                 pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
+            finally:
+                f.close()
         else:
             return doctree
 
@@ -446,9 +463,9 @@
         includefiles_len = len(includefiles)
         for i, includefile in enumerate(includefiles):
             # the "previous" file for the first toctree item is the parent
-            previous = includefiles[i-1] if i > 0 else filename
+            previous = i > 0 and includefiles[i-1] or filename
             # the "next" file for the last toctree item is the parent again
-            next = includefiles[i+1] if i < includefiles_len-1 else filename
+            next = i < includefiles_len-1 and includefiles[i+1] or filename
             self.toctree_relations[includefile] = [filename, previous, next]
             # note that if the included file is rebuilt, this one must be
             # too (since the TOC of the included file could have changed)
@@ -539,8 +556,11 @@
     def get_doctree(self, filename):
         """Read the doctree for a file from the pickle and return it."""
         doctree_filename = path.join(self.doctreedir, os_path(filename)[:-3] + 'doctree')
-        with file(doctree_filename, 'rb') as f:
+        f = open(doctree_filename, 'rb')
+        try:
             doctree = pickle.load(f)
+        finally:
+            f.close()
         doctree.reporter = Reporter(filename, 2, 4, stream=RedirStream(self._warnfunc))
         return doctree
 
@@ -617,9 +637,11 @@
                         if filename == docfilename:
                             newnode['refid'] = labelid
                         else:
-                            # in case the following calls raises NoUri...
-                            # else the final node will contain a label name
-                            contnode = innernode
+                            # set more info in contnode in case the following call
+                            # raises NoUri, the builder will have to resolve these
+                            contnode = addnodes.pending_xref('')
+                            contnode['reffilename'] = filename
+                            contnode['refsectname'] = sectname
                             newnode['refuri'] = builder.get_relative_uri(
                                 docfilename, filename) + '#' + labelid
                         newnode.append(innernode)
@@ -669,14 +691,14 @@
                         newnode['refuri'] = (
                             builder.get_relative_uri(docfilename, filename) + anchor)
                         newnode['reftitle'] = '%s%s%s' % (
-                            ('(%s) ' % platform if platform else ''),
-                            synopsis, (' (deprecated)' if deprecated else ''))
+                            (platform and '(%s) ' % platform),
+                            synopsis, (deprecated and ' (deprecated)' or ''))
                         newnode.append(contnode)
                 else:
                     # "descrefs"
                     modname = node['modname']
                     clsname = node['classname']
-                    searchorder = 1 if node.hasattr('refspecific') else 0
+                    searchorder = node.hasattr('refspecific') and 1 or 0
                     name, desc = self.find_desc(modname, clsname,
                                                 target, typ, searchorder)
                     if not desc:
@@ -716,7 +738,10 @@
             # new entry types must be listed in directives.py!
             for type, string, tid, alias in entries:
                 if type == 'single':
-                    entry, _, subentry = string.partition(';')
+                    try:
+                        entry, subentry = string.split(';', 1)
+                    except:
+                        entry, subentry = string, ''
                     add_entry(entry.strip(), subentry.strip())
                 elif type == 'pair':
                     first, second = map(lambda x: x.strip(), string.split(';', 1))

Modified: doctools/trunk/sphinx/highlighting.py
==============================================================================
--- doctools/trunk/sphinx/highlighting.py	(original)
+++ doctools/trunk/sphinx/highlighting.py	Wed Jan 16 21:27:25 2008
@@ -9,9 +9,9 @@
     :license: BSD.
 """
 
+import sys
 import cgi
 import parser
-from collections import defaultdict
 
 try:
     import pygments
@@ -42,7 +42,7 @@
             Number: '#208050',
         })
 
-    lexers = defaultdict(TextLexer,
+    lexers = dict(
         none = TextLexer(),
         python = PythonLexer(),
         pycon = PythonConsoleLexer(),
@@ -71,8 +71,12 @@
         else:
             # maybe Python -- try parsing it
             try:
-                parser.suite('from __future__ import with_statement\n' +
-                             source + '\n')
+                # if we're using 2.5, use the with statement
+                if sys.version_info >= (2, 5):
+                    parser.suite('from __future__ import with_statement\n' +
+                                 source + '\n')
+                else:
+                    parser.suite(source + '\n')
             except (SyntaxError, UnicodeEncodeError):
                 return unhighlighted()
             else:

Modified: doctools/trunk/sphinx/htmlhelp.py
==============================================================================
--- doctools/trunk/sphinx/htmlhelp.py	(original)
+++ doctools/trunk/sphinx/htmlhelp.py	Wed Jan 16 21:27:25 2008
@@ -9,7 +9,6 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import os
 import cgi
@@ -17,7 +16,7 @@
 
 from docutils import nodes
 
-from . import addnodes
+from sphinx import addnodes
 
 # Project file (*.hhp) template.  'outname' is the file basename (like
 # the pythlp in pythlp.hhp); 'version' is the doc version number (like
@@ -64,10 +63,10 @@
 Full-text search=Yes
 Index file=%(outname)s.hhk
 Language=0x409
-Title=Python %(version)s Documentation
+Title=%(project)s %(version)s Documentation
 
 [WINDOWS]
-%(outname)s="Python %(version)s Documentation","%(outname)s.hhc","%(outname)s.hhk",\
+%(outname)s="%(project)s %(version)s Documentation","%(outname)s.hhc","%(outname)s.hhk",\
 "index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
 
 [FILES]
@@ -119,24 +118,32 @@
 
 def build_hhx(builder, outdir, outname):
     builder.msg('dumping stopword list...')
-    with open(path.join(outdir, outname+'.stp'), 'w') as f:
+    f = open(path.join(outdir, outname+'.stp'), 'w')
+    try:
         for word in sorted(stopwords):
             print >>f, word
+    finally:
+        f.close()
 
     builder.msg('writing project file...')
-    with open(path.join(outdir, outname+'.hhp'), 'w') as f:
+    f = open(path.join(outdir, outname+'.hhp'), 'w')
+    try:
         f.write(project_template % {'outname': outname,
-                                    'version': builder.config['version']})
+                                    'version': builder.config['version'],
+                                    'project': builder.config['project']})
         if not outdir.endswith(os.sep):
             outdir += os.sep
         olen = len(outdir)
         for root, dirs, files in os.walk(outdir):
             for fn in files:
-                if fn.endswith(('.html', '.css', '.js')):
+                if fn.endswith('.html') or fn.endswith('.css') or fn.endswith('.js'):
                     print >>f, path.join(root, fn)[olen:].replace('/', '\\')
+    finally:
+        f.close()
 
     builder.msg('writing TOC file...')
-    with open(path.join(outdir, outname+'.hhc'), 'w') as f:
+    f = open(path.join(outdir, outname+'.hhc'), 'w')
+    try:
         f.write(contents_header)
         # special books
         f.write('<LI> ' + object_sitemap % ('Main page', 'index.html'))
@@ -167,9 +174,12 @@
                 write_toc(node[0], ullevel)
         write_toc(toc)
         f.write(contents_footer)
+    finally:
+        f.close()
 
     builder.msg('writing index file...')
-    with open(path.join(outdir, outname+'.hhk'), 'w') as f:
+    f = open(path.join(outdir, outname+'.hhk'), 'w')
+    try:
         f.write('<UL>\n')
         def write_index(title, refs, subitems):
             if refs:
@@ -186,3 +196,5 @@
             for title, (refs, subitems) in group:
                 write_index(title, refs, subitems)
         f.write('</UL>\n')
+    finally:
+        f.close()

Modified: doctools/trunk/sphinx/htmlwriter.py
==============================================================================
--- doctools/trunk/sphinx/htmlwriter.py	(original)
+++ doctools/trunk/sphinx/htmlwriter.py	Wed Jan 16 21:27:25 2008
@@ -12,7 +12,7 @@
 from docutils import nodes
 from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
 
-from .util.smartypants import sphinx_smarty_pants
+from sphinx.util.smartypants import sphinx_smarty_pants
 
 
 class HTMLWriter(Writer):
@@ -162,7 +162,7 @@
 
         # overwritten
         def visit_literal_block(self, node):
-            from .highlighting import highlight_block
+            from sphinx.highlighting import highlight_block
             self.body.append(highlight_block(node.rawsource, self.highlightlang))
             raise nodes.SkipNode
 
@@ -246,7 +246,8 @@
         def depart_title(self, node):
             close_tag = self.context[-1]
             if builder.name != 'htmlhelp' and \
-                   close_tag.startswith(('</h', '</a></h')) and \
+                   (close_tag.startswith('</h') or
+                    close_tag.startswith('</a></h')) and \
                    node.parent.hasattr('ids') and node.parent['ids']:
                 aname = node.parent['ids'][0]
                 # add permalink anchor

Modified: doctools/trunk/sphinx/latexwriter.py
==============================================================================
--- doctools/trunk/sphinx/latexwriter.py	(original)
+++ doctools/trunk/sphinx/latexwriter.py	Wed Jan 16 21:27:25 2008
@@ -18,8 +18,8 @@
 
 from docutils import frontend, nodes, languages, writers, utils
 
-from . import addnodes
-from . import highlighting
+from sphinx import addnodes
+from sphinx import highlighting
 
 
 HEADER = r'''%% Generated by Sphinx.
@@ -30,12 +30,8 @@
 \title{%(title)s}
 \date{%(date)s}
 \release{%(release)s}
-\author{Guido van Rossum\\    %% XXX
-  Fred L. Drake, Jr., editor}
-\authoraddress{
-  \strong{Python Software Foundation}\\
-  Email: \email{docs at python.org}
-}
+\author{%(author)s}
+%(preamble)s
 \makeindex
 \makemodindex
 '''
@@ -103,6 +99,8 @@
         self.options = {'docclass': docclass,
                         'papersize': paper,
                         'pointsize': builder.config.get('latex_font_size', '10pt'),
+                        'preamble': builder.config['latex_preamble'],
+                        'author': document.settings.author,
                         'filename': document.settings.filename,
                         'title': None, # is determined later
                         'release': builder.config['release'],
@@ -112,7 +110,10 @@
         self.descstack = []
         self.highlightlang = 'python'
         self.written_ids = set()
-        self.top_sectionlevel = 0 if docclass == 'manual' else 1
+        if docclass == 'manual':
+            self.top_sectionlevel = 0
+        else:
+            self.top_sectionlevel = 1
         # flags
         self.verbatim = None
         self.in_title = 0
@@ -577,7 +578,8 @@
         uri = node.get('refuri', '')
         if self.in_title or not uri:
             self.context.append('')
-        elif uri.startswith(('mailto:', 'http:', 'ftp:')):
+        elif uri.startswith('mailto:') or uri.startswith('http:') or \
+             uri.startswith('ftp:'):
             self.body.append('\\href{%s}{' % self.encode(uri))
             self.context.append('}')
         elif uri.startswith('#'):

Modified: doctools/trunk/sphinx/patchlevel.py
==============================================================================
--- doctools/trunk/sphinx/patchlevel.py	(original)
+++ doctools/trunk/sphinx/patchlevel.py	Wed Jan 16 21:27:25 2008
@@ -6,10 +6,11 @@
     Extract version info from Include/patchlevel.h.
     Adapted from Doc/tools/getversioninfo.
 
+    XXX Python specific
+
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import os
 import re
@@ -23,12 +24,15 @@
     rx = re.compile(r"\s*#define\s+([a-zA-Z][a-zA-Z_0-9]*)\s+([a-zA-Z_0-9]+)")
 
     d = {}
-    with open(patchlevel_h) as f:
+    f = open(patchlevel_h)
+    try:
         for line in f:
             m = rx.match(line)
             if m is not None:
                 name, value = m.group(1, 2)
                 d[name] = value
+    finally:
+        f.close()
 
     release = version = "%s.%s" % (d["PY_MAJOR_VERSION"], d["PY_MINOR_VERSION"])
     micro = int(d["PY_MICRO_VERSION"])

Modified: doctools/trunk/sphinx/refcounting.py
==============================================================================
--- doctools/trunk/sphinx/refcounting.py	(original)
+++ doctools/trunk/sphinx/refcounting.py	Wed Jan 16 21:27:25 2008
@@ -9,8 +9,6 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
-
 
 class RCEntry:
     def __init__(self, name):
@@ -24,7 +22,8 @@
     @classmethod
     def fromfile(cls, filename):
         d = cls()
-        with open(filename, 'r') as fp:
+        fp = open(filename, 'r')
+        try:
             for line in fp:
                 line = line.strip()
                 if line[:1] in ("", "#"):
@@ -49,4 +48,6 @@
                 else:
                     entry.result_type = type
                     entry.result_refs = refcount
+        finally:
+            fp.close()
         return d

Modified: doctools/trunk/sphinx/roles.py
==============================================================================
--- doctools/trunk/sphinx/roles.py	(original)
+++ doctools/trunk/sphinx/roles.py	Wed Jan 16 21:27:25 2008
@@ -14,7 +14,7 @@
 from docutils import nodes, utils
 from docutils.parsers.rst import roles
 
-from . import addnodes
+from sphinx import addnodes
 
 ws_re = re.compile(r'\s+')
 
@@ -128,7 +128,10 @@
     if typ == 'term':
         pnode['reftarget'] = ws_re.sub(' ', text).lower()
     elif typ == 'option':
-        pnode['reftarget'] = text[1:] if text[0] in '-/' else text
+        if text[0] in '-/':
+            pnode['reftarget'] = text[1:]
+        else:
+            pnode['reftarget'] = text
     else:
         pnode['reftarget'] = ws_re.sub('', text)
     pnode['modname'] = env.currmodule

Modified: doctools/trunk/sphinx/search.py
==============================================================================
--- doctools/trunk/sphinx/search.py	(original)
+++ doctools/trunk/sphinx/search.py	Wed Jan 16 21:27:25 2008
@@ -10,12 +10,11 @@
 """
 import re
 import pickle
-from collections import defaultdict
 
 from docutils.nodes import Text, NodeVisitor
 
-from .util.stemmer import PorterStemmer
-from .util.json import dump_json, load_json
+from sphinx.util.stemmer import PorterStemmer
+from sphinx.util.json import dump_json, load_json
 
 
 word_re = re.compile(r'\w+(?u)')
@@ -61,18 +60,14 @@
         self._titles = {}
         # stemmed word -> set(filenames)
         self._mapping = {}
-        # category -> set(filenames)
-        self._categories = {}
 
     def load(self, stream, format):
         """Reconstruct from frozen data."""
         frozen = self.formats[format][1](stream.read())
         index2fn = frozen[0]
-        self._titles = dict(zip(frozen[0], frozen[2]))
-        self._categories = dict((k, set(index2fn[i] for i in v))
-                                for (k, v) in frozen[1].iteritems())
+        self._titles = dict(zip(frozen[0], frozen[1]))
         self._mapping = dict((k, set(index2fn[i] for i in v))
-                             for (k, v) in frozen[3].iteritems())
+                             for (k, v) in frozen[2].iteritems())
 
     def dump(self, stream, format):
         """Dump the frozen index to a stream."""
@@ -87,8 +82,6 @@
         fn2index = dict((f, i) for (i, f) in enumerate(fns))
         return [
             fns,
-            dict((k, [fn2index[fn] for fn in v])
-                 for (k, v) in self._categories.iteritems()),
             titles,
             dict((k, [fn2index[fn] for fn in v])
                  for (k, v) in self._mapping.iteritems()),
@@ -103,13 +96,10 @@
         self._titles = new_titles
         for wordnames in self._mapping.itervalues():
             wordnames.intersection_update(filenames)
-        for catnames in self._categories.itervalues():
-            catnames.intersection_update(filenames)
 
-    def feed(self, filename, category, title, doctree):
+    def feed(self, filename, title, doctree):
         """Feed a doctree to the index."""
         self._titles[filename] = title
-        self._categories.setdefault(category, set()).add(filename)
 
         visitor = WordCollector(doctree)
         doctree.walk(visitor)
@@ -125,25 +115,24 @@
     """
 
     def __init__(self, index):
-        self.filenames, self.areas, self.titles, self.words = index
+        self.filenames, self.titles, self.words = index
         self._stemmer = Stemmer()
 
-    def query(self, required, excluded, areas):
-        file_map = defaultdict(set)
+    def query(self, required, excluded):
+        file_map = {}
         for word in required:
             if word not in self.words:
                 break
             for fid in self.words[word]:
-                file_map[fid].add(word)
+                file_map.setdefault(fid, set()).add(word)
 
         return sorted(((self.filenames[fid], self.titles[fid])
             for fid, words in file_map.iteritems()
-            if len(words) == len(required) and
-               any(fid in self.areas.get(area, ()) for area in areas) and not
+            if len(words) == len(required) and not
                any(fid in self.words.get(word, ()) for word in excluded)
         ), key=lambda x: x[1].lower())
 
-    def search(self, searchstring, areas):
+    def search(self, searchstring):
         required = set()
         excluded = set()
         for word in searchstring.split():
@@ -154,4 +143,4 @@
                 storage = required
             storage.add(self._stemmer.stem(word.lower()))
 
-        return self.query(required, excluded, areas)
+        return self.query(required, excluded)

Modified: doctools/trunk/sphinx/style/default.css
==============================================================================
--- doctools/trunk/sphinx/style/default.css	(original)
+++ doctools/trunk/sphinx/style/default.css	Wed Jan 16 21:27:25 2008
@@ -1,5 +1,5 @@
 /**
- * Python Doc Design
+ * Sphinx Doc Design
  */
 
 body {

Modified: doctools/trunk/sphinx/style/rightsidebar.css
==============================================================================
--- doctools/trunk/sphinx/style/rightsidebar.css	(original)
+++ doctools/trunk/sphinx/style/rightsidebar.css	Wed Jan 16 21:27:25 2008
@@ -1,5 +1,5 @@
 /**
- * Python Doc Design -- Right Side Bar Overrides
+ * Sphinx Doc Design -- Right Side Bar Overrides
  */
 
 

Modified: doctools/trunk/sphinx/style/searchtools.js
==============================================================================
--- doctools/trunk/sphinx/style/searchtools.js	(original)
+++ doctools/trunk/sphinx/style/searchtools.js	Wed Jan 16 21:27:25 2008
@@ -228,27 +228,15 @@
         var params = $.getQueryParameters();
         if (params.q) {
             var query = params.q[0];
-            var areas = params.area || [];
-
-            // auto default
-            if (areas.length == 1 && areas[0] == 'default') {
-                areas = ['tutorial', 'library', 'install', 'distutils'];
-            }
-
-            // update input fields
-            $('input[@type="checkbox"]').each(function() {
-                    this.checked = $.contains(areas, this.value);
-                });
             $('input[@name="q"]')[0].value = query;
-
-            this.performSearch(query, areas);
+            this.performSearch(query);
         }
     },
 
     /**
      * perform a search for something
      */
-    performSearch : function(query, areas) {
+    performSearch : function(query) {
         // create the required interface elements
         var out = $('#search-results');
         var title = $('<h2>Searching</h2>').appendTo(out);
@@ -301,14 +289,12 @@
         console.debug('SEARCH: searching for:');
         console.info('required: ', searchwords);
         console.info('excluded: ', excluded);
-        console.info('areas:    ', areas);
 
         // fetch searchindex and perform search
         $.getJSON('searchindex.json', function(data) {
 
                 // prepare search
                 var filenames = data[0];
-                var areaMap = data[1];
                 var titles = data[2]
                     var words = data[3];
                 var fileMap = {};
@@ -342,38 +328,25 @@
                     if (fileMap[file].length != searchwords.length) {
                         continue;
                     }
-                    var valid = false;
-
-                    // check if the file is in one of the searched
-                    // areas.
-                    for (var i = 0; i < areas.length; i++) {
-                        if ($.contains(areaMap[areas[i]] || [], file)) {
-                            valid = true;
-                            break;
-                        }
-                    };
-
                     // ensure that none of the excluded words is in the
                     // search result.
-                    if (valid) {
-                        for (var i = 0; i < excluded.length; i++) {
-                            if ($.contains(words[excluded[i]] || [], file)) {
-                                valid = false;
-                                break;
-                            }
+                    for (var i = 0; i < excluded.length; i++) {
+                        if ($.contains(words[excluded[i]] || [], file)) {
+                            valid = false;
+                            break;
                         }
+                    }
 
-                        // if we have still a valid result we can add it
-                        // to the result list
-                        if (valid) {
-                            results.push([filenames[file], titles[file]]);
-                        }
+                    // if we have still a valid result we can add it
+                    // to the result list
+                    if (valid) {
+                        results.push([filenames[file], titles[file]]);
                     }
                 }
 
                 // delete unused variables in order to not waste
                 // memory until list is retrieved completely
-                delete filenames, areaMap, titles, words, data;
+                delete filenames, titles, words, data;
 
                 // now sort the results by title
                 results.sort(function(a, b) {

Modified: doctools/trunk/sphinx/style/stickysidebar.css
==============================================================================
--- doctools/trunk/sphinx/style/stickysidebar.css	(original)
+++ doctools/trunk/sphinx/style/stickysidebar.css	Wed Jan 16 21:27:25 2008
@@ -1,5 +1,5 @@
 /**
- * Python Doc Design -- Sticky Sidebar Overrides
+ * Sphinx Doc Design -- Sticky Sidebar Overrides
  */
 
 div.sidebar {

Modified: doctools/trunk/sphinx/style/traditional.css
==============================================================================
--- doctools/trunk/sphinx/style/traditional.css	(original)
+++ doctools/trunk/sphinx/style/traditional.css	Wed Jan 16 21:27:25 2008
@@ -1,5 +1,5 @@
 /**
- * Python Doc Design
+ * Sphinx Doc Design -- traditional python.org style
  */
 
 body {

Deleted: /doctools/trunk/sphinx/templates/_commentform.html
==============================================================================
--- /doctools/trunk/sphinx/templates/_commentform.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,34 +0,0 @@
-<form action="?target={{ comments_form.target|e(true) }}" method="post">
-    {% if comments_form.error %}
-    <div class="error">{{ comments_form.error|e }}</div>
-    {% endif %}
-    <p>Note: you can also <a href="{{ pathto(suggest_url, 1)|e }}">suggest
-    changes</a> to the official documentation text.</p>
-    <dl>
-      <dt>Name:</dt>
-      <dd><input type="text" size="24" name="author" value="{{ comments_form.author|e(true) }}"></dd>
-      <dt>E-Mail Address:</dt>
-      <dd><input type="text" size="24" name="author_mail" value="{{ comments_form.author_mail|e(true) }}"></dd>
-      <dt>Comment Title:</dt>
-      <dd><input type="text" size="36" name="title" value="{{ comments_form.title|e(true) }}"></dd>
-    </dl>
-    <input type="text" size="12" name="homepage" id="homepage">
-    <textarea name="comment_body" rows="7" cols="50">{{ comments_form.comment_body|e }}</textarea>
-    {% if preview %}
-    <div class="preview">
-      <h4>Preview</h4>
-      <div class="comment">
-        <h4>{{ preview.title|e or '&nbsp;' }}</h4>
-        <div class="text">{{ preview.parsed_comment_body or '&nbsp;' }}</div>
-        <div class="meta">by {{ preview.author|e }}, written on
-        {{ preview.pub_date|datetimeformat }} |
-        <a href="#">#</a></div>
-      </div>
-    </div>
-    {% endif %}
-    <div class="actions">
-      <input type="submit" value="Submit comment">
-      <input type="submit" name="preview" value="Preview">
-      <input type="reset" value="Reset form">
-    </div>
-  </form>

Copied: doctools/trunk/sphinx/templates/changes/frameset.html (from r59608, doctools/trunk/sphinx/templates/versionchanges_frameset.html)
==============================================================================
--- doctools/trunk/sphinx/templates/versionchanges_frameset.html	(original)
+++ doctools/trunk/sphinx/templates/changes/frameset.html	Wed Jan 16 21:27:25 2008
@@ -2,7 +2,7 @@
   "http://www.w3.org/TR/html4/frameset.dtd">
 <html>
   <head>
-    <title>Changes in Version {{ version }} &mdash; Python Documentation</title>
+    <title>Changes in Version {{ version }} &mdash; {{ project }} Documentation</title>
   </head>
   <frameset cols="45%,*">
     <frame name="main" src="changes.html">

Copied: doctools/trunk/sphinx/templates/changes/rstsource.html (from r59608, doctools/trunk/sphinx/templates/rstsource.html)
==============================================================================
--- doctools/trunk/sphinx/templates/rstsource.html	(original)
+++ doctools/trunk/sphinx/templates/changes/rstsource.html	Wed Jan 16 21:27:25 2008
@@ -2,7 +2,7 @@
   "http://www.w3.org/TR/html4/loose.dtd">
 <html>
   <head>
-    <title>{{ filename }} &mdash; Python Documentation</title>
+    <title>{{ filename }} &mdash; {{ project }} Documentation</title>
     <style type="text/css">
       .hl { background-color: yellow }
     </style>

Copied: doctools/trunk/sphinx/templates/changes/versionchanges.html (from r59608, doctools/trunk/sphinx/templates/versionchanges.html)
==============================================================================
--- doctools/trunk/sphinx/templates/versionchanges.html	(original)
+++ doctools/trunk/sphinx/templates/changes/versionchanges.html	Wed Jan 16 21:27:25 2008
@@ -9,7 +9,7 @@
   <head>
     <link rel="stylesheet" href="default.css">
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>Changes in Version {{ version }} &mdash; Python Documentation</title>
+    <title>Changes in Version {{ version }} &mdash; {{ project }} Documentation</title>
   </head>
   <body>
     <div class="document">

Deleted: /doctools/trunk/sphinx/templates/commentform.html
==============================================================================
--- /doctools/trunk/sphinx/templates/commentform.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,26 +0,0 @@
-{% extends "layout.html" %}
-{% block body %}
-  <div id="new-commment-box">
-    <h4 id="comments-new-comment">New Comment</h4>
-    {{ form }}
-    <div class="help">
-      <p>
-        <strong>You can format a comment using the
-        following syntax elements provided:</strong>
-      </p>
-      <p>
-        `code` / ``code too`` / **strong** /
-        *emphasized* / !!!important!!! /
-        [[link_target Link Title]] /
-        [[link_target_only]] / &lt;code&gt;code block with
-        syntax highlighting&lt;/code&gt; / &lt;quote&gt;some
-        quoted text&lt;/quote&gt;.
-      </p>
-      <p>
-        HTML is not supported, relative link targets are treated as
-        quicklinks and code blocks that start with "&gt;&gt;&gt;" are
-        highlighted as interactive python sessions.
-      </p>
-    </div>
-  </div>
-{% endblock %}

Deleted: /doctools/trunk/sphinx/templates/comments.html
==============================================================================
--- /doctools/trunk/sphinx/templates/comments.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,22 +0,0 @@
-  <div id="comments">
-    <h3>Comments</h3>
-    {% for comment in comments %}
-      <div class="comment" id="comment-{{ comment.comment_id }}">
-        <h4>{{ comment.title|e }}
-        {%- if comment.associated_name %} &mdash; on
-        <a href="#{{ comment.associated_name }}">{{-
-          comment.associated_name }}</a>{% endif %}</h4>
-        <div class="text">{{ comment.parsed_comment_body }}</div>
-        <div class="meta">by {{ comment.author|e }}, written on
-          {{ comment.pub_date|datetimeformat }} |
-          <a href="#comment-{{ comment.comment_id }}">#</a></div>
-      </div>
-    {% else %}
-      <div class="nocomments">
-        There are no user contributed notes for this page.
-      </div>
-    {% endfor %}
-    <div class="actions">
-      <a class="newcomment" href="{{ pathto(comment_url, 1)|e }}">add comment to page</a>
-    </div>
-  </div>

Deleted: /doctools/trunk/sphinx/templates/download.html
==============================================================================
--- /doctools/trunk/sphinx/templates/download.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,53 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Download' %}
-{% block body %}
-
-<h1>Download Python {{ release }} Documentation
-  {%- if last_updated %} (last updated on {{ last_updated }}){% endif %}</h1>
-
-<p>To download an archive containing all the documents for this version of
-Python in one of various formats, follow one of links in this table. The numbers
-in the table are the size of the download files in Kilobytes.</p>
-
-{# XXX download links, relative to download_base_url #}
-
-
-<p>These archives contain all the content in the documentation section.</p>
-
-<h2>Unpacking</h2>
-
-<p>Unix users should download the .tar.bz2 archives; these are bzipped tar
-archives and can be handled in the usual way using tar and the bzip2
-program. The <a href="http://www.info-zip.org">InfoZIP</a> unzip program can be
-used to handle the ZIP archives if desired. The .tar.bz2 archives provide the
-best compression and fastest download times.</p>
-
-<p>Windows users can use the ZIP archives since those are customary on that
-platform. These are created on Unix using the InfoZIP zip program. They may be
-unpacked using the free WiZ tool (from the InfoZIP developers) or any other
-tool for handling ZIP archives; any of them should work.</p>
-
-<p>Note that the .tar.bz2 files are smaller than the other archives; Windows
-users may want to install the bzip2 tools on their systems as well. Windows
-binaries for a command-line tool are available at <a
-href="http://www.bzip.org">The bzip2 and libbzip2 official home page</a>, but
-most other archiving utilities support the tar and bzip2 formats as well.</p>
-
-
-<h2>Problems</h2>
-
-<p><strong>Printing PDFs using Adobe Acrobat Reader 5.0:</strong> Adobe has
-reportedly admitted that there is a bug in Acrobat Reader 5.0 which causes it
-not to print at least some PDF files generated by pdfTeX. This software is used
-to produce the PDF version of the Python documentation, and our documents
-definately trigger this bug in Acrobat Reader. To print the PDF files, use
-Acrobat Reader 4.x, ghostscript, or xpdf.</p>
-
-<p>Reportedly, Acrobat Reader 6.0 can print these documents without this
-problem, but we've not yet had an opportunity to confirm the report. Sadly,
-version 6.0 is not yet available on Unix platforms.</p>
-
-<p>If you have comments or suggestions for the Python documentation, please send
-email to <a href="docs at python.org">docs at python.org</a>.</p>
-
-{% endblock %}

Deleted: /doctools/trunk/sphinx/templates/edit.html
==============================================================================
--- /doctools/trunk/sphinx/templates/edit.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,53 +0,0 @@
-{% extends "layout.html" %}
-{% if rendered %}{% set title = "Suggest changes - Preview" %}
-{% else %}{% set title = "Suggest changes" %}{% endif %}
-{% block body %}
-{% if rendered %}
-  <h1>Preview</h1>
-  <div class="preview">
-    <div class="previewwrapper">
-      {{ rendered }}
-    </div>
-  </div>
-  {% if warnings %}
-  <h1>Warnings</h1>
-  <p>You must fix these warnings before you can submit your patch.</p>
-  <ul>
-    {% for warning in warnings %}
-    <li>{{ warning }}</li>
-    {% endfor %}
-  </ul>
-  {% endif %}
-{% endif %}
-  <h1 id="suggest-changes-for-this-page">Suggest changes for this page</h1>
-{% if not rendered %}
-  <p>Here you can edit the source of &#8220;{{ doctitle|striptags }}&#8221; and
-    submit the results as a patch to the Python documentation team.  If you want
-    to know more about reST, the markup language used, read
-    <a href="{{ pathto('documenting/index.rst') }}">Documenting Python</a>.</p>
-{% endif %}
-  <form action="{{ submiturl }}" method="post">
-    <div id="suggest-changes-box">
-      <textarea name="contents">{{ contents|e }}</textarea>
-      {# XXX: shortcuts to make the edit area larger/smaller #}
-      {% if form_error %}
-      <div class="error">{{ form_error|e }}</div>
-      {% endif %}
-      <dl>
-        <dt>Name:</dt>
-        <dd><input type="text" size="24" name="name" value="{{ author }}"></dd>
-        <dt>E-mail Address:</dt>
-        <dd><input type="text" size="24" name="email" value="{{ email }}"></dd>
-        <dt>Summary of the change:</dt>
-        <dd><input type="text" size="48" name="summary" value="{{ summary }}"></dd>
-      </dl>
-      <input type="text" name="homepage" size="12" id="homepage">
-      <div class="actions">
-        <input type="submit" value="Submit patch for review">
-        <input type="submit" name="preview" value="Preview changes">
-        <input type="reset" value="Reset form">
-        <input type="submit" name="cancel" value="Cancel">
-      </div>
-    </div>
-  </form>
-{% endblock %}

Modified: doctools/trunk/sphinx/templates/index.html
==============================================================================
--- doctools/trunk/sphinx/templates/index.html	(original)
+++ doctools/trunk/sphinx/templates/index.html	Wed Jan 16 21:27:25 2008
@@ -4,67 +4,27 @@
   (pathto('@rss/recent'), 'application/rss+xml', 'Recent Comments')
 ] %}
 {% block body %}
-  <h1>Python Documentation</h1>
+  <h1>{{ project }} Documentation</h1>
   <p>
-    Welcome! This is the documentation for Python
+    Welcome! This is the documentation for {{ project }}
     {{ release }}{% if last_updated %}, last updated {{ last_updated }}{% endif %}.
   </p>
-
-  <p><strong>Parts of the documentation:</strong></p>
-  <table class="contentstable" align="center"><tr>
-    <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version + ".rst") }}">What's new in Python {{ version }}?</a><br>
-         <span class="linkdescr">changes since previous major release</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/index.rst") }}">Tutorial</a><br>
-         <span class="linkdescr">start here</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("using/index.rst") }}">Using Python</a><br>
-         <span class="linkdescr">how to use Python on different platforms</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index.rst") }}">Language Reference</a><br>
-         <span class="linkdescr">describes syntax and language elements</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("library/index.rst") }}">Library Reference</a><br>
-         <span class="linkdescr">keep this under your pillow</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("howto/index.rst") }}">Python HOWTOs</a><br>
-         <span class="linkdescr">in-depth documents on specific topics</span></p>
-    </td><td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("extending/index.rst") }}">Extending and Embedding</a><br>
-         <span class="linkdescr">tutorial for C/C++ programmers</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("c-api/index.rst") }}">Python/C API</a><br>
-         <span class="linkdescr">reference for C/C++ programmers</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("install/index.rst") }}">Installing Python Modules</a><br>
-         <span class="linkdescr">information for installers &amp; sys-admins</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("distutils/index.rst") }}">Distributing Python Modules</a><br>
-         <span class="linkdescr">sharing modules with others</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("documenting/index.rst") }}">Documenting Python</a><br>
-         <span class="linkdescr">guide for documentation authors</span></p>
-    </td></tr>
-  </table>
-
+  {% if indextemplate %}
+  {{ rendertemplate(indextemplate) }}
+  {% else %}
   <p><strong>Indices and tables:</strong></p>
   <table class="contentstable" align="center"><tr>
     <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("modindex.rst") }}">Global Module Index</a><br>
-         <span class="linkdescr">quick access to all modules</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("genindex.rst") }}">General Index</a><br>
-         <span class="linkdescr">all functions, classes, terms</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("glossary.rst") }}">Glossary</a><br>
-         <span class="linkdescr">the most important terms explained</span></p>
-    </td><td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("search.rst") }}">Search page</a><br>
-         <span class="linkdescr">search this documentation</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("contents.rst") }}">Complete Table of Contents</a><br>
+      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br>
          <span class="linkdescr">lists all sections and subsections</span></p>
-    </td></tr>
-  </table>
-
-  <p><strong>Meta information:</strong></p>
-  <table class="contentstable" align="center"><tr>
-    <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("bugs.rst") }}">Reporting bugs</a></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("about.rst") }}">About the documentation</a></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br>
+         <span class="linkdescr">search this documentation</span></p>
     </td><td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("license.rst") }}">History and License of Python</a></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("copyright.rst") }}">Copyright</a></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("modindex") }}">Global Module Index</a><br>
+         <span class="linkdescr">quick access to all modules</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br>
+         <span class="linkdescr">all functions, classes, terms</span></p>
     </td></tr>
   </table>
-
+  {% endif %}
 {% endblock %}

Deleted: /doctools/trunk/sphinx/templates/inlinecomments.html
==============================================================================
--- /doctools/trunk/sphinx/templates/inlinecomments.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,36 +0,0 @@
-{# rendered for inline comments -#}
-<div class="inlinecomments">
-{%- if mode == 'bottom' %}
-  {%- if comments -%}
-    <a class="bubble" href="#comment-{{ comments[0].comment_id }}"><span>[Read Comments]</span></a>
-  {%- else -%}
-    <a class="bubble emptybubble" href="{{ pathto(comment_url, 1) }}?target={{ id }}"><span>[Write Comments]</span></a>
-  {%- endif %}
-{%- else %}
-  <div>
-    {%- if comments -%}
-      <a class="bubble" href="{{ pathto(comment_url, 1) }}?target={{ id
-        }}"><span>[</span>{{ comments|length }}<span> Comments]</span></a>
-    {%- else -%}
-      <a class="bubble emptybubble" href="{{ pathto(comment_url, 1)
-        }}?target={{ id }}"><span>[Write Comment]</span></a>
-    {%- endif -%}
-  </div>
-  {%- if comments %}
-  <div class="comments">
-    <h3>Comments</h3>
-    <div class="actions"><a href="{{ pathto(comment_url, 1) }}?target={{
-        id }}" onclick="Documentation.newCommentFromBox(this); return false">write new comment</a></div>
-    {%- for comment in comments %}
-    <div class="comment" id="comment-{{ comment.comment_id }}">
-      <h4>{{ comment.title|e }}</h4>
-      <div class="text">{{ comment.parsed_comment_body }}</div>
-      <div class="meta">by {{ comment.author|e }}, written on
-      {{ comment.pub_date|datetimeformat }} |
-      <a href="#comment-{{ comment.comment_id }}">#</a></div>
-    </div>
-    {%- endfor %}
-  </div>
-  {%- endif %}
-{%- endif %}
-</div>

Deleted: /doctools/trunk/sphinx/templates/keyword_not_found.html
==============================================================================
--- /doctools/trunk/sphinx/templates/keyword_not_found.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,31 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Keyword Not Found' %}
-{% block body %}
-  <h1 id="keyword-not-found">Keyword Not Found</h1>
-  <p>
-    The keyword <strong>{{ keyword|e }}</strong> is not directly associated with
-    a page. {% if close_matches %}A similarity search returned {{
-    close_matches|length }} items that are possible matches.
-    {% if good_matches_count %}{{ good_matches_count }} of them are really
-    good matches and emphasized.{% endif %}{% endif %}
-  </p>
-  {% if close_matches %}
-    <ul class="keywordmatches">
-    {% for item in close_matches %}
-      <li{% if item.good_match %} class="goodmatch"{% endif
-        %}><a href="{{ item.href }}">{{ item.title|e }}</a> ({{
-          item.type }}) {% if item.description
-      %} &mdash; {{ item.description|e }}{% endif %}</li>
-    {% endfor %}
-    </ul>
-  {% endif %}
-  <p>
-    If you want to search the entire Python documentation for the string
-    "{{ keyword|e }}", then <a href="{{ pathto('search.rst') }}?q={{ keyword|e
-    }}">use the search function</a>.
-  </p>
-  <p>
-    For a quick overview over all documented modules,
-    <a href="{{ pathto('library/index.rst') }}">click here</a>.
-  </p>
-{% endblock %}

Modified: doctools/trunk/sphinx/templates/layout.html
==============================================================================
--- doctools/trunk/sphinx/templates/layout.html	(original)
+++ doctools/trunk/sphinx/templates/layout.html	Wed Jan 16 21:27:25 2008
@@ -1,4 +1,4 @@
-{% if builder != 'htmlhelp' %}{% set titlesuffix = " &mdash; Python Documentation" %}{% endif -%}
+{% if builder != 'htmlhelp' %}{% set titlesuffix = " &mdash; " + project + " Documentation" %}{% endif -%}
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
 <html>
@@ -6,7 +6,7 @@
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>{{ title|striptags }}{{ titlesuffix }}</title>
     {%- if builder == 'web' %}
-    <link rel="stylesheet" href="{{ pathto('index.rst') }}?do=stylesheet{%
+    <link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
       if in_admin_panel %}&admin=yes{% endif %}" type="text/css">
     {%- for link, type, title in page_links %}
     <link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}">
@@ -26,12 +26,16 @@
     <script type="text/javascript" src="{{ pathto('style/interface.js', 1) }}"></script>
     <script type="text/javascript" src="{{ pathto('style/doctools.js', 1) }}"></script>
     {%- endif %}
-    <link rel="author" title="About these documents" href="{{ pathto('about.rst') }}">
-    <link rel="contents" title="Global table of contents" href="{{ pathto('contents.rst') }}">
-    <link rel="index" title="Global index" href="{{ pathto('genindex.rst') }}">
-    <link rel="search" title="Search" href="{{ pathto('search.rst') }}">
-    <link rel="copyright" title="Copyright" href="{{ pathto('copyright.rst') }}">
-    <link rel="top" title="Python Documentation" href="{{ pathto('index.rst') }}">
+    {%- if hasdoc('about') %}
+    <link rel="author" title="About these documents" href="{{ pathto('about') }}">
+    {%- endif %}
+    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
+    <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
+    <link rel="search" title="Search" href="{{ pathto('search') }}">
+    {%- if hasdoc('copyright') %}
+    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
+    {%- endif %}
+    <link rel="top" title="{{ project }} Documentation" href="{{ pathto('index') }}">
     {%- if parents %}
     <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
     {%- endif %}
@@ -48,8 +52,8 @@
     <div class="related">
       <h3>Navigation</h3>
       <ul>
-        <li class="right" style="margin-right: 10px"><a href="{{ pathto('genindex.rst') }}" title="General Index" accesskey="I">index</a></li>
-        <li class="right"><a href="{{ pathto('modindex.rst') }}" title="Global Module Index" accesskey="M">modules</a> |</li>
+        <li class="right" style="margin-right: 10px"><a href="{{ pathto('genindex') }}" title="General Index" accesskey="I">index</a></li>
+        <li class="right"><a href="{{ pathto('modindex') }}" title="Global Module Index" accesskey="M">modules</a> |</li>
         {%- if next %}
           <li class="right"><a href="{{ next.link|e }}" title="{{ next.title|striptags }}" accesskey="N">next</a> |</li>
         {%- endif %}
@@ -57,10 +61,10 @@
           <li class="right"><a href="{{ prev.link|e }}" title="{{ prev.title|striptags }}" accesskey="P">previous</a> |</li>
         {%- endif %}
         {%- if builder == 'web' %}
-          <li class="right"><a href="{{ pathto('settings.rst') }}"
+          <li class="right"><a href="{{ pathto('settings') }}"
                                title="Customize your viewing settings" accesskey="S">settings</a> |</li>
         {%- endif %}
-        <li><a href="{{ pathto('index.rst') }}">Python v{{ release }} Documentation</a> &raquo;</li>
+        <li><a href="{{ pathto('index') }}">{{ project }} v{{ release }} Documentation</a> &raquo;</li>
         {%- for parent in parents %}
           <li><a href="{{ parent.link|e }}" accesskey="U">{{ parent.title }}</a> &raquo;</li>
         {%- endfor %}
@@ -69,26 +73,72 @@
 {% endfilter %}
     <div class="document">
       <div class="documentwrapper">
-        {%- if builder != 'htmlhelp' %}
+      {%- if builder != 'htmlhelp' %}
         <div class="bodywrapper">
-        {%- endif %}
+      {%- endif %}
           <div class="body">
             {% block body %}{% endblock %}
           </div>
-        {%- if builder != 'htmlhelp' %}
+      {%- if builder != 'htmlhelp' %}
         </div>
-        {%- endif %}
+      {%- endif %}
       </div>
       {%- if builder != 'htmlhelp' %}
-      {%- include "sidebar.html" %}
+      <div class="sidebar">
+        <div class="sidebarwrapper">
+          {% if display_toc %}
+            <h3>Table Of Contents</h3>
+            {{ toc }}
+          {% endif %}
+          {%- if prev %}
+            <h4>Previous topic</h4>
+            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
+          {%- endif %}
+          {%- if next %}
+            <h4>Next topic</h4>
+            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
+          {%- endif %}
+          {% if sourcename %}
+            <h3>This Page</h3>
+            <ul class="this-page-menu">
+            {% if builder == 'web' %}
+              <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
+              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
+              <li><a href="{{ pathto('@source/' + sourcename)|e }}">Show Source</a></li>
+            {% elif builder == 'html' %}
+              <li><a href="{{ pathto(sourcename, true)|e }}">Show Source</a></li>
+            {% endif %}
+            </ul>
+          {% endif %}
+          {% if customsidebar %}
+          {{ rendertemplate(customsidebar) }}
+          {% endif %}
+          {% if current_page_name != "search" %}
+            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
+            <form class="search" action="{{ pathto('search') }}" method="get">
+              <input type="text" name="q" size="18"> <input type="submit" value="Go">
+              <input type="hidden" name="check_keywords" value="yes">
+              <input type="hidden" name="area" value="default">
+            </form>
+            {% if builder == 'web' %}
+            <p style="font-size: 90%">Enter a module, class or function name.</p>
+            {% endif %}
+          {% endif %}
+        </div>
+      </div>
       {%- endif %}
       <div class="clearer"></div>
     </div>
 {{ relbar }}
     <div class="footer">
-      &copy; <a href="{{ pathto('copyright.rst') }}">Copyright</a>
-      1990-2007, Python Software Foundation.
-      {% if last_updated %}Last updated on {{ last_updated }}.{% endif %}
+    {%- if hasdoc('copyright') %}
+      &copy; <a href="{{ pathto('copyright') }}">Copyright</a> {{ copyright }}.
+    {%- else %}
+      &copy; Copyright {{ copyright }}.
+    {%- endif %}
+    {%- if last_updated %}
+      Last updated on {{ last_updated }}.
+    {%- endif %}
     </div>
   </body>
 </html>

Deleted: /doctools/trunk/sphinx/templates/not_found.html
==============================================================================
--- /doctools/trunk/sphinx/templates/not_found.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,11 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Page Not Found' %}
-{% block body %}
-  <h1 id="page-not-found">Page Not Found</h1>
-  <p>
-    The page {{ req.path|e }} does not exist on this server.
-  </p>
-  <p>
-    Click here to <a href="{{ pathto('index.rst') }}">return to the index</a>.
-  </p>
-{% endblock %}

Deleted: /doctools/trunk/sphinx/templates/rstsource.html
==============================================================================
--- /doctools/trunk/sphinx/templates/rstsource.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,15 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-  "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-  <head>
-    <title>{{ filename }} &mdash; Python Documentation</title>
-    <style type="text/css">
-      .hl { background-color: yellow }
-    </style>
-  </head>
-  <body style="font-size: 90%">
-    <pre>
-      {{ text }}
-    </pre>
-  </body>
-</html>
\ No newline at end of file

Modified: doctools/trunk/sphinx/templates/search.html
==============================================================================
--- doctools/trunk/sphinx/templates/search.html	(original)
+++ doctools/trunk/sphinx/templates/search.html	Wed Jan 16 21:27:25 2008
@@ -6,39 +6,14 @@
 {% block body %}
   <h1 id="search-documentation">Search Documentation</h1>
   <p>
-    From here you can search the Python documentation. Enter your search
+    From here you can search the {{ project }} documentation. Enter your search
     words into the box below and click "search". Note that the search
     function will automatically search for all of the words. Pages
     containing less words won't appear in the result list.
   </p>
-  <p>
-    In order to speed up the results you can limit your search by
-    excluding some of the sections listed below.
-  </p>
   <form action="" method="get">
     <input type="text" name="q" value="">
     <input type="submit" value="search">
-    <p>
-      Sections:
-    </p>
-    <ul class="fakelist">
-    {% for id, name, checked in [
-      ('tutorial', 'Python Tutorial', true),
-      ('library', 'Library Reference', true),
-      ('using', 'Using Python', true),
-      ('reference', 'Language Reference', false),
-      ('extending', 'Extending and Embedding', false),
-      ('c-api', 'Python/C API', false),
-      ('install', 'Installing Python Modules', true),
-      ('distutils', 'Distributing Python Modules', true),
-      ('documenting', 'Documenting Python', false),
-      ('whatsnew', 'What\'s new in Python?', false),
-    ] -%}
-      <li><input type="checkbox" name="area" id="area-{{ id }}" value="{{ id
-          }}"{% if checked %} checked{% endif %}>
-          <label for="area-{{ id }}">{{ name }}</label></li>
-    {% endfor %}
-    </ul>
   </form>
   {% if search_performed %}
     <h2>Search Results</h2>

Deleted: /doctools/trunk/sphinx/templates/settings.html
==============================================================================
--- /doctools/trunk/sphinx/templates/settings.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,37 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Settings' %}
-{% set current_page_name = 'settings' %}
-{% block body %}
-  <h1>Python Documentation Settings</h1>
-  <p>
-    Here you can customize how you want to view the Python documentation.
-    These settings are saved using a cookie on your computer.
-  </p>
-
-  <form action="{{ pathto('settings.rst') }}" method="post">
-    <p class="subhead">Select your stylesheet:</p>
-    <p>
-      {%- for design, (foo, descr) in known_designs %}
-      <input type="radio" name="design" value="{{ design }}" id="stylesheet-{{ design }}"
-             {% if curdesign == design %}checked="checked"{% endif %}>
-        <label for="stylesheet-{{ design }}">{{ design }} &mdash; {{ descr }}</label><br>
-      {%- endfor %}
-    </p>
-
-    <p class="subhead">Select how you want to view comments:</p>
-    <p>
-      {%- for meth, descr in comments_methods %}
-      <input type="radio" name="comments" value="{{ meth }}" id="comments-{{ meth }}"
-             {% if curcomments == meth %}checked="checked"{% endif %}>
-        <label for="comments-{{ meth }}">{{ descr }}</label><br>
-      {%- endfor %}
-    </p>
-    <input type="hidden" name="referer" value="{{ referer|e}}">
-    <p>
-      <input type="submit" name="goback" value="Save and back to last page">&nbsp;&nbsp;
-      <input type="submit" value="Save">&nbsp;&nbsp;
-      <input type="submit" name="cancel" value="Cancel and back to last page">&nbsp;&nbsp;
-    </p>
-  </form>
-
-{% endblock %}

Deleted: /doctools/trunk/sphinx/templates/show_source.html
==============================================================================
--- /doctools/trunk/sphinx/templates/show_source.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,6 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Page Source' %}
-{% block body %}
-  <h1 id="page-source">Page Source</h1>
-  {{ highlighted_code }}
-{% endblock %}

Deleted: /doctools/trunk/sphinx/templates/sidebar.html
==============================================================================
--- /doctools/trunk/sphinx/templates/sidebar.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,62 +0,0 @@
-{# this file is included by layout.html #}
-      <div class="sidebar">
-        <div class="sidebarwrapper">
-          {% if display_toc %}
-            <h3>Table Of Contents</h3>
-            {{ toc }}
-          {% endif %}
-          {%- if prev %}
-            <h4>Previous topic</h4>
-            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
-          {%- endif %}
-          {%- if next %}
-            <h4>Next topic</h4>
-            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
-          {%- endif %}
-          {% if sourcename %}
-            <h3>This Page</h3>
-            <ul class="this-page-menu">
-              {% if builder == 'web' %}
-                <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
-                <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
-                <li><a href="{{ pathto('@source/' + sourcename)|e }}">Show Source</a></li>
-              {% elif builder == 'html' %}
-                <li><a href="{{ pathto(sourcename, true)|e }}">Show Source</a></li>
-              {% endif %}
-              {# <li><a href="http://bugs.python.org/XXX?page={{ sourcename|e }}">Report Bug</a></li> #}
-            </ul>
-          {% endif %}
-          {% if current_page_name == "index" %}
-            <h3>Download</h3>
-            <p><a href="{{ pathto('download.rst')|e }}">Download these documents</a></p>
-            <h3>Other resources</h3>
-            <ul>
-              {# XXX: many of these should probably be merged in the main docs #}
-              <li><a href="http://www.python.org/doc/faq/">FAQs</a></li>
-              <li><a href="http://www.python.org/doc/intros/">Introductions</a></li>
-              <li><a href="http://www.python.org/doc/essays/">Guido's Essays</a></li>
-              <li><a href="http://www.python.org/doc/newstyle/">New-style Classes</a></li>
-              <li><a href="http://www.python.org/dev/peps/">PEP Index</a></li>
-              <li><a href="http://wiki.python.org/moin/BeginnersGuide">Beginner's Guide</a></li>
-              <li><a href="http://www.python.org/topics/">Topic Guides</a></li>
-              <li><a href="http://wiki.python.org/moin/PythonBooks">Book List</a></li>
-              <li><a href="http://www.python.org/doc/av/">Audio/Visual Talks</a></li>
-              <li><a href="http://www.python.org/doc/other/">Other Doc Collections</a></li>
-              <li>&nbsp;</li>
-              <li><a href="http://www.python.org/doc/versions/">Previous versions</a></li>
-              <li>&nbsp;</li>
-            </ul>
-          {% endif %}
-          {% if current_page_name != "search" %}
-            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
-            <form class="search" action="{{ pathto('search.rst') }}" method="get">
-              <input type="text" name="q" size="18"> <input type="submit" value="Go">
-              <input type="hidden" name="check_keywords" value="yes">
-              <input type="hidden" name="area" value="default">
-            </form>
-            {% if builder == 'web' %}
-            <p style="font-size: 90%">Enter a module, class or function name.</p>
-            {% endif %}
-          {% endif %}
-        </div>
-      </div>

Deleted: /doctools/trunk/sphinx/templates/submitted.html
==============================================================================
--- /doctools/trunk/sphinx/templates/submitted.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,12 +0,0 @@
-{% extends "layout.html" %}
-{% set title = "Patch submitted" %}
-{% block head %}
-<meta http-equiv="refresh" content="2; URL={{ backlink|e }}">
-{% endblock %}
-{% block body %}
-<h1>Patch submitted</h1>
-<p>Your patch has been submitted to the Python documentation team and will be
-  processed shortly.</p>
-<p>You will be redirected to the
- <a href="{{ backlink|e }}">original documentation page</a> shortly.</p>
-{% endblock %}
\ No newline at end of file

Deleted: /doctools/trunk/sphinx/templates/versionchanges.html
==============================================================================
--- /doctools/trunk/sphinx/templates/versionchanges.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,33 +0,0 @@
-{% macro entries changes %}
-<ul>{% for entry, filename, lineno in changes %}
-<li><a href="rst/{{ filename }}.html#L{{ lineno-10 }}" target="src">{{ entry }}</a></li>
-{% endfor %}</ul>
-{% endmacro -%}
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-  "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-  <head>
-    <link rel="stylesheet" href="default.css">
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>Changes in Version {{ version }} &mdash; Python Documentation</title>
-  </head>
-  <body>
-    <div class="document">
-      <div class="body">
-    <h1>Automatically generated list of changes in version {{ version }}</h1>
-    <h2>Library changes</h2>
-    {% for modname, changes in libchanges %}
-    <h4>{{ modname }}</h4>
-    {{ entries(changes) }}
-    {% endfor %}
-    <h2>C API changes</h2>
-    {{ entries(apichanges) }}
-    <h2>Other changes</h2>
-    {% for (fn, title), changes in otherchanges %}
-    <h4>{{ title }} <span style="font-size: 50%">({{ fn }})</span></h4>
-    {{ entries(changes) }}
-    {% endfor %}
-      </div>
-    </div>
-  </body>
-</html>
\ No newline at end of file

Deleted: /doctools/trunk/sphinx/templates/versionchanges_frameset.html
==============================================================================
--- /doctools/trunk/sphinx/templates/versionchanges_frameset.html	Wed Jan 16 21:27:25 2008
+++ (empty file)
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
-  "http://www.w3.org/TR/html4/frameset.dtd">
-<html>
-  <head>
-    <title>Changes in Version {{ version }} &mdash; Python Documentation</title>
-  </head>
-  <frameset cols="45%,*">
-    <frame name="main" src="changes.html">
-    <frame name="src" src="about:blank">
-  </frameset>
-</html>
\ No newline at end of file

Modified: doctools/trunk/sphinx/templates/web/admin/moderate_comments.html
==============================================================================
--- doctools/trunk/sphinx/templates/admin/moderate_comments.html	(original)
+++ doctools/trunk/sphinx/templates/web/admin/moderate_comments.html	Wed Jan 16 21:27:25 2008
@@ -3,7 +3,7 @@
   <h1>Moderate Comments</h1>
   <p>
     From here you can delete and edit comments. If you want to be
-    informed about new comments you can use the <a href="{{ pathto('index.rst')
+    informed about new comments you can use the <a href="{{ pathto('index')
     }}?feed=recent_comments">feed</a> provided.
   </p>
   <form action="" method="post">
@@ -71,7 +71,7 @@
           <th colspan="4" class="recent_comments">
             <a href="{{ pathto('@admin/moderate_comments/recent_comments/', true)
               }}">Recent Comments</a>
-            <span class="meta">(<a href="{{ pathto('index.rst')
+            <span class="meta">(<a href="{{ pathto('index')
               }}?feed=recent_comments">feed</a>)</span>
           </th>
         </tr>

Copied: doctools/trunk/sphinx/templates/web/commentform.html (from r57711, doctools/trunk/sphinx/templates/commentform.html)
==============================================================================
--- doctools/trunk/sphinx/templates/commentform.html	(original)
+++ doctools/trunk/sphinx/templates/web/commentform.html	Wed Jan 16 21:27:25 2008
@@ -19,7 +19,7 @@
       <p>
         HTML is not supported, relative link targets are treated as
         quicklinks and code blocks that start with "&gt;&gt;&gt;" are
-        highlighted as interactive python sessions.
+        highlighted as interactive Python sessions.
       </p>
     </div>
   </div>

Copied: doctools/trunk/sphinx/templates/web/edit.html (from r57711, doctools/trunk/sphinx/templates/edit.html)
==============================================================================
--- doctools/trunk/sphinx/templates/edit.html	(original)
+++ doctools/trunk/sphinx/templates/web/edit.html	Wed Jan 16 21:27:25 2008
@@ -22,9 +22,10 @@
   <h1 id="suggest-changes-for-this-page">Suggest changes for this page</h1>
 {% if not rendered %}
   <p>Here you can edit the source of &#8220;{{ doctitle|striptags }}&#8221; and
-    submit the results as a patch to the Python documentation team.  If you want
-    to know more about reST, the markup language used, read
-    <a href="{{ pathto('documenting/index.rst') }}">Documenting Python</a>.</p>
+    submit the results as a patch to the {{ project }} documentation team.
+    {# XXX Python specific #}
+    If you want to know more about reST, the markup language used, read
+    <a href="{{ pathto('documenting/index') }}">Documenting Python</a>.</p>
 {% endif %}
   <form action="{{ submiturl }}" method="post">
     <div id="suggest-changes-box">

Copied: doctools/trunk/sphinx/templates/web/keyword_not_found.html (from r57711, doctools/trunk/sphinx/templates/keyword_not_found.html)
==============================================================================
--- doctools/trunk/sphinx/templates/keyword_not_found.html	(original)
+++ doctools/trunk/sphinx/templates/web/keyword_not_found.html	Wed Jan 16 21:27:25 2008
@@ -20,12 +20,12 @@
     </ul>
   {% endif %}
   <p>
-    If you want to search the entire Python documentation for the string
-    "{{ keyword|e }}", then <a href="{{ pathto('search.rst') }}?q={{ keyword|e
+    If you want to search the entire {{ project }} documentation for the string
+    "{{ keyword|e }}", then <a href="{{ pathto('search') }}?q={{ keyword|e
     }}">use the search function</a>.
   </p>
   <p>
     For a quick overview over all documented modules,
-    <a href="{{ pathto('library/index.rst') }}">click here</a>.
+    <a href="{{ pathto('modindex') }}">click here</a>.
   </p>
 {% endblock %}

Copied: doctools/trunk/sphinx/templates/web/not_found.html (from r57711, doctools/trunk/sphinx/templates/not_found.html)
==============================================================================
--- doctools/trunk/sphinx/templates/not_found.html	(original)
+++ doctools/trunk/sphinx/templates/web/not_found.html	Wed Jan 16 21:27:25 2008
@@ -6,6 +6,6 @@
     The page {{ req.path|e }} does not exist on this server.
   </p>
   <p>
-    Click here to <a href="{{ pathto('index.rst') }}">return to the index</a>.
+    Click here to <a href="{{ pathto('index') }}">return to the index</a>.
   </p>
 {% endblock %}

Copied: doctools/trunk/sphinx/templates/web/settings.html (from r57711, doctools/trunk/sphinx/templates/settings.html)
==============================================================================
--- doctools/trunk/sphinx/templates/settings.html	(original)
+++ doctools/trunk/sphinx/templates/web/settings.html	Wed Jan 16 21:27:25 2008
@@ -2,13 +2,13 @@
 {% set title = 'Settings' %}
 {% set current_page_name = 'settings' %}
 {% block body %}
-  <h1>Python Documentation Settings</h1>
+  <h1>{{ project }} Documentation Settings</h1>
   <p>
-    Here you can customize how you want to view the Python documentation.
+    Here you can customize how you want to view the {{ project }} documentation.
     These settings are saved using a cookie on your computer.
   </p>
 
-  <form action="{{ pathto('settings.rst') }}" method="post">
+  <form action="{{ pathto('settings') }}" method="post">
     <p class="subhead">Select your stylesheet:</p>
     <p>
       {%- for design, (foo, descr) in known_designs %}

Copied: doctools/trunk/sphinx/templates/web/submitted.html (from r57711, doctools/trunk/sphinx/templates/submitted.html)
==============================================================================
--- doctools/trunk/sphinx/templates/submitted.html	(original)
+++ doctools/trunk/sphinx/templates/web/submitted.html	Wed Jan 16 21:27:25 2008
@@ -5,7 +5,7 @@
 {% endblock %}
 {% block body %}
 <h1>Patch submitted</h1>
-<p>Your patch has been submitted to the Python documentation team and will be
+<p>Your patch has been submitted to the {{ project }} documentation team and will be
   processed shortly.</p>
 <p>You will be redirected to the
  <a href="{{ backlink|e }}">original documentation page</a> shortly.</p>

Modified: doctools/trunk/sphinx/util/__init__.py
==============================================================================
--- doctools/trunk/sphinx/util/__init__.py	(original)
+++ doctools/trunk/sphinx/util/__init__.py	Wed Jan 16 21:27:25 2008
@@ -77,14 +77,6 @@
             yield canonical_path(qualified_name)
 
 
-def get_category(filename):
-    """Get the "category" part of a RST filename."""
-    parts = filename.split(SEP, 1)
-    if len(parts) < 2:
-        return
-    return parts[0]
-
-
 def shorten_result(text='', keywords=[], maxlen=240, fuzz=60):
     if not text:
         text = ''

Modified: doctools/trunk/sphinx/util/stemmer.py
==============================================================================
--- doctools/trunk/sphinx/util/stemmer.py	(original)
+++ doctools/trunk/sphinx/util/stemmer.py	Wed Jan 16 21:27:25 2008
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 """
     sphinx.util.stemmer

Modified: doctools/trunk/sphinx/web/admin.py
==============================================================================
--- doctools/trunk/sphinx/web/admin.py	(original)
+++ doctools/trunk/sphinx/web/admin.py	Wed Jan 16 21:27:25 2008
@@ -9,9 +9,9 @@
     :license: BSD.
 """
 
-from .util import render_template
-from .wsgiutil import Response, RedirectResponse, NotFound
-from .database import Comment
+from sphinx.web.util import render_template
+from sphinx.web.wsgiutil import Response, RedirectResponse, NotFound
+from sphinx.web.database import Comment
 
 
 class AdminPanel(object):

Modified: doctools/trunk/sphinx/web/antispam.py
==============================================================================
--- doctools/trunk/sphinx/web/antispam.py	(original)
+++ doctools/trunk/sphinx/web/antispam.py	Wed Jan 16 21:27:25 2008
@@ -9,7 +9,7 @@
     :copyright: 2007-2008 by Armin Ronacher.
     :license: BSD.
 """
-from __future__ import with_statement
+
 import re
 import urllib
 import time
@@ -43,14 +43,20 @@
             else:
                 lines = [l.strip() for l in data.splitlines()
                               if not l.startswith('#')]
-                with file(bad_content_file, 'w') as f:
+                f = open(bad_content_file, 'w')
+                try:
                     f.write('\n'.join(lines))
+                finally:
+                    f.close()
                 last_change = int(time.time())
 
         if lines is None:
             try:
-                with file(bad_content_file) as f:
+                f = open(bad_content_file)
+                try:
                     lines = [l.strip() for l in f]
+                finally:
+                    f.close()
             except:
                 lines = []
         self.rules = [re.compile(rule) for rule in lines if rule]

Modified: doctools/trunk/sphinx/web/application.py
==============================================================================
--- doctools/trunk/sphinx/web/application.py	(original)
+++ doctools/trunk/sphinx/web/application.py	Wed Jan 16 21:27:25 2008
@@ -9,7 +9,6 @@
     :copyright: 2007-2008 by Georg Brandl, Armin Ronacher.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import os
 import re
@@ -24,24 +23,23 @@
 import cStringIO as StringIO
 from os import path
 from itertools import groupby
-from collections import defaultdict
 
-from .feed import Feed
-from .mail import Email
-from .util import render_template, get_target_uri, blackhole_dict, striptags
-from .admin import AdminPanel
-from .userdb import UserDatabase
-from .robots import robots_txt
-from .oldurls import handle_html_url
-from .antispam import AntiSpam
-from .database import connect, set_connection, Comment
-from .wsgiutil import Request, Response, RedirectResponse, \
+from sphinx.web.feed import Feed
+from sphinx.web.mail import Email
+from sphinx.web.util import render_template, get_target_uri, blackhole_dict, striptags
+from sphinx.web.admin import AdminPanel
+from sphinx.web.userdb import UserDatabase
+from sphinx.web.robots import robots_txt
+from sphinx.web.oldurls import handle_html_url
+from sphinx.web.antispam import AntiSpam
+from sphinx.web.database import connect, set_connection, Comment
+from sphinx.web.wsgiutil import Request, Response, RedirectResponse, \
      JSONResponse, SharedDataMiddleware, NotFound, get_base_uri
 
-from ..util import relative_uri
-from ..search import SearchFrontend
-from ..htmlwriter import HTMLWriter
-from ..builder import LAST_BUILD_FILENAME, ENV_PICKLE_FILENAME
+from sphinx.util import relative_uri
+from sphinx.search import SearchFrontend
+from sphinx.htmlwriter import HTMLWriter
+from sphinx.builder import LAST_BUILD_FILENAME, ENV_PICKLE_FILENAME
 
 from docutils.io import StringOutput
 from docutils.utils import Reporter
@@ -123,8 +121,11 @@
     """
 
     def __init__(self, config):
-        self.cache = blackhole_dict() if config['debug'] else {}
-        self.freqmodules = defaultdict(int)
+        if config['debug']:
+            self.cache = blackhole_dict()
+        else:
+            self.cache = {}
+        self.freqmodules = {}
         self.last_most_frequent = []
         self.generated_stylesheets = {}
         self.config = config
@@ -139,19 +140,31 @@
 
 
     def load_env(self, new_mtime):
-        with env_lock:
+        env_lock.acquire()
+        try:
             if self.buildmtime == new_mtime:
                 # happens if another thread already reloaded the env
                 return
             print "* Loading the environment..."
-            with file(path.join(self.data_root, ENV_PICKLE_FILENAME), 'rb') as f:
+            f = open(path.join(self.data_root, ENV_PICKLE_FILENAME), 'rb')
+            try:
                 self.env = pickle.load(f)
-            with file(path.join(self.data_root, 'globalcontext.pickle'), 'rb') as f:
+            finally:
+                f.close()
+            f = open(path.join(self.data_root, 'globalcontext.pickle'), 'rb')
+            try:
                 self.globalcontext = pickle.load(f)
-            with file(path.join(self.data_root, 'searchindex.pickle'), 'rb') as f:
+            finally:
+                f.close()
+            f = open(path.join(self.data_root, 'searchindex.pickle'), 'rb')
+            try:
                 self.search_frontend = SearchFrontend(pickle.load(f))
+            finally:
+                f.close()
             self.buildmtime = new_mtime
             self.cache.clear()
+        finally:
+            env_lock.release()
 
 
     def search(self, req):
@@ -167,12 +180,15 @@
         """
         Get the reST source of a page.
         """
-        page_id = self.env.get_real_filename(page)
+        page_id = self.env.get_real_filename(page)[:-4]
         if page_id is None:
             raise NotFound()
-        filename = path.join(self.data_root, 'sources', page_id)[:-3] + 'txt'
-        with file(filename) as f:
+        filename = path.join(self.data_root, 'sources', page_id) + '.txt'
+        f = open(filename)
+        try:
             return page_id, f.read()
+        finally:
+            f.close()
 
 
     def show_source(self, req, page):
@@ -191,7 +207,7 @@
         return Response(render_template(req, 'edit.html', self.globalcontext, dict(
             contents=contents,
             pagename=page,
-            doctitle=self.globalcontext['titles'].get(page_id) or 'this page',
+            doctitle=self.globalcontext['titles'].get(page_id+'.rst') or 'this page',
             submiturl=relative_uri('/@edit/'+page+'/', '/@submit/'+page),
         )))
 
@@ -209,11 +225,11 @@
         builder = MockBuilder()
         builder.config = env2.config
         writer = HTMLWriter(builder)
-        doctree = env2.read_file(page_id, pathname, save_parsed=False)
-        doctree = env2.get_and_resolve_doctree(page_id, builder, doctree)
+        doctree = env2.read_file(page_id+'.rst', pathname, save_parsed=False)
+        doctree = env2.get_and_resolve_doctree(page_id+'.rst', builder, doctree)
         doctree.settings = OptionParser(defaults=env2.settings,
                                         components=(writer,)).get_default_values()
-        doctree.reporter = Reporter(page_id, 2, 4, stream=warning_stream)
+        doctree.reporter = Reporter(page_id+'.rst', 2, 4, stream=warning_stream)
         output = writer.write(doctree, destination)
         writer.assemble_parts()
         return writer.parts['fragment']
@@ -302,7 +318,7 @@
                 referer = ''
             else:
                 referer = referer[len(base):]
-                referer = referer.rpartition('?')[0] or referer
+                referer = referer.split('?')[0] or referer
 
         if req.method == 'POST':
             if req.form.get('cancel'):
@@ -362,8 +378,11 @@
             yield '@modindex'
 
         filename = path.join(self.data_root, 'modindex.fpickle')
-        with open(filename, 'rb') as f:
+        f = open(filename, 'rb')
+        try:
             context = pickle.load(f)
+        finally:
+            f.close()
         if showpf:
             entries = context['modindexentries']
             i = 0
@@ -386,7 +405,7 @@
         """
         Show the "new comment" form.
         """
-        page_id = self.env.get_real_filename(page)
+        page_id = self.env.get_real_filename(page)[:-4]
         ajax_mode = req.args.get('mode') == 'ajax'
         target = req.args.get('target')
         page_comment_mode = not target
@@ -466,7 +485,7 @@
             return
 
         comment_url = '@comments/%s/' % url
-        page_id = self.env.get_real_filename(url)
+        page_id = self.env.get_real_filename(url)[:-4]
         tx = context['body']
         all_comments = Comment.get_for_page(page_id)
         global_comments = []
@@ -509,17 +528,17 @@
         Show the requested documentation page or raise an
         `NotFound` exception to display a page with close matches.
         """
-        page_id = self.env.get_real_filename(url)
+        page_id = self.env.get_real_filename(url)[:-4]
         if page_id is None:
             raise NotFound(show_keyword_matches=True)
         # increment view count of all modules on that page
-        for modname in self.env.filemodules.get(page_id, ()):
-            self.freqmodules[modname] += 1
+        for modname in self.env.filemodules.get(page_id+'.rst', ()):
+            self.freqmodules[modname] = self.freqmodules.get(modname, 0) + 1
         # comments enabled?
-        comments = self.env.metadata[page_id].get('nocomments', False)
+        comments = self.env.metadata[page_id+'.rst'].get('nocomments', False)
 
         # how does the user want to view comments?
-        commentmode = req.session.get('comments', 'inline') if comments else ''
+        commentmode = comments and req.session.get('comments', 'inline') or ''
 
         # show "old URL" message? -> no caching possible
         oldurl = req.args.get('oldurl')
@@ -530,9 +549,12 @@
             yield page_id + '|' + commentmode
 
         # cache miss; load the page and render it
-        filename = path.join(self.data_root, page_id[:-3] + 'fpickle')
-        with open(filename, 'rb') as f:
+        filename = path.join(self.data_root, page_id + '.fpickle')
+        f = open(filename, 'rb')
+        try:
             context = pickle.load(f)
+        finally:
+            f.close()
 
         # add comments to paqe text
         if commentmode != 'none':
@@ -546,8 +568,11 @@
     def get_special_page(self, req, name):
         yield '@'+name
         filename = path.join(self.data_root, name + '.fpickle')
-        with open(filename, 'rb') as f:
+        f = open(filename, 'rb')
+        try:
             context = pickle.load(f)
+        finally:
+            f.close()
         yield render_template(req, name+'.html',
                               self.globalcontext, context)
 
@@ -559,8 +584,8 @@
                 feed.add_item(comment.title, comment.author, comment.url,
                               comment.parsed_comment_body, comment.pub_date)
         else:
-            page_id = self.env.get_real_filename(url)
-            doctitle = striptags(self.globalcontext['titles'].get(page_id, url))
+            page_id = self.env.get_real_filename(url)[:-4]
+            doctitle = striptags(self.globalcontext['titles'].get(page_id+'.rst', url))
             feed = Feed(req, 'Comments for "%s"' % doctitle,
                         'List of comments for the topic "%s"' % doctitle, url)
             for comment in Comment.get_for_page(page_id):
@@ -632,7 +657,7 @@
                 'close_matches':        close_matches,
                 'good_matches_count':   good_matches,
                 'keyword':              term
-            }, self.globalcontext), status=404 if is_error_page else 404)
+            }, self.globalcontext), status=404)
 
 
     def get_user_stylesheet(self, req):
@@ -650,15 +675,21 @@
         else:
             stylesheet = []
             for filename in known_designs[style][0]:
-                with file(path.join(self.data_root, 'style', filename)) as f:
+                f = open(path.join(self.data_root, 'style', filename))
+                try:
                     stylesheet.append(f.read())
+                finally:
+                    f.close()
             stylesheet = '\n'.join(stylesheet)
             if not self.config.get('debug'):
                 self.generated_stylesheets[style] = stylesheet
 
         if req.args.get('admin') == 'yes':
-            with file(path.join(self.data_root, 'style', 'admin.css')) as f:
+            f = open(path.join(self.data_root, 'style', 'admin.css'))
+            try:
                 stylesheet += '\n' + f.read()
+            finally:
+                f.close()
 
         # XXX: add timestamp based http caching
         return Response(stylesheet, mimetype='text/css')

Modified: doctools/trunk/sphinx/web/database.py
==============================================================================
--- doctools/trunk/sphinx/web/database.py	(original)
+++ doctools/trunk/sphinx/web/database.py	Wed Jan 16 21:27:25 2008
@@ -17,7 +17,7 @@
 from datetime import datetime
 from threading import local
 
-from .markup import markup
+from sphinx.web.markup import markup
 
 
 _thread_local = local()
@@ -88,14 +88,14 @@
     @property
     def url(self):
         return '%s#comment-%s' % (
-            self.associated_page[:-4],
+            self.associated_page,
             self.comment_id
         )
 
     @property
     def parsed_comment_body(self):
-        from .util import get_target_uri
-        from ..util import relative_uri
+        from sphinx.web.util import get_target_uri
+        from sphinx.util import relative_uri
         uri = get_target_uri(self.associated_page)
         def make_rel_link(keyword):
             return relative_uri(uri, 'q/%s/' % keyword)
@@ -153,7 +153,7 @@
         cur = get_cursor()
         cur.execute('''select * from comments where associated_page = ?
                     order by associated_name, comment_id %s''' %
-                     ('desc' if reverse else 'asc'),
+                     (reverse and 'desc' or 'asc'),
                     (associated_page,))
         try:
             return [Comment._make_comment(row) for row in cur]

Modified: doctools/trunk/sphinx/web/markup.py
==============================================================================
--- doctools/trunk/sphinx/web/markup.py	(original)
+++ doctools/trunk/sphinx/web/markup.py	Wed Jan 16 21:27:25 2008
@@ -42,7 +42,7 @@
 import re
 from urlparse import urlparse
 
-from ..highlighting import highlight_block
+from sphinx.highlighting import highlight_block
 
 
 inline_formatting = {
@@ -212,7 +212,7 @@
                 elif protocol == 'javascript':
                     href = href[11:]
                 paragraph.append('<a href="%s"%s>%s</a>' % (cgi.escape(href),
-                                 ' rel="nofollow"' if nofollow else '',
+                                 nofollow and ' rel="nofollow"' or '',
                                  cgi.escape(caption)))
             elif token == 'code_block':
                 result.append(highlight_block(data, 'python'))

Modified: doctools/trunk/sphinx/web/oldurls.py
==============================================================================
--- doctools/trunk/sphinx/web/oldurls.py	(original)
+++ doctools/trunk/sphinx/web/oldurls.py	Wed Jan 16 21:27:25 2008
@@ -11,7 +11,7 @@
 
 import re
 
-from .wsgiutil import RedirectResponse, NotFound
+from sphinx.web.wsgiutil import RedirectResponse, NotFound
 
 
 _module_re = re.compile(r'module-(.*)\.html')
@@ -78,7 +78,7 @@
         # tutorial
         elif url[:4] == 'tut/':
             try:
-                node = int(url[8:].partition('.html')[0])
+                node = int(url[8:].split('.html')[0])
             except ValueError:
                 pass
             else:

Modified: doctools/trunk/sphinx/web/serve.py
==============================================================================
--- doctools/trunk/sphinx/web/serve.py	(original)
+++ doctools/trunk/sphinx/web/serve.py	Wed Jan 16 21:27:25 2008
@@ -63,7 +63,7 @@
 
 def run_with_reloader(main_func, extra_watch):
     """
-    Run the given function in an independent python interpreter.
+    Run the given function in an independent Python interpreter.
     """
     if os.environ.get('RUN_MAIN') == 'true':
         thread.start_new_thread(main_func, ())

Modified: doctools/trunk/sphinx/web/userdb.py
==============================================================================
--- doctools/trunk/sphinx/web/userdb.py	(original)
+++ doctools/trunk/sphinx/web/userdb.py	Wed Jan 16 21:27:25 2008
@@ -10,11 +10,10 @@
     :copyright: 2007-2008 by Armin Ronacher.
     :license: BSD.
 """
-from __future__ import with_statement
+
 from os import path
 from hashlib import sha1
 from random import choice, randrange
-from collections import defaultdict
 
 
 def gen_password(length=8, add_numbers=True, mix_case=True,
@@ -56,17 +55,19 @@
     def __init__(self, filename):
         self.filename = filename
         self.users = {}
-        self.privileges = defaultdict(set)
+        self.privileges = {}
         if path.exists(filename):
-            with file(filename) as f:
+            f = open(filename)
+            try:
                 for line in f:
                     line = line.strip()
                     if line and line[0] != '#':
                         parts = line.split(':')
                         self.users[parts[0]] = parts[1]
-                        self.privileges[parts[0]].update(x for x in
-                                                         parts[2].split(',')
-                                                         if x)
+                        self.privileges.setdefault(parts[0], set()).update(
+                            x for x in parts[2].split(',') if x)
+            finally:
+                f.close()
 
     def set_password(self, user, password):
         """Encode the password for a user (also adds users)."""
@@ -84,7 +85,10 @@
             self.users[user] == sha1('%s|%s' % (user, password)).hexdigest()
 
     def save(self):
-        with file(self.filename, 'w') as f:
+        f = open(self.filename, 'w')
+        try:
             for username, password in self.users.iteritems():
                 privileges = ','.join(self.privileges.get(username, ()))
                 f.write('%s:%s:%s\n' % (username, password, privileges))
+        finally:
+            f.close()

Modified: doctools/trunk/sphinx/web/util.py
==============================================================================
--- doctools/trunk/sphinx/web/util.py	(original)
+++ doctools/trunk/sphinx/web/util.py	Wed Jan 16 21:27:25 2008
@@ -8,22 +8,21 @@
     :copyright: 2007-2008 by Georg Brandl.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import re
 from os import path
 
-from ..util import relative_uri
-from .._jinja import Environment, FileSystemLoader
+from sphinx.util import relative_uri
+from sphinx._jinja import Environment, FileSystemLoader
 
 
 def get_target_uri(source_filename):
-    """Get the web-URI for a given reST file name."""
-    if source_filename == 'index.rst':
+    """Get the web-URI for a given reST file name (without extension)."""
+    if source_filename == 'index':
         return ''
-    if source_filename.endswith('/index.rst'):
-        return source_filename[:-9] # up to /
-    return source_filename[:-4] + '/'
+    if source_filename.endswith('/index'):
+        return source_filename[:-5] # up to /
+    return source_filename + '/'
 
 
 # ------------------------------------------------------------------------------

Modified: doctools/trunk/sphinx/web/webconf.py
==============================================================================
--- doctools/trunk/sphinx/web/webconf.py	(original)
+++ doctools/trunk/sphinx/web/webconf.py	Wed Jan 16 21:27:25 2008
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Python documentation web application configuration file
+# Sphinx documentation web application configuration file
 #
 
 # Where the server listens.

Modified: doctools/trunk/sphinx/web/wsgiutil.py
==============================================================================
--- doctools/trunk/sphinx/web/wsgiutil.py	(original)
+++ doctools/trunk/sphinx/web/wsgiutil.py	Wed Jan 16 21:27:25 2008
@@ -9,7 +9,6 @@
     :copyright: 2007-2008 by Armin Ronacher.
     :license: BSD.
 """
-from __future__ import with_statement
 
 import cgi
 import urllib
@@ -23,8 +22,8 @@
 from datetime import datetime
 from cStringIO import StringIO
 
-from .util import lazy_property
-from ..util.json import dump_json
+from sphinx.web.util import lazy_property
+from sphinx.util.json import dump_json
 
 
 HTTP_STATUS_CODES = {
@@ -371,8 +370,11 @@
         self.sid = sid
         if sid is not None:
             if path.exists(self.filename):
-                with file(self.filename, 'rb') as f:
+                f = open(self.filename, 'rb')
+                try:
                     self.update(pickle.load(f))
+                finally:
+                    f.close()
         self._orig = dict(self)
 
     @property
@@ -387,8 +389,11 @@
     def save(self):
         if self.sid is None:
             self.sid = sha1('%s|%s' % (time(), random())).hexdigest()
-        with file(self.filename, 'wb') as f:
+        f = open(self.filename, 'wb')
+        try:
             pickle.dump(dict(self), f, pickle.HIGHEST_PROTOCOL)
+        finally:
+            f.close()
         self._orig = dict(self)
 
 
@@ -669,8 +674,11 @@
         start_response('200 OK', [('Content-Type', mime_type),
                                   ('Cache-Control', 'public'),
                                   ('Expires', expiry)])
-        with open(filename, 'rb') as f:
+        f = open(filename, 'rb')
+        try:
             return [f.read()]
+        finally:
+            f.close()
 
     def __call__(self, environ, start_response):
         p = environ.get('PATH_INFO', '')


More information about the Python-checkins mailing list