Commits

Georg Brandl  committed 3702678 Merge

merge pre-domain state with tip from 0.6

  • Participants
  • Parent commits 7130d8e, c45e790

Comments (0)

Files changed (19)

 Release 0.6.3 (in development)
 ==============================
 
+* Properly format bullet lists nested in definition lists for LaTeX.
+
+* Section titles are now allowed inside ``only`` directives.
+
+* #201: Make ``centered`` directive work in LaTeX output.
+
+* #206: Refuse to overwrite an existing master document in
+  sphinx-quickstart.
+
+* #208: Use MS-sanctioned locale settings, determined by the
+  ``language`` config option, in the HTML help builder.
+
+* #210: Fix nesting of HTML tags for displayed math from pngmath
+  extension.
+
+* #213: Fix centering of images in LaTeX output.
+
+* #211: Fix compatibility with docutils 0.5.
+
+
 Release 0.6.2 (Jun 16, 2009)
 ============================
 
   ``setup()`` function.
 
 * #158: Allow '..' in template names, and absolute template paths;
-  Jinja 2 by default disables both.  
+  Jinja 2 by default disables both.
 
 * When highlighting Python code, ignore extra indentation before
   trying to parse it as Python.
 * #134: Fix pending_xref leftover nodes when using the todolist
   directive from the todo extension.
 
- 
+
 Release 0.6.1 (Mar 26, 2009)
 ============================
 
     using the ``figwidth`` option and right/left alignment.
 
 * New translations:
-  
+
   - Italian by Sandro Dentella.
   - Ukrainian by Petro Sasnyk.
   - Finnish by Jukka Inkeri.
 * Cython: http://docs.cython.org/
 * C\\C++ Python language binding project: http://language-binding.net/index.html
 * Director: http://packages.python.org/director/
+* Djagios: http://djagios.org/
 * Django: http://docs.djangoproject.com/
 * F2py: http://www.f2py.org/html/
 * GeoDjango: http://geodjango.org/docs/
 * Hedge: http://documen.tician.de/hedge/
 * IFM: http://fluffybunny.memebot.com/ifm-docs/index.html
 * Jinja: http://jinja.pocoo.org/2/documentation/
+* LEPL: http://www.acooke.org/lepl/
 * MapServer: http://mapserver.org/
 * Matplotlib: http://matplotlib.sourceforge.net/
 * Mayavi: http://code.enthought.com/projects/mayavi/docs/development/html/mayavi
 * MeshPy: http://documen.tician.de/meshpy/
+* MirrorBrain: http://mirrorbrain.org/docs/
 * Mixin.com: http://dev.mixin.com/
 * mpmath: http://mpmath.googlecode.com/svn/trunk/doc/build/index.html
 * MyHDL: http://www.myhdl.org/doc/0.6/
 * NumPy: http://docs.scipy.org/doc/numpy/reference/
 * ObjectListView: http://objectlistview.sourceforge.net/python
 * Open ERP: http://doc.openerp.com/
+* OpenEXR: http://excamera.com/articles/26/doc/index.html
 * OpenLayers: http://docs.openlayers.org/
 * openWNS: http://docs.openwns.org/
 * Paste: http://pythonpaste.org/script/
 * sqlparse: http://python-sqlparse.googlecode.com/svn/docs/api/index.html
 * SymPy: http://docs.sympy.org/
 * tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
+* The Wine Cellar Book: http://www.thewinecellarbook.com/doc/en/
 * TurboGears: http://turbogears.org/2.0/docs/
 * VOR: http://www.vor-cycling.be/
 * Werkzeug: http://werkzeug.pocoo.org/documentation/dev/

File doc/intro.rst

   <http://svn.python.org/projects/doctools/converter>`_.  It contains generic
   code to convert Python-doc-style LaTeX markup to Sphinx reST.
 
+* Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx
+  markup; it is at `Google Code <http://code.google.com/p/db2rst/>`_.
+
 
 Prerequisites
 -------------

