Skip to content

Commit

Permalink
Removed the unneeded workarounds for tempfile
Browse files Browse the repository at this point in the history
- remove special_names argument
- use modules_to_reload instead to reload tempfile
- fixes #340
mrbean-bremen committed Jan 12, 2018
1 parent 08f45ff commit d52dfe0
Showing 4 changed files with 25 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ must use pyfakefs 3.3 or earlier.

#### New Features
* Added support to fake out backported `scandir` module ([#332](../../issues/332))
* Dynamic loading of modules after setup is now on by default and no more considered experimental (see [#340](../../issues/340)).

#### Infrastructure
* Changed API to be PEP-8 conform [#186](../../issues/186). Note: The old API is still available.
66 changes: 14 additions & 52 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@

def load_doctests(loader, tests, ignore, module,
additional_skip_names=None,
patch_path=True, special_names=None): # pylint: disable=unused-argument
patch_path=True): # pylint: disable=unused-argument
"""Load the doctest tests for the specified module into unittest.
Args:
loader, tests, ignore : arguments passed in from `load_tests()`
@@ -96,7 +96,7 @@ def load_doctests(loader, tests, ignore, module,
File `example_test.py` in the pyfakefs release provides a usage example.
"""
_patcher = Patcher(additional_skip_names=additional_skip_names,
patch_path=patch_path, special_names=special_names)
patch_path=patch_path)
globs = _patcher.replace_globs(vars(module))
tests.addTests(doctest.DocTestSuite(module,
globs=globs,
@@ -111,7 +111,7 @@ class TestCase(unittest.TestCase):
"""

def __init__(self, methodName='runTest', additional_skip_names=None,
patch_path=True, special_names=None,
patch_path=True,
modules_to_reload=None,
use_dynamic_patch=True):
"""Creates the test class instance and the stubber used to stub out
@@ -129,11 +129,6 @@ def __init__(self, methodName='runTest', additional_skip_names=None,
Irrespective of patch_path, module 'os.path' is still correctly faked
if imported the usual way using `import os` or `import os.path`.
special_names: A dictionary with module names as key and a dictionary as
value, where the key is the original name of the module to be patched,
and the value is the name as it is imported.
This allows to patch modules where some of the file system modules are
imported as another name (e.g. `import os as _os`).
modules_to_reload (experimental): A list of modules that need to be reloaded
to be patched dynamically; may be needed if the module
imports file system modules under an alias
@@ -155,20 +150,13 @@ class MyTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
super(MyTestCase, self).__init__(
methodName=methodName, additional_skip_names=['posixpath'])
class AnotherTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
# allow patching a module that imports `os` as `my_os`
special_names = {'amodule': {'os': 'my_os'}}
super(MyTestCase, self).__init__(
methodName=methodName, special_names=special_names)
"""
super(TestCase, self).__init__(methodName)
self._stubber = Patcher(additional_skip_names=additional_skip_names,
patch_path=patch_path,
special_names=special_names)
self._modules_to_reload = modules_to_reload or []
patch_path=patch_path)
self._modules_to_reload = [tempfile]
if modules_to_reload is not None:
self._modules_to_reload.extend(modules_to_reload)
self._use_dynamic_patch = use_dynamic_patch

@property
@@ -223,15 +211,19 @@ def setUpPyfakefs(self):
"""
self._stubber.setUp()
self.addCleanup(self._stubber.tearDown)
dyn_patcher = DynamicPatcher(self._stubber)
sys.meta_path.insert(0, dyn_patcher)

for module in self._modules_to_reload:
if module.__name__ in sys.modules:
reload(module)

if self._use_dynamic_patch:
dyn_patcher = DynamicPatcher(self._stubber)
sys.meta_path.insert(0, dyn_patcher)
self.addCleanup(lambda: sys.meta_path.pop(0))
self.addCleanup(dyn_patcher.cleanup)
else:
dyn_patcher.cleanup()
sys.meta_path.pop(0)

@DeprecationWarning
def tearDownPyfakefs(self):
@@ -268,13 +260,10 @@ class Patcher(object):
if HAS_PATHLIB:
SKIPNAMES.add('pathlib')

def __init__(self, additional_skip_names=None, patch_path=True,
special_names=None):
def __init__(self, additional_skip_names=None, patch_path=True):
"""For a description of the arguments, see TestCase.__init__"""

self._skipNames = self.SKIPNAMES.copy()
self._special_names = special_names or {}
self._special_names['tempfile'] = {'os': '_os', 'io': '_io'}

if additional_skip_names is not None:
self._skipNames.update(additional_skip_names)
@@ -343,12 +332,6 @@ def _find_modules(self):
for name in self._modules:
if inspect.ismodule(module.__dict__.get(name)):
self._modules[name].add((module, name))
if '__name__' in module.__dict__ and module.__name__ in self._special_names:
module_names = self._special_names[module.__name__]
for name in self._modules:
if name in module_names:
if inspect.ismodule(module.__dict__.get(module_names[name])):
self._modules[name].add((module, module_names[name]))

def _refresh(self):
"""Renew the fake file system and set the _isStale flag to `False`."""
@@ -362,29 +345,8 @@ def _refresh(self):
self._fake_modules['path'] = self._fake_modules['os'].path
self.fake_open = fake_filesystem.FakeFileOpen(self.fs)

if not self.IS_WINDOWS and 'tempfile' in sys.modules:
self._patch_tempfile()

self._isStale = False

def _patch_tempfile(self):
"""Hack to work around cached `os` functions in `tempfile`.
Shall be replaced by a more generic mechanism.
"""
if 'unlink' in tempfile._TemporaryFileWrapper.__dict__:
# Python 2.7 to 3.2: unlink is a class method of _TemporaryFileWrapper
tempfile._TemporaryFileWrapper.unlink = self._fake_modules['os'].unlink

# Python 3.0 to 3.2 (and PyPy3 based on Python 3.2):
# `TemporaryDirectory._rmtree` is used instead of `shutil.rmtree`
# which uses several cached os functions - replace it with `shutil.rmtree`
if 'TemporaryDirectory' in tempfile.__dict__:
tempfile.TemporaryDirectory._rmtree = lambda o, path: shutil.rmtree(path)
else:
# Python > 3.2 - unlink is a default parameter of _TemporaryFileCloser
tempfile._TemporaryFileCloser.close.__defaults__ = (
self._fake_modules['os'].unlink,)

def setUp(self, doctester=None):
"""Bind the file-related modules to the :py:mod:`pyfakefs` fake
modules real ones. Also bind the fake `file()` and `open()` functions.
6 changes: 6 additions & 0 deletions tests/fake_filesystem_shutil_test.py
Original file line number Diff line number Diff line change
@@ -27,6 +27,8 @@
from pyfakefs import fake_filesystem_unittest
from tests.test_utils import RealFsTestMixin

is_windows = sys.platform == 'win32'


class RealFsTestCase(fake_filesystem_unittest.TestCase, RealFsTestMixin):
def __init__(self, methodName='runTest'):
@@ -91,6 +93,7 @@ def test_rmtree_without_permission_for_a_file_in_windows(self):
self.assertTrue(os.path.exists(file_path))
self.os.chmod(file_path, 0o666)

@unittest.skipIf(is_windows, 'Posix specific behavior')
def test_rmtree_without_permission_for_a_dir_in_posix(self):
self.check_posix_only()
dir_path = self.make_path('foo')
@@ -102,6 +105,7 @@ def test_rmtree_without_permission_for_a_dir_in_posix(self):
self.assertTrue(os.path.exists(file_path))
self.os.chmod(dir_path, 0o777)

@unittest.skipIf(is_windows, 'Posix specific behavior')
def test_rmtree_with_open_file_posix(self):
self.check_posix_only()
dir_path = self.make_path('foo')
@@ -405,6 +409,7 @@ def test_raises_if_dest_exists_and_is_not_writable(self):
self.assertRaises(IOError, shutil.copyfile, src_file, dst_file)
os.chmod(dst_file, 0o666)

@unittest.skipIf(is_windows, 'Posix specific behavior')
def test_raises_if_dest_dir_is_not_writable_under_posix(self):
self.check_posix_only()
src_file = self.make_path('xyzzy')
@@ -425,6 +430,7 @@ def test_raises_if_src_doesnt_exist(self):
self.assertFalse(os.path.exists(src_file))
self.assertRaises(IOError, shutil.copyfile, src_file, dst_file)

@unittest.skipIf(is_windows, 'Posix specific behavior')
def test_raises_if_src_not_readable(self):
self.check_posix_only()
src_file = self.make_path('xyzzy')
8 changes: 4 additions & 4 deletions tests/fake_filesystem_unittest_test.py
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@

from pyfakefs import fake_filesystem_unittest
from pyfakefs.fake_filesystem_unittest import Patcher
from tests.import_as_example import check_if_exists
import tests.import_as_example

if sys.version_info >= (3, 4):
import pathlib
@@ -135,9 +135,9 @@ def test_fakepathlib(self):

class TestImportAsOtherName(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='RunTest'):
special_names = {'tests.import_as_example': {'os': '_os'}}
modules_to_load = [tests.import_as_example]
super(TestImportAsOtherName, self).__init__(methodName,
special_names=special_names)
modules_to_reload=modules_to_load)

def setUp(self):
self.setUpPyfakefs()
@@ -146,7 +146,7 @@ def test_file_exists(self):
file_path = '/foo/bar/baz'
self.fs.create_file(file_path)
self.assertTrue(self.fs.exists(file_path))
self.assertTrue(check_if_exists(file_path))
self.assertTrue(tests.import_as_example.check_if_exists(file_path))


from tests.fixtures import module_with_attributes

0 comments on commit d52dfe0

Please sign in to comment.