Stop importing `pytest` to avoid upcoming import cycles
Don't import `pytest` from within some `_pytest` modules since an upcoming commit will import from them into `pytest`. It would have been nice not to have to do it, so that internal plugins look more like external plugins, but with the existing layout this seems unavoidable.
This commit is contained in:
parent
3bcd316f07
commit
1cbb0c3554
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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``.
|
||||||
|
|
||||||
|
|
|
@ -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?!)
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue