diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2025-05-05 12:31:52 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2025-05-05 12:41:33 +0300 |
commit | 6ff49ec58061f642c3a2f83c61eba12820787dfc (patch) | |
tree | c733ec9bdb15ed280080d31dea8725bfec717acd /contrib/python/pytest/py3/_pytest/doctest.py | |
parent | eefca8305c6a545cc6b16dca3eb0d91dcef2adcd (diff) | |
download | ydb-6ff49ec58061f642c3a2f83c61eba12820787dfc.tar.gz |
Intermediate changes
commit_hash:8b3bb826b17db8329ed1221f545c0645f12c552d
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/doctest.py')
-rw-r--r-- | contrib/python/pytest/py3/_pytest/doctest.py | 94 |
1 files changed, 41 insertions, 53 deletions
diff --git a/contrib/python/pytest/py3/_pytest/doctest.py b/contrib/python/pytest/py3/_pytest/doctest.py index ca41a98ea9c..c6b1a9df5cc 100644 --- a/contrib/python/pytest/py3/_pytest/doctest.py +++ b/contrib/python/pytest/py3/_pytest/doctest.py @@ -1,15 +1,15 @@ """Discover and run doctests in modules and test files.""" + import bdb +from contextlib import contextmanager import functools import inspect import os +from pathlib import Path import platform import sys import traceback import types -import warnings -from contextlib import contextmanager -from pathlib import Path from typing import Any from typing import Callable from typing import Dict @@ -23,6 +23,7 @@ from typing import Tuple from typing import Type from typing import TYPE_CHECKING from typing import Union +import warnings from _pytest import outcomes from _pytest._code.code import ExceptionInfo @@ -33,17 +34,17 @@ from _pytest.compat import safe_getattr from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.fixtures import fixture -from _pytest.fixtures import FixtureRequest +from _pytest.fixtures import TopRequest from _pytest.nodes import Collector from _pytest.nodes import Item from _pytest.outcomes import OutcomeException from _pytest.outcomes import skip from _pytest.pathlib import fnmatch_ex -from _pytest.pathlib import import_path from _pytest.python import Module from _pytest.python_api import approx from _pytest.warning_types import PytestWarning + if TYPE_CHECKING: import doctest @@ -105,7 +106,7 @@ def pytest_addoption(parser: Parser) -> None: "--doctest-ignore-import-errors", action="store_true", default=False, - help="Ignore doctest ImportErrors", + help="Ignore doctest collection errors", dest="doctest_ignore_import_errors", ) group.addoption( @@ -255,14 +256,20 @@ class DoctestItem(Item): self, name: str, parent: "Union[DoctestTextfile, DoctestModule]", - runner: Optional["doctest.DocTestRunner"] = None, - dtest: Optional["doctest.DocTest"] = None, + runner: "doctest.DocTestRunner", + dtest: "doctest.DocTest", ) -> None: super().__init__(name, parent) self.runner = runner self.dtest = dtest + + # Stuff needed for fixture support. self.obj = None - self.fixture_request: Optional[FixtureRequest] = None + fm = self.session._fixturemanager + fixtureinfo = fm.getfixtureinfo(node=self, func=None, cls=None) + self._fixtureinfo = fixtureinfo + self.fixturenames = fixtureinfo.names_closure + self._initrequest() @classmethod def from_parent( # type: ignore @@ -277,19 +284,18 @@ class DoctestItem(Item): """The public named constructor.""" return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) + def _initrequest(self) -> None: + self.funcargs: Dict[str, object] = {} + self._request = TopRequest(self, _ispytest=True) # type: ignore[arg-type] + 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) + self._request._fillfixtures() + globs = dict(getfixture=self._request.getfixturevalue) + for name, value in self._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() failures: List["doctest.DocTestFailure"] = [] @@ -376,7 +382,6 @@ class DoctestItem(Item): return ReprFailDoctest(reprlocation_lines) def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: - assert self.dtest is not None return self.path, self.dtest.lineno, "[doctest] %s" % self.name @@ -396,8 +401,8 @@ def _get_flag_lookup() -> Dict[str, int]: ) -def get_optionflags(parent): - optionflags_str = parent.config.getini("doctest_optionflags") +def get_optionflags(config: Config) -> int: + optionflags_str = config.getini("doctest_optionflags") flag_lookup_table = _get_flag_lookup() flag_acc = 0 for flag in optionflags_str: @@ -405,8 +410,8 @@ def get_optionflags(parent): return flag_acc -def _get_continue_on_failure(config): - continue_on_failure = config.getvalue("doctest_continue_on_failure") +def _get_continue_on_failure(config: Config) -> bool: + continue_on_failure: bool = 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. @@ -429,7 +434,7 @@ class DoctestTextfile(Module): name = self.path.name globs = {"__name__": "__main__"} - optionflags = get_optionflags(self) + optionflags = get_optionflags(self.config) runner = _get_runner( verbose=False, @@ -481,9 +486,9 @@ def _patch_unwrap_mock_aware() -> Generator[None, None, None]: return real_unwrap(func, stop=lambda obj: _is_mocked(obj) or _stop(func)) except Exception as e: warnings.warn( - "Got %r when unwrapping %r. This is usually caused " + f"Got {e!r} when unwrapping {func!r}. This is usually caused " "by a violation of Python's object protocol; see e.g. " - "https://github.com/pytest-dev/pytest/issues/5080" % (e, func), + "https://github.com/pytest-dev/pytest/issues/5080", PytestWarning, ) raise @@ -545,9 +550,7 @@ class DoctestModule(Module): Here we override `_from_module` to check the underlying function instead. https://github.com/python/cpython/issues/107995 """ - if hasattr(functools, "cached_property") and isinstance( - object, functools.cached_property - ): + if isinstance(object, functools.cached_property): object = object.func # Type ignored because this is a private function. @@ -564,19 +567,20 @@ class DoctestModule(Module): ) else: try: - module = import_path( - self.path, - root=self.config.rootpath, - mode=self.config.getoption("importmode"), - ) - except ImportError: + module = self.obj + except Collector.CollectError: if self.config.getvalue("doctest_ignore_import_errors"): skip("unable to import module %r" % self.path) else: raise + + # While doctests currently don't support fixtures directly, we still + # need to pick up autouse fixtures. + self.session._fixturemanager.parsefactories(self) + # Uses internal doctest module parsing mechanism. finder = MockAwareDocTestFinder() - optionflags = get_optionflags(self) + optionflags = get_optionflags(self.config) runner = _get_runner( verbose=False, optionflags=optionflags, @@ -591,22 +595,6 @@ class DoctestModule(Module): ) -def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest: - """Used by DoctestTextfile and DoctestItem to setup fixture information.""" - - def func() -> None: - pass - - doctest_item.funcargs = {} # type: ignore[attr-defined] - fm = doctest_item.session._fixturemanager - doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] - node=doctest_item, func=func, cls=None, funcargs=False - ) - fixture_request = FixtureRequest(doctest_item, _ispytest=True) - fixture_request._fillfixtures() - return fixture_request - - def _init_checker_class() -> Type["doctest.OutputChecker"]: import doctest import re |