Permalink
Browse files

Added additional possibility to configure Patcher

- added argument that allows adding modules for patching that import file system modules under another name
- fixes #231
  • Loading branch information...
mrbean-bremen committed Jun 25, 2017
1 parent b04087a commit d8439c8724f061dc26e8cb9b7281222828582a97
Showing with 98 additions and 28 deletions.
  1. +2 −0 CHANGES.md
  2. +20 −0 fake_filesystem_unittest_test.py
  3. +21 −0 import_as_example.py
  4. +55 −28 pyfakefs/fake_filesystem_unittest.py
View
@@ -4,6 +4,8 @@ The release versions are PyPi releases.
## Version 3.3 (as yet unreleased)
#### New Features
* Added possibility to patch modules that import file system modules under another name,
e.g. `import os as '_os` ([#231](../../issues/231)).
* Added support for `dir_fd` argument in several `os` functions ([#206](../../issues/206)).
* Added support for open file descriptor as path argument
in `os.utime`, `os.chmod`, `os.chdir`, `os.chown`, `os.listdir`, `os.stat` and `os.lstat`
@@ -26,6 +26,8 @@
import tempfile
import sys
from import_as_example import check_if_exists
if sys.version_info >= (3, 4):
import pathlib
@@ -139,6 +141,22 @@ def test_fakepathlib(self):
self.assertTrue(self.fs.Exists('/fake_file.txt'))
class TestImportAsOtherName(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='RunTest'):
special_names = {'import_as_example': {'os': '_os'}}
super(TestImportAsOtherName, self).__init__(methodName,
special_names=special_names)
def setUp(self):
self.setUpPyfakefs()
def testFileExists(self):
file_path = '/foo/bar/baz'
self.fs.CreateFile(file_path)
self.assertTrue(self.fs.Exists(file_path))
self.assertTrue(check_if_exists(file_path))
sys.path.append(os.path.join(os.path.dirname(__file__), 'fixtures'))
import module_with_attributes
@@ -161,6 +179,8 @@ def testAttributes(self):
import math as path
class TestPatchPathUnittestFailing(TestPyfakefsUnittestBase):
"""Tests the default behavior regarding the argument patch_path:
An own path module (in this case an alias to math) cannot be imported,
View
@@ -0,0 +1,21 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Example module that is used for testing modules that import file system modules
to be patched under another name.
"""
import os as _os
def check_if_exists(filepath):
return _os.path.exists(filepath)
@@ -63,7 +63,8 @@
def load_doctests(loader, tests, ignore, module,
additional_skip_names=None, patch_path=True): # pylint: disable=unused-argument
additional_skip_names=None,
patch_path=True, special_names=None): # pylint: disable=unused-argument
"""Load the doctest tests for the specified module into unittest.
Args:
loader, tests, ignore : arguments passed in from `load_tests()`
@@ -74,7 +75,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)
patch_path=patch_path, special_names=special_names)
globs = _patcher.replaceGlobs(vars(module))
tests.addTests(doctest.DocTestSuite(module,
globs=globs,
@@ -88,7 +89,8 @@ class TestCase(unittest.TestCase):
modules by fake implementations.
"""
def __init__(self, methodName='runTest', additional_skip_names=None, patch_path=True):
def __init__(self, methodName='runTest', additional_skip_names=None,
patch_path=True, special_names=None):
"""Creates the test class instance and the stubber used to stub out
file system related modules.
@@ -103,21 +105,34 @@ def __init__(self, methodName='runTest', additional_skip_names=None, patch_path=
from my_module import path
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`).
If you specify arguments `additional_skip_names` or `patch_path` here
and you have DocTests, consider also specifying the same arguments to
:py:func:`load_doctests`.
Example usage in a derived test class::
Example usage in derived test classes::
class MyTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
super(MyTestCase, self).__init__(
methodName=methodName, additional_skip_names=['posixpath'])
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)
patch_path=patch_path, special_names=special_names)
@property
def fs(self):
@@ -210,10 +225,11 @@ class Patcher(object):
if HAS_PATHLIB:
SKIPNAMES.add('pathlib')
def __init__(self, additional_skip_names=None, patch_path=True):
def __init__(self, additional_skip_names=None, patch_path=True, special_names=None):
"""For a description of the arguments, see TestCase.__init__"""
self._skipNames = self.SKIPNAMES.copy()
self._special_names = special_names or {}
if additional_skip_names is not None:
self._skipNames.update(additional_skip_names)
self._patchPath = patch_path
@@ -282,17 +298,28 @@ def _findModules(self):
# and a test in fake_filesystem_unittest_test.py, class
# TestAttributesWithFakeModuleNames.
if inspect.ismodule(module.__dict__.get('os')):
self._os_modules.add(module)
self._os_modules.add((module, 'os'))
if self._patchPath and inspect.ismodule(module.__dict__.get('path')):
self._path_modules.add(module)
self._path_modules.add((module, 'path'))
if self.HAS_PATHLIB and inspect.ismodule(module.__dict__.get('pathlib')):
self._pathlib_modules.add(module)
self._pathlib_modules.add((module, 'pathlib'))
if inspect.ismodule(module.__dict__.get('shutil')):
self._shutil_modules.add(module)
self._shutil_modules.add((module, 'shutil'))
if inspect.ismodule(module.__dict__.get('tempfile')):
self._tempfile_modules.add(module)
self._tempfile_modules.add((module, 'tempfile'))
if inspect.ismodule(module.__dict__.get('io')):
self._io_modules.add(module)
self._io_modules.add((module, 'io'))
print(module, type(module))
if '__name__' in module.__dict__ and module.__name__ in self._special_names:
module_names = self._special_names[module.__name__]
if 'os' in module_names:
self._os_modules.add((module, module_names['os']))
if self._patchPath and 'path' in module_names:
self._path_modules.add((module, module_names['path']))
if self.HAS_PATHLIB and 'pathlib' in module_names:
self._pathlib_modules.add((module, module_names['pathlib']))
if 'io' in module_names:
self._io_modules.add((module, module_names['io']))
def _refresh(self):
"""Renew the fake file system and set the _isStale flag to `False`."""
@@ -326,19 +353,19 @@ def setUp(self, doctester=None):
self._stubs.SmartSet(builtins, 'file', self.fake_open)
self._stubs.SmartSet(builtins, 'open', self.fake_open)
for module in self._os_modules:
self._stubs.SmartSet(module, 'os', self.fake_os)
for module in self._path_modules:
self._stubs.SmartSet(module, 'path', self.fake_path)
for module, attr in self._os_modules:
self._stubs.SmartSet(module, attr, self.fake_os)
for module, attr in self._path_modules:
self._stubs.SmartSet(module, attr, self.fake_path)
if self.HAS_PATHLIB:
for module in self._pathlib_modules:
self._stubs.SmartSet(module, 'pathlib', self.fake_pathlib)
for module in self._shutil_modules:
self._stubs.SmartSet(module, 'shutil', self.fake_shutil)
for module in self._tempfile_modules:
self._stubs.SmartSet(module, 'tempfile', self.fake_tempfile_)
for module in self._io_modules:
self._stubs.SmartSet(module, 'io', self.fake_io)
for module, attr in self._pathlib_modules:
self._stubs.SmartSet(module, attr, self.fake_pathlib)
for module, attr in self._shutil_modules:
self._stubs.SmartSet(module, attr, self.fake_shutil)
for module, attr in self._tempfile_modules:
self._stubs.SmartSet(module, attr, self.fake_tempfile_)
for module, attr in self._io_modules:
self._stubs.SmartSet(module, attr, self.fake_io)
def replaceGlobs(self, globs_):
globs = globs_.copy()

0 comments on commit d8439c8

Please sign in to comment.