File sphinx/__init__.py

 import sys
 from os import path
 
-__revision__ = '$Revision$'
 __version__ = '1.0'
-__released__ = '1.0 (hg)'
+__released__ = '1.0 (hg)'  # used when Sphinx builds its own docs
 
 package_dir = path.abspath(path.dirname(__file__))
 
+if '+' in __version__ or 'pre' in __version__:
+    # try to find out the changeset hash if checked out from hg, and append
+    # it to __version__ (since we use this value from setup.py, it gets
+    # automatically propagated to an installed copy as well)
+    try:
+        import subprocess
+        p = subprocess.Popen(['hg', 'id', '-i', '-R',
+                              path.join(package_dir, '..')],
+                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        out, err = p.communicate()
+        if out:
+            __version__ += '/' + out.strip()
+    except Exception:
+        pass
+
 
 def main(argv=sys.argv):
     if sys.version_info[:3] < (2, 4, 0):
                         'first.')
             else:
                 whichmod += ' module'
-            print >>sys.stderr, \
-                  'Error: The %s cannot be found. Did you install Sphinx '\
-                  'and its dependencies correctly?' % whichmod
+            print >>sys.stderr, ('Error: The %s cannot be found. '
+                                 'Did you install Sphinx and its dependencies '
+                                 'correctly?' % whichmod)
             if hint:
                 print >> sys.stderr, hint
             return 1

File sphinx/application.py

         self._events = events.copy()
 
         # say hello to the world
-        self.info(bold('Running Sphinx v%s' % sphinx.__released__))
+        self.info(bold('Running Sphinx v%s' % sphinx.__version__))
 
         # status code for command-line application
         self.statuscode = 0

File sphinx/builders/htmlhelp.py

 
 import os
 import cgi
+import codecs
 from os import path
 
 from docutils import nodes
 Full text search stop list file=%(outname)s.stp
 Full-text search=Yes
 Index file=%(outname)s.hhk
-Language=0x409
+Language=%(lcid)#x
 Title=%(title)s
 
 [WINDOWS]
 was  will  with
 """.split()
 
+# The following list includes only languages supported by Sphinx.
+# See http://msdn.microsoft.com/en-us/library/ms930130.aspx for more.
+chm_locales = {
+    # lang:   LCID,  encoding
+    'cs':    (0x405, 'iso8859_2'),
+    'de':    (0x407, 'iso8859_1'),
+    'en':    (0x409, 'iso8859_1'),
+    'es':    (0x40a, 'iso8859_1'),
+    'fi':    (0x40b, 'iso8859_1'),
+    'fr':    (0x40c, 'iso8859_1'),
+    'it':    (0x410, 'iso8859_1'),
+    'ja':    (0x411, 'cp932'),
+    'nl':    (0x413, 'iso8859_1'),
+    'pl':    (0x415, 'iso8859_2'),
+    'pt_BR': (0x416, 'iso8859_1'),
+    'ru':    (0x419, 'cp1251'),
+    'sl':    (0x424, 'iso8859_2'),
+    'uk_UA': (0x422, 'cp1251'),
+    'zh_TW': (0x404, 'cp950'),
+}
+
 
 class HTMLHelpBuilder(StandaloneHTMLBuilder):
     """
     # don't add sidebar etc.
     embedded = True
 
+    lcid = 0x409
+    encoding = 'iso8859_1'
+
     def init(self):
         StandaloneHTMLBuilder.init(self)
         # the output files for HTML help must be .html only
         self.out_suffix = '.html'
+        # determine the correct locale setting
+        locale = chm_locales.get(self.config.language)
+        if locale is not None:
+            self.lcid, self.encoding = locale
+
+    def open_file(self, outdir, basename, mode='w'):
+        # open a file with the correct encoding for the selected language
+        return codecs.open(path.join(outdir, basename), mode,
+            self.encoding, 'xmlcharrefreplace')
 
     def handle_finish(self):
         self.build_hhx(self.outdir, self.config.htmlhelp_basename)
 
     def build_hhx(self, outdir, outname):
         self.info('dumping stopword list...')
