Merge pull request #8005 from bluetech/pytest-import

Stop importing `pytest` to avoid upcoming import cycles
This commit is contained in:
Ran Benita 2020-11-08 14:15:19 +02:00 committed by GitHub
commit 29f2f4e854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 67 deletions

View File

@ -15,7 +15,6 @@ from typing import Union
import attr import attr
import py import py
import pytest
from .pathlib import resolve_from_str from .pathlib import resolve_from_str
from .pathlib import rm_rf from .pathlib import rm_rf
from .reports import CollectReport from .reports import CollectReport
@ -24,7 +23,9 @@ from _pytest._io import TerminalWriter
from _pytest.compat import final from _pytest.compat import final
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.python import Module from _pytest.python import Module
@ -182,7 +183,7 @@ class LFPluginCollWrapper:
self.lfplugin = lfplugin self.lfplugin = lfplugin
self._collected_at_least_one_failure = False self._collected_at_least_one_failure = False
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_make_collect_report(self, collector: nodes.Collector): def pytest_make_collect_report(self, collector: nodes.Collector):
if isinstance(collector, Session): if isinstance(collector, Session):
out = yield out = yield
@ -229,7 +230,7 @@ class LFPluginCollSkipfiles:
def __init__(self, lfplugin: "LFPlugin") -> None: def __init__(self, lfplugin: "LFPlugin") -> None:
self.lfplugin = lfplugin self.lfplugin = lfplugin
@pytest.hookimpl @hookimpl
def pytest_make_collect_report( def pytest_make_collect_report(
self, collector: nodes.Collector self, collector: nodes.Collector
) -> Optional[CollectReport]: ) -> Optional[CollectReport]:
@ -291,7 +292,7 @@ class LFPlugin:
else: else:
self.lastfailed[report.nodeid] = True self.lastfailed[report.nodeid] = True
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_collection_modifyitems( def pytest_collection_modifyitems(
self, config: Config, items: List[nodes.Item] self, config: Config, items: List[nodes.Item]
) -> Generator[None, None, None]: ) -> Generator[None, None, None]:
@ -363,7 +364,7 @@ class NFPlugin:
assert config.cache is not None assert config.cache is not None
self.cached_nodeids = set(config.cache.get("cache/nodeids", [])) self.cached_nodeids = set(config.cache.get("cache/nodeids", []))
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_collection_modifyitems( def pytest_collection_modifyitems(
self, items: List[nodes.Item] self, items: List[nodes.Item]
) -> Generator[None, None, None]: ) -> Generator[None, None, None]:
@ -466,14 +467,14 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
return None return None
@pytest.hookimpl(tryfirst=True) @hookimpl(tryfirst=True)
def pytest_configure(config: Config) -> None: def pytest_configure(config: Config) -> None:
config.cache = Cache.for_config(config) config.cache = Cache.for_config(config)
config.pluginmanager.register(LFPlugin(config), "lfplugin") config.pluginmanager.register(LFPlugin(config), "lfplugin")
config.pluginmanager.register(NFPlugin(config), "nfplugin") config.pluginmanager.register(NFPlugin(config), "nfplugin")
@pytest.fixture @fixture
def cache(request: FixtureRequest) -> Cache: def cache(request: FixtureRequest) -> Cache:
"""Return a cache object that can persist state between testing sessions. """Return a cache object that can persist state between testing sessions.

View File

