summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2011-01-04 00:35:27 +0100
committerGeorg Brandl <georg@python.org>2011-01-04 00:35:27 +0100
commit3642b521ed5a8c85faf4b37eb1bc83d6cfa63716 (patch)
treeeed02f129e674a183307a35cd383b9c6f369b6bf
parent8fd5bd1e1909ac5c5e857049dafcdcc2975eb90d (diff)
parenteecd8bff03e6617dc3644e319f9447e3320af9c3 (diff)
downloadsphinx-git-3642b521ed5a8c85faf4b37eb1bc83d6cfa63716.tar.gz
merge with 1.0
-rw-r--r--CHANGES18
-rw-r--r--doc/markup/misc.rst27
-rw-r--r--sphinx/builders/html.py2
-rw-r--r--sphinx/domains/c.py3
-rw-r--r--sphinx/domains/cpp.py5
-rw-r--r--sphinx/domains/python.py6
-rw-r--r--sphinx/environment.py3
-rw-r--r--sphinx/ext/autodoc.py11
-rw-r--r--sphinx/ext/viewcode.py2
-rw-r--r--sphinx/texinputs/Makefile9
-rw-r--r--sphinx/util/docfields.py21
-rw-r--r--sphinx/writers/latex.py48
-rw-r--r--tests/root/autodoc_fodder.py7
-rw-r--r--tests/root/objects.txt10
-rw-r--r--tests/test_build_html.py8
15 files changed, 138 insertions, 42 deletions
diff --git a/CHANGES b/CHANGES
index ccce082bf..174998567 100644
--- a/CHANGES
+++ b/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.
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst
index 44da3aacc..55370de7e 100644
--- a/doc/markup/misc.rst
+++ b/doc/markup/misc.rst
@@ -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.
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index a99d50d58..947cc3a00 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -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:
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index c49dc2843..1b4588173 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -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:
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 901b96f49..d11745130 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -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):
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index e3090a29f..4c9700487 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -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),
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 3e69baa1b..6096090a3 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -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)
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index b61e606aa..a1dfeb1f2 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -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
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index b9bb9d77e..64aa6be20 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -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:
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile
index ce0ebb837..f219a2fe6 100644
--- a/sphinx/texinputs/Makefile
+++ b/sphinx/texinputs/Makefile
@@ -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)
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index 89f81e8cb..745557a79 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -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)
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 9322de14d..3ad8310de 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -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')
diff --git a/tests/root/autodoc_fodder.py b/tests/root/autodoc_fodder.py
new file mode 100644
index 000000000..e5fd74139
--- /dev/null
+++ b/tests/root/autodoc_fodder.py
@@ -0,0 +1,7 @@
+
+class MarkupError(object):
+ """
+ .. note:: This is a docstring with a
+ small markup error which should have
+ correct location information.
+ """
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index e62f6d962..7b70b0624 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -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
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index df4d5ad56..446c5a942 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -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']", ''),