summaryrefslogtreecommitdiff
path: root/sphinx/ext/doctest.py
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2019-07-03 02:01:42 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2019-07-04 11:49:09 +0900
commitdcff6d7cbceea55f681284c327b24169f4285ae2 (patch)
tree972b4aa06e67ae713c9ebaf3bf955d24857dd7b5 /sphinx/ext/doctest.py
parentf82d6c429b6379663b71cba783e780535d73343b (diff)
downloadsphinx-git-dcff6d7cbceea55f681284c327b24169f4285ae2.tar.gz
Migrate to py3 style type annotation: sphinx.ext.doctest
Diffstat (limited to 'sphinx/ext/doctest.py')
-rw-r--r--sphinx/ext/doctest.py99
1 files changed, 38 insertions, 61 deletions
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
index 01ab38efe..68df253d5 100644
--- a/sphinx/ext/doctest.py
+++ b/sphinx/ext/doctest.py
@@ -16,8 +16,10 @@ import time
import warnings
from io import StringIO
from os import path
+from typing import Any, Callable, Dict, Iterable, List, Sequence, Set, Tuple, Type
from docutils import nodes
+from docutils.nodes import Element, Node, TextElement
from docutils.parsers.rst import directives
from packaging.specifiers import SpecifierSet, InvalidSpecifier
from packaging.version import Version
@@ -33,8 +35,8 @@ from sphinx.util.osutil import relpath
if False:
# For type annotation
- from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Type # NOQA
- from sphinx.application import Sphinx # NOQA
+ from sphinx.application import Sphinx
+
logger = logging.getLogger(__name__)
@@ -42,15 +44,13 @@ blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
-def doctest_encode(text, encoding):
- # type: (str, str) -> str
+def doctest_encode(text: str, encoding: str) -> str:
warnings.warn('doctest_encode() is deprecated.',
RemovedInSphinx40Warning)
return text
-def is_allowed_version(spec, version):
- # type: (str, str) -> bool
+def is_allowed_version(spec: str, version: str) -> bool:
"""Check `spec` satisfies `version` or not.
This obeys PEP-440 specifiers:
@@ -80,8 +80,7 @@ class TestDirective(SphinxDirective):
optional_arguments = 1
final_argument_whitespace = True
- def run(self):
- # type: () -> List[nodes.Node]
+ def run(self) -> List[Node]:
# 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(self.content)
@@ -95,7 +94,7 @@ class TestDirective(SphinxDirective):
if not test:
test = code
code = doctestopt_re.sub('', code)
- nodetype = nodes.literal_block # type: Type[nodes.TextElement]
+ nodetype = nodes.literal_block # type: Type[TextElement]
if self.name in ('testsetup', 'testcleanup') or 'hide' in self.options:
nodetype = nodes.comment
if self.arguments:
@@ -194,15 +193,13 @@ parser = doctest.DocTestParser()
# helper classes
class TestGroup:
- def __init__(self, name):
- # type: (str) -> None
+ def __init__(self, name: str) -> None:
self.name = name
self.setup = [] # type: List[TestCode]
self.tests = [] # type: List[List[TestCode]]
self.cleanup = [] # type: List[TestCode]
- def add_code(self, code, prepend=False):
- # type: (TestCode, bool) -> None
+ def add_code(self, code: "TestCode", prepend: bool = False) -> None:
if code.type == 'testsetup':
if prepend:
self.setup.insert(0, code)
@@ -220,30 +217,28 @@ class TestGroup:
else:
raise RuntimeError(__('invalid TestCode type'))
- def __repr__(self):
- # type: () -> str
+ def __repr__(self) -> str:
return 'TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r)' % (
self.name, self.setup, self.cleanup, self.tests)
class TestCode:
- def __init__(self, code, type, filename, lineno, options=None):
- # type: (str, str, Optional[str], int, Optional[Dict]) -> None
+ def __init__(self, code: str, type: str, filename: str,
+ lineno: int, options: Dict = None) -> None:
self.code = code
self.type = type
self.filename = filename
self.lineno = lineno
self.options = options or {}
- def __repr__(self):
- # type: () -> str
+ def __repr__(self) -> str:
return 'TestCode(%r, %r, filename=%r, lineno=%r, options=%r)' % (
self.code, self.type, self.filename, self.lineno, self.options)
class SphinxDocTestRunner(doctest.DocTestRunner):
- def summarize(self, out, verbose=None): # type: ignore
- # type: (Callable, bool) -> Tuple[int, int]
+ def summarize(self, out: Callable, verbose: bool = None # type: ignore
+ ) -> Tuple[int, int]:
string_io = StringIO()
old_stdout = sys.stdout
sys.stdout = string_io
@@ -254,9 +249,8 @@ class SphinxDocTestRunner(doctest.DocTestRunner):
out(string_io.getvalue())
return res
- def _DocTestRunner__patched_linecache_getlines(self, filename,
- module_globals=None):
- # type: (str, Any) -> Any
+ def _DocTestRunner__patched_linecache_getlines(self, filename: str,
+ module_globals: Any = None) -> Any:
# this is overridden from DocTestRunner adding the try-except below
m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename) # type: ignore
if m and m.group('name') == self.test.name:
@@ -282,8 +276,7 @@ class DocTestBuilder(Builder):
epilog = __('Testing of doctests in the sources finished, look at the '
'results in %(outdir)s/output.txt.')
- def init(self):
- # type: () -> None
+ def init(self) -> None:
# default options
self.opt = self.config.doctest_default_flags
@@ -312,32 +305,26 @@ class DocTestBuilder(Builder):
'==================================%s\n') %
(date, '=' * len(date)))
- def _out(self, text):
- # type: (str) -> None
+ def _out(self, text: str) -> None:
logger.info(text, nonl=True)
self.outfile.write(text)
- def _warn_out(self, text):
- # type: (str) -> None
+ def _warn_out(self, text: str) -> None:
if self.app.quiet or self.app.warningiserror:
logger.warning(text)
else:
logger.info(text, nonl=True)
self.outfile.write(text)
- def get_target_uri(self, docname, typ=None):
- # type: (str, str) -> str
+ def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
- def get_outdated_docs(self):
- # type: () -> Set[str]
+ def get_outdated_docs(self) -> Set[str]:
return self.env.found_docs
- def finish(self):
- # type: () -> None
+ def finish(self) -> None:
# write executive summary
- def s(v):
- # type: (int) -> str
+ def s(v: int) -> str:
return v != 1 and 's' or ''
repl = (self.total_tries, s(self.total_tries),
self.total_failures, s(self.total_failures),
@@ -356,8 +343,8 @@ Doctest summary
if self.total_failures or self.setup_failures or self.cleanup_failures:
self.app.statuscode = 1
- def write(self, build_docnames, updated_docnames, method='update'):
- # type: (Iterable[str], Sequence[str], str) -> None
+ def write(self, build_docnames: Iterable[str], updated_docnames: Sequence[str],
+ method: str = 'update') -> None:
if build_docnames is None:
build_docnames = sorted(self.env.all_docs)
@@ -367,8 +354,7 @@ Doctest summary
doctree = self.env.get_doctree(docname)
self.test_doc(docname, doctree)
- def get_filename_for_node(self, node, docname):
- # type: (nodes.Node, str) -> str
+ def get_filename_for_node(self, node: Node, docname: str) -> str:
"""Try to get the file which actually contains the doctest, not the
filename of the document it's included in."""
try:
@@ -379,8 +365,7 @@ Doctest summary
return filename
@staticmethod
- def get_line_number(node):
- # type: (nodes.Node) -> Optional[int]
+ def get_line_number(node: Node) -> int:
"""Get the real line number or admit we don't know."""
# TODO: Work out how to store or calculate real (file-relative)
# line numbers for doctest blocks in docstrings.
@@ -395,8 +380,7 @@ Doctest summary
return node.line - 1
return None
- def skipped(self, node):
- # type: (nodes.Element) -> bool
+ def skipped(self, node: Element) -> bool:
if 'skipif' not in node:
return False
else:
@@ -409,8 +393,7 @@ Doctest summary
exec(self.config.doctest_global_cleanup, context)
return should_skip
- def test_doc(self, docname, doctree):
- # type: (str, nodes.Node) -> None
+ def test_doc(self, docname: str, doctree: Node) -> None:
groups = {} # type: Dict[str, TestGroup]
add_to_all_groups = []
self.setup_runner = SphinxDocTestRunner(verbose=False,
@@ -424,17 +407,15 @@ Doctest summary
self.cleanup_runner._fakeout = self.setup_runner._fakeout # type: ignore
if self.config.doctest_test_doctest_blocks:
- def condition(node):
- # type: (nodes.Node) -> bool
+ def condition(node: Node) -> bool:
return (isinstance(node, (nodes.literal_block, nodes.comment)) and
'testnodetype' in node) or \
isinstance(node, nodes.doctest_block)
else:
- def condition(node):
- # type: (nodes.Node) -> bool
+ def condition(node: Node) -> bool:
return isinstance(node, (nodes.literal_block, nodes.comment)) \
and 'testnodetype' in node
- for node in doctree.traverse(condition): # type: nodes.Element
+ for node in doctree.traverse(condition): # type: Element
if self.skipped(node):
continue
@@ -490,16 +471,13 @@ Doctest summary
self.cleanup_failures += res_f
self.cleanup_tries += res_t
- def compile(self, code, name, type, flags, dont_inherit):
- # type: (str, str, str, Any, 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)
- def test_group(self, group):
- # type: (TestGroup) -> None
+ def test_group(self, group: TestGroup) -> None:
ns = {} # type: Dict
- def run_setup_cleanup(runner, testcodes, what):
- # type: (Any, List[TestCode], Any) -> bool
+ def run_setup_cleanup(runner: Any, testcodes: List[TestCode], what: Any) -> bool:
examples = []
for testcode in testcodes:
example = doctest.Example(testcode.code, '', lineno=testcode.lineno)
@@ -568,8 +546,7 @@ Doctest summary
run_setup_cleanup(self.cleanup_runner, group.cleanup, 'cleanup')
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_directive('testsetup', TestsetupDirective)
app.add_directive('testcleanup', TestcleanupDirective)
app.add_directive('doctest', DoctestDirective)