merge with 1.0

This commit is contained in:
Georg Brandl 2011-01-04 00:35:27 +01:00
commit 3642b521ed
15 changed files with 138 additions and 42 deletions

18
CHANGES
View File

@ -42,6 +42,24 @@ Release 1.1 (in development)
Release 1.0.6 (in development)
==============================
* #574: Add special code for better support of Japanese documents
in the LaTeX builder.
* Regression of #77: If there is only one parameter given with
``:param:`` markup, the bullet list is now suppressed again.
* #556: Fix missing paragraph breaks in LaTeX output in certain
situations.
* #567: Emit the ``autodoc-process-docstring`` event even for objects
without a docstring so that it can add content.
* #565: In the LaTeX builder, not only literal blocks require different
table handling, but also quite a few other list-like block elements.
* #515: Fix tracebacks in the viewcode extension for Python objects
that do not have a valid signature.
* Fix strange reportings of line numbers for warnings generated from
autodoc-included docstrings, due to different behavior depending
on docutils version.

View File

@ -13,10 +13,12 @@ like this::
:fieldname: Field content
A field list at the very top of a file is parsed by docutils as the "docinfo",
A field list near the top of a file is parsed by docutils as the "docinfo"
which is normally used to record the author, date of publication and other
metadata. *In Sphinx*, the docinfo is used as metadata, too, but not displayed
in the output.
metadata. *In Sphinx*, a field list preceding any other markup is moved from
the docinfo to the Sphinx environment as document metadata and is not displayed
in the output; a field list appearing after the document title will be part of
the docinfo as normal and will be displayed in the output.
At the moment, these metadata fields are recognized:
@ -203,9 +205,16 @@ following directive exists:
.. warning::
Tables that contain literal blocks cannot be set with ``tabulary``. They are
therefore set with the standard LaTeX ``tabular`` environment. Also, the
verbatim environment used for literal blocks only works in ``p{width}``
columns, which means that by default, Sphinx generates such column specs for
such tables. Use the :rst:dir:`tabularcolumns` directive to get finer control
over such tables.
Tables that contain list-like elements such as object descriptions,
blockquotes or any kind of lists cannot be set out of the box with
``tabulary``. They are therefore set with the standard LaTeX ``tabular``
environment if you don't give a ``tabularcolumns`` directive. If you do, the
table will be set with ``tabulary``, but you must use the ``p{width}``
construct for the columns that contain these elements.
Literal blocks do not work with ``tabulary`` at all, so tables containing a
literal block are always set with ``tabular``. Also, the verbatim
environment used for literal blocks only works in ``p{width}`` columns, which
means that by default, Sphinx generates such column specs for such tables.
Use the :rst:dir:`tabularcolumns` directive to get finer control over such
tables.

View File

@ -720,7 +720,7 @@ class StandaloneHTMLBuilder(Builder):
# outfilename's path is in general different from self.outdir
ensuredir(path.dirname(outfilename))
try:
f = codecs.open(outfilename, 'w', encoding)
f = codecs.open(outfilename, 'w', encoding, 'xmlcharrefreplace')
try:
f.write(output)
finally:

View File

@ -121,7 +121,8 @@ class CObject(ObjectDescription):
self._parse_type(param, arg)
else:
self._parse_type(param, ctype)
param += nodes.emphasis(' '+argname, ' '+argname)
# separate by non-breaking space in the output
param += nodes.emphasis(' '+argname, u'\xa0'+argname)
paramlist += param
signode += paramlist
if const:

View File

@ -326,9 +326,8 @@ class ArgumentDefExpr(DefExpr):
return self.type.get_id()
def __unicode__(self):
return (self.type is not None and u'%s %s' % (self.type, self.name)
or unicode(self.name)) + (self.default is not None and
u'=%s' % self.default or u'')
return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
(self.default is not None and u'=%s' % self.default or u'')
class NamedDefExpr(DefExpr):

View File

@ -94,10 +94,12 @@ class PyObject(ObjectDescription):
TypedField('parameter', label=l_('Parameters'),
names=('param', 'parameter', 'arg', 'argument',
'keyword', 'kwarg', 'kwparam'),
typerolename='obj', typenames=('paramtype', 'type')),
typerolename='obj', typenames=('paramtype', 'type'),
can_collapse=True),
TypedField('variable', label=l_('Variables'), rolename='obj',
names=('var', 'ivar', 'cvar'),
typerolename='obj', typenames=('vartype',)),
typerolename='obj', typenames=('vartype',),
can_collapse=True),
GroupedField('exceptions', label=l_('Raises'), rolename='exc',
names=('raises', 'raise', 'exception', 'except'),
can_collapse=True),

View File

@ -565,8 +565,7 @@ class BuildEnvironment:
self.clear_doc(docname)
# read all new and changed files
to_read = added | changed
for docname in sorted(to_read):
for docname in sorted(added | changed):
yield docname
self.read_doc(docname, app=app)

View File

