aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/doctest.py
diff options
context:
space:
mode:
authordeshevoy <deshevoy@yandex-team.ru>2022-02-10 16:46:57 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:57 +0300
commit28148f76dbfcc644d96427d41c92f36cbf2fdc6e (patch)
treeb83306b6e37edeea782e9eed673d89286c4fef35 /contrib/python/pytest/py3/_pytest/doctest.py
parente988f30484abe5fdeedcc7a5d3c226c01a21800c (diff)
downloadydb-28148f76dbfcc644d96427d41c92f36cbf2fdc6e.tar.gz
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/doctest.py')
-rw-r--r--contrib/python/pytest/py3/_pytest/doctest.py720
1 files changed, 360 insertions, 360 deletions
diff --git a/contrib/python/pytest/py3/_pytest/doctest.py b/contrib/python/pytest/py3/_pytest/doctest.py
index 8e4b1ca6ad..64e8f0e0ee 100644
--- a/contrib/python/pytest/py3/_pytest/doctest.py
+++ b/contrib/python/pytest/py3/_pytest/doctest.py
@@ -1,9 +1,9 @@
"""Discover and run doctests in modules and test files."""
import bdb
import inspect
-import platform
-import sys
-import traceback
+import platform
+import sys
+import traceback
import types
import warnings
from contextlib import contextmanager
@@ -20,98 +20,98 @@ from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
from typing import Union
-
+
import py.path
-import pytest
+import pytest
from _pytest import outcomes
-from _pytest._code.code import ExceptionInfo
-from _pytest._code.code import ReprFileLocation
-from _pytest._code.code import TerminalRepr
+from _pytest._code.code import ExceptionInfo
+from _pytest._code.code import ReprFileLocation
+from _pytest._code.code import TerminalRepr
from _pytest._io import TerminalWriter
from _pytest.compat import safe_getattr
from _pytest.config import Config
from _pytest.config.argparsing import Parser
-from _pytest.fixtures import FixtureRequest
+from _pytest.fixtures import FixtureRequest
from _pytest.nodes import Collector
from _pytest.outcomes import OutcomeException
from _pytest.pathlib import import_path
from _pytest.python_api import approx
from _pytest.warning_types import PytestWarning
-
+
if TYPE_CHECKING:
import doctest
-DOCTEST_REPORT_CHOICE_NONE = "none"
-DOCTEST_REPORT_CHOICE_CDIFF = "cdiff"
-DOCTEST_REPORT_CHOICE_NDIFF = "ndiff"
-DOCTEST_REPORT_CHOICE_UDIFF = "udiff"
-DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE = "only_first_failure"
-
-DOCTEST_REPORT_CHOICES = (
- DOCTEST_REPORT_CHOICE_NONE,
- DOCTEST_REPORT_CHOICE_CDIFF,
- DOCTEST_REPORT_CHOICE_NDIFF,
- DOCTEST_REPORT_CHOICE_UDIFF,
- DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE,
-)
-
-# Lazy definition of runner class
-RUNNER_CLASS = None
+DOCTEST_REPORT_CHOICE_NONE = "none"
+DOCTEST_REPORT_CHOICE_CDIFF = "cdiff"
+DOCTEST_REPORT_CHOICE_NDIFF = "ndiff"
+DOCTEST_REPORT_CHOICE_UDIFF = "udiff"
+DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE = "only_first_failure"
+
+DOCTEST_REPORT_CHOICES = (
+ DOCTEST_REPORT_CHOICE_NONE,
+ DOCTEST_REPORT_CHOICE_CDIFF,
+ DOCTEST_REPORT_CHOICE_NDIFF,
+ DOCTEST_REPORT_CHOICE_UDIFF,
+ DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE,
+)
+
+# Lazy definition of runner class
+RUNNER_CLASS = None
# Lazy definition of output checker class
CHECKER_CLASS: Optional[Type["doctest.OutputChecker"]] = None
-
-
+
+
def pytest_addoption(parser: Parser) -> None:
- parser.addini(
- "doctest_optionflags",
- "option flags for doctests",
- type="args",
- default=["ELLIPSIS"],
- )
- parser.addini(
- "doctest_encoding", "encoding used for doctest files", default="utf-8"
- )
- group = parser.getgroup("collect")
- group.addoption(
- "--doctest-modules",
- action="store_true",
- default=False,
- help="run doctests in all .py modules",
- dest="doctestmodules",
- )
- group.addoption(
- "--doctest-report",
- type=str.lower,
- default="udiff",
- help="choose another output format for diffs on doctest failure",
- choices=DOCTEST_REPORT_CHOICES,
- dest="doctestreport",
- )
- group.addoption(
- "--doctest-glob",
- action="append",
- default=[],
- metavar="pat",
- help="doctests file matching pattern, default: test*.txt",
- dest="doctestglob",
- )
- group.addoption(
- "--doctest-ignore-import-errors",
- action="store_true",
- default=False,
- help="ignore doctest ImportErrors",
- dest="doctest_ignore_import_errors",
- )
- group.addoption(
- "--doctest-continue-on-failure",
- action="store_true",
- default=False,
- help="for a given doctest, continue to run after the first failure",
- dest="doctest_continue_on_failure",
- )
-
-
+ parser.addini(
+ "doctest_optionflags",
+ "option flags for doctests",
+ type="args",
+ default=["ELLIPSIS"],
+ )
+ parser.addini(
+ "doctest_encoding", "encoding used for doctest files", default="utf-8"
+ )
+ group = parser.getgroup("collect")
+ group.addoption(
+ "--doctest-modules",
+ action="store_true",
+ default=False,
+ help="run doctests in all .py modules",
+ dest="doctestmodules",
+ )
+ group.addoption(
+ "--doctest-report",
+ type=str.lower,
+ default="udiff",
+ help="choose another output format for diffs on doctest failure",
+ choices=DOCTEST_REPORT_CHOICES,
+ dest="doctestreport",
+ )
+ group.addoption(
+ "--doctest-glob",
+ action="append",
+ default=[],
+ metavar="pat",
+ help="doctests file matching pattern, default: test*.txt",
+ dest="doctestglob",
+ )
+ group.addoption(
+ "--doctest-ignore-import-errors",
+ action="store_true",
+ default=False,
+ help="ignore doctest ImportErrors",
+ dest="doctest_ignore_import_errors",
+ )
+ group.addoption(
+ "--doctest-continue-on-failure",
+ action="store_true",
+ default=False,
+ help="for a given doctest, continue to run after the first failure",
+ dest="doctest_continue_on_failure",
+ )
+
+
def pytest_unconfigure() -> None:
global RUNNER_CLASS
@@ -121,84 +121,84 @@ def pytest_unconfigure() -> None:
def pytest_collect_file(
path: py.path.local, parent: Collector,
) -> Optional[Union["DoctestModule", "DoctestTextfile"]]:
- config = parent.config
- if path.ext == ".py":
+ config = parent.config
+ if path.ext == ".py":
if config.option.doctestmodules and not _is_setup_py(path):
mod: DoctestModule = DoctestModule.from_parent(parent, fspath=path)
return mod
- elif _is_doctest(config, path, parent):
+ elif _is_doctest(config, path, parent):
txt: DoctestTextfile = DoctestTextfile.from_parent(parent, fspath=path)
return txt
return None
-
-
+
+
def _is_setup_py(path: py.path.local) -> bool:
- if path.basename != "setup.py":
- return False
+ if path.basename != "setup.py":
+ return False
contents = path.read_binary()
return b"setuptools" in contents or b"distutils" in contents
-
-
+
+
def _is_doctest(config: Config, path: py.path.local, parent) -> bool:
- if path.ext in (".txt", ".rst") and parent.session.isinitpath(path):
- return True
- globs = config.getoption("doctestglob") or ["test*.txt"]
- for glob in globs:
- if path.check(fnmatch=glob):
- return True
- return False
-
-
-class ReprFailDoctest(TerminalRepr):
+ if path.ext in (".txt", ".rst") and parent.session.isinitpath(path):
+ return True
+ globs = config.getoption("doctestglob") or ["test*.txt"]
+ for glob in globs:
+ if path.check(fnmatch=glob):
+ return True
+ return False
+
+
+class ReprFailDoctest(TerminalRepr):
def __init__(
self, reprlocation_lines: Sequence[Tuple[ReprFileLocation, Sequence[str]]]
) -> None:
- self.reprlocation_lines = reprlocation_lines
-
+ self.reprlocation_lines = reprlocation_lines
+
def toterminal(self, tw: TerminalWriter) -> None:
- for reprlocation, lines in self.reprlocation_lines:
- for line in lines:
- tw.line(line)
- reprlocation.toterminal(tw)
-
-
-class MultipleDoctestFailures(Exception):
+ for reprlocation, lines in self.reprlocation_lines:
+ for line in lines:
+ tw.line(line)
+ reprlocation.toterminal(tw)
+
+
+class MultipleDoctestFailures(Exception):
def __init__(self, failures: Sequence["doctest.DocTestFailure"]) -> None:
super().__init__()
- self.failures = failures
-
-
+ self.failures = failures
+
+
def _init_runner_class() -> Type["doctest.DocTestRunner"]:
- import doctest
-
- class PytestDoctestRunner(doctest.DebugRunner):
+ import doctest
+
+ class PytestDoctestRunner(doctest.DebugRunner):
"""Runner to collect failures.
Note that the out variable in this case is a list instead of a
stdout-like object.
- """
-
- def __init__(
+ """
+
+ def __init__(
self,
checker: Optional["doctest.OutputChecker"] = None,
verbose: Optional[bool] = None,
optionflags: int = 0,
continue_on_failure: bool = True,
) -> None:
- doctest.DebugRunner.__init__(
- self, checker=checker, verbose=verbose, optionflags=optionflags
- )
- self.continue_on_failure = continue_on_failure
-
+ doctest.DebugRunner.__init__(
+ self, checker=checker, verbose=verbose, optionflags=optionflags
+ )
+ self.continue_on_failure = continue_on_failure
+
def report_failure(
self, out, test: "doctest.DocTest", example: "doctest.Example", got: str,
) -> None:
- failure = doctest.DocTestFailure(test, example, got)
- if self.continue_on_failure:
- out.append(failure)
- else:
- raise failure
-
+ failure = doctest.DocTestFailure(test, example, got)
+ if self.continue_on_failure:
+ out.append(failure)
+ else:
+ raise failure
+
def report_unexpected_exception(
self,
out,
@@ -210,36 +210,36 @@ def _init_runner_class() -> Type["doctest.DocTestRunner"]:
raise exc_info[1]
if isinstance(exc_info[1], bdb.BdbQuit):
outcomes.exit("Quitting debugger")
- failure = doctest.UnexpectedException(test, example, exc_info)
- if self.continue_on_failure:
- out.append(failure)
- else:
- raise failure
-
- return PytestDoctestRunner
-
-
+ failure = doctest.UnexpectedException(test, example, exc_info)
+ if self.continue_on_failure:
+ out.append(failure)
+ else:
+ raise failure
+
+ return PytestDoctestRunner
+
+
def _get_runner(
checker: Optional["doctest.OutputChecker"] = None,
verbose: Optional[bool] = None,
optionflags: int = 0,
continue_on_failure: bool = True,
) -> "doctest.DocTestRunner":
- # We need this in order to do a lazy import on doctest
- global RUNNER_CLASS
- if RUNNER_CLASS is None:
- RUNNER_CLASS = _init_runner_class()
+ # We need this in order to do a lazy import on doctest
+ global RUNNER_CLASS
+ if RUNNER_CLASS is None:
+ RUNNER_CLASS = _init_runner_class()
# Type ignored because the continue_on_failure argument is only defined on
# PytestDoctestRunner, which is lazily defined so can't be used as a type.
return RUNNER_CLASS( # type: ignore
- checker=checker,
- verbose=verbose,
- optionflags=optionflags,
- continue_on_failure=continue_on_failure,
- )
-
-
-class DoctestItem(pytest.Item):
+ checker=checker,
+ verbose=verbose,
+ optionflags=optionflags,
+ continue_on_failure=continue_on_failure,
+ )
+
+
+class DoctestItem(pytest.Item):
def __init__(
self,
name: str,
@@ -248,11 +248,11 @@ class DoctestItem(pytest.Item):
dtest: Optional["doctest.DocTest"] = None,
) -> None:
super().__init__(name, parent)
- self.runner = runner
- self.dtest = dtest
- self.obj = None
+ self.runner = runner
+ self.dtest = dtest
+ self.obj = None
self.fixture_request: Optional[FixtureRequest] = None
-
+
@classmethod
def from_parent( # type: ignore
cls,
@@ -267,187 +267,187 @@ class DoctestItem(pytest.Item):
return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest)
def setup(self) -> None:
- if self.dtest is not None:
- self.fixture_request = _setup_fixtures(self)
- globs = dict(getfixture=self.fixture_request.getfixturevalue)
- for name, value in self.fixture_request.getfixturevalue(
- "doctest_namespace"
- ).items():
- globs[name] = value
- self.dtest.globs.update(globs)
-
+ if self.dtest is not None:
+ self.fixture_request = _setup_fixtures(self)
+ globs = dict(getfixture=self.fixture_request.getfixturevalue)
+ for name, value in self.fixture_request.getfixturevalue(
+ "doctest_namespace"
+ ).items():
+ globs[name] = value
+ self.dtest.globs.update(globs)
+
def runtest(self) -> None:
assert self.dtest is not None
assert self.runner is not None
- _check_all_skipped(self.dtest)
- self._disable_output_capturing_for_darwin()
+ _check_all_skipped(self.dtest)
+ self._disable_output_capturing_for_darwin()
failures: List["doctest.DocTestFailure"] = []
# Type ignored because we change the type of `out` from what
# doctest expects.
self.runner.run(self.dtest, out=failures) # type: ignore[arg-type]
- if failures:
- raise MultipleDoctestFailures(failures)
-
+ if failures:
+ raise MultipleDoctestFailures(failures)
+
def _disable_output_capturing_for_darwin(self) -> None:
"""Disable output capturing. Otherwise, stdout is lost to doctest (#985)."""
- if platform.system() != "Darwin":
- return
- capman = self.config.pluginmanager.getplugin("capturemanager")
- if capman:
- capman.suspend_global_capture(in_=True)
- out, err = capman.read_global_capture()
- sys.stdout.write(out)
- sys.stderr.write(err)
-
+ if platform.system() != "Darwin":
+ return
+ capman = self.config.pluginmanager.getplugin("capturemanager")
+ if capman:
+ capman.suspend_global_capture(in_=True)
+ out, err = capman.read_global_capture()
+ sys.stdout.write(out)
+ sys.stderr.write(err)
+
# TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override]
self, excinfo: ExceptionInfo[BaseException],
) -> Union[str, TerminalRepr]:
- import doctest
-
+ import doctest
+
failures: Optional[
Sequence[Union[doctest.DocTestFailure, doctest.UnexpectedException]]
] = (None)
if isinstance(
excinfo.value, (doctest.DocTestFailure, doctest.UnexpectedException)
):
- failures = [excinfo.value]
+ failures = [excinfo.value]
elif isinstance(excinfo.value, MultipleDoctestFailures):
- failures = excinfo.value.failures
-
- if failures is not None:
- reprlocation_lines = []
- for failure in failures:
- example = failure.example
- test = failure.test
- filename = test.filename
- if test.lineno is None:
- lineno = None
- else:
- lineno = test.lineno + example.lineno + 1
- message = type(failure).__name__
+ failures = excinfo.value.failures
+
+ if failures is not None:
+ reprlocation_lines = []
+ for failure in failures:
+ example = failure.example
+ test = failure.test
+ filename = test.filename
+ if test.lineno is None:
+ lineno = None
+ else:
+ lineno = test.lineno + example.lineno + 1
+ message = type(failure).__name__
# TODO: ReprFileLocation doesn't expect a None lineno.
reprlocation = ReprFileLocation(filename, lineno, message) # type: ignore[arg-type]
- checker = _get_checker()
- report_choice = _get_report_choice(
- self.config.getoption("doctestreport")
- )
- if lineno is not None:
+ checker = _get_checker()
+ report_choice = _get_report_choice(
+ self.config.getoption("doctestreport")
+ )
+ if lineno is not None:
assert failure.test.docstring is not None
- lines = failure.test.docstring.splitlines(False)
- # add line numbers to the left of the error message
+ lines = failure.test.docstring.splitlines(False)
+ # add line numbers to the left of the error message
assert test.lineno is not None
- lines = [
- "%03d %s" % (i + test.lineno + 1, x)
- for (i, x) in enumerate(lines)
- ]
- # trim docstring error lines to 10
- lines = lines[max(example.lineno - 9, 0) : example.lineno + 1]
- else:
- lines = [
- "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example"
- ]
- indent = ">>>"
- for line in example.source.splitlines():
+ lines = [
+ "%03d %s" % (i + test.lineno + 1, x)
+ for (i, x) in enumerate(lines)
+ ]
+ # trim docstring error lines to 10
+ lines = lines[max(example.lineno - 9, 0) : example.lineno + 1]
+ else:
+ lines = [
+ "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example"
+ ]
+ indent = ">>>"
+ for line in example.source.splitlines():
lines.append(f"??? {indent} {line}")
- indent = "..."
- if isinstance(failure, doctest.DocTestFailure):
- lines += checker.output_difference(
- example, failure.got, report_choice
- ).split("\n")
- else:
- inner_excinfo = ExceptionInfo(failure.exc_info)
- lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)]
+ indent = "..."
+ if isinstance(failure, doctest.DocTestFailure):
+ lines += checker.output_difference(
+ example, failure.got, report_choice
+ ).split("\n")
+ else:
+ inner_excinfo = ExceptionInfo(failure.exc_info)
+ lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)]
lines += [
x.strip("\n")
for x in traceback.format_exception(*failure.exc_info)
]
- reprlocation_lines.append((reprlocation, lines))
- return ReprFailDoctest(reprlocation_lines)
- else:
+ reprlocation_lines.append((reprlocation, lines))
+ return ReprFailDoctest(reprlocation_lines)
+ else:
return super().repr_failure(excinfo)
-
+
def reportinfo(self):
assert self.dtest is not None
- return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name
-
-
+ return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name
+
+
def _get_flag_lookup() -> Dict[str, int]:
- import doctest
-
- return dict(
- DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
- DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
- NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
- ELLIPSIS=doctest.ELLIPSIS,
- IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
- COMPARISON_FLAGS=doctest.COMPARISON_FLAGS,
- ALLOW_UNICODE=_get_allow_unicode_flag(),
- ALLOW_BYTES=_get_allow_bytes_flag(),
+ import doctest
+
+ return dict(
+ DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
+ DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
+ NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
+ ELLIPSIS=doctest.ELLIPSIS,
+ IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
+ COMPARISON_FLAGS=doctest.COMPARISON_FLAGS,
+ ALLOW_UNICODE=_get_allow_unicode_flag(),
+ ALLOW_BYTES=_get_allow_bytes_flag(),
NUMBER=_get_number_flag(),
- )
-
-
-def get_optionflags(parent):
- optionflags_str = parent.config.getini("doctest_optionflags")
- flag_lookup_table = _get_flag_lookup()
- flag_acc = 0
- for flag in optionflags_str:
- flag_acc |= flag_lookup_table[flag]
- return flag_acc
-
-
-def _get_continue_on_failure(config):
- continue_on_failure = config.getvalue("doctest_continue_on_failure")
- if continue_on_failure:
- # We need to turn off this if we use pdb since we should stop at
+ )
+
+
+def get_optionflags(parent):
+ optionflags_str = parent.config.getini("doctest_optionflags")
+ flag_lookup_table = _get_flag_lookup()
+ flag_acc = 0
+ for flag in optionflags_str:
+ flag_acc |= flag_lookup_table[flag]
+ return flag_acc
+
+
+def _get_continue_on_failure(config):
+ continue_on_failure = config.getvalue("doctest_continue_on_failure")
+ if continue_on_failure:
+ # We need to turn off this if we use pdb since we should stop at
# the first failure.
- if config.getvalue("usepdb"):
- continue_on_failure = False
- return continue_on_failure
-
-
-class DoctestTextfile(pytest.Module):
- obj = None
-
+ if config.getvalue("usepdb"):
+ continue_on_failure = False
+ return continue_on_failure
+
+
+class DoctestTextfile(pytest.Module):
+ obj = None
+
def collect(self) -> Iterable[DoctestItem]:
- import doctest
-
+ import doctest
+
# Inspired by doctest.testfile; ideally we would use it directly,
# but it doesn't support passing a custom checker.
- encoding = self.config.getini("doctest_encoding")
- text = self.fspath.read_text(encoding)
- filename = str(self.fspath)
- name = self.fspath.basename
- globs = {"__name__": "__main__"}
-
- optionflags = get_optionflags(self)
-
- runner = _get_runner(
+ encoding = self.config.getini("doctest_encoding")
+ text = self.fspath.read_text(encoding)
+ filename = str(self.fspath)
+ name = self.fspath.basename
+ globs = {"__name__": "__main__"}
+
+ optionflags = get_optionflags(self)
+
+ runner = _get_runner(
verbose=False,
- optionflags=optionflags,
- checker=_get_checker(),
- continue_on_failure=_get_continue_on_failure(self.config),
- )
-
- parser = doctest.DocTestParser()
- test = parser.get_doctest(text, globs, name, filename, 0)
- if test.examples:
+ optionflags=optionflags,
+ checker=_get_checker(),
+ continue_on_failure=_get_continue_on_failure(self.config),
+ )
+
+ parser = doctest.DocTestParser()
+ test = parser.get_doctest(text, globs, name, filename, 0)
+ if test.examples:
yield DoctestItem.from_parent(
self, name=test.name, runner=runner, dtest=test
)
-
-
+
+
def _check_all_skipped(test: "doctest.DocTest") -> None:
"""Raise pytest.skip() if all examples in the given DocTest have the SKIP
option set."""
- import doctest
-
- all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples)
- if all_skipped:
- pytest.skip("all tests skipped by +SKIP option")
-
-
+ import doctest
+
+ all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples)
+ if all_skipped:
+ pytest.skip("all tests skipped by +SKIP option")
+
+
def _is_mocked(obj: object) -> bool:
"""Return if an object is possibly a mock object by checking the
existence of a highly improbable attribute."""
@@ -487,10 +487,10 @@ def _patch_unwrap_mock_aware() -> Generator[None, None, None]:
inspect.unwrap = real_unwrap
-class DoctestModule(pytest.Module):
+class DoctestModule(pytest.Module):
def collect(self) -> Iterable[DoctestItem]:
- import doctest
-
+ import doctest
+
class MockAwareDocTestFinder(doctest.DocTestFinder):
"""A hackish doctest finder that overrides stdlib internals to fix a stdlib bug.
@@ -523,62 +523,62 @@ class DoctestModule(pytest.Module):
self, tests, obj, name, module, source_lines, globs, seen
)
- if self.fspath.basename == "conftest.py":
+ if self.fspath.basename == "conftest.py":
module = self.config.pluginmanager._importconftest(
self.fspath, self.config.getoption("importmode")
)
- else:
- try:
+ else:
+ try:
module = import_path(self.fspath)
- except ImportError:
- if self.config.getvalue("doctest_ignore_import_errors"):
- pytest.skip("unable to import module %r" % self.fspath)
- else:
- raise
+ except ImportError:
+ if self.config.getvalue("doctest_ignore_import_errors"):
+ pytest.skip("unable to import module %r" % self.fspath)
+ else:
+ raise
# Uses internal doctest module parsing mechanism.
finder = MockAwareDocTestFinder()
- optionflags = get_optionflags(self)
- runner = _get_runner(
+ optionflags = get_optionflags(self)
+ runner = _get_runner(
verbose=False,
- optionflags=optionflags,
- checker=_get_checker(),
- continue_on_failure=_get_continue_on_failure(self.config),
- )
-
- for test in finder.find(module, module.__name__):
- if test.examples: # skip empty doctests
+ optionflags=optionflags,
+ checker=_get_checker(),
+ continue_on_failure=_get_continue_on_failure(self.config),
+ )
+
+ for test in finder.find(module, module.__name__):
+ if test.examples: # skip empty doctests
yield DoctestItem.from_parent(
self, name=test.name, runner=runner, dtest=test
)
-
-
+
+
def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest:
"""Used by DoctestTextfile and DoctestItem to setup fixture information."""
-
+
def func() -> None:
- pass
-
+ pass
+
doctest_item.funcargs = {} # type: ignore[attr-defined]
- fm = doctest_item.session._fixturemanager
+ fm = doctest_item.session._fixturemanager
doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined]
- node=doctest_item, func=func, cls=None, funcargs=False
- )
+ node=doctest_item, func=func, cls=None, funcargs=False
+ )
fixture_request = FixtureRequest(doctest_item, _ispytest=True)
- fixture_request._fillfixtures()
- return fixture_request
-
-
+ fixture_request._fillfixtures()
+ return fixture_request
+
+
def _init_checker_class() -> Type["doctest.OutputChecker"]:
- import doctest
- import re
-
- class LiteralsOutputChecker(doctest.OutputChecker):
+ import doctest
+ import re
+
+ class LiteralsOutputChecker(doctest.OutputChecker):
# Based on doctest_nose_plugin.py from the nltk project
# (https://github.com/nltk/nltk) and on the "numtest" doctest extension
# by Sebastien Boisgerault (https://github.com/boisgera/numtest).
-
- _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
- _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)
+
+ _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
+ _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)
_number_re = re.compile(
r"""
(?P<number>
@@ -601,34 +601,34 @@ def _init_checker_class() -> Type["doctest.OutputChecker"]:
""",
re.VERBOSE,
)
-
+
def check_output(self, want: str, got: str, optionflags: int) -> bool:
if doctest.OutputChecker.check_output(self, want, got, optionflags):
- return True
-
- allow_unicode = optionflags & _get_allow_unicode_flag()
- allow_bytes = optionflags & _get_allow_bytes_flag()
+ return True
+
+ allow_unicode = optionflags & _get_allow_unicode_flag()
+ allow_bytes = optionflags & _get_allow_bytes_flag()
allow_number = optionflags & _get_number_flag()
if not allow_unicode and not allow_bytes and not allow_number:
- return False
-
+ return False
+
def remove_prefixes(regex: Pattern[str], txt: str) -> str:
return re.sub(regex, r"\1\2", txt)
-
+
if allow_unicode:
want = remove_prefixes(self._unicode_literal_re, want)
got = remove_prefixes(self._unicode_literal_re, got)
-
+
if allow_bytes:
want = remove_prefixes(self._bytes_literal_re, want)
got = remove_prefixes(self._bytes_literal_re, got)
-
+
if allow_number:
got = self._remove_unwanted_precision(want, got)
-
+
return doctest.OutputChecker.check_output(self, want, got, optionflags)
-
+
def _remove_unwanted_precision(self, want: str, got: str) -> str:
wants = list(self._number_re.finditer(want))
gots = list(self._number_re.finditer(got))
@@ -681,18 +681,18 @@ def _get_checker() -> "doctest.OutputChecker":
def _get_allow_unicode_flag() -> int:
"""Register and return the ALLOW_UNICODE flag."""
- import doctest
-
- return doctest.register_optionflag("ALLOW_UNICODE")
-
-
+ import doctest
+
+ return doctest.register_optionflag("ALLOW_UNICODE")
+
+
def _get_allow_bytes_flag() -> int:
"""Register and return the ALLOW_BYTES flag."""
- import doctest
-
- return doctest.register_optionflag("ALLOW_BYTES")
-
-
+ import doctest
+
+ return doctest.register_optionflag("ALLOW_BYTES")
+
+
def _get_number_flag() -> int:
"""Register and return the NUMBER flag."""
import doctest
@@ -706,19 +706,19 @@ def _get_report_choice(key: str) -> int:
We want to do it as late as possible to avoid importing `doctest` and all
its dependencies when parsing options, as it adds overhead and breaks tests.
"""
- import doctest
-
- return {
- DOCTEST_REPORT_CHOICE_UDIFF: doctest.REPORT_UDIFF,
- DOCTEST_REPORT_CHOICE_CDIFF: doctest.REPORT_CDIFF,
- DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
- DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
- DOCTEST_REPORT_CHOICE_NONE: 0,
- }[key]
-
-
-@pytest.fixture(scope="session")
+ import doctest
+
+ return {
+ DOCTEST_REPORT_CHOICE_UDIFF: doctest.REPORT_UDIFF,
+ DOCTEST_REPORT_CHOICE_CDIFF: doctest.REPORT_CDIFF,
+ DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
+ DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
+ DOCTEST_REPORT_CHOICE_NONE: 0,
+ }[key]
+
+
+@pytest.fixture(scope="session")
def doctest_namespace() -> Dict[str, Any]:
"""Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests."""
- return dict()
+ return dict()