Skip to content

Commit bbc9b5b

Browse files
committed
pytest: bring back direct imports of TempdirFactory, Testdir
The monkeypatch approach doesn't work for `import pytest; pytest.TempdirFactory`. Fix #9432.
1 parent 0fecfff commit bbc9b5b

File tree

2 files changed

+32
-31
lines changed

2 files changed

+32
-31
lines changed

src/_pytest/legacypath.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@
1414
from _pytest.compat import final
1515
from _pytest.compat import LEGACY_PATH
1616
from _pytest.compat import legacy_path
17+
from _pytest.config import PytestPluginManager
1718
from _pytest.deprecated import check_ispytest
19+
from _pytest.main import Session
20+
from _pytest.monkeypatch import MonkeyPatch
21+
from _pytest.nodes import Collector
22+
from _pytest.nodes import Item
1823
from _pytest.nodes import Node
24+
from _pytest.pytester import HookRecorder
25+
from _pytest.pytester import Pytester
26+
from _pytest.pytester import RunResult
1927
from _pytest.terminal import TerminalReporter
28+
from _pytest.tmpdir import TempPathFactory
2029

2130
if TYPE_CHECKING:
2231
from typing_extensions import Final
@@ -35,10 +44,10 @@ class Testdir:
3544

3645
__test__ = False
3746

38-
CLOSE_STDIN: "Final" = pytest.Pytester.CLOSE_STDIN
39-
TimeoutExpired: "Final" = pytest.Pytester.TimeoutExpired
47+
CLOSE_STDIN: "Final" = Pytester.CLOSE_STDIN
48+
TimeoutExpired: "Final" = Pytester.TimeoutExpired
4049

41-
def __init__(self, pytester: pytest.Pytester, *, _ispytest: bool = False) -> None:
50+
def __init__(self, pytester: Pytester, *, _ispytest: bool = False) -> None:
4251
check_ispytest(_ispytest)
4352
self._pytester = pytester
4453

@@ -64,10 +73,10 @@ def plugins(self, plugins):
6473
self._pytester.plugins = plugins
6574

6675
@property
67-
def monkeypatch(self) -> pytest.MonkeyPatch:
76+
def monkeypatch(self) -> MonkeyPatch:
6877
return self._pytester._monkeypatch
6978

70-
def make_hook_recorder(self, pluginmanager) -> pytest.HookRecorder:
79+
def make_hook_recorder(self, pluginmanager) -> HookRecorder:
7180
"""See :meth:`Pytester.make_hook_recorder`."""
7281
return self._pytester.make_hook_recorder(pluginmanager)
7382

@@ -131,19 +140,15 @@ def copy_example(self, name=None) -> LEGACY_PATH:
131140
"""See :meth:`Pytester.copy_example`."""
132141
return legacy_path(self._pytester.copy_example(name))
133142

134-
def getnode(
135-
self, config: pytest.Config, arg
136-
) -> Optional[Union[pytest.Item, pytest.Collector]]:
143+
def getnode(self, config: pytest.Config, arg) -> Optional[Union[Item, Collector]]:
137144
"""See :meth:`Pytester.getnode`."""
138145
return self._pytester.getnode(config, arg)
139146

140147
def getpathnode(self, path):
141148
"""See :meth:`Pytester.getpathnode`."""
142149
return self._pytester.getpathnode(path)
143150

144-
def genitems(
145-
self, colitems: List[Union[pytest.Item, pytest.Collector]]
146-
) -> List[pytest.Item]:
151+
def genitems(self, colitems: List[Union[Item, Collector]]) -> List[Item]:
147152
"""See :meth:`Pytester.genitems`."""
148153
return self._pytester.genitems(colitems)
149154

@@ -165,11 +170,11 @@ def inline_run(self, *args, plugins=(), no_reraise_ctrlc: bool = False):
165170
*args, plugins=plugins, no_reraise_ctrlc=no_reraise_ctrlc
166171
)
167172

168-
def runpytest_inprocess(self, *args, **kwargs) -> pytest.RunResult:
173+
def runpytest_inprocess(self, *args, **kwargs) -> RunResult:
169174
"""See :meth:`Pytester.runpytest_inprocess`."""
170175
return self._pytester.runpytest_inprocess(*args, **kwargs)
171176

172-
def runpytest(self, *args, **kwargs) -> pytest.RunResult:
177+
def runpytest(self, *args, **kwargs) -> RunResult:
173178
"""See :meth:`Pytester.runpytest`."""
174179
return self._pytester.runpytest(*args, **kwargs)
175180

@@ -196,8 +201,8 @@ def getmodulecol(self, source, configargs=(), withinit=False):
196201
)
197202

198203
def collect_by_name(
199-
self, modcol: pytest.Collector, name: str
200-
) -> Optional[Union[pytest.Item, pytest.Collector]]:
204+
self, modcol: Collector, name: str
205+
) -> Optional[Union[Item, Collector]]:
201206
"""See :meth:`Pytester.collect_by_name`."""
202207
return self._pytester.collect_by_name(modcol, name)
203208