@ -461,6 +461,11 @@ class Documenter(object):
if not no_docstring:
encoding = self.analyzer and self.analyzer.encoding
docstrings = self.get_doc(encoding)
if not docstrings:
# append at least a dummy docstring, so that the event
# autodoc-process-docstring is fired and can add some
# content if desired
docstrings.append([])
for i, line in enumerate(self.process_doc(docstrings)):
self.add_line(line, sourcename, i)
@ -982,9 +987,9 @@ class ClassDocumenter(ModuleLevelDocumenter):
content = self.env.config.autoclass_content
docstrings = []
docstring = self.get_attr(self.object, '__doc__', None)
if docstring:
docstrings.append(docstring)
attrdocstring = self.get_attr(self.object, '__doc__', None)
if attrdocstring:
docstrings.append(attrdocstring)
# for classes, what the "docstring" is can be controlled via a
# config value; the default is only the class docstring

View File

@ -54,7 +54,7 @@ def doctree_read(app, doctree):
modname = signode.get('module')
if not modname:
continue
fullname = signode['fullname']
fullname = signode.get('fullname')
if not has_tag(modname, fullname, env.docname):
continue
if fullname in names:

View File

@ -14,6 +14,15 @@ all-pdf: $(ALLPDF)
all-dvi: $(ALLDVI)
all-ps: all-dvi
for f in *.dvi; do dvips $$f; done
all-pdf-ja: $(wildcard *.tex)
ebb $(wildcard *.pdf *.png *.gif *.jpeg)
platex -kanji=utf8 $(LATEXOPTS) '$<'
platex -kanji=utf8 $(LATEXOPTS) '$<'
platex -kanji=utf8 $(LATEXOPTS) '$<'
-mendex -U -f -d '$(basename $<).dic' -s python.ist '$(basename $<).idx'
platex -kanji=utf8 $(LATEXOPTS) '$<'
platex -kanji=utf8 $(LATEXOPTS) '$<'
dvipdfmx '$(basename $<).dvi'
zip: all-$(FMT)
mkdir $(ARCHIVEPREFIX)docs-$(FMT)

View File

@ -129,15 +129,13 @@ class TypedField(GroupedField):
is_typed = True
def __init__(self, name, names=(), typenames=(), label=None,
rolename=None, typerolename=None):
GroupedField.__init__(self, name, names, label, rolename, False)
rolename=None, typerolename=None, can_collapse=False):
GroupedField.__init__(self, name, names, label, rolename, can_collapse)
self.typenames = typenames
self.typerolename = typerolename
def make_field(self, types, domain, items):
fieldname = nodes.field_name('', self.label)
listnode = self.list_type()
for fieldarg, content in items:
def handle_item(fieldarg, content):
par = nodes.paragraph()
par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
if fieldarg in types:
@ -154,8 +152,17 @@ class TypedField(GroupedField):
par += nodes.Text(')')
par += nodes.Text(' -- ')
par += content
listnode += nodes.list_item('', par)
fieldbody = nodes.field_body('', listnode)
return par
fieldname = nodes.field_name('', self.label)
if len(items) == 1 and self.can_collapse:
fieldarg, content = items[0]
bodynode = handle_item(fieldarg, content)
else:
bodynode = self.list_type()
for fieldarg, content in items:
bodynode += nodes.list_item('', handle_item(fieldarg, content))
fieldbody = nodes.field_body('', bodynode)
return nodes.field('', fieldname, fieldbody)

View File