@ -17,12 +17,14 @@ from typing import Tuple
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Union from typing import Union
import pytest
from _pytest.compat import final from _pytest.compat import final
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.fixtures import fixture
from _pytest.fixtures import SubRequest from _pytest.fixtures import SubRequest
from _pytest.nodes import Collector from _pytest.nodes import Collector
from _pytest.nodes import File
from _pytest.nodes import Item from _pytest.nodes import Item
if TYPE_CHECKING: if TYPE_CHECKING:
@ -145,7 +147,7 @@ def _py36_windowsconsoleio_workaround(stream: TextIO) -> None:
sys.stderr = _reopen_stdio(sys.stderr, "wb") sys.stderr = _reopen_stdio(sys.stderr, "wb")
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_load_initial_conftests(early_config: Config): def pytest_load_initial_conftests(early_config: Config):
ns = early_config.known_args_namespace ns = early_config.known_args_namespace
if ns.capture == "fd": if ns.capture == "fd":
@ -784,9 +786,9 @@ class CaptureManager:
# Hooks # Hooks
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_make_collect_report(self, collector: Collector): def pytest_make_collect_report(self, collector: Collector):
if isinstance(collector, pytest.File): if isinstance(collector, File):
self.resume_global_capture() self.resume_global_capture()
outcome = yield outcome = yield
self.suspend_global_capture() self.suspend_global_capture()
@ -799,26 +801,26 @@ class CaptureManager:
else: else:
yield yield
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]: def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("setup", item): with self.item_capture("setup", item):
yield yield
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]: def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("call", item): with self.item_capture("call", item):
yield yield
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]: def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("teardown", item): with self.item_capture("teardown", item):
yield yield
@pytest.hookimpl(tryfirst=True) @hookimpl(tryfirst=True)
def pytest_keyboard_interrupt(self) -> None: def pytest_keyboard_interrupt(self) -> None:
self.stop_global_capturing() self.stop_global_capturing()
@pytest.hookimpl(tryfirst=True) @hookimpl(tryfirst=True)
def pytest_internalerror(self) -> None: def pytest_internalerror(self) -> None:
self.stop_global_capturing() self.stop_global_capturing()
@ -893,7 +895,7 @@ class CaptureFixture(Generic[AnyStr]):
# The fixtures. # The fixtures.
@pytest.fixture @fixture
def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. """Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
@ -910,7 +912,7 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
capman.unset_fixture() capman.unset_fixture()
@pytest.fixture @fixture
def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]: def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]:
"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. """Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
@ -927,7 +929,7 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None,
capman.unset_fixture() capman.unset_fixture()
@pytest.fixture @fixture
def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
"""Enable text capturing of writes to file descriptors ``1`` and ``2``. """Enable text capturing of writes to file descriptors ``1`` and ``2``.
@ -944,7 +946,7 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
capman.unset_fixture() capman.unset_fixture()
@pytest.fixture @fixture
def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]: def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]:
"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``. """Enable bytes capturing of writes to file descriptors ``1`` and ``2``.

View File

