diff options
| -rw-r--r-- | doc/markup/misc.rst | 7 | ||||
| -rw-r--r-- | sphinx/builders/html.py | 3 | ||||
| -rw-r--r-- | sphinx/directives/other.py | 43 | ||||
| -rw-r--r-- | sphinx/environment.py | 1 | ||||
| -rw-r--r-- | sphinx/ext/autodoc.py | 5 | ||||
| -rw-r--r-- | sphinx/ext/graphviz.py | 4 | ||||
| -rw-r--r-- | sphinx/highlighting.py | 2 | ||||
| -rw-r--r-- | sphinx/writers/latex.py | 3 | ||||
| -rw-r--r-- | tests/root/contents.txt | 1 | ||||
| -rw-r--r-- | tests/root/only.txt | 203 | ||||
| -rw-r--r-- | tests/test_autodoc.py | 13 | ||||
| -rw-r--r-- | tests/test_env.py | 1 | ||||
| -rw-r--r-- | tests/test_only_directive.py | 61 |
13 files changed, 332 insertions, 15 deletions
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst index 3a2ffa32..f5eaac9c 100644 --- a/doc/markup/misc.rst +++ b/doc/markup/misc.rst @@ -182,13 +182,6 @@ Including content based on tags The format of the current builder (``html``, ``latex`` or ``text``) is always set as a tag. - .. note:: - - Due to docutils' specifics of parsing of directive content, you cannot put - a section with the same level as the main document heading inside an - ``only`` directive. Such sections will appear to be ignored in the parsed - document. - .. versionadded:: 0.6 diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 81840374..f5218673 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -610,7 +610,8 @@ class StandaloneHTMLBuilder(Builder): """ Builder.post_process_images(self, doctree) for node in doctree.traverse(nodes.image): - if not node.has_key('scale') or \ + scale_keys = ('scale', 'width', 'height') + if not any((key in node) for key in scale_keys) or \ isinstance(node.parent, nodes.reference): # docutils does unfortunately not preserve the # ``target`` attribute on images, so we need to check diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index aa4142d6..506d4be9 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -338,9 +338,46 @@ class Only(Directive): node.document = self.state.document set_source_info(self, node) node['expr'] = self.arguments[0] - self.state.nested_parse(self.content, self.content_offset, node, - match_titles=1) - return [node] + + # Same as util.nested_parse_with_titles but try to handle nested + # sections which should be raised higher up the doctree. + surrounding_title_styles = self.state.memo.title_styles + surrounding_section_level = self.state.memo.section_level + self.state.memo.title_styles = [] + self.state.memo.section_level = 0 + try: + result = self.state.nested_parse(self.content, self.content_offset, + node, match_titles=1) + title_styles = self.state.memo.title_styles + if (not surrounding_title_styles + or not title_styles + or title_styles[0] not in surrounding_title_styles + or not self.state.parent): + # No nested sections so no special handling needed. + return [node] + # Calculate the depths of the current and nested sections. + current_depth = 0 + parent = self.state.parent + while parent: + current_depth += 1 + parent = parent.parent + current_depth -= 2 + title_style = title_styles[0] + nested_depth = len(surrounding_title_styles) + if title_style in surrounding_title_styles: + nested_depth = surrounding_title_styles.index(title_style) + # Use these depths to determine where the nested sections should + # be placed in the doctree. + n_sects_to_raise = current_depth - nested_depth + 1 + parent = self.state.parent + for i in xrange(n_sects_to_raise): + if parent.parent: + parent = parent.parent + parent.append(node) + return [] + finally: + self.state.memo.title_styles = surrounding_title_styles + self.state.memo.section_level = surrounding_section_level class Include(BaseInclude): diff --git a/sphinx/environment.py b/sphinx/environment.py index a4bbbe3b..824d9c18 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -66,6 +66,7 @@ default_settings = { 'doctitle_xform': False, 'sectsubtitle_xform': False, 'halt_level': 5, + 'file_insertion_enabled': True, } # This is increased every time an environment attribute is added diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 9c6575f5..c15726b4 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -862,7 +862,7 @@ class DocstringSignatureMixin(object): """ def _find_signature(self, encoding=None): - docstrings = Documenter.get_doc(self, encoding, 2) + docstrings = Documenter.get_doc(self, encoding) if len(docstrings) != 1: return doclines = docstrings[0] @@ -877,6 +877,9 @@ class DocstringSignatureMixin(object): # the base name must match ours if not self.objpath or base != self.objpath[-1]: return + # re-prepare docstring to ignore indentation after signature + docstrings = Documenter.get_doc(self, encoding, 2) + doclines = docstrings[0] # ok, now jump over remaining empty lines and set the remaining # lines as the new doclines i = 1 diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 4e72761e..bacd7248 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -229,10 +229,10 @@ def render_dot_html(self, node, code, options, prefix='graphviz', (fname, alt, imgcss)) else: # has a map: get the name of the map and connect the parts - mapname = mapname_re.match(imgmap[0]).group(1) + mapname = mapname_re.match(imgmap[0].decode('utf-8')).group(1) self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' % (fname, alt, mapname, imgcss)) - self.body.extend(imgmap) + self.body.extend([item.decode('utf-8') for item in imgmap]) if node.get('caption') and not inline: self.body.append('</p>\n<p class="caption">') self.body.append(self.encode(node['caption'])) diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 2f61c1ef..63464914 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -207,6 +207,8 @@ class PygmentsBridge(object): if self.dest == 'html': return hlsource else: + if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6 + hlsource = hlsource.decode() return hlsource.translate(tex_hl_escape_map_new) except ErrorToken: # this is most probably not the selected language, diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index f2ebad36..e5ef3a61 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -100,7 +100,8 @@ class LaTeXWriter(writers.Writer): class ExtBabel(Babel): def get_shorthandoff(self): shortlang = self.language.split('_')[0] - if shortlang in ('de', 'sl', 'pt', 'es', 'nl', 'pl', 'it'): + if shortlang in ('de', 'ngerman', 'sl', 'slovene', 'pt', 'portuges', 'es', 'spanish', + 'nl', 'dutch', 'pl', 'polish', 'it', 'italian'): return '\\shorthandoff{"}' return '' diff --git a/tests/root/contents.txt b/tests/root/contents.txt index 280953b4..ad246cb7 100644 --- a/tests/root/contents.txt +++ b/tests/root/contents.txt @@ -27,6 +27,7 @@ Contents: doctest extensions versioning/index + only Python <http://python.org/> diff --git a/tests/root/only.txt b/tests/root/only.txt new file mode 100644 index 00000000..4a3eb48a --- /dev/null +++ b/tests/root/only.txt @@ -0,0 +1,203 @@ + +1. Sections in only directives +============================== + +Testing sections in only directives. + +.. only:: nonexisting_tag + + Skipped Section + --------------- + Should not be here. + +.. only:: not nonexisting_tag + + 1.1. Section + ------------ + Should be here. + +1.2. Section +------------ + +.. only:: not nonexisting_tag + + 1.2.1. Subsection + ~~~~~~~~~~~~~~~~~ + Should be here. + +.. only:: nonexisting_tag + + Skipped Subsection + ~~~~~~~~~~~~~~~~~~ + Should not be here. + +1.3. Section +------------ + +1.3.1. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +1.4. Section +------------ + +.. only:: not nonexisting_tag + + 1.4.1. Subsection + ~~~~~~~~~~~~~~~~~ + Should be here. + +1.5. Section +------------ + +.. only:: not nonexisting_tag + + 1.5.1. Subsection + ~~~~~~~~~~~~~~~~~ + Should be here. + +1.5.2. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +1.6. Section +------------ + +1.6.1. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +.. only:: not nonexisting_tag + + 1.6.2. Subsection + ~~~~~~~~~~~~~~~~~ + Should be here. + +1.6.3. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +1.7. Section +------------ + +1.7.1. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +.. only:: not nonexisting_tag + + 1.7.1.1. Subsubsection + ...................... + Should be here. + +1.8. Section +------------ + +1.8.1. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +1.8.1.1. Subsubsection +...................... +Should be here. + +.. only:: not nonexisting_tag + + 1.8.1.2. Subsubsection + ...................... + Should be here. + +1.9. Section +------------ + +.. only:: nonexisting_tag + + Skipped Subsection + ~~~~~~~~~~~~~~~~~~ + +1.9.1. Subsection +~~~~~~~~~~~~~~~~~ +Should be here. + +1.9.1.1. Subsubsection +...................... +Should be here. + +.. only:: not nonexisting_tag + + 1.10. Section + ------------- + Should be here. + +1.11. Section +------------- + +Text before subsection 11.1. + +.. only:: not nonexisting_tag + + More text before subsection 11.1. + + 1.11.1. Subsection + ~~~~~~~~~~~~~~~~~~ + Should be here. + +Text after subsection 11.1. + +.. only:: not nonexisting_tag + + 1.12. Section + ------------- + Should be here. + + 1.12.1. Subsection + ~~~~~~~~~~~~~~~~~~ + Should be here. + + 1.13. Section + ------------- + Should be here. + +.. only:: not nonexisting_tag + + 1.14. Section + ------------- + Should be here. + + .. only:: not nonexisting_tag + + 1.14.1. Subsection + ~~~~~~~~~~~~~~~~~~ + Should be here. + + 1.15. Section + ------------- + Should be here. + +.. only:: nonexisting_tag + + Skipped document level heading + ============================== + Should not be here. + +.. only:: not nonexisting_tag + + 2. Included document level heading + ================================== + Should be here. + +3. Document level heading +========================= +Should be here. + +.. only:: nonexisting_tag + + Skipped document level heading + ============================== + Should not be here. + +.. only:: not nonexisting_tag + + 4. Another included document level heading + ========================================== + Should be here. diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 965064c3..6dedaad8 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -519,6 +519,12 @@ def test_generate(): assert_result_contains( ' rest of docstring', 'method', 'test_autodoc.DocstringSig.meth') assert_result_contains( + '.. py:method:: DocstringSig.meth2()', 'method', + 'test_autodoc.DocstringSig.meth2') + assert_result_contains( + ' indented line', 'method', + 'test_autodoc.DocstringSig.meth2') + assert_result_contains( '.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method', 'test_autodoc.Class.moore') @@ -660,6 +666,13 @@ First line of docstring rest of docstring """ + def meth2(self): + """First line, no signature + Second line followed by indentation:: + + indented line + """ + class StrRepr(str): def __repr__(self): return self diff --git a/tests/test_env.py b/tests/test_env.py index e62db33b..2f75187f 100644 --- a/tests/test_env.py +++ b/tests/test_env.py @@ -54,6 +54,7 @@ def test_images(): tree = env.get_doctree('images') app._warning.reset() htmlbuilder = StandaloneHTMLBuilder(app) + htmlbuilder.imgpath = 'dummy' htmlbuilder.post_process_images(tree) image_uri_message = "no matching candidate for image URI u'foo.*'" if sys.version_info >= (3, 0): diff --git a/tests/test_only_directive.py b/tests/test_only_directive.py new file mode 100644 index 00000000..2396046e --- /dev/null +++ b/tests/test_only_directive.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +""" + test_only_directive + ~~~~~~~~~~~~~~~~~~~ + + Test the only directive with the test root. + + :copyright: Copyright 2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re + +from docutils import nodes + +from util import * + + +def teardown_module(): + (test_root / '_build').rmtree(True) + + +@with_app(buildername='text') +def test_sectioning(app): + + def getsects(section): + if not isinstance(section, nodes.section): + return [getsects(n) for n in section.children] + title = section.next_node(nodes.title).astext().strip() + subsects = [] + children = section.children[:] + while children: + node = children.pop(0) + if isinstance(node, nodes.section): + subsects.append(node) + continue + children = list(node.children) + children + return [title, [getsects(subsect) for subsect in subsects]] + + def testsects(prefix, sects, indent=0): + title = sects[0] + parent_num = title.split()[0] + assert prefix == parent_num, \ + 'Section out of place: %r' % title + for i, subsect in enumerate(sects[1]): + num = subsect[0].split()[0] + assert re.match('[0-9]+[.0-9]*[.]', num), \ + 'Unnumbered section: %r' % subsect[0] + testsects(prefix + str(i+1) + '.', subsect, indent+4) + + app.builder.build(['only']) + doctree = app.env.get_doctree('only') + app.env.process_only_nodes(doctree, app.builder) + + parts = [getsects(n) + for n in filter(lambda n: isinstance(n, nodes.section), + doctree.children)] + for i, s in enumerate(parts): + testsects(str(i+1) + '.', s, 4) + assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \ + '\n'.join([p[0] for p in parts]) |