@@ -212,19 +217,19 @@ def popen(
212217
"""See :meth:`Pytester.popen`."""
213218
return self._pytester.popen(cmdargs, stdout, stderr, stdin, **kw)
214219

215-
def run(self, *cmdargs, timeout=None, stdin=CLOSE_STDIN) -> pytest.RunResult:
220+
def run(self, *cmdargs, timeout=None, stdin=CLOSE_STDIN) -> RunResult:
216221
"""See :meth:`Pytester.run`."""
217222
return self._pytester.run(*cmdargs, timeout=timeout, stdin=stdin)
218223

219-
def runpython(self, script) -> pytest.RunResult:
224+
def runpython(self, script) -> RunResult:
220225
"""See :meth:`Pytester.runpython`."""
221226
return self._pytester.runpython(script)
222227

223228
def runpython_c(self, command):
224229
"""See :meth:`Pytester.runpython_c`."""
225230
return self._pytester.runpython_c(command)
226231

227-
def runpytest_subprocess(self, *args, timeout=None) -> pytest.RunResult:
232+
def runpytest_subprocess(self, *args, timeout=None) -> RunResult:
228233
"""See :meth:`Pytester.runpytest_subprocess`."""
229234
return self._pytester.runpytest_subprocess(*args, timeout=timeout)
230235

@@ -245,13 +250,10 @@ def __str__(self) -> str:
245250
return str(self.tmpdir)
246251

247252

248-
pytest.Testdir = Testdir # type: ignore[attr-defined]
249-
250-
251253
class LegacyTestdirPlugin:
252254
@staticmethod
253255
@pytest.fixture
254-
def testdir(pytester: pytest.Pytester) -> Testdir:
256+
def testdir(pytester: Pytester) -> Testdir:
255257
"""
256258
Identical to :fixture:`pytester`, and provides an instance whose methods return
257259
legacy ``LEGACY_PATH`` objects instead when applicable.
@@ -267,10 +269,10 @@ class TempdirFactory:
267269
"""Backward compatibility wrapper that implements :class:``_pytest.compat.LEGACY_PATH``
268270
for :class:``TempPathFactory``."""
269271

270-
_tmppath_factory: pytest.TempPathFactory
272+
_tmppath_factory: TempPathFactory
271273

272274
def __init__(
273-
self, tmppath_factory: pytest.TempPathFactory, *, _ispytest: bool = False
275+
self, tmppath_factory: TempPathFactory, *, _ispytest: bool = False
274276
) -> None:
275277
check_ispytest(_ispytest)
276278
self._tmppath_factory = tmppath_factory
@@ -284,9 +286,6 @@ def getbasetemp(self) -> LEGACY_PATH:
284286
return legacy_path(self._tmppath_factory.getbasetemp().resolve())
285287

286288

287-
pytest.TempdirFactory = TempdirFactory # type: ignore[attr-defined]
288-
289-
290289
class LegacyTmpdirPlugin:
291290
@staticmethod
292291
@pytest.fixture(scope="session")
@@ -368,7 +367,7 @@ def Config_inifile(self: pytest.Config) -> Optional[LEGACY_PATH]:
368367
return legacy_path(str(self.inipath)) if self.inipath else None
369368

370369

371-
def Session_stardir(self: pytest.Session) -> LEGACY_PATH:
370+
def Session_stardir(self: Session) -> LEGACY_PATH:
372371
"""The path from which pytest was invoked.
373372
374373
Prefer to use ``startpath`` which is a :class:`pathlib.Path`.
@@ -453,9 +452,7 @@ def pytest_configure(config: pytest.Config) -> None:
453452

454453

455454
@pytest.hookimpl
456-
def pytest_plugin_registered(
457-
plugin: object, manager: pytest.PytestPluginManager
458-
) -> None:
455+
def pytest_plugin_registered(plugin: object, manager: PytestPluginManager) -> None:
459456
# pytester is not loaded by default and is commonly loaded from a conftest,
460457
# so checking for it in `pytest_configure` is not enough.
461458
is_pytester = plugin is manager.get_plugin("pytester")

src/pytest/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
from _pytest.fixtures import FixtureRequest
2424
from _pytest.fixtures import yield_fixture
2525
from _pytest.freeze_support import freeze_includes
26+
from _pytest.legacypath import TempdirFactory
27+
from _pytest.legacypath import Testdir
2628
from _pytest.logging import LogCaptureFixture
2729
from _pytest.main import Session
2830
from _pytest.mark import Mark
@@ -142,7 +144,9 @@
142144
"Stash",
143145
"StashKey",
144146
"version_tuple",
147+
"TempdirFactory",
145148
"TempPathFactory",
149+
"Testdir",
146150
"TestReport",
147151
"UsageError",
148152
"WarningsRecorder",

0 commit comments

Comments
 (0)