merge pre-domain state with tip from 0.6

This commit is contained in:
Georg Brandl
2009-08-06 21:36:57 +02:00
19 changed files with 186 additions and 64 deletions

26
CHANGES
View File

@@ -38,6 +38,26 @@ Release 1.0 (in development)
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)
============================
@@ -49,7 +69,7 @@ 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.
@@ -107,7 +127,7 @@ Release 0.6.2 (Jun 16, 2009)
* #134: Fix pending_xref leftover nodes when using the todolist
directive from the todo extension.
Release 0.6.1 (Mar 26, 2009)
============================
@@ -252,7 +272,7 @@ New features added
using the ``figwidth`` option and right/left alignment.
* New translations:
- Italian by Sandro Dentella.
- Ukrainian by Petro Sasnyk.
- Finnish by Jukka Inkeri.

View File

@@ -14,6 +14,7 @@ included, please mail to `the Google group
* 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/
@@ -23,10 +24,12 @@ included, please mail to `the Google group
* 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/
@@ -35,6 +38,7 @@ included, please mail to `the Google group
* 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/
@@ -71,6 +75,7 @@ included, please mail to `the Google group
* 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/

View File

@@ -31,6 +31,9 @@ to reStructuredText/Sphinx from other documentation systems.
<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
-------------

View File

@@ -12,12 +12,26 @@
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):
@@ -43,9 +57,9 @@ def main(argv=sys.argv):
'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

View File

@@ -84,7 +84,7 @@ class Sphinx(object):
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

View File

@@ -12,6 +12,7 @@
import os
import cgi
import codecs
from os import path
from docutils import nodes
@@ -66,7 +67,7 @@ Display compile progress=No
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]
@@ -119,6 +120,27 @@ that the their then there these they this to
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):
"""
@@ -136,17 +158,29 @@ 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
@@ -154,12 +188,13 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
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)
@@ -174,7 +209,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
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
@@ -194,8 +229,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
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')
@@ -217,7 +251,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
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):

View File

@@ -150,7 +150,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
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'):

View File

@@ -554,7 +554,8 @@ class Only(Directive):
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]

View File

@@ -21,7 +21,6 @@ import difflib
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
@@ -1421,35 +1420,35 @@ class BuildEnvironment:
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)
@@ -1457,8 +1456,15 @@ class BuildEnvironment:
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)
@@ -1472,7 +1478,7 @@ class BuildEnvironment:
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:
@@ -1490,12 +1496,12 @@ class BuildEnvironment:
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

View File

@@ -194,10 +194,21 @@ def between(marker, what=None, keepempty=False):
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
@@ -235,7 +246,7 @@ class Documenter(object):
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):
@@ -731,11 +742,12 @@ class ModuleDocumenter(Documenter):
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
@@ -922,9 +934,12 @@ class ClassDocumenter(ModuleLevelDocumenter):
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)

View File

@@ -95,7 +95,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
if hasattr(self.builder, '_graphviz_warned_dot') or \
hasattr(self.builder, '_graphviz_warned_ps2pdf'):
return None
return None, None
ensuredir(path.dirname(outfn))
@@ -114,7 +114,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
'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')
@@ -169,7 +169,7 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
raise nodes.SkipNode
if fname is not None:
self.body.append('\\includegraphics[]{%s}' % fname)
self.body.append('\\includegraphics{%s}' % fname)
raise nodes.SkipNode

View File

@@ -223,12 +223,11 @@ def html_visit_displaymath(self, node):
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
@@ -237,7 +236,8 @@ def setup(app):
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)

View File

@@ -234,6 +234,7 @@ class ModuleAnalyzer(object):
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):

View File

@@ -623,6 +623,17 @@ of the documents. Normally, this is "index", but if your "index"
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 '

View File

@@ -695,8 +695,10 @@
\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%

View File

@@ -21,6 +21,9 @@ import posixpath
import traceback
from os import path
import docutils
import sphinx
# Generally useful regular expressions.
ws_re = re.compile(r'\s+')
@@ -206,6 +209,9 @@ def save_traceback():
"""
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

View File

@@ -27,7 +27,8 @@ if sys.version_info < (2, 5):
# 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

View File

@@ -303,11 +303,11 @@ class HTMLTranslator(BaseTranslator):
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')

View File

@@ -261,7 +261,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# ... 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
@@ -640,13 +640,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
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:
@@ -749,7 +751,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
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[')
@@ -789,9 +791,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
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