mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
* sphinx.ext.doctest: Replace <BLANKLINE> in doctest blocks by
real blank lines for presentation output. * sphinx.environment: Move doctest_blocks out of block_quotes to support indented doctest blocks.
This commit is contained in:
parent
fa089ae583
commit
b82b162729
6
CHANGES
6
CHANGES
@ -4,6 +4,12 @@ Changes in trunk
|
||||
* sphinx.ext.doctest: Make the group in which doctest blocks are
|
||||
placed selectable, and default to ``'default'``.
|
||||
|
||||
* sphinx.ext.doctest: Replace <BLANKLINE> in doctest blocks by
|
||||
real blank lines for presentation output.
|
||||
|
||||
* sphinx.environment: Move doctest_blocks out of block_quotes to
|
||||
support indented doctest blocks.
|
||||
|
||||
|
||||
Release 0.1.61611
|
||||
=================
|
||||
|
@ -65,6 +65,10 @@ names.
|
||||
explicit flags per example, with doctest comments, but they will show up in
|
||||
other builders too.)
|
||||
|
||||
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
|
||||
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
|
||||
when building presentation output (HTML, LaTeX etc.).
|
||||
|
||||
|
||||
.. directive:: .. testcode:: [group]
|
||||
|
||||
|
@ -129,6 +129,31 @@ class MoveModuleTargets(Transform):
|
||||
node.parent.remove(node)
|
||||
|
||||
|
||||
class HandleCodeBlocks(Transform):
|
||||
"""
|
||||
Move doctest blocks out of blockquotes and connect adjacent code blocks.
|
||||
"""
|
||||
default_priority = 210
|
||||
|
||||
def apply(self):
|
||||
for node in self.document.traverse(nodes.block_quote):
|
||||
if len(node.children) == 1 and isinstance(node.children[0],
|
||||
nodes.doctest_block):
|
||||
node.replace_self(node.children[0])
|
||||
for node in self.document.traverse(nodes.literal_block):
|
||||
if not node.parent:
|
||||
continue
|
||||
idx = node.parent.index(node)
|
||||
try:
|
||||
while isinstance(node.parent[idx+1], nodes.literal_block):
|
||||
node.children[0] += '\n' + node.parent[idx+1].children[0]
|
||||
import pdb; pdb.set_trace()
|
||||
node.parent[idx+1].parent = None
|
||||
del node.parent[idx+1]
|
||||
except IndexError:
|
||||
continue
|
||||
|
||||
|
||||
class MyStandaloneReader(standalone.Reader):
|
||||
"""
|
||||
Add our own transforms.
|
||||
@ -136,7 +161,7 @@ class MyStandaloneReader(standalone.Reader):
|
||||
def get_transforms(self):
|
||||
tf = standalone.Reader.get_transforms(self)
|
||||
return tf + [DefaultSubstitutions, MoveModuleTargets,
|
||||
FilterMessages]
|
||||
FilterMessages, HandleCodeBlocks]
|
||||
|
||||
|
||||
class MyContentsFilter(ContentsFilter):
|
||||
|
@ -28,10 +28,15 @@ except NameError:
|
||||
|
||||
|
||||
def prepare_docstring(s):
|
||||
"""Convert a docstring into lines of parseable reST."""
|
||||
"""
|
||||
Convert a docstring into lines of parseable reST. Return it as a list of
|
||||
lines usable for inserting into a docutils ViewList (used as argument
|
||||
of nested_parse().) An empty line is added to act as a separator between
|
||||
this docstring and following content.
|
||||
"""
|
||||
if not s or s.isspace():
|
||||
return ['']
|
||||
nl = s.rstrip().find('\n')
|
||||
nl = s.expandtabs().rstrip().find('\n')
|
||||
if nl == -1:
|
||||
# Only one line...
|
||||
return [s.strip(), '']
|
||||
|
@ -10,6 +10,7 @@
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import StringIO
|
||||
@ -23,6 +24,8 @@ from docutils.parsers.rst import directives
|
||||
from sphinx.builder import Builder
|
||||
from sphinx.util.console import bold
|
||||
|
||||
blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
|
||||
|
||||
|
||||
# set up the necessary directives
|
||||
|
||||
@ -31,17 +34,23 @@ def test_directive(name, arguments, options, content, lineno,
|
||||
# use ordinary docutils nodes for test code: they get special attributes
|
||||
# so that our builder recognizes them, and the other builders are happy.
|
||||
code = '\n'.join(content)
|
||||
test = None
|
||||
if name == 'doctest' and '<BLANKLINE>' in code:
|
||||
# convert <BLANKLINE>s to ordinary blank lines for presentation
|
||||
test = code
|
||||
code = blankline_re.sub('', code)
|
||||
nodetype = nodes.literal_block
|
||||
if name == 'testsetup' or 'hide' in options:
|
||||
nodetype = nodes.comment
|
||||
node = nodetype(code, code)
|
||||
node.line = lineno
|
||||
if arguments:
|
||||
groups = [x.strip() for x in arguments[0].split(',')]
|
||||
else:
|
||||
groups = ['default']
|
||||
node['testnodetype'] = name
|
||||
node['groups'] = groups
|
||||
node = nodetype(code, code, testnodetype=name, groups=groups)
|
||||
node.line = lineno
|
||||
if test is not None:
|
||||
# only save if it differs from code
|
||||
node['test'] = test
|
||||
if name == 'testoutput':
|
||||
# don't try to highlight output
|
||||
node['language'] = 'none'
|
||||
@ -215,7 +224,7 @@ Doctest summary
|
||||
return isinstance(node, (nodes.literal_block, nodes.comment)) \
|
||||
and node.has_key('testnodetype')
|
||||
for node in doctree.traverse(condition):
|
||||
code = TestCode(node.astext(),
|
||||
code = TestCode(node.has_key('test') and node['test'] or node.astext(),
|
||||
type=node.get('testnodetype', 'doctest'),
|
||||
lineno=node.line, options=node.get('options'))
|
||||
node_groups = node.get('groups', ['default'])
|
||||
@ -281,7 +290,9 @@ Doctest summary
|
||||
self.type = 'single' # ordinary doctests
|
||||
else:
|
||||
output = code[1] and code[1].code or ''
|
||||
options = code[1] and code[1].options or None
|
||||
options = code[1] and code[1].options or {}
|
||||
# disable <BLANKLINE> processing as it is not needed
|
||||
options[doctest.DONT_ACCEPT_BLANKLINE] = True
|
||||
example = doctest.Example(code[0].code, output,
|
||||
lineno=code[0].lineno,
|
||||
options=options)
|
||||
|
Loading…
Reference in New Issue
Block a user