@ -16,7 +16,6 @@ from typing import Tuple
from typing import TypeVar from typing import TypeVar
from typing import Union from typing import Union
import pytest
from _pytest import nodes from _pytest import nodes
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest.capture import CaptureManager from _pytest.capture import CaptureManager
@ -25,7 +24,10 @@ from _pytest.compat import nullcontext
from _pytest.config import _strtobool from _pytest.config import _strtobool
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import create_terminal_writer from _pytest.config import create_terminal_writer
from _pytest.config import hookimpl
from _pytest.config import UsageError
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.store import StoreKey from _pytest.store import StoreKey
@ -468,7 +470,7 @@ class LogCaptureFixture:
self.handler.setLevel(handler_orig_level) self.handler.setLevel(handler_orig_level)
@pytest.fixture @fixture
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]: def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:
"""Access and control log capturing. """Access and control log capturing.
@ -501,7 +503,7 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
return int(getattr(logging, log_level, log_level)) return int(getattr(logging, log_level, log_level))
except ValueError as e: except ValueError as e:
# Python logging does not recognise this as a logging level # Python logging does not recognise this as a logging level
raise pytest.UsageError( raise UsageError(
"'{}' is not recognized as a logging level name for " "'{}' is not recognized as a logging level name for "
"'{}'. Please consider passing the " "'{}'. Please consider passing the "
"logging level num instead.".format(log_level, setting_name) "logging level num instead.".format(log_level, setting_name)
@ -509,7 +511,7 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
# run after terminalreporter/capturemanager are configured # run after terminalreporter/capturemanager are configured
@pytest.hookimpl(trylast=True) @hookimpl(trylast=True)
def pytest_configure(config: Config) -> None: def pytest_configure(config: Config) -> None:
config.pluginmanager.register(LoggingPlugin(config), "logging-plugin") config.pluginmanager.register(LoggingPlugin(config), "logging-plugin")
@ -639,7 +641,7 @@ class LoggingPlugin:
return True return True
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_sessionstart(self) -> Generator[None, None, None]: def pytest_sessionstart(self) -> Generator[None, None, None]:
self.log_cli_handler.set_when("sessionstart") self.log_cli_handler.set_when("sessionstart")
@ -647,7 +649,7 @@ class LoggingPlugin:
with catching_logs(self.log_file_handler, level=self.log_file_level): with catching_logs(self.log_file_handler, level=self.log_file_level):
yield yield
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_collection(self) -> Generator[None, None, None]: def pytest_collection(self) -> Generator[None, None, None]:
self.log_cli_handler.set_when("collection") self.log_cli_handler.set_when("collection")
@ -655,7 +657,7 @@ class LoggingPlugin:
with catching_logs(self.log_file_handler, level=self.log_file_level): with catching_logs(self.log_file_handler, level=self.log_file_level):
yield yield
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]: def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]:
if session.config.option.collectonly: if session.config.option.collectonly:
yield yield
@ -669,12 +671,12 @@ class LoggingPlugin:
with catching_logs(self.log_file_handler, level=self.log_file_level): with catching_logs(self.log_file_handler, level=self.log_file_level):
yield # Run all the tests. yield # Run all the tests.
@pytest.hookimpl @hookimpl
def pytest_runtest_logstart(self) -> None: def pytest_runtest_logstart(self) -> None:
self.log_cli_handler.reset() self.log_cli_handler.reset()
self.log_cli_handler.set_when("start") self.log_cli_handler.set_when("start")
@pytest.hookimpl @hookimpl
def pytest_runtest_logreport(self) -> None: def pytest_runtest_logreport(self) -> None:
self.log_cli_handler.set_when("logreport") self.log_cli_handler.set_when("logreport")
@ -695,7 +697,7 @@ class LoggingPlugin:
log = report_handler.stream.getvalue().strip() log = report_handler.stream.getvalue().strip()
item.add_report_section(when, "log", log) item.add_report_section(when, "log", log)
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]:
self.log_cli_handler.set_when("setup") self.log_cli_handler.set_when("setup")
@ -703,13 +705,13 @@ class LoggingPlugin:
item._store[caplog_records_key] = empty item._store[caplog_records_key] = empty
yield from self._runtest_for(item, "setup") yield from self._runtest_for(item, "setup")
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_call(self, item: nodes.Item) -> Generator[None, None, None]: def pytest_runtest_call(self, item: nodes.Item) -> Generator[None, None, None]:
self.log_cli_handler.set_when("call") self.log_cli_handler.set_when("call")
yield from self._runtest_for(item, "call") yield from self._runtest_for(item, "call")
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None, None, None]: def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None, None, None]:
self.log_cli_handler.set_when("teardown") self.log_cli_handler.set_when("teardown")
@ -717,11 +719,11 @@ class LoggingPlugin:
del item._store[caplog_records_key] del item._store[caplog_records_key]
del item._store[caplog_handler_key] del item._store[caplog_handler_key]
@pytest.hookimpl @hookimpl
def pytest_runtest_logfinish(self) -> None: def pytest_runtest_logfinish(self) -> None:
self.log_cli_handler.set_when("finish") self.log_cli_handler.set_when("finish")
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_sessionfinish(self) -> Generator[None, None, None]: def pytest_sessionfinish(self) -> Generator[None, None, None]:
self.log_cli_handler.set_when("sessionfinish") self.log_cli_handler.set_when("sessionfinish")
@ -729,7 +731,7 @@ class LoggingPlugin:
with catching_logs(self.log_file_handler, level=self.log_file_level): with catching_logs(self.log_file_handler, level=self.log_file_level):
yield yield
@pytest.hookimpl @hookimpl
def pytest_unconfigure(self) -> None: def pytest_unconfigure(self) -> None:
# Close the FileHandler explicitly. # Close the FileHandler explicitly.
# (logging.shutdown might have lost the weakref?!) # (logging.shutdown might have lost the weakref?!)