-        f = open(path.join(outdir, outname+'.stp'), 'w')
+        f = self.open_file(outdir, outname+'.stp')
         try:
             for word in sorted(stopwords):
                 print >>f, word
             f.close()
 
         self.info('writing project file...')
-        f = open(path.join(outdir, outname+'.hhp'), 'w')
+        f = self.open_file(outdir, outname+'.hhp')
         try:
             f.write(project_template % {'outname': outname,
                                         'title': self.config.html_title,
                                         'version': self.config.version,
-                                        'project': self.config.project})
+                                        'project': self.config.project,
+                                        'lcid': self.lcid})
             if not outdir.endswith(os.sep):
                 outdir += os.sep
             olen = len(outdir)
             f.close()
 
         self.info('writing TOC file...')
-        f = open(path.join(outdir, outname+'.hhc'), 'w')
+        f = self.open_file(outdir, outname+'.hhc')
         try:
             f.write(contents_header)
             # special books
                 elif isinstance(node, nodes.reference):
                     link = node['refuri']
                     title = cgi.escape(node.astext()).replace('"','&quot;')
-                    item = object_sitemap % (title, link)
-                    f.write(item.encode('ascii', 'xmlcharrefreplace'))
+                    f.write(object_sitemap % (title, link))
                 elif isinstance(node, nodes.bullet_list):
                     if ullevel != 0:
                         f.write('<UL>\n')
 
         self.info('writing index file...')
         index = self.env.create_index(self)
-        f = open(path.join(outdir, outname+'.hhk'), 'w')
+        f = self.open_file(outdir, outname+'.hhk')
         try:
             f.write('<UL>\n')
             def write_index(title, refs, subitems):

File sphinx/builders/qthelp.py

         staticdir = path.join(outdir, '_static')
         imagesdir = path.join(outdir, '_images')
         for root, dirs, files in os.walk(outdir):
-            resourcedir = root.startswith(staticdir) or root.startswith(imagesdir)
+            resourcedir = root.startswith(staticdir) or \
+                          root.startswith(imagesdir)
             for fn in files:
                 if (resourcedir and not fn.endswith('.js')) or \
                        fn.endswith('.html'):

File sphinx/directives/other.py

         node.document = self.state.document
         node.line = self.lineno
         node['expr'] = self.arguments[0]
-        self.state.nested_parse(self.content, self.content_offset, node)
+        self.state.nested_parse(self.content, self.content_offset, node,
+                                match_titles=1)
         return [node]
 
 

File sphinx/environment.py

 import cPickle as pickle
 from os import path
 from glob import glob
-from string import ascii_uppercase as uppercase
 from itertools import izip, groupby
 try:
     from hashlib import md5
 
         for fn, entries in self.indexentries.iteritems():
             # new entry types must be listed in directives/other.py!
-            for type, string, tid, alias in entries:
+            for type, value, tid, alias in entries:
                 if type == 'single':
                     try:
-                        entry, subentry = string.split(';', 1)
+                        entry, subentry = value.split(';', 1)
                     except ValueError:
-                        entry, subentry = string, ''
+                        entry, subentry = value, ''
                     if not entry:
-                        self.warn(fn, 'invalid index entry %r' % string)
+                        self.warn(fn, 'invalid index entry %r' % value)
                         continue
                     add_entry(entry.strip(), subentry.strip())
                 elif type == 'pair':
                     try:
                         first, second = map(lambda x: x.strip(),
-                                            string.split(';', 1))
+                                            value.split(';', 1))
                         if not first or not second:
                             raise ValueError
                     except ValueError:
