Skip to content

Commit

Permalink
legacypath: only add testdir and tmpdir fixtures if corresponding…
Browse files Browse the repository at this point in the history
… plugins are registered

This preserves the existing behavior and gives a proper error message
in case e.g. `testdir` is requested without the `pytester` plugin being
loaded.
  • Loading branch information
bluetech committed Oct 29, 2021
1 parent c3dff75 commit e6eac28
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 41 deletions.
2 changes: 1 addition & 1 deletion doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ tmpdir

:ref:`tmpdir and tmpdir_factory`

.. autofunction:: _pytest.legacypath.tmpdir()
.. autofunction:: _pytest.legacypath.LegacyTmpdirPlugin.tmpdir()
:no-auto-options:


Expand Down
90 changes: 50 additions & 40 deletions src/_pytest/legacypath.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,17 @@ def __str__(self) -> str:
pytest.Testdir = Testdir # type: ignore[attr-defined]


@pytest.fixture
def testdir(pytester: pytest.Pytester) -> Testdir:
"""
Identical to :fixture:`pytester`, and provides an instance whose methods return
legacy ``LEGACY_PATH`` objects instead when applicable.
class LegacyTestdirPlugin:
@staticmethod
@pytest.fixture
def testdir(pytester: pytest.Pytester) -> Testdir:
"""
Identical to :fixture:`pytester`, and provides an instance whose methods return
legacy ``LEGACY_PATH`` objects instead when applicable.
New code should avoid using :fixture:`testdir` in favor of :fixture:`pytester`.
"""
return Testdir(pytester, _ispytest=True)
New code should avoid using :fixture:`testdir` in favor of :fixture:`pytester`.
"""
return Testdir(pytester, _ispytest=True)


@final
Expand Down Expand Up @@ -285,29 +287,31 @@ def getbasetemp(self) -> LEGACY_PATH:
pytest.TempdirFactory = TempdirFactory # type: ignore[attr-defined]


@pytest.fixture(scope="session")
def tmpdir_factory(request: pytest.FixtureRequest) -> TempdirFactory:
"""Return a :class:`pytest.TempdirFactory` instance for the test session."""
# Set dynamically by pytest_configure().
return request.config._tmpdirhandler # type: ignore
class LegacyTmpdirPlugin:
@staticmethod
@pytest.fixture(scope="session")
def tmpdir_factory(request: pytest.FixtureRequest) -> TempdirFactory:
"""Return a :class:`pytest.TempdirFactory` instance for the test session."""
# Set dynamically by pytest_configure().
return request.config._tmpdirhandler # type: ignore

@staticmethod
@pytest.fixture
def tmpdir(tmp_path: Path) -> LEGACY_PATH:
"""Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
@pytest.fixture
def tmpdir(tmp_path: Path) -> LEGACY_PATH:
"""Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
By default, a new base temporary directory is created each test session,
and old bases are removed after 3 sessions, to aid in debugging. If
``--basetemp`` is used then it is cleared each session. See :ref:`base
temporary directory`.
By default, a new base temporary directory is created each test session,
and old bases are removed after 3 sessions, to aid in debugging. If
``--basetemp`` is used then it is cleared each session. See :ref:`base
temporary directory`.
The returned object is a `legacy_path`_ object.
The returned object is a `legacy_path`_ object.
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html
"""
return legacy_path(tmp_path)
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html
"""
return legacy_path(tmp_path)


def Cache_makedir(self: pytest.Cache, name: str) -> LEGACY_PATH:
Expand Down Expand Up @@ -400,19 +404,25 @@ def pytest_configure(config: pytest.Config) -> None:
mp = pytest.MonkeyPatch()
config.add_cleanup(mp.undo)

# Create TmpdirFactory and attach it to the config object.
#
# This is to comply with existing plugins which expect the handler to be
# available at pytest_configure time, but ideally should be moved entirely
# to the tmpdir_factory session fixture.
try:
tmp_path_factory = config._tmp_path_factory # type: ignore[attr-defined]
except AttributeError:
# tmpdir plugin is blocked.
pass
else:
_tmpdirhandler = TempdirFactory(tmp_path_factory, _ispytest=True)
mp.setattr(config, "_tmpdirhandler", _tmpdirhandler, raising=False)
if config.pluginmanager.has_plugin("pytester"):
config.pluginmanager.register(LegacyTestdirPlugin, "legacypath-pytester")

if config.pluginmanager.has_plugin("tmpdir"):
# Create TmpdirFactory and attach it to the config object.
#
# This is to comply with existing plugins which expect the handler to be
# available at pytest_configure time, but ideally should be moved entirely
# to the tmpdir_factory session fixture.
try:
tmp_path_factory = config._tmp_path_factory # type: ignore[attr-defined]
except AttributeError:
# tmpdir plugin is blocked.
pass
else:
_tmpdirhandler = TempdirFactory(tmp_path_factory, _ispytest=True)
mp.setattr(config, "_tmpdirhandler", _tmpdirhandler, raising=False)

config.pluginmanager.register(LegacyTmpdirPlugin, "legacypath-tmpdir")

# Add Cache.makedir().
mp.setattr(pytest.Cache, "makedir", Cache_makedir, raising=False)
Expand Down

0 comments on commit e6eac28

Please sign in to comment.