Export MonkeyPatch as pytest.MonkeyPatch
We want to export `pytest.MonkeyPatch` for the purpose of type-annotating the `monkeypatch` fixture. For other fixtures we export in this way, we also make direct construction of them (e.g. `MonkeyPatch()`) private. But unlike the others, `MonkeyPatch` is also widely used directly already, mostly because the `monkeypatch` fixture only works in `function` scope (issue #363), but also in other cases. So making it private will be annoying and we don't offer a decent replacement yet. So, let's just make direct construction public & documented.
This commit is contained in:
parent
3bcd316f07
commit
6f13d1b03b
|
@ -0,0 +1,8 @@
|
||||||
|
It is now possible to construct a :class:`~pytest.MonkeyPatch` object directly as ``pytest.MonkeyPatch()``,
|
||||||
|
in cases when the :fixture:`monkeypatch` fixture cannot be used. Previously some users imported it
|
||||||
|
from the private `_pytest.monkeypatch.MonkeyPatch` namespace.
|
||||||
|
|
||||||
|
Additionally, :meth:`MonkeyPatch.context <pytest.MonkeyPatch.context>` is now a classmethod,
|
||||||
|
and can be used as ``with MonkeyPatch.context() as mp: ...``. This is the recommended way to use
|
||||||
|
``MonkeyPatch`` directly, since unlike the ``monkeypatch`` fixture, an instance created directly
|
||||||
|
is not ``undo()``-ed automatically.
|
|
@ -486,16 +486,14 @@ caplog
|
||||||
monkeypatch
|
monkeypatch
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. currentmodule:: _pytest.monkeypatch
|
|
||||||
|
|
||||||
**Tutorial**: :doc:`monkeypatch`.
|
**Tutorial**: :doc:`monkeypatch`.
|
||||||
|
|
||||||
.. autofunction:: _pytest.monkeypatch.monkeypatch()
|
.. autofunction:: _pytest.monkeypatch.monkeypatch()
|
||||||
:no-auto-options:
|
:no-auto-options:
|
||||||
|
|
||||||
Returns a :class:`MonkeyPatch` instance.
|
Returns a :class:`~pytest.MonkeyPatch` instance.
|
||||||
|
|
||||||
.. autoclass:: _pytest.monkeypatch.MonkeyPatch
|
.. autoclass:: pytest.MonkeyPatch
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,17 @@ notset = Notset()
|
||||||
|
|
||||||
@final
|
@final
|
||||||
class MonkeyPatch:
|
class MonkeyPatch:
|
||||||
"""Object returned by the ``monkeypatch`` fixture keeping a record of
|
"""Helper to conveniently monkeypatch attributes/items/environment
|
||||||
setattr/item/env/syspath changes."""
|
variables/syspath.
|
||||||
|
|
||||||
|
Returned by the :fixture:`monkeypatch` fixture.
|
||||||
|
|
||||||
|
:versionchanged:: 6.2
|
||||||
|
Can now also be used directly as `pytest.MonkeyPatch()`, for when
|
||||||
|
the fixture is not available. In this case, use
|
||||||
|
:meth:`with MonkeyPatch.context() as mp: <context>` or remember to call
|
||||||
|
:meth:`undo` explicitly.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._setattr: List[Tuple[object, str, object]] = []
|
self._setattr: List[Tuple[object, str, object]] = []
|
||||||
|
@ -120,8 +129,9 @@ class MonkeyPatch:
|
||||||
self._cwd: Optional[str] = None
|
self._cwd: Optional[str] = None
|
||||||
self._savesyspath: Optional[List[str]] = None
|
self._savesyspath: Optional[List[str]] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def context(self) -> Generator["MonkeyPatch", None, None]:
|
def context(cls) -> Generator["MonkeyPatch", None, None]:
|
||||||
"""Context manager that returns a new :class:`MonkeyPatch` object
|
"""Context manager that returns a new :class:`MonkeyPatch` object
|
||||||
which undoes any patching done inside the ``with`` block upon exit.
|
which undoes any patching done inside the ``with`` block upon exit.
|
||||||
|
|
||||||
|
@ -140,7 +150,7 @@ class MonkeyPatch:
|
||||||
such as mocking ``stdlib`` functions that might break pytest itself if mocked (for examples
|
such as mocking ``stdlib`` functions that might break pytest itself if mocked (for examples
|
||||||
of this see `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_.
|
of this see `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_.
|
||||||
"""
|
"""
|
||||||
m = MonkeyPatch()
|
m = cls()
|
||||||
try:
|
try:
|
||||||
yield m
|
yield m
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -19,6 +19,7 @@ from _pytest.freeze_support import freeze_includes
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.mark import MARK_GEN as mark
|
from _pytest.mark import MARK_GEN as mark
|
||||||
from _pytest.mark import param
|
from _pytest.mark import param
|
||||||
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
from _pytest.nodes import File
|
from _pytest.nodes import File
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
|
@ -74,6 +75,7 @@ __all__ = [
|
||||||
"main",
|
"main",
|
||||||
"mark",
|
"mark",
|
||||||
"Module",
|
"Module",
|
||||||
|
"MonkeyPatch",
|
||||||
"Package",
|
"Package",
|
||||||
"param",
|
"param",
|
||||||
"PytestAssertRewriteWarning",
|
"PytestAssertRewriteWarning",
|
||||||
|
|
|
@ -409,6 +409,16 @@ def test_context() -> None:
|
||||||
assert inspect.isclass(functools.partial)
|
assert inspect.isclass(functools.partial)
|
||||||
|
|
||||||
|
|
||||||
|
def test_context_classmethod() -> None:
|
||||||
|
class A:
|
||||||
|
x = 1
|
||||||
|
|
||||||
|
with MonkeyPatch.context() as m:
|
||||||
|
m.setattr(A, "x", 2)
|
||||||
|
assert A.x == 2
|
||||||
|
assert A.x == 1
|
||||||
|
|
||||||
|
|
||||||
def test_syspath_prepend_with_namespace_packages(
|
def test_syspath_prepend_with_namespace_packages(
|
||||||
testdir: Testdir, monkeypatch: MonkeyPatch
|
testdir: Testdir, monkeypatch: MonkeyPatch
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Reference in New Issue