-                        self.warn(fn, 'invalid pair index entry %r' % string)
+                        self.warn(fn, 'invalid pair index entry %r' % value)
                         continue
                     add_entry(first, second)
                     add_entry(second, first)
                 elif type == 'triple':
                     try:
                         first, second, third = map(lambda x: x.strip(),
-                                                   string.split(';', 2))
+                                                   value.split(';', 2))
                         if not first or not second or not third:
                             raise ValueError
                     except ValueError:
-                        self.warn(fn, 'invalid triple index entry %r' % string)
+                        self.warn(fn, 'invalid triple index entry %r' % value)
                         continue
                     add_entry(first, second+' '+third)
                     add_entry(second, third+', '+first)
                 else:
                     self.warn(fn, 'unknown index entry type %r' % type)
 
+        # sort the index entries; put all symbols at the front, even those
+        # following the letters in ASCII, this is where the chr(127) comes from
+        def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
+            lckey = entry[0].lower()
+            if lckey[0:1] in lcletters:
+                return chr(127) + lckey
+            return lckey
         newlist = new.items()
-        newlist.sort(key=lambda t: t[0].lower())
+        newlist.sort(key=keyfunc)
 
         # fixup entries: transform
         #   func() (in module foo)
         i = 0
         while i < len(newlist):
             key, (targets, subitems) = newlist[i]
-            # cannot move if it hassubitems; structure gets too complex
+            # cannot move if it has subitems; structure gets too complex
             if not subitems:
                 m = _fixre.match(key)
                 if m:
             i += 1
 
         # group the entries by letter
-        def keyfunc((k, v), ltrs=uppercase+'_'):
-            # hack: mutate the subitems dicts to a list in the keyfunc
+        def keyfunc((k, v), letters=string.ascii_uppercase + '_'):
+            # hack: mutating the subitems dicts to a list in the keyfunc
             v[1] = sorted((si, se) for (si, (se, void)) in v[1].iteritems())
             # now calculate the key
             letter = k[0].upper()
-            if letter in ltrs:
+            if letter in letters:
                 return letter
             else:
                 # get all other symbols under one heading

File sphinx/ext/autodoc.py

     return process
 
 
+def safe_getattr(obj, name, *defargs):
+    try:
+        return getattr(obj, name, *defargs)
+    except Exception:
+        # this is a catch-all for all the weird things that some modules do
+        # with attribute access
+        if defargs:
+            return defargs[0]
+        raise AttributeError
+
+
 def isdescriptor(x):
     """Check if the object is some kind of descriptor."""
     for item in '__get__', '__set__', '__delete__':
-        if hasattr(getattr(x, item, None), '__call__'):
+        if hasattr(safe_getattr(x, item, None), '__call__'):
             return True
     return False
 
         for typ, func in AutoDirective._special_attrgetters.iteritems():
             if isinstance(obj, typ):
                 return func(obj, name, *defargs)
-        return getattr(obj, name, *defargs)
+        return safe_getattr(obj, name, *defargs)
 
     @classmethod
     def can_document_member(cls, member, membername, isattr, parent):
         ret = []
         for mname in memberlist:
             try:
-                ret.append((mname, getattr(self.object, mname)))
+                ret.append((mname, safe_getattr(self.object, mname)))
             except AttributeError:
-                self.directive.warn('missing attribute mentioned in :members: '
-                                    'or __all__: module %s, attribute %s' %
-                                    (self.object.__name__, mname))
+                self.directive.warn(
+                    'missing attribute mentioned in :members: or __all__: '
+                    'module %s, attribute %s' % (
+                    safe_getattr(self.object, '__name__', '???'), mname))
         return False, ret
 
 
 
     def add_content(self, more_content, no_docstring=False):
         if self.doc_as_attr:
