mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Enable automatic formatting for `sphinx/ext/doctest.py
`
This commit is contained in:
parent
aecb60c057
commit
01d993b359
@ -415,7 +415,6 @@ exclude = [
|
|||||||
"sphinx/domains/python/_object.py",
|
"sphinx/domains/python/_object.py",
|
||||||
"sphinx/domains/rst.py",
|
"sphinx/domains/rst.py",
|
||||||
"sphinx/domains/std/__init__.py",
|
"sphinx/domains/std/__init__.py",
|
||||||
"sphinx/ext/doctest.py",
|
|
||||||
"sphinx/ext/duration.py",
|
"sphinx/ext/duration.py",
|
||||||
"sphinx/ext/extlinks.py",
|
"sphinx/ext/extlinks.py",
|
||||||
"sphinx/ext/githubpages.py",
|
"sphinx/ext/githubpages.py",
|
||||||
|
@ -61,6 +61,7 @@ def is_allowed_version(spec: str, version: str) -> bool:
|
|||||||
|
|
||||||
# set up the necessary directives
|
# set up the necessary directives
|
||||||
|
|
||||||
|
|
||||||
class TestDirective(SphinxDirective):
|
class TestDirective(SphinxDirective):
|
||||||
"""
|
"""
|
||||||
Base class for doctest-related directives.
|
Base class for doctest-related directives.
|
||||||
@ -81,7 +82,10 @@ class TestDirective(SphinxDirective):
|
|||||||
# convert <BLANKLINE>s to ordinary blank lines for presentation
|
# convert <BLANKLINE>s to ordinary blank lines for presentation
|
||||||
test = code
|
test = code
|
||||||
code = blankline_re.sub('', code)
|
code = blankline_re.sub('', code)
|
||||||
if doctestopt_re.search(code) and 'no-trim-doctest-flags' not in self.options:
|
if (
|
||||||
|
doctestopt_re.search(code)
|
||||||
|
and 'no-trim-doctest-flags' not in self.options
|
||||||
|
):
|
||||||
if not test:
|
if not test:
|
||||||
test = code
|
test = code
|
||||||
code = doctestopt_re.sub('', code)
|
code = doctestopt_re.sub('', code)
|
||||||
@ -113,15 +117,17 @@ class TestDirective(SphinxDirective):
|
|||||||
if prefix not in '+-':
|
if prefix not in '+-':
|
||||||
self.state.document.reporter.warning(
|
self.state.document.reporter.warning(
|
||||||
__("missing '+' or '-' in '%s' option.") % option,
|
__("missing '+' or '-' in '%s' option.") % option,
|
||||||
line=self.lineno)
|
line=self.lineno,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
if option_name not in doctest.OPTIONFLAGS_BY_NAME:
|
if option_name not in doctest.OPTIONFLAGS_BY_NAME:
|
||||||
self.state.document.reporter.warning(
|
self.state.document.reporter.warning(
|
||||||
__("'%s' is not a valid option.") % option_name,
|
__("'%s' is not a valid option.") % option_name,
|
||||||
line=self.lineno)
|
line=self.lineno,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]]
|
flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]]
|
||||||
node['options'][flag] = (option[0] == '+')
|
node['options'][flag] = option[0] == '+'
|
||||||
if self.name == 'doctest' and 'pyversion' in self.options:
|
if self.name == 'doctest' and 'pyversion' in self.options:
|
||||||
try:
|
try:
|
||||||
spec = self.options['pyversion']
|
spec = self.options['pyversion']
|
||||||
@ -131,8 +137,8 @@ class TestDirective(SphinxDirective):
|
|||||||
node['options'][flag] = True # Skip the test
|
node['options'][flag] = True # Skip the test
|
||||||
except InvalidSpecifier:
|
except InvalidSpecifier:
|
||||||
self.state.document.reporter.warning(
|
self.state.document.reporter.warning(
|
||||||
__("'%s' is not a valid pyversion option") % spec,
|
__("'%s' is not a valid pyversion option") % spec, line=self.lineno
|
||||||
line=self.lineno)
|
)
|
||||||
if 'skipif' in self.options:
|
if 'skipif' in self.options:
|
||||||
node['skipif'] = self.options['skipif']
|
node['skipif'] = self.options['skipif']
|
||||||
if 'trim-doctest-flags' in self.options:
|
if 'trim-doctest-flags' in self.options:
|
||||||
@ -191,6 +197,7 @@ parser = doctest.DocTestParser()
|
|||||||
|
|
||||||
# helper classes
|
# helper classes
|
||||||
|
|
||||||
|
|
||||||
class TestGroup:
|
class TestGroup:
|
||||||
def __init__(self, name: str) -> None:
|
def __init__(self, name: str) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -220,13 +227,21 @@ class TestGroup:
|
|||||||
raise RuntimeError(__('invalid TestCode type'))
|
raise RuntimeError(__('invalid TestCode type'))
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (f'TestGroup(name={self.name!r}, setup={self.setup!r}, '
|
return (
|
||||||
f'cleanup={self.cleanup!r}, tests={self.tests!r})')
|
f'TestGroup(name={self.name!r}, setup={self.setup!r}, '
|
||||||
|
f'cleanup={self.cleanup!r}, tests={self.tests!r})'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCode:
|
class TestCode:
|
||||||
def __init__(self, code: str, type: str, filename: str,
|
def __init__(
|
||||||
lineno: int, options: dict | None = None) -> None:
|
self,
|
||||||
|
code: str,
|
||||||
|
type: str,
|
||||||
|
filename: str,
|
||||||
|
lineno: int,
|
||||||
|
options: dict | None = None,
|
||||||
|
) -> None:
|
||||||
self.code = code
|
self.code = code
|
||||||
self.type = type
|
self.type = type
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
@ -234,12 +249,15 @@ class TestCode:
|
|||||||
self.options = options or {}
|
self.options = options or {}
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (f'TestCode({self.code!r}, {self.type!r}, filename={self.filename!r}, '
|
return (
|
||||||
f'lineno={self.lineno!r}, options={self.options!r})')
|
f'TestCode({self.code!r}, {self.type!r}, filename={self.filename!r}, '
|
||||||
|
f'lineno={self.lineno!r}, options={self.options!r})'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SphinxDocTestRunner(doctest.DocTestRunner):
|
class SphinxDocTestRunner(doctest.DocTestRunner):
|
||||||
def summarize(self, out: Callable, verbose: bool | None = None, # type: ignore[override]
|
def summarize( # type: ignore[override]
|
||||||
|
self, out: Callable, verbose: bool | None = None
|
||||||
) -> tuple[int, int]:
|
) -> tuple[int, int]:
|
||||||
string_io = StringIO()
|
string_io = StringIO()
|
||||||
old_stdout = sys.stdout
|
old_stdout = sys.stdout
|
||||||
@ -251,11 +269,11 @@ class SphinxDocTestRunner(doctest.DocTestRunner):
|
|||||||
out(string_io.getvalue())
|
out(string_io.getvalue())
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _DocTestRunner__patched_linecache_getlines(self, filename: str,
|
def _DocTestRunner__patched_linecache_getlines(
|
||||||
module_globals: Any = None) -> Any:
|
self, filename: str, module_globals: Any = None
|
||||||
|
) -> Any:
|
||||||
# this is overridden from DocTestRunner adding the try-except below
|
# this is overridden from DocTestRunner adding the try-except below
|
||||||
m = self._DocTestRunner__LINECACHE_FILENAME_RE.match( # type: ignore[attr-defined]
|
m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename) # type: ignore[attr-defined]
|
||||||
filename)
|
|
||||||
if m and m.group('name') == self.test.name:
|
if m and m.group('name') == self.test.name:
|
||||||
try:
|
try:
|
||||||
example = self.test.examples[int(m.group('examplenum'))]
|
example = self.test.examples[int(m.group('examplenum'))]
|
||||||
@ -266,20 +284,22 @@ class SphinxDocTestRunner(doctest.DocTestRunner):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return example.source.splitlines(True)
|
return example.source.splitlines(True)
|
||||||
return self.save_linecache_getlines( # type: ignore[attr-defined]
|
return self.save_linecache_getlines(filename, module_globals) # type: ignore[attr-defined]
|
||||||
filename, module_globals)
|
|
||||||
|
|
||||||
|
|
||||||
# the new builder -- use sphinx-build.py -b doctest to run
|
# the new builder -- use sphinx-build.py -b doctest to run
|
||||||
|
|
||||||
|
|
||||||
class DocTestBuilder(Builder):
|
class DocTestBuilder(Builder):
|
||||||
"""
|
"""
|
||||||
Runs test snippets in the documentation.
|
Runs test snippets in the documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = 'doctest'
|
name = 'doctest'
|
||||||
epilog = __('Testing of doctests in the sources finished, look at the '
|
epilog = __(
|
||||||
'results in %(outdir)s/output.txt.')
|
'Testing of doctests in the sources finished, look at the '
|
||||||
|
'results in %(outdir)s/output.txt.'
|
||||||
|
)
|
||||||
|
|
||||||
def init(self) -> None:
|
def init(self) -> None:
|
||||||
# default options
|
# default options
|
||||||
@ -307,9 +327,11 @@ class DocTestBuilder(Builder):
|
|||||||
|
|
||||||
outpath = self.outdir.joinpath('output.txt')
|
outpath = self.outdir.joinpath('output.txt')
|
||||||
self.outfile = outpath.open('w', encoding='utf-8') # NoQA: SIM115
|
self.outfile = outpath.open('w', encoding='utf-8') # NoQA: SIM115
|
||||||
self.outfile.write(('Results of doctest builder run on %s\n'
|
line = '=' * len(date)
|
||||||
'==================================%s\n') %
|
self.outfile.write(
|
||||||
(date, '=' * len(date)))
|
f'Results of doctest builder run on {date}\n'
|
||||||
|
f'=================================={line}\n'
|
||||||
|
)
|
||||||
|
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
# free resources upon destruction (the file handler might not be
|
# free resources upon destruction (the file handler might not be
|
||||||
@ -338,18 +360,17 @@ class DocTestBuilder(Builder):
|
|||||||
# write executive summary
|
# write executive summary
|
||||||
def s(v: int) -> str:
|
def s(v: int) -> str:
|
||||||
return 's' if v != 1 else ''
|
return 's' if v != 1 else ''
|
||||||
repl = (self.total_tries, s(self.total_tries),
|
|
||||||
self.total_failures, s(self.total_failures),
|
self._out(
|
||||||
self.setup_failures, s(self.setup_failures),
|
f"""
|
||||||
self.cleanup_failures, s(self.cleanup_failures))
|
|
||||||
self._out('''
|
|
||||||
Doctest summary
|
Doctest summary
|
||||||
===============
|
===============
|
||||||
%5d test%s
|
{self.total_tries:5} test{s(self.total_tries)}
|
||||||
%5d failure%s in tests
|
{self.total_failures:5} failure{s(self.total_failures)} in tests
|
||||||
%5d failure%s in setup code
|
{self.setup_failures:5} failure{s(self.setup_failures)} in setup code
|
||||||
%5d failure%s in cleanup code
|
{self.cleanup_failures:5} failure{s(self.cleanup_failures)} in cleanup code
|
||||||
''' % repl)
|
"""
|
||||||
|
)
|
||||||
self.outfile.close()
|
self.outfile.close()
|
||||||
|
|
||||||
if self.total_failures or self.setup_failures or self.cleanup_failures:
|
if self.total_failures or self.setup_failures or self.cleanup_failures:
|
||||||
@ -367,10 +388,10 @@ Doctest summary
|
|||||||
filename of the document it's included in.
|
filename of the document it's included in.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
filename = relpath(node.source, self.env.srcdir).rsplit(':docstring of ', maxsplit=1)[0] # type: ignore[arg-type] # noqa: E501
|
filename = relpath(node.source, self.env.srcdir) # type: ignore[arg-type]
|
||||||
|
return filename.rsplit(':docstring of ', maxsplit=1)[0]
|
||||||
except Exception:
|
except Exception:
|
||||||
filename = str(self.env.doc2path(docname, False))
|
return str(self.env.doc2path(docname, False))
|
||||||
return filename
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_line_number(node: Node) -> int | None:
|
def get_line_number(node: Node) -> int | None:
|
||||||
@ -404,25 +425,29 @@ Doctest summary
|
|||||||
def test_doc(self, docname: str, doctree: Node) -> None:
|
def test_doc(self, docname: str, doctree: Node) -> None:
|
||||||
groups: dict[str, TestGroup] = {}
|
groups: dict[str, TestGroup] = {}
|
||||||
add_to_all_groups = []
|
add_to_all_groups = []
|
||||||
self.setup_runner = SphinxDocTestRunner(verbose=False,
|
self.setup_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt)
|
||||||
optionflags=self.opt)
|
self.test_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt)
|
||||||
self.test_runner = SphinxDocTestRunner(verbose=False,
|
self.cleanup_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt)
|
||||||
optionflags=self.opt)
|
|
||||||
self.cleanup_runner = SphinxDocTestRunner(verbose=False,
|
|
||||||
optionflags=self.opt)
|
|
||||||
|
|
||||||
self.test_runner._fakeout = self.setup_runner._fakeout # type: ignore[attr-defined]
|
self.test_runner._fakeout = self.setup_runner._fakeout # type: ignore[attr-defined]
|
||||||
self.cleanup_runner._fakeout = self.setup_runner._fakeout # type: ignore[attr-defined]
|
self.cleanup_runner._fakeout = self.setup_runner._fakeout # type: ignore[attr-defined]
|
||||||
|
|
||||||
if self.config.doctest_test_doctest_blocks:
|
if self.config.doctest_test_doctest_blocks:
|
||||||
|
|
||||||
def condition(node: Node) -> bool:
|
def condition(node: Node) -> bool:
|
||||||
return (isinstance(node, nodes.literal_block | nodes.comment) and
|
return (
|
||||||
'testnodetype' in node) or \
|
isinstance(node, nodes.literal_block | nodes.comment)
|
||||||
isinstance(node, nodes.doctest_block)
|
|
||||||
else:
|
|
||||||
def condition(node: Node) -> bool:
|
|
||||||
return isinstance(node, nodes.literal_block | nodes.comment) \
|
|
||||||
and 'testnodetype' in node
|
and 'testnodetype' in node
|
||||||
|
) or isinstance(node, nodes.doctest_block)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
def condition(node: Node) -> bool:
|
||||||
|
return (
|
||||||
|
isinstance(node, nodes.literal_block | nodes.comment)
|
||||||
|
and 'testnodetype' in node
|
||||||
|
)
|
||||||
|
|
||||||
for node in doctree.findall(condition):
|
for node in doctree.findall(condition):
|
||||||
if self.skipped(node): # type: ignore[arg-type]
|
if self.skipped(node): # type: ignore[arg-type]
|
||||||
continue
|
continue
|
||||||
@ -431,12 +456,19 @@ Doctest summary
|
|||||||
filename = self.get_filename_for_node(node, docname)
|
filename = self.get_filename_for_node(node, docname)
|
||||||
line_number = self.get_line_number(node)
|
line_number = self.get_line_number(node)
|
||||||
if not source:
|
if not source:
|
||||||
logger.warning(__('no code/output in %s block at %s:%s'),
|
logger.warning(
|
||||||
|
__('no code/output in %s block at %s:%s'),
|
||||||
node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
|
node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
|
||||||
filename, line_number)
|
filename,
|
||||||
code = TestCode(source, type=node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
|
line_number,
|
||||||
filename=filename, lineno=line_number, # type: ignore[arg-type]
|
)
|
||||||
options=node.get('options')) # type: ignore[attr-defined]
|
code = TestCode(
|
||||||
|
source,
|
||||||
|
type=node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
|
||||||
|
filename=filename,
|
||||||
|
lineno=line_number, # type: ignore[arg-type]
|
||||||
|
options=node.get('options'), # type: ignore[attr-defined]
|
||||||
|
)
|
||||||
node_groups = node.get('groups', ['default']) # type: ignore[attr-defined]
|
node_groups = node.get('groups', ['default']) # type: ignore[attr-defined]
|
||||||
if '*' in node_groups:
|
if '*' in node_groups:
|
||||||
add_to_all_groups.append(code)
|
add_to_all_groups.append(code)
|
||||||
@ -449,13 +481,21 @@ Doctest summary
|
|||||||
for group in groups.values():
|
for group in groups.values():
|
||||||
group.add_code(code)
|
group.add_code(code)
|
||||||
if self.config.doctest_global_setup:
|
if self.config.doctest_global_setup:
|
||||||
code = TestCode(self.config.doctest_global_setup,
|
code = TestCode(
|
||||||
'testsetup', filename='<global_setup>', lineno=0)
|
self.config.doctest_global_setup,
|
||||||
|
'testsetup',
|
||||||
|
filename='<global_setup>',
|
||||||
|
lineno=0,
|
||||||
|
)
|
||||||
for group in groups.values():
|
for group in groups.values():
|
||||||
group.add_code(code, prepend=True)
|
group.add_code(code, prepend=True)
|
||||||
if self.config.doctest_global_cleanup:
|
if self.config.doctest_global_cleanup:
|
||||||
code = TestCode(self.config.doctest_global_cleanup,
|
code = TestCode(
|
||||||
'testcleanup', filename='<global_cleanup>', lineno=0)
|
self.config.doctest_global_cleanup,
|
||||||
|
'testcleanup',
|
||||||
|
filename='<global_cleanup>',
|
||||||
|
lineno=0,
|
||||||
|
)
|
||||||
for group in groups.values():
|
for group in groups.values():
|
||||||
group.add_code(code)
|
group.add_code(code)
|
||||||
if not groups:
|
if not groups:
|
||||||
@ -463,9 +503,7 @@ Doctest summary
|
|||||||
|
|
||||||
show_successes = self.config.doctest_show_successes
|
show_successes = self.config.doctest_show_successes
|
||||||
if show_successes:
|
if show_successes:
|
||||||
self._out('\n'
|
self._out(f'\nDocument: {docname}\n----------{"-" * len(docname)}\n')
|
||||||
f'Document: {docname}\n'
|
|
||||||
f'----------{"-" * len(docname)}\n')
|
|
||||||
for group in groups.values():
|
for group in groups.values():
|
||||||
self.test_group(group)
|
self.test_group(group)
|
||||||
# Separately count results from setup code
|
# Separately count results from setup code
|
||||||
@ -473,23 +511,27 @@ Doctest summary
|
|||||||
self.setup_failures += res_f
|
self.setup_failures += res_f
|
||||||
self.setup_tries += res_t
|
self.setup_tries += res_t
|
||||||
if self.test_runner.tries:
|
if self.test_runner.tries:
|
||||||
res_f, res_t = self.test_runner.summarize(
|
res_f, res_t = self.test_runner.summarize(self._out, verbose=show_successes)
|
||||||
self._out, verbose=show_successes)
|
|
||||||
self.total_failures += res_f
|
self.total_failures += res_f
|
||||||
self.total_tries += res_t
|
self.total_tries += res_t
|
||||||
if self.cleanup_runner.tries:
|
if self.cleanup_runner.tries:
|
||||||
res_f, res_t = self.cleanup_runner.summarize(
|
res_f, res_t = self.cleanup_runner.summarize(
|
||||||
self._out, verbose=show_successes)
|
self._out, verbose=show_successes
|
||||||
|
)
|
||||||
self.cleanup_failures += res_f
|
self.cleanup_failures += res_f
|
||||||
self.cleanup_tries += res_t
|
self.cleanup_tries += res_t
|
||||||
|
|
||||||
def compile(self, code: str, name: str, type: str, flags: Any, dont_inherit: bool) -> Any:
|
def compile(
|
||||||
|
self, code: str, name: str, type: str, flags: Any, dont_inherit: bool
|
||||||
|
) -> Any:
|
||||||
return compile(code, name, self.type, flags, dont_inherit)
|
return compile(code, name, self.type, flags, dont_inherit)
|
||||||
|
|
||||||
def test_group(self, group: TestGroup) -> None:
|
def test_group(self, group: TestGroup) -> None:
|
||||||
ns: dict = {}
|
ns: dict = {}
|
||||||
|
|
||||||
def run_setup_cleanup(runner: Any, testcodes: list[TestCode], what: Any) -> bool:
|
def run_setup_cleanup(
|
||||||
|
runner: Any, testcodes: list[TestCode], what: Any
|
||||||
|
) -> bool:
|
||||||
examples = []
|
examples = []
|
||||||
for testcode in testcodes:
|
for testcode in testcodes:
|
||||||
example = doctest.Example(testcode.code, '', lineno=testcode.lineno)
|
example = doctest.Example(testcode.code, '', lineno=testcode.lineno)
|
||||||
@ -497,9 +539,14 @@ Doctest summary
|
|||||||
if not examples:
|
if not examples:
|
||||||
return True
|
return True
|
||||||
# simulate a doctest with the code
|
# simulate a doctest with the code
|
||||||
sim_doctest = doctest.DocTest(examples, {},
|
sim_doctest = doctest.DocTest(
|
||||||
|
examples,
|
||||||
|
{},
|
||||||
f'{group.name} ({what} code)',
|
f'{group.name} ({what} code)',
|
||||||
testcodes[0].filename, 0, None)
|
testcodes[0].filename,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
)
|
||||||
sim_doctest.globs = ns
|
sim_doctest.globs = ns
|
||||||
old_f = runner.failures
|
old_f = runner.failures
|
||||||
self.type = 'exec' # the snippet may contain multiple statements
|
self.type = 'exec' # the snippet may contain multiple statements
|
||||||
@ -516,11 +563,15 @@ Doctest summary
|
|||||||
if len(code) == 1:
|
if len(code) == 1:
|
||||||
# ordinary doctests (code/output interleaved)
|
# ordinary doctests (code/output interleaved)
|
||||||
try:
|
try:
|
||||||
test = parser.get_doctest(code[0].code, {}, group.name,
|
test = parser.get_doctest(
|
||||||
code[0].filename, code[0].lineno)
|
code[0].code, {}, group.name, code[0].filename, code[0].lineno
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning(__('ignoring invalid doctest code: %r'), code[0].code,
|
logger.warning(
|
||||||
location=(code[0].filename, code[0].lineno))
|
__('ignoring invalid doctest code: %r'),
|
||||||
|
code[0].code,
|
||||||
|
location=(code[0].filename, code[0].lineno),
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
if not test.examples:
|
if not test.examples:
|
||||||
continue
|
continue
|
||||||
@ -542,10 +593,21 @@ Doctest summary
|
|||||||
exc_msg = m.group('msg')
|
exc_msg = m.group('msg')
|
||||||
else:
|
else:
|
||||||
exc_msg = None
|
exc_msg = None
|
||||||
example = doctest.Example(code[0].code, output, exc_msg=exc_msg,
|
example = doctest.Example(
|
||||||
lineno=code[0].lineno, options=options)
|
code[0].code,
|
||||||
test = doctest.DocTest([example], {}, group.name,
|
output,
|
||||||
code[0].filename, code[0].lineno, None)
|
exc_msg=exc_msg,
|
||||||
|
lineno=code[0].lineno,
|
||||||
|
options=options,
|
||||||
|
)
|
||||||
|
test = doctest.DocTest(
|
||||||
|
[example],
|
||||||
|
{},
|
||||||
|
group.name,
|
||||||
|
code[0].filename,
|
||||||
|
code[0].lineno,
|
||||||
|
None,
|
||||||
|
)
|
||||||
self.type = 'exec' # multiple statements again
|
self.type = 'exec' # multiple statements again
|
||||||
# DocTest.__init__ copies the globs namespace, which we don't want
|
# DocTest.__init__ copies the globs namespace, which we don't want
|
||||||
test.globs = ns
|
test.globs = ns
|
||||||
@ -571,6 +633,9 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|||||||
app.add_config_value('doctest_global_cleanup', '', '')
|
app.add_config_value('doctest_global_cleanup', '', '')
|
||||||
app.add_config_value(
|
app.add_config_value(
|
||||||
'doctest_default_flags',
|
'doctest_default_flags',
|
||||||
doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL,
|
doctest.DONT_ACCEPT_TRUE_FOR_1
|
||||||
'')
|
| doctest.ELLIPSIS
|
||||||
|
| doctest.IGNORE_EXCEPTION_DETAIL,
|
||||||
|
'',
|
||||||
|
)
|
||||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||||
|
Loading…
Reference in New Issue
Block a user