Skip to content

Commit ac6e3e5

Browse files
committed
Remove the "module_cleanup_mode" argument from Patcher
- had been introduced in the previous patch release as a stop-gap measure for problems with django - superseded by module cleanup handlers
1 parent 99a8a2d commit ac6e3e5

File tree

3 files changed

+10
-56
lines changed

3 files changed

+10
-56
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The released versions correspond to PyPI releases.
66
### Changes
77
* the handling of file permissions under Posix is should now mostly match the behavior
88
of the real filesystem, which may change the behavior of some tests
9+
* removed the argument `module_cleanup_mode`, that was introduced as a temporary workaround
10+
in the previous version - related problems shall be handled using a cleanup handler
911

1012
### Fixes
1113
* fixed a specific problem on reloading a pandas-related module (see [#947](../../issues/947)),

docs/usage.rst

+4-18
Original file line numberDiff line numberDiff line change
@@ -678,24 +678,10 @@ for modules loaded locally inside of functions).
678678
Can be switched off if it causes unwanted side effects, though that would mean that
679679
dynamically loaded modules are no longer patched, if they use file system functions.
680680

681-
module_cleanup_mode
682-
~~~~~~~~~~~~~~~~~~~
683-
This is a setting that works around a potential problem with the cleanup of
684-
dynamically loaded modules (e.g. modules loaded after the test has started).
685-
As the original problem related to `django` has now been resolved in another way (see below),
686-
the setting may not be needed anymore, and is subject to removal in a future version.
687-
688-
The setting defines how the dynamically loaded modules are cleaned up after the test.
689-
Any dynamically loaded module is cleaned up after the test to ensure that no patched modules
690-
can be used after that.
691-
The default (`ModuleCleanupMode.AUTO`) is currently the same as `ModuleCleanupMode.DELETE`.
692-
`DELETE` will delete all dynamically loaded modules (so that they are reloaded the next time
693-
they are needed), while `RELOAD` will reload them immediately.
694-
Under some rare conditions, changing this setting may help to avoid problems related
695-
to incorrect test cleanup.
696-
697-
Problems with unloading dynamically loaded modules may also be solved more
698-
specifically by registering a handler for specific modules (using `Patcher.register_cleanup_handler`),
681+
A possible problem with dynamically loaded modules is their unloading, for example if
682+
reloading the module fails after unloading due to a problem in the module.
683+
This kind of problem may be solved more specifically by registering a handler
684+
for specific modules (using `Patcher.register_cleanup_handler`),
699685
that will be called during the cleanup process. This is used internally
700686
to handle known problems with the `django` and `pandas` packages.
701687

pyfakefs/fake_filesystem_unittest.py

+4-38
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import sys
4848
import tempfile
4949
import tokenize
50-
from enum import Enum
5150
from importlib.abc import Loader, MetaPathFinder
5251
from types import ModuleType, TracebackType, FunctionType
5352
from typing import (
@@ -95,14 +94,6 @@
9594
PATH_MODULE = "ntpath" if sys.platform == "win32" else "posixpath"
9695

9796

98-
class ModuleCleanupMode(Enum):
99-
"""Defines the behavior of module cleanup on dynamic patcher shutdown."""
100-
101-
AUTO = 1
102-
DELETE = 2
103-
RELOAD = 3
104-
105-
10697
def patchfs(
10798
_func: Optional[Callable] = None,
10899
*,
@@ -115,7 +106,6 @@ def patchfs(
115106
patch_default_args: bool = False,
116107
use_cache: bool = True,
117108
use_dynamic_patch: bool = True,
118-
module_cleanup_mode: ModuleCleanupMode = ModuleCleanupMode.AUTO,
119109
) -> Callable:
120110
"""Convenience decorator to use patcher with additional parameters in a
121111
test function.
@@ -144,7 +134,6 @@ def wrapped(*args, **kwargs):
144134
patch_default_args=patch_default_args,
145135
use_cache=use_cache,
146136
use_dynamic_patch=use_dynamic_patch,
147-
module_cleanup_mode=module_cleanup_mode,
148137
) as p:
149138
args = list(args)
150139
args.append(p.fs)
@@ -181,7 +170,6 @@ def load_doctests(
181170
patch_open_code: PatchMode = PatchMode.OFF,
182171
patch_default_args: bool = False,
183172
use_dynamic_patch: bool = True,
184-
module_cleanup_mode: ModuleCleanupMode = ModuleCleanupMode.AUTO,
185173
) -> TestSuite: # pylint:disable=unused-argument
186174
"""Load the doctest tests for the specified module into unittest.
187175
Args:
@@ -202,7 +190,6 @@ def load_doctests(
202190
patch_open_code=patch_open_code,
203191
patch_default_args=patch_default_args,
204192
use_dynamic_patch=use_dynamic_patch,
205-
module_cleanup_mode=module_cleanup_mode,
206193
is_doc_test=True,
207194
)
208195
assert Patcher.DOC_PATCHER is not None
@@ -283,7 +270,6 @@ def setUpPyfakefs(
283270
patch_default_args: bool = False,
284271
use_cache: bool = True,
285272
use_dynamic_patch: bool = True,
286-
module_cleanup_mode: ModuleCleanupMode = ModuleCleanupMode.AUTO,
287273
) -> None:
288274
"""Bind the file-related modules to the :py:class:`pyfakefs` fake file
289275
system instead of the real file system. Also bind the fake `open()`
@@ -316,7 +302,6 @@ def setUpPyfakefs(
316302
patch_default_args=patch_default_args,
317303
use_cache=use_cache,
318304
use_dynamic_patch=use_dynamic_patch,
319-
module_cleanup_mode=module_cleanup_mode,
320305
)
321306

322307
self._patcher.setUp()
@@ -334,7 +319,6 @@ def setUpClassPyfakefs(
334319
patch_default_args: bool = False,
335320
use_cache: bool = True,
336321
use_dynamic_patch: bool = True,
337-
module_cleanup_mode: ModuleCleanupMode = ModuleCleanupMode.AUTO,
338322
) -> None:
339323
"""Similar to :py:func:`setUpPyfakefs`, but as a class method that
340324
can be used in `setUpClass` instead of in `setUp`.
@@ -373,7 +357,6 @@ def setUpClassPyfakefs(
373357
patch_default_args=patch_default_args,
374358
use_cache=use_cache,
375359
use_dynamic_patch=use_dynamic_patch,
376-
module_cleanup_mode=module_cleanup_mode,
377360
)
378361

379362
Patcher.PATCHER.setUp()
@@ -539,7 +522,6 @@ def __init__(
539522
patch_default_args: bool = False,
540523
use_cache: bool = True,
541524
use_dynamic_patch: bool = True,
542-
module_cleanup_mode: ModuleCleanupMode = ModuleCleanupMode.AUTO,
543525
is_doc_test: bool = False,
544526
) -> None:
545527
"""
@@ -575,11 +557,6 @@ def __init__(
575557
use_dynamic_patch: If `True`, dynamic patching after setup is used
576558
(for example for modules loaded locally inside of functions).
577559
Can be switched off if it causes unwanted side effects.
578-
module_cleanup_mode: Defines how the modules in the dynamic patcher are
579-
cleaned up after the test. The default (AUTO) currently depends
580-
on the availability of the `django` module, DELETE will delete
581-
all dynamically loaded modules, RELOAD will reload them.
582-
This option is subject to change in later versions.
583560
"""
584561
self.is_doc_test = is_doc_test
585562
if is_doc_test:
@@ -618,7 +595,6 @@ def __init__(
618595
self.patch_default_args = patch_default_args
619596
self.use_cache = use_cache
620597
self.use_dynamic_patch = use_dynamic_patch
621-
self.module_cleanup_mode = module_cleanup_mode
622598
self.cleanup_handlers: Dict[str, Callable[[str], bool]] = {}
623599

624600
if use_known_patches:
@@ -971,7 +947,7 @@ def start_patching(self) -> None:
971947
if sys.modules.get(module.__name__) is module:
972948
reload(module)
973949
if not self.use_dynamic_patch:
974-
self._dyn_patcher.cleanup(ModuleCleanupMode.DELETE)
950+
self._dyn_patcher.cleanup()
975951
sys.meta_path.pop(0)
976952

977953
def patch_functions(self) -> None:
@@ -1049,7 +1025,7 @@ def stop_patching(self, temporary=False) -> None:
10491025
self._stubs.smart_unset_all()
10501026
self.unset_defaults()
10511027
if self.use_dynamic_patch and self._dyn_patcher:
1052-
self._dyn_patcher.cleanup(self.module_cleanup_mode)
1028+
self._dyn_patcher.cleanup()
10531029
sys.meta_path.pop(0)
10541030

10551031
@property
@@ -1142,7 +1118,7 @@ def __init__(self, patcher: Patcher) -> None:
11421118
for name, module in self.modules.items():
11431119
sys.modules[name] = module
11441120

1145-
def cleanup(self, cleanup_mode: ModuleCleanupMode) -> None:
1121+
def cleanup(self) -> None:
11461122
for module_name in self.sysmodules:
11471123
sys.modules[module_name] = self.sysmodules[module_name]
11481124
for module in self._patcher.modules_to_reload:
@@ -1153,21 +1129,11 @@ def cleanup(self, cleanup_mode: ModuleCleanupMode) -> None:
11531129
]
11541130
# Delete all modules loaded during the test, ensuring that
11551131
# they are reloaded after the test.
1156-
# If cleanup_mode is set to RELOAD, reload the modules instead.
1157-
# This is probably not needed anymore with the cleanup handlers in place.
1158-
if cleanup_mode == ModuleCleanupMode.AUTO:
1159-
cleanup_mode = ModuleCleanupMode.DELETE
11601132
for name in self._loaded_module_names:
11611133
if name in sys.modules and name not in reloaded_module_names:
11621134
if name in self.cleanup_handlers and self.cleanup_handlers[name](name):
11631135
continue
1164-
if cleanup_mode == ModuleCleanupMode.RELOAD:
1165-
try:
1166-
reload(sys.modules[name])
1167-
except Exception:
1168-
del sys.modules[name]
1169-
else:
1170-
del sys.modules[name]
1136+
del sys.modules[name]
11711137

11721138
def needs_patch(self, name: str) -> bool:
11731139
"""Check if the module with the given name shall be replaced."""

0 commit comments

Comments
 (0)