-            content = ViewList(
-                [_('alias of :class:`%s`') % self.object.__name__], source='')
-            ModuleLevelDocumenter.add_content(self, content, no_docstring=True)
+            classname = safe_getattr(self.object, '__name__', None)
+            if classname:
+                content = ViewList(
+                    [_('alias of :class:`%s`') % classname], source='')
+                ModuleLevelDocumenter.add_content(self, content,
+                                                  no_docstring=True)
         else:
             ModuleLevelDocumenter.add_content(self, more_content)
 

File sphinx/ext/graphviz.py

 
     if hasattr(self.builder, '_graphviz_warned_dot') or \
        hasattr(self.builder, '_graphviz_warned_ps2pdf'):
-        return None
+        return None, None
 
     ensuredir(path.dirname(outfn))
 
                           'output), check the graphviz_dot setting' %
                           self.builder.config.graphviz_dot)
         self.builder._graphviz_warned_dot = True
-        return None
+        return None, None
     # graphviz expects UTF-8 by default
     if isinstance(code, unicode):
         code = code.encode('utf-8')
         raise nodes.SkipNode
 
     if fname is not None:
-        self.body.append('\\includegraphics[]{%s}' % fname)
+        self.body.append('\\includegraphics{%s}' % fname)
     raise nodes.SkipNode
 
 

File sphinx/ext/pngmath.py

         self.body.append('<span class="eqno">(%s)</span>' % node['number'])
     if fname is None:
         # something failed -- use text-only as a bad substitute
