Skip to content

Commit

Permalink
Make sure that pyfakefs is not active during pytest reporting
Browse files Browse the repository at this point in the history
- pause the patching in pytest_runtest_logreport
- fixes #904
  • Loading branch information
mrbean-bremen committed Nov 13, 2023
1 parent 26ed458 commit 73fb5d2
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 20 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ The released versions correspond to PyPI releases.

## Unreleased

### Fixes
* fixes the problem that filesystem patching was still active in the pytest
logreport phase (see [#904](../../issues/904))

## [Version 5.3.0](https://pypi.python.org/pypi/pyfakefs/5.3.0) (2023-10-11)
Adds official support for Python 3.12.

Expand Down
14 changes: 11 additions & 3 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ def __init__(
self._isStale = True
self._dyn_patcher: Optional[DynamicPatcher] = None
self._patching = False
self._paused = False

@classmethod
def clear_fs_cache(cls) -> None:
Expand Down Expand Up @@ -898,6 +899,7 @@ def setUp(self, doctester: Any = None) -> None:
def start_patching(self) -> None:
if not self._patching:
self._patching = True
self._paused = False

self.patch_modules()
self.patch_functions()
Expand Down Expand Up @@ -975,17 +977,22 @@ def tearDown(self, doctester: Any = None):
else:
self.__class__.PATCHER = None

def stop_patching(self) -> None:
def stop_patching(self, temporary=False) -> None:
if self._patching:
self._isStale = True
self._patching = False
self._paused = temporary
if self._stubs:
self._stubs.smart_unset_all()
self.unset_defaults()
if self._dyn_patcher:
self._dyn_patcher.cleanup()
sys.meta_path.pop(0)

@property
def is_patching(self):
return self._patching

def unset_defaults(self) -> None:
for fct, idx, ft in self.FS_DEFARGS:
new_defaults = []
Expand All @@ -1003,15 +1010,16 @@ def pause(self) -> None:
Calling pause() twice is silently ignored.
"""
self.stop_patching()
self.stop_patching(temporary=True)

def resume(self) -> None:
"""Resume the patching of the file system modules if `pause` has
been called before. After that call, all file system calls are
executed in the fake file system.
Does nothing if patching is not paused.
"""
self.start_patching()
if self._paused:
self.start_patching()


class Pause:
Expand Down
13 changes: 13 additions & 0 deletions pyfakefs/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,16 @@ def fs_session(request):
def pytest_sessionfinish(session, exitstatus):
"""Make sure that the cache is cleared before the final test shutdown."""
Patcher.clear_fs_cache()


@pytest.hookimpl(tryfirst=True)
def pytest_runtest_logreport(report):
"""Make sure that patching is not active during reporting."""
if report.when == "call" and Patcher.PATCHER is not None:
Patcher.PATCHER.pause()


def pytest_runtest_call(item):
"""Resume paused patching before test start."""
if Patcher.PATCHER is not None:
Patcher.PATCHER.resume()
14 changes: 13 additions & 1 deletion pyfakefs/pytest_tests/pytest_module_fixture_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,19 @@ def use_fs(fs_module):
yield fs_module


@pytest.fixture(autouse=True)
def check_patching_stopped(fs):
# patching shall be paused at test end, even in module scope (see #904)
yield
assert not fs.patcher.is_patching


@pytest.mark.usefixtures("fs")
def test_fs_uses_fs_module():
def test_fs_uses_fs_module1():
# check that `fs` uses the same filesystem as `fs_module`
assert os.path.exists(os.path.join("foo", "bar"))


def test_fs_uses_fs_module2(fs):
# check that testing was not stopped by the first test
assert os.path.exists(os.path.join("foo", "bar"))
16 changes: 0 additions & 16 deletions pyfakefs/pytest_tests/segfault_test.py

This file was deleted.

0 comments on commit 73fb5d2

Please sign in to comment.