summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/markup/misc.rst7
-rw-r--r--sphinx/directives/other.py43
-rw-r--r--sphinx/environment.py1
-rw-r--r--sphinx/ext/autodoc.py5
-rw-r--r--sphinx/highlighting.py2
-rw-r--r--tests/root/contents.txt1
-rw-r--r--tests/root/only.txt203
-rw-r--r--tests/test_autodoc.py13
-rw-r--r--tests/test_only_directive.py61
9 files changed, 325 insertions, 11 deletions
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst
index 3a2ffa32e..f5eaac9ce 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/directives/other.py b/sphinx/directives/other.py
index aa4142d6f..506d4be91 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 8f18acc67..04d0e6a7f 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 6c796eec0..b0657dc9e 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -866,7 +866,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]
@@ -881,6 +881,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/highlighting.py b/sphinx/highlighting.py
index 2f61c1ef1..63464914a 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/tests/root/contents.txt b/tests/root/contents.txt
index 280953b46..ad246cb77 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 000000000..4a3eb48a6
--- /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 965064c37..6dedaad8f 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_only_directive.py b/tests/test_only_directive.py
new file mode 100644
index 000000000..2396046e4
--- /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])