-        self.body.append('<span class="math">%s</span>' %
+        self.body.append('<span class="math">%s</span></p>\n</div>' %
                          self.encode(node['latex']).strip())
     else:
-        self.body.append('<img src="%s" alt="%s" />\n</div>' %
+        self.body.append('<img src="%s" alt="%s" /></p>\n</div>' %
                          (fname, self.encode(node['latex']).strip()))
-    self.body.append('</p>')
     raise nodes.SkipNode
 
 
     app.add_config_value('pngmath_dvipng', 'dvipng', 'html')
     app.add_config_value('pngmath_latex', 'latex', 'html')
     app.add_config_value('pngmath_use_preview', False, 'html')
-    app.add_config_value('pngmath_dvipng_args', ['-gamma 1.5', '-D 110'], 'html')
+    app.add_config_value('pngmath_dvipng_args',
+                         ['-gamma 1.5', '-D 110'], 'html')
     app.add_config_value('pngmath_latex_args', [], 'html')
     app.add_config_value('pngmath_latex_preamble', '', 'html')
     app.connect('build-finished', cleanup_tempdir)

File sphinx/pycode/__init__.py

         attr_visitor = AttrDocVisitor(number2name, scope, self.encoding)
         attr_visitor.visit(self.parsetree)
         self.attr_docs = attr_visitor.collected
+        self.parsetree = None
         return attr_visitor.collected
 
     def find_tags(self):

File sphinx/quickstart.py

 document is a custom template, you can also set this to another filename.'''
     do_prompt(d, 'master', 'Name of your master document (without suffix)',
               'index')
+
+    while path.isfile(path.join(d['path'], d['master']+d['suffix'])) or \
+          path.isfile(path.join(d['path'], 'source', d['master']+d['suffix'])):
+        print
+        print bold('Error: the master file %s has already been found in the '
+                   'selected root path.' % (d['master']+d['suffix']))
+        print 'sphinx-quickstart will not overwrite the existing file.'
+        print
+        do_prompt(d, 'master', 'Please enter a new file name, or rename the '
+                  'existing file and press Enter', d['master'])
+
     print '''
 Please indicate if you want to use one of the following Sphinx extensions:'''
     do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings '

File sphinx/texinputs/sphinx.sty

     \image@width\wd\image@box%
     \ifdim \image@width>\linewidth%
       \setbox\image@box=\hbox{\py@Oldincludegraphics[width=\linewidth]{#2}}%
+      \box\image@box%
+    \else%
+      \py@Oldincludegraphics{#2}%
     \fi%
-    \box\image@box%
   \else%
     \py@Oldincludegraphics[#1]{#2}%
   \fi%

File sphinx/util/__init__.py

 import traceback
 from os import path
 
+import docutils
+import sphinx
+
 
 # Generally useful regular expressions.
 ws_re = re.compile(r'\s+')
     """
     exc = traceback.format_exc()
     fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
+    os.write(fd, '# Sphinx version: %s\n' % sphinx.__version__)
+    os.write(fd, '# Docutils version: %s %s\n' % (docutils.__version__,
+                                                  docutils.__version_details__))
     os.write(fd, exc)
     os.close(fd)
     return path

File sphinx/util/pycompat.py

     # begin code copied from utf_8_sig.py in Python 2.6
 
     def encode(input, errors='strict'):
-        return (codecs.BOM_UTF8 + codecs.utf_8_encode(input, errors)[0], len(input))
+        return (codecs.BOM_UTF8 +
+                codecs.utf_8_encode(input, errors)[0], len(input))
 
     def decode(input, errors='strict'):
         prefix = 0

File sphinx/writers/html.py

         if node['uri'].lower().endswith('svg') or \
            node['uri'].lower().endswith('svgz'):
             atts = {'data': node['uri'], 'type': 'image/svg+xml'}
-            if 'width' in node:
+            if node.has_key('width'):
                 atts['width'] = node['width']
-            if 'height' in node:
+            if node.has_key('height'):
                 atts['height'] = node['height']
-            if 'align' in node:
+            if node.has_key('align'):
                 self.body.append('<div align="%s" class="align-%s">' %
                                  (node['align'], node['align']))
                 self.context.append('</div>\n')

File sphinx/writers/latex.py

             # ... and all others are the appendices
             self.body.append('\n\\appendix\n')
             self.first_document = -1
-        if 'docname' in node:
+        if node.has_key('docname'):
             self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
         # "- 1" because the level is increased before the title is visited
         self.sectionlevel = self.top_sectionlevel - 1
         if self.table.longtable:
             self.body.append('\\hline\n')
             self.body.append('\\endfirsthead\n\n')
-            self.body.append('\multicolumn{%s}{c}%%\n' % self.table.colcount)
-            self.body.append('{{\\bfseries \\tablename\\ \\thetable{} -- %s}} \\\\\n' % _('continued from previous page'))
-            self.body.append('\\hline\n')
+            self.body.append('\\multicolumn{%s}{c}%%\n' % self.table.colcount)
+            self.body.append(r'{{\bfseries \tablename\ \thetable{} -- %s}} \\'
+                             % _('continued from previous page'))
+            self.body.append('\n\\hline\n')
             self.body.append('\\endhead\n\n')
-            self.body.append('\\hline \multicolumn{%s}{|r|}{{%s}} \\\\ \\hline\n' % (
-                self.table.colcount, _('Continued on next page')))
-            self.body.append('\\endfoot\n\n')
+            self.body.append(r'\hline \multicolumn{%s}{|r|}{{%s}} \\ \hline'
+                             % (self.table.colcount,
+                                _('Continued on next page')))
+            self.body.append('\n\\endfoot\n\n')
             self.body.append('\\hline\n')
             self.body.append('\\endlastfoot\n\n')
         else:
         pass
 
     def visit_term(self, node):
-        ctx = ']'
+        ctx = '] \\leavevmode'
         if node.has_key('ids') and node['ids']:
             ctx += '\\hypertarget{%s}{}' % node['ids'][0]
         self.body.append('\\item[')
         self.body.append('\n')
 
     def visit_centered(self, node):
-        self.body.append('\n\\begin{centering}')
+        self.body.append('\n\\begin{center}')
     def depart_centered(self, node):
-        self.body.append('\n\\end{centering}')
+        self.body.append('\n\\end{center}')
 
     def visit_hlist(self, node):
         # for now, we don't support a more compact list format