@ -113,6 +113,7 @@ class Table(object):
self.colspec = None
self.rowcount = 0
self.had_head = False
self.has_problematic = False
self.has_verbatim = False
self.caption = None
self.longtable = False
@ -191,6 +192,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
lang = babel.get_language()
if lang:
self.elements['classoptions'] += ',' + babel.get_language()
elif builder.config.language == 'ja':
self.elements['classoptions'] += ',english,dvipdfm'
# not elements of babel, but this should be above sphinx.sty.
# because pTeX (Japanese TeX) cannot handle this count.
self.elements['babel'] += r'\newcount\pdfoutput\pdfoutput=0'
# to make the pdf with correct encoded hyperref bookmarks
self.elements['preamble'] += r'\AtBeginDvi{\special{pdf:tounicode EUC-UCS2}}'
else:
self.builder.warn('no Babel option known for language %r' %
builder.config.language)
@ -482,6 +490,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_desc(self, node):
self.body.append('\n\n\\begin{fulllineitems}\n')
if self.table:
self.table.has_problematic = True
def depart_desc(self, node):
self.body.append('\n\\end{fulllineitems}\n\n')
@ -615,14 +625,22 @@ class LaTeXTranslator(nodes.NodeVisitor):
u'\\capstart\\caption{%s}\n' % self.table.caption)
if self.table.longtable:
self.body.append('\n\\begin{longtable}')
endmacro = '\\end{longtable}\n\n'
elif self.table.has_verbatim:
self.body.append('\n\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
elif self.table.has_problematic and not self.table.colspec:
# if the user has given us tabularcolumns, accept them and use
# tabulary nevertheless
self.body.append('\n\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
else:
self.body.append('\n\\begin{tabulary}{\\linewidth}')
endmacro = '\\end{tabulary}\n\n'
if self.table.colspec:
self.body.append(self.table.colspec)
else:
if self.table.has_verbatim:
if self.table.has_problematic:
colwidth = 0.95 / self.table.colcount
colspec = ('p{%.3f\\linewidth}|' % colwidth) * \
self.table.colcount
@ -655,12 +673,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
else:
self.body.append('\\hline\n')
self.body.extend(self.tablebody)
if self.table.longtable:
self.body.append('\\end{longtable}\n\n')
elif self.table.has_verbatim:
self.body.append('\\end{tabular}\n\n')
else:
self.body.append('\\end{tabulary}\n\n')
self.body.append(endmacro)
if not self.table.longtable and self.table.caption is not None:
self.body.append('\\end{threeparttable}\n\n')
self.table = None
@ -725,6 +738,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_bullet_list(self, node):
if not self.compact_list:
self.body.append('\\begin{itemize}\n' )
if self.table:
self.table.has_problematic = True
def depart_bullet_list(self, node):
if not self.compact_list:
self.body.append('\\end{itemize}\n' )
@ -733,6 +748,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\\begin{enumerate}\n' )
if 'start' in node:
self.body.append('\\setcounter{enumi}{%d}\n' % (node['start'] - 1))
if self.table:
self.table.has_problematic = True
def depart_enumerated_list(self, node):
self.body.append('\\end{enumerate}\n' )
@ -745,6 +762,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_definition_list(self, node):
self.body.append('\\begin{description}\n')
if self.table:
self.table.has_problematic = True
def depart_definition_list(self, node):
self.body.append('\\end{description}\n')
@ -774,6 +793,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_field_list(self, node):
self.body.append('\\begin{quote}\\begin{description}\n')
if self.table:
self.table.has_problematic = True
def depart_field_list(self, node):
self.body.append('\\end{description}\\end{quote}\n')
@ -791,10 +812,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_paragraph(self, node):
self.body.append('\n')
def depart_paragraph(self, node):
self.body.append('\n')
self.body.append('\n\n')
def visit_centered(self, node):
self.body.append('\n\\begin{center}')
if self.table:
self.table.has_problematic = True
def depart_centered(self, node):
self.body.append('\n\\end{center}')
@ -804,6 +827,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.compact_list += 1
self.body.append('\\begin{itemize}\\setlength{\\itemsep}{0pt}'
'\\setlength{\\parskip}{0pt}\n')
if self.table:
self.table.has_problematic = True
def depart_hlist(self, node):
self.compact_list -= 1
self.body.append('\\end{itemize}\n')
@ -1220,6 +1245,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if self.table:
hlcode = hlcode.replace('\\begin{Verbatim}',
'\\begin{OriginalVerbatim}')
self.table.has_problematic = True
self.table.has_verbatim = True
# get consistent trailer
hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
@ -1241,6 +1267,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
'\\begin{DUlineblock}{\\DUlineblockindent}\n')
else:
self.body.append('\n\\begin{DUlineblock}{0em}\n')
if self.table:
self.table.has_problematic = True
def depart_line_block(self, node):
self.body.append('\\end{DUlineblock}\n')
@ -1256,6 +1284,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
done = 1
if not done:
self.body.append('\\begin{quote}\n')
if self.table:
self.table.has_problematic = True
def depart_block_quote(self, node):
done = 0
if len(node.children) == 1:
@ -1292,6 +1322,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_option_list(self, node):
self.body.append('\\begin{optionlist}{3cm}\n')
if self.table:
self.table.has_problematic = True
def depart_option_list(self, node):
self.body.append('\\end{optionlist}\n')

View File

@ -0,0 +1,7 @@
class MarkupError(object):
"""
.. note:: This is a docstring with a
small markup error which should have
correct location information.
"""

View File

@ -47,6 +47,8 @@ Testing object descriptions
.. class:: TimeInt
Has only one parameter (triggers special behavior...)
:param moo: |test|
:type moo: |test|
@ -54,8 +56,8 @@ Testing object descriptions
.. class:: Time(hour, minute, isdst)
:param hour: The year.
:type hour: TimeInt
:param year: The year.
:type year: TimeInt
:param TimeInt minute: The minute.
:param isdst: whether it's DST
:type isdst: * some complex
@ -66,8 +68,10 @@ Testing object descriptions
:ivar int hour: like *hour*
:ivar minute: like *minute*
:vartype minute: int
:param hour: Some parameter
:type hour: DuplicateType
:param hour: Duplicate param. Should not lead to crashes.
:type hour: Duplicate type.
:type hour: DuplicateType
C items

View File

@ -193,9 +193,13 @@ HTML_XPATH = {
# custom sidebar
(".//h4", 'Custom sidebar'),
# docfields
(".//td[@class='field-body']/ul/li/strong", '^moo$'),
(".//td[@class='field-body']/ul/li/strong",
(".//td[@class='field-body']/strong", '^moo$'),
(".//td[@class='field-body']/strong",
tail_check(r'\(Moo\) .* Moo')),
(".//td[@class='field-body']/ul/li/strong", '^hour$'),
(".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
(".//td[@class='field-body']/ul/li/em",
tail_check(r'.* Some parameter')),
],
'contents.html': [
(".//meta[@name='hc'][@content='hcval']", ''),