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
  • Loading branch information
mrbean-bremen committed Jan 12, 2018
1 parent 08f45ff commit d52dfe0
Show file tree
Hide file tree
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
Expand Up @@ -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.
Expand Down
66 changes: 14 additions & 52 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()`
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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`."""
Expand All @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions tests/fake_filesystem_shutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'):
Expand Down Expand Up @@ -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')
Expand All @@ -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')
Expand Down Expand Up @@ -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')
Expand All @@ -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')
Expand Down
8 changes: 4 additions & 4 deletions tests/fake_filesystem_unittest_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down

0 comments on commit d52dfe0

Please sign in to comment.