mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
merge with 1.0
This commit is contained in:
commit
3642b521ed
18
CHANGES
18
CHANGES
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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')
|
||||
|
||||
|
7
tests/root/autodoc_fodder.py
Normal file
7
tests/root/autodoc_fodder.py
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
class MarkupError(object):
|
||||
"""
|
||||
.. note:: This is a docstring with a
|
||||
small markup error which should have
|
||||
correct location information.
|
||||
"""
|
@ -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
|
||||
|
@ -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']", ''),
|
||||
|
Loading…
Reference in New Issue
Block a user