View File

@ -15,9 +15,9 @@ from typing import Tuple
from typing import TypeVar from typing import TypeVar
from typing import Union from typing import Union
import pytest
from _pytest.compat import final from _pytest.compat import final
from _pytest.fixtures import fixture from _pytest.fixtures import fixture
from _pytest.warning_types import PytestWarning
RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$") RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$")
@ -271,7 +271,7 @@ class MonkeyPatch:
""" """
if not isinstance(value, str): if not isinstance(value, str):
warnings.warn( # type: ignore[unreachable] warnings.warn( # type: ignore[unreachable]
pytest.PytestWarning( PytestWarning(
"Value of environment variable {name} type should be str, but got " "Value of environment variable {name} type should be str, but got "
"{value!r} (type: {type}); converted to str implicitly".format( "{value!r} (type: {type}); converted to str implicitly".format(
name=name, value=value, type=type(value).__name__ name=name, value=value, type=type(value).__name__

View File

@ -34,7 +34,6 @@ import py
from iniconfig import IniConfig from iniconfig import IniConfig
from iniconfig import SectionWrapper from iniconfig import SectionWrapper
import pytest
from _pytest import timing from _pytest import timing
from _pytest._code import Source from _pytest._code import Source
from _pytest.capture import _get_multicapture from _pytest.capture import _get_multicapture
@ -42,17 +41,24 @@ from _pytest.compat import final
from _pytest.config import _PluggyPlugin from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config import main
from _pytest.config import PytestPluginManager from _pytest.config import PytestPluginManager
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
from _pytest.nodes import Collector from _pytest.nodes import Collector
from _pytest.nodes import Item from _pytest.nodes import Item
from _pytest.outcomes import fail
from _pytest.outcomes import importorskip
from _pytest.outcomes import skip
from _pytest.pathlib import make_numbered_dir from _pytest.pathlib import make_numbered_dir
from _pytest.reports import CollectReport from _pytest.reports import CollectReport
from _pytest.reports import TestReport from _pytest.reports import TestReport
from _pytest.tmpdir import TempPathFactory from _pytest.tmpdir import TempPathFactory
from _pytest.warning_types import PytestWarning
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Literal from typing_extensions import Literal
@ -143,7 +149,7 @@ class LsofFdLeakChecker:
else: else:
return True return True
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]: def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]:
lines1 = self.get_open_files() lines1 = self.get_open_files()
yield yield
@ -165,13 +171,13 @@ class LsofFdLeakChecker:
"*** function %s:%s: %s " % item.location, "*** function %s:%s: %s " % item.location,
"See issue #2366", "See issue #2366",
] ]
item.warn(pytest.PytestWarning("\n".join(error))) item.warn(PytestWarning("\n".join(error)))
# used at least by pytest-xdist plugin # used at least by pytest-xdist plugin
@pytest.fixture @fixture
def _pytest(request: FixtureRequest) -> "PytestArg": def _pytest(request: FixtureRequest) -> "PytestArg":
"""Return a helper which offers a gethookrecorder(hook) method which """Return a helper which offers a gethookrecorder(hook) method which
returns a HookRecorder instance which helps to make assertions about called returns a HookRecorder instance which helps to make assertions about called
@ -257,7 +263,7 @@ class HookRecorder:
break break
print("NONAMEMATCH", name, "with", call) print("NONAMEMATCH", name, "with", call)
else: else:
pytest.fail(f"could not find {name!r} check {check!r}") fail(f"could not find {name!r} check {check!r}")
def popcall(self, name: str) -> ParsedCall: def popcall(self, name: str) -> ParsedCall:
__tracebackhide__ = True __tracebackhide__ = True
@ -267,7 +273,7 @@ class HookRecorder:
return call return call
lines = [f"could not find call {name!r}, in:"] lines = [f"could not find call {name!r}, in:"]
lines.extend([" %s" % x for x in self.calls]) lines.extend([" %s" % x for x in self.calls])
pytest.fail("\n".join(lines)) fail("\n".join(lines))
def getcall(self, name: str) -> ParsedCall: def getcall(self, name: str) -> ParsedCall:
values = self.getcalls(name) values = self.getcalls(name)
@ -417,14 +423,14 @@ class HookRecorder:
self.calls[:] = [] self.calls[:] = []
@pytest.fixture @fixture
def linecomp() -> "LineComp": def linecomp() -> "LineComp":
"""A :class: `LineComp` instance for checking that an input linearly """A :class: `LineComp` instance for checking that an input linearly
contains a sequence of strings.""" contains a sequence of strings."""
return LineComp() return LineComp()
@pytest.fixture(name="LineMatcher") @fixture(name="LineMatcher")
def LineMatcher_fixture(request: FixtureRequest) -> Type["LineMatcher"]: def LineMatcher_fixture(request: FixtureRequest) -> Type["LineMatcher"]:
"""A reference to the :class: `LineMatcher`. """A reference to the :class: `LineMatcher`.
@ -434,7 +440,7 @@ def LineMatcher_fixture(request: FixtureRequest) -> Type["LineMatcher"]:
return LineMatcher return LineMatcher
@pytest.fixture @fixture
def pytester(request: FixtureRequest, tmp_path_factory: TempPathFactory) -> "Pytester": def pytester(request: FixtureRequest, tmp_path_factory: TempPathFactory) -> "Pytester":
""" """
Facilities to write tests/configuration files, execute pytest in isolation, and match Facilities to write tests/configuration files, execute pytest in isolation, and match
@ -449,7 +455,7 @@ def pytester(request: FixtureRequest, tmp_path_factory: TempPathFactory) -> "Pyt
return Pytester(request, tmp_path_factory) return Pytester(request, tmp_path_factory)
@pytest.fixture @fixture
def testdir(pytester: "Pytester") -> "Testdir": def testdir(pytester: "Pytester") -> "Testdir":
""" """
Identical to :fixture:`pytester`, and provides an instance whose methods return Identical to :fixture:`pytester`, and provides an instance whose methods return
@ -460,7 +466,7 @@ def testdir(pytester: "Pytester") -> "Testdir":
return Testdir(pytester) return Testdir(pytester)
@pytest.fixture @fixture
def _sys_snapshot() -> Generator[None, None, None]: def _sys_snapshot() -> Generator[None, None, None]:
snappaths = SysPathsSnapshot() snappaths = SysPathsSnapshot()
snapmods = SysModulesSnapshot() snapmods = SysModulesSnapshot()
@ -469,7 +475,7 @@ def _sys_snapshot() -> Generator[None, None, None]:
snappaths.restore() snappaths.restore()
@pytest.fixture @fixture
def _config_for_test() -> Generator[Config, None, None]: def _config_for_test() -> Generator[Config, None, None]:
from _pytest.config import get_config from _pytest.config import get_config
@ -495,7 +501,7 @@ class RunResult:
duration: float, duration: float,
) -> None: ) -> None:
try: try:
self.ret: Union[int, ExitCode] = pytest.ExitCode(ret) self.ret: Union[int, ExitCode] = ExitCode(ret)
"""The return value.""" """The return value."""
except ValueError: except ValueError:
self.ret = ret self.ret = ret
@ -1062,7 +1068,7 @@ class Pytester:
rec.append(self.make_hook_recorder(config.pluginmanager)) rec.append(self.make_hook_recorder(config.pluginmanager))
plugins.append(Collect()) plugins.append(Collect())
ret = pytest.main([str(x) for x in args], plugins=plugins) ret = main([str(x) for x in args], plugins=plugins)
if len(rec) == 1: if len(rec) == 1:
reprec = rec.pop() reprec = rec.pop()
else: else:
@ -1448,11 +1454,11 @@ class Pytester:
The pexpect child is returned. The pexpect child is returned.
""" """
pexpect = pytest.importorskip("pexpect", "3.0") pexpect = importorskip("pexpect", "3.0")
if hasattr(sys, "pypy_version_info") and "64" in platform.machine(): if hasattr(sys, "pypy_version_info") and "64" in platform.machine():
pytest.skip("pypy-64 bit not supported") skip("pypy-64 bit not supported")
if not hasattr(pexpect, "spawn"): if not hasattr(pexpect, "spawn"):
pytest.skip("pexpect.spawn not available") skip("pexpect.spawn not available")
logfile = self.path.joinpath("spawn.out").open("wb") logfile = self.path.joinpath("spawn.out").open("wb")
child = pexpect.spawn(cmd, logfile=logfile, timeout=expect_timeout) child = pexpect.spawn(cmd, logfile=logfile, timeout=expect_timeout)
@ -1899,7 +1905,7 @@ class LineMatcher:
__tracebackhide__ = True __tracebackhide__ = True
log_text = self._log_text log_text = self._log_text
self._log_output = [] self._log_output = []
pytest.fail(log_text) fail(log_text)
def str(self) -> str: def str(self) -> str:
"""Return the entire original text.""" """Return the entire original text."""

View File

@ -29,7 +29,7 @@ import attr
import pluggy import pluggy
import py import py
import pytest import _pytest._version
from _pytest import nodes from _pytest import nodes
from _pytest import timing from _pytest import timing
from _pytest._code import ExceptionInfo from _pytest._code import ExceptionInfo
@ -39,6 +39,7 @@ from _pytest.compat import final
from _pytest.config import _PluggyPlugin from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.nodes import Item from _pytest.nodes import Item
from _pytest.nodes import Node from _pytest.nodes import Node
@ -259,7 +260,7 @@ def getreportopt(config: Config) -> str:
return reportopts return reportopts
@pytest.hookimpl(trylast=True) # after _pytest.runner @hookimpl(trylast=True) # after _pytest.runner
def pytest_report_teststatus(report: BaseReport) -> Tuple[str, str, str]: def pytest_report_teststatus(report: BaseReport) -> Tuple[str, str, str]:
letter = "F" letter = "F"
if report.passed: if report.passed:
@ -628,7 +629,7 @@ class TerminalReporter:
self._add_stats("error", [report]) self._add_stats("error", [report])
elif report.skipped: elif report.skipped:
self._add_stats("skipped", [report]) self._add_stats("skipped", [report])
items = [x for x in report.result if isinstance(x, pytest.Item)] items = [x for x in report.result if isinstance(x, Item)]
self._numcollected += len(items) self._numcollected += len(items)
if self.isatty: if self.isatty:
self.report_collect() self.report_collect()
@ -673,7 +674,7 @@ class TerminalReporter:
else: else:
self.write_line(line) self.write_line(line)
@pytest.hookimpl(trylast=True) @hookimpl(trylast=True)
def pytest_sessionstart(self, session: "Session") -> None: def pytest_sessionstart(self, session: "Session") -> None:
self._session = session self._session = session
self._sessionstarttime = timing.time() self._sessionstarttime = timing.time()
@ -688,7 +689,7 @@ class TerminalReporter:
verinfo = ".".join(map(str, pypy_version_info[:3])) verinfo = ".".join(map(str, pypy_version_info[:3]))
msg += "[pypy-{}-{}]".format(verinfo, pypy_version_info[3]) msg += "[pypy-{}-{}]".format(verinfo, pypy_version_info[3])
msg += ", pytest-{}, py-{}, pluggy-{}".format( msg += ", pytest-{}, py-{}, pluggy-{}".format(
pytest.__version__, py.__version__, pluggy.__version__ _pytest._version.version, py.__version__, pluggy.__version__
) )
if ( if (
self.verbosity > 0 self.verbosity > 0
@ -783,7 +784,7 @@ class TerminalReporter:
for line in doc.splitlines(): for line in doc.splitlines():
self._tw.line("{}{}".format(indent + " ", line)) self._tw.line("{}{}".format(indent + " ", line))
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_sessionfinish( def pytest_sessionfinish(
self, session: "Session", exitstatus: Union[int, ExitCode] self, session: "Session", exitstatus: Union[int, ExitCode]
): ):
@ -810,7 +811,7 @@ class TerminalReporter:
self.write_sep("!", str(session.shouldstop), red=True) self.write_sep("!", str(session.shouldstop), red=True)
self.summary_stats() self.summary_stats()
@pytest.hookimpl(hookwrapper=True) @hookimpl(hookwrapper=True)
def pytest_terminal_summary(self) -> Generator[None, None, None]: def pytest_terminal_summary(self) -> Generator[None, None, None]:
self.summary_errors() self.summary_errors()
self.summary_failures() self.summary_failures()

View File

@ -8,13 +8,13 @@ from typing import Optional
import attr import attr
import py import py
import pytest
from .pathlib import ensure_reset_dir from .pathlib import ensure_reset_dir
from .pathlib import LOCK_TIMEOUT from .pathlib import LOCK_TIMEOUT
from .pathlib import make_numbered_dir from .pathlib import make_numbered_dir
from .pathlib import make_numbered_dir_with_cleanup from .pathlib import make_numbered_dir_with_cleanup
from _pytest.compat import final from _pytest.compat import final
from _pytest.config import Config from _pytest.config import Config
from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
@ -146,14 +146,14 @@ def pytest_configure(config: Config) -> None:
mp.setattr(config, "_tmpdirhandler", t, raising=False) mp.setattr(config, "_tmpdirhandler", t, raising=False)
@pytest.fixture(scope="session") @fixture(scope="session")
def tmpdir_factory(request: FixtureRequest) -> TempdirFactory: def tmpdir_factory(request: FixtureRequest) -> TempdirFactory:
"""Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.""" """Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session."""
# Set dynamically by pytest_configure() above. # Set dynamically by pytest_configure() above.
return request.config._tmpdirhandler # type: ignore return request.config._tmpdirhandler # type: ignore
@pytest.fixture(scope="session") @fixture(scope="session")
def tmp_path_factory(request: FixtureRequest) -> TempPathFactory: def tmp_path_factory(request: FixtureRequest) -> TempPathFactory:
"""Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.""" """Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session."""
# Set dynamically by pytest_configure() above. # Set dynamically by pytest_configure() above.
@ -168,7 +168,7 @@ def _mk_tmp(request: FixtureRequest, factory: TempPathFactory) -> Path:
return factory.mktemp(name, numbered=True) return factory.mktemp(name, numbered=True)
@pytest.fixture @fixture
def tmpdir(tmp_path: Path) -> py.path.local: def tmpdir(tmp_path: Path) -> py.path.local:
"""Return a temporary directory path object which is unique to each test """Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary function invocation, created as a sub directory of the base temporary
@ -181,7 +181,7 @@ def tmpdir(tmp_path: Path) -> py.path.local:
return py.path.local(tmp_path) return py.path.local(tmp_path)
@pytest.fixture @fixture
def tmp_path(request: FixtureRequest, tmp_path_factory: TempPathFactory) -> Path: def tmp_path(request: FixtureRequest, tmp_path_factory: TempPathFactory) -> Path:
"""Return a temporary directory path object which is unique to each test """Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary function invocation, created as a sub directory of the base temporary