Skip to content

Commit 29f2f4e

Browse files
authored
Merge pull request #8005 from bluetech/pytest-import
Stop importing `pytest` to avoid upcoming import cycles
2 parents 10a3a49 + 1cbb0c3 commit 29f2f4e

File tree

7 files changed

+79
-67
lines changed

7 files changed

+79
-67
lines changed

src/_pytest/cacheprovider.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import attr
1616
import py
1717

18-
import pytest
1918
from .pathlib import resolve_from_str
2019
from .pathlib import rm_rf
2120
from .reports import CollectReport
@@ -24,7 +23,9 @@
2423
from _pytest.compat import final
2524
from _pytest.config import Config
2625
from _pytest.config import ExitCode
26+
from _pytest.config import hookimpl
2727
from _pytest.config.argparsing import Parser
28+
from _pytest.fixtures import fixture
2829
from _pytest.fixtures import FixtureRequest
2930
from _pytest.main import Session
3031
from _pytest.python import Module
@@ -182,7 +183,7 @@ def __init__(self, lfplugin: "LFPlugin") -> None:
182183
self.lfplugin = lfplugin
183184
self._collected_at_least_one_failure = False
184185

185-
@pytest.hookimpl(hookwrapper=True)
186+
@hookimpl(hookwrapper=True)
186187
def pytest_make_collect_report(self, collector: nodes.Collector):
187188
if isinstance(collector, Session):
188189
out = yield
@@ -229,7 +230,7 @@ class LFPluginCollSkipfiles:
229230
def __init__(self, lfplugin: "LFPlugin") -> None:
230231
self.lfplugin = lfplugin
231232

232-
@pytest.hookimpl
233+
@hookimpl
233234
def pytest_make_collect_report(
234235
self, collector: nodes.Collector
235236
) -> Optional[CollectReport]:
@@ -291,7 +292,7 @@ def pytest_collectreport(self, report: CollectReport) -> None:
291292
else:
292293
self.lastfailed[report.nodeid] = True
293294

294-
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
295+
@hookimpl(hookwrapper=True, tryfirst=True)
295296
def pytest_collection_modifyitems(
296297
self, config: Config, items: List[nodes.Item]
297298
) -> Generator[None, None, None]:
@@ -363,7 +364,7 @@ def __init__(self, config: Config) -> None:
363364
assert config.cache is not None
364365
self.cached_nodeids = set(config.cache.get("cache/nodeids", []))
365366

366-
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
367+
@hookimpl(hookwrapper=True, tryfirst=True)
367368
def pytest_collection_modifyitems(
368369
self, items: List[nodes.Item]
369370
) -> Generator[None, None, None]:
@@ -466,14 +467,14 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
466467
return None
467468

468469

469-
@pytest.hookimpl(tryfirst=True)
470+
@hookimpl(tryfirst=True)
470471
def pytest_configure(config: Config) -> None:
471472
config.cache = Cache.for_config(config)
472473
config.pluginmanager.register(LFPlugin(config), "lfplugin")
473474
config.pluginmanager.register(NFPlugin(config), "nfplugin")
474475

475476

476-
@pytest.fixture
477+
@fixture
477478
def cache(request: FixtureRequest) -> Cache:
478479
"""Return a cache object that can persist state between testing sessions.
479480

src/_pytest/capture.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
from typing import TYPE_CHECKING
1818
from typing import Union
1919

20-
import pytest
2120
from _pytest.compat import final
2221
from _pytest.config import Config
22+
from _pytest.config import hookimpl
2323
from _pytest.config.argparsing import Parser
24+
from _pytest.fixtures import fixture
2425
from _pytest.fixtures import SubRequest
2526
from _pytest.nodes import Collector
27+
from _pytest.nodes import File
2628
from _pytest.nodes import Item
2729

2830
if TYPE_CHECKING:
@@ -145,7 +147,7 @@ def _reopen_stdio(f, mode):
145147
sys.stderr = _reopen_stdio(sys.stderr, "wb")
146148

147149

148-
@pytest.hookimpl(hookwrapper=True)
150+
@hookimpl(hookwrapper=True)
149151
def pytest_load_initial_conftests(early_config: Config):
150152
ns = early_config.known_args_namespace
151153
if ns.capture == "fd":
@@ -784,9 +786,9 @@ def item_capture(self, when: str, item: Item) -> Generator[None, None, None]:
784786

785787
# Hooks
786788

787-
@pytest.hookimpl(hookwrapper=True)
789+
@hookimpl(hookwrapper=True)
788790
def pytest_make_collect_report(self, collector: Collector):
789-
if isinstance(collector, pytest.File):
791+
if isinstance(collector, File):
790792
self.resume_global_capture()
791793
outcome = yield
792794
self.suspend_global_capture()
@@ -799,26 +801,26 @@ def pytest_make_collect_report(self, collector: Collector):
799801
else:
800802
yield
801803

802-
@pytest.hookimpl(hookwrapper=True)
804+
@hookimpl(hookwrapper=True)
803805
def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]:
804806
with self.item_capture("setup", item):
805807
yield
806808

807-
@pytest.hookimpl(hookwrapper=True)
809+
@hookimpl(hookwrapper=True)
808810
def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]:
809811
with self.item_capture("call", item):
810812
yield
811813

812-
@pytest.hookimpl(hookwrapper=True)
814+
@hookimpl(hookwrapper=True)
813815
def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]:
814816
with self.item_capture("teardown", item):
815817
yield
816818

817-
@pytest.hookimpl(tryfirst=True)
819+
@hookimpl(tryfirst=True)
818820
def pytest_keyboard_interrupt(self) -> None:
819821
self.stop_global_capturing()
820822

821-
@pytest.hookimpl(tryfirst=True)
823+
@hookimpl(tryfirst=True)
822824
def pytest_internalerror(self) -> None:
823825
self.stop_global_capturing()
824826

@@ -893,7 +895,7 @@ def disabled(self) -> Generator[None, None, None]:
893895
# The fixtures.
894896

895897

896-
@pytest.fixture
898+
@fixture
897899
def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
898900
"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
899901
@@ -910,7 +912,7 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
910912
capman.unset_fixture()
911913

912914

913-
@pytest.fixture
915+
@fixture
914916
def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]:
915917
"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
916918
@@ -927,7 +929,7 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None,
927929
capman.unset_fixture()
928930

929931

930-
@pytest.fixture
932+
@fixture
931933
def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
932934
"""Enable text capturing of writes to file descriptors ``1`` and ``2``.
933935
@@ -944,7 +946,7 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
944946
capman.unset_fixture()
945947

946948

947-
@pytest.fixture
949+
@fixture
948950
def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]:
949951
"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
950952

src/_pytest/logging.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from typing import TypeVar
1717
from typing import Union
1818

19-
import pytest
2019
from _pytest import nodes
2120
from _pytest._io import TerminalWriter
2221
from _pytest.capture import CaptureManager
@@ -25,7 +24,10 @@
2524
from _pytest.config import _strtobool
2625
from _pytest.config import Config
2726
from _pytest.config import create_terminal_writer
27+
from _pytest.config import hookimpl
28+
from _pytest.config import UsageError
2829
from _pytest.config.argparsing import Parser
30+
from _pytest.fixtures import fixture
2931
from _pytest.fixtures import FixtureRequest
3032
from _pytest.main import Session
3133
from _pytest.store import StoreKey
@@ -468,7 +470,7 @@ def at_level(
468470
self.handler.setLevel(handler_orig_level)
469471

470472

471-
@pytest.fixture
473+
@fixture
472474
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:
473475
"""Access and control log capturing.
474476
@@ -501,15 +503,15 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
501503
return int(getattr(logging, log_level, log_level))
502504
except ValueError as e:
503505
# Python logging does not recognise this as a logging level
504-
raise pytest.UsageError(
506+
raise UsageError(
505507
"'{}' is not recognized as a logging level name for "
506508
"'{}'. Please consider passing the "
507509
"logging level num instead.".format(log_level, setting_name)
508510
) from e
509511

510512

511513
# run after terminalreporter/capturemanager are configured
512-
@pytest.hookimpl(trylast=True)
514+
@hookimpl(trylast=True)
513515
def pytest_configure(config: Config) -> None:
514516
config.pluginmanager.register(LoggingPlugin(config), "logging-plugin")
515517

@@ -639,23 +641,23 @@ def _log_cli_enabled(self):
639641

640642
return True
641643

642-
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
644+
@hookimpl(hookwrapper=True, tryfirst=True)
643645
def pytest_sessionstart(self) -> Generator[None, None, None]:
644646
self.log_cli_handler.set_when("sessionstart")
645647

646648
with catching_logs(self.log_cli_handler, level=self.log_cli_level):
647649
with catching_logs(self.log_file_handler, level=self.log_file_level):
648650
yield
649651

650-
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
652+
@hookimpl(hookwrapper=True, tryfirst=True)
651653
def pytest_collection(self) -> Generator[None, None, None]:
652654
self.log_cli_handler.set_when("collection")
653655

654656
with catching_logs(self.log_cli_handler, level=self.log_cli_level):
655657
with catching_logs(self.log_file_handler, level=self.log_file_level):
656658
yield
657659

658-
@pytest.hookimpl(hookwrapper=True)
660+
@hookimpl(hookwrapper=True)
659661
def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]:
660662
if session.config.option.collectonly:
661663
yield
@@ -669,12 +671,12 @@ def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]:
669671
with catching_logs(self.log_file_handler, level=self.log_file_level):
670672
yield # Run all the tests.
671673

672-
@pytest.hookimpl
674+
@hookimpl
673675
def pytest_runtest_logstart(self) -> None:
674676
self.log_cli_handler.reset()
675677
self.log_cli_handler.set_when("start")
676678

677-
@pytest.hookimpl
679+
@hookimpl
678680
def pytest_runtest_logreport(self) -> None:
679681
self.log_cli_handler.set_when("logreport")
680682

@@ -695,41 +697,41 @@ def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, Non
695697
log = report_handler.stream.getvalue().strip()
696698
item.add_report_section(when, "log", log)
697699

698-
@pytest.hookimpl(hookwrapper=True)
700+
@hookimpl(hookwrapper=True)
699701
def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]:
700702
self.log_cli_handler.set_when("setup")
701703

702704
empty: Dict[str, List[logging.LogRecord]] = {}
703705
item._store[caplog_records_key] = empty
704706
yield from self._runtest_for(item, "setup")
705707

706-
@pytest.hookimpl(hookwrapper=True)
708+
@hookimpl(hookwrapper=True)
707709
def pytest_runtest_call(self, item: nodes.Item) -> Generator[None, None, None]:
708710
self.log_cli_handler.set_when("call")
709711

710712
yield from self._runtest_for(item, "call")
711713

712-
@pytest.hookimpl(hookwrapper=True)
714+
@hookimpl(hookwrapper=True)
713715
def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None, None, None]:
714716
self.log_cli_handler.set_when("teardown")
715717

716718
yield from self._runtest_for(item, "teardown")
717719
del item._store[caplog_records_key]
718720
del item._store[caplog_handler_key]
719721

720-
@pytest.hookimpl
722+
@hookimpl
721723
def pytest_runtest_logfinish(self) -> None:
722724
self.log_cli_handler.set_when("finish")
723725

724-
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
726+
@hookimpl(hookwrapper=True, tryfirst=True)
725727
def pytest_sessionfinish(self) -> Generator[None, None, None]:
726728
self.log_cli_handler.set_when("sessionfinish")
727729

728730
with catching_logs(self.log_cli_handler, level=self.log_cli_level):
729731
with catching_logs(self.log_file_handler, level=self.log_file_level):
730732
yield
731733

732-
@pytest.hookimpl
734+
@hookimpl
733735
def pytest_unconfigure(self) -> None:
734736
# Close the FileHandler explicitly.
735737
# (logging.shutdown might have lost the weakref?!)

src/_pytest/monkeypatch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
from typing import TypeVar
1616
from typing import Union
1717

18-
import pytest
1918
from _pytest.compat import final
2019
from _pytest.fixtures import fixture
20+
from _pytest.warning_types import PytestWarning
2121

2222
RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$")
2323

@@ -271,7 +271,7 @@ def setenv(self, name: str, value: str, prepend: Optional[str] = None) -> None:
271271
"""
272272
if not isinstance(value, str):
273273
warnings.warn( # type: ignore[unreachable]
274-
pytest.PytestWarning(
274+
PytestWarning(
275275
"Value of environment variable {name} type should be str, but got "
276276
"{value!r} (type: {type}); converted to str implicitly".format(
277277
name=name, value=value, type=type(value).__name__

0 commit comments

Comments
 (0)