aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/doctest.py
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2025-05-05 12:31:52 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2025-05-05 12:41:33 +0300
commit6ff49ec58061f642c3a2f83c61eba12820787dfc (patch)
treec733ec9bdb15ed280080d31dea8725bfec717acd /contrib/python/pytest/py3/_pytest/doctest.py
parenteefca8305c6a545cc6b16dca3eb0d91dcef2adcd (diff)
downloadydb-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.py94
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