diff options
author | Georg Brandl <georg@python.org> | 2011-01-04 00:35:27 +0100 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2011-01-04 00:35:27 +0100 |
commit | 3642b521ed5a8c85faf4b37eb1bc83d6cfa63716 (patch) | |
tree | eed02f129e674a183307a35cd383b9c6f369b6bf | |
parent | 8fd5bd1e1909ac5c5e857049dafcdcc2975eb90d (diff) | |
parent | eecd8bff03e6617dc3644e319f9447e3320af9c3 (diff) | |
download | sphinx-git-3642b521ed5a8c85faf4b37eb1bc83d6cfa63716.tar.gz |
merge with 1.0
-rw-r--r-- | CHANGES | 18 | ||||
-rw-r--r-- | doc/markup/misc.rst | 27 | ||||
-rw-r--r-- | sphinx/builders/html.py | 2 | ||||
-rw-r--r-- | sphinx/domains/c.py | 3 | ||||
-rw-r--r-- | sphinx/domains/cpp.py | 5 | ||||
-rw-r--r-- | sphinx/domains/python.py | 6 | ||||
-rw-r--r-- | sphinx/environment.py | 3 | ||||
-rw-r--r-- | sphinx/ext/autodoc.py | 11 | ||||
-rw-r--r-- | sphinx/ext/viewcode.py | 2 | ||||
-rw-r--r-- | sphinx/texinputs/Makefile | 9 | ||||
-rw-r--r-- | sphinx/util/docfields.py | 21 | ||||
-rw-r--r-- | sphinx/writers/latex.py | 48 | ||||
-rw-r--r-- | tests/root/autodoc_fodder.py | 7 | ||||
-rw-r--r-- | tests/root/objects.txt | 10 | ||||
-rw-r--r-- | tests/test_build_html.py | 8 |
15 files changed, 138 insertions, 42 deletions
@@ -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']", ''), |