Created
November 16, 2017 15:58
-
-
Save Quibi/05ba9afeb94994123dcfd0bb1e7bbb1f to your computer and use it in GitHub Desktop.
Proposal for avoid creating fake temporary directory until needed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2014 Altera Corporation. All Rights Reserved. | |
# Copyright 2015-2017 John McGehee | |
# | |
# 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. | |
"""This module provides a base class derived from `unittest.TestClass` | |
for unit tests using the :py:class:`pyfakefs` module. | |
`fake_filesystem_unittest.TestCase` searches `sys.modules` for modules | |
that import the `os`, `io`, `path` `shutil`, and `pathlib` modules. | |
The `setUpPyfakefs()` method binds these modules to the corresponding fake | |
modules from `pyfakefs`. Further, the `open()` built-in is bound to a fake | |
`open()`. In Python 2, built-in `file()` is similarly bound to the fake | |
`open()`. | |
It is expected that `setUpPyfakefs()` be invoked at the beginning of the derived | |
class' `setUp()` method. There is no need to add anything to the derived | |
class' `tearDown()` method. | |
During the test, everything uses the fake file system and modules. This means | |
that even in your test fixture, familiar functions like `open()` and | |
`os.makedirs()` manipulate the fake file system. | |
Existing unit tests that use the real file system can be retrofitted to use | |
pyfakefs by simply changing their base class from `:py:class`unittest.TestCase` | |
to `:py:class`pyfakefs.fake_filesystem_unittest.TestCase`. | |
""" | |
import doctest | |
import importlib | |
import inspect | |
import shutil | |
import sys | |
import tempfile | |
# HACK: in order to retrieve original method at stub | |
original_sanitize_params = tempfile._sanitize_params | |
try: | |
from importlib.machinery import ModuleSpec | |
except ImportError: | |
ModuleSpec = object | |
try: | |
# python >= 3.4 | |
from importlib import reload | |
except ImportError: | |
try: | |
# python 3.0 - 3.3 | |
from imp import reload | |
except ImportError: | |
# python 2 - reload is built-in | |
pass | |
from pyfakefs import fake_filesystem | |
from pyfakefs import fake_filesystem_shutil | |
from pyfakefs import mox3_stubout | |
if sys.version_info >= (3, 4): | |
from pyfakefs import fake_pathlib | |
if sys.version_info < (2, 7): | |
import unittest2 as unittest | |
else: | |
import unittest | |
if sys.version_info < (3,): | |
import __builtin__ as builtins # pylint: disable=import-error | |
else: | |
import builtins | |
def load_doctests(loader, tests, ignore, module, | |
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()` | |
module: module under test | |
additional_skip_names: see :py:class:`TestCase` for an explanation | |
patch_path: see :py:class:`TestCase` for an explanation | |
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) | |
globs = _patcher.replaceGlobs(vars(module)) | |
tests.addTests(doctest.DocTestSuite(module, | |
globs=globs, | |
setUp=_patcher.setUp, | |
tearDown=_patcher.tearDown)) | |
return tests | |
class TestCase(unittest.TestCase): | |
"""Test case class that automatically replaces file-system related | |
modules by fake implementations. | |
""" | |
def __init__(self, methodName='runTest', additional_skip_names=None, | |
patch_path=True, special_names=None, | |
modules_to_reload=None, | |
use_dynamic_patch=False): | |
"""Creates the test class instance and the stubber used to stub out | |
file system related modules. | |
Args: | |
methodName: the name of the test method (same as unittest.TestCase) | |
additional_skip_names: names of modules inside of which no module | |
replacement shall be performed, in addition to the names in | |
attribute :py:attr:`fake_filesystem_unittest.Patcher.SKIPNAMES`. | |
patch_path: if False, modules named 'path' will not be patched with the | |
fake 'os.path' module. Set this to False when you need to import | |
some other module named 'path', for example:: | |
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`). | |
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 | |
Note: this is done independently of `use_dynamic_patch` | |
Caution: this may not work with some Python versions | |
or have unwanted side effects. | |
use_dynamic_patch (experimental): If `True`, dynamic patching | |
after setup is used (for example for modules loaded locally | |
inside of functions). | |
Caution: this may not work with some Python versions | |
or have unwanted side effects. | |
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 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 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 [] | |
self._use_dynamic_patch = use_dynamic_patch | |
@property | |
def fs(self): | |
return self._stubber.fs | |
@property | |
def patches(self): | |
return self._stubber.patches | |
def copyRealFile(self, real_file_path, fake_file_path=None, | |
create_missing_dirs=True): | |
"""Add the file `real_file_path` in the real file system to the same | |
path in the fake file system. | |
**This method is deprecated** in favor of :py:meth:`FakeFilesystem..add_real_file`. | |
`copyRealFile()` is retained with limited functionality for backward | |
compatability only. | |
Args: | |
real_file_path: Path to the file in both the real and fake file systems | |
fake_file_path: Deprecated. Use the default, which is `real_file_path`. | |
If a value other than `real_file_path` is specified, an `ValueError` | |
exception will be raised. | |
create_missing_dirs: Deprecated. Use the default, which creates missing | |
directories in the fake file system. If `False` is specified, an | |
`ValueError` exception is raised. | |
Returns: | |
The newly created FakeFile object. | |
Raises: | |
IOError: If the file already exists in the fake file system. | |
ValueError: If deprecated argument values are specified | |
See: | |
:py:meth:`FakeFileSystem.add_real_file` | |
""" | |
if fake_file_path is not None and real_file_path != fake_file_path: | |
raise ValueError("CopyRealFile() is deprecated and no longer supports " | |
"different real and fake file paths") | |
if not create_missing_dirs: | |
raise ValueError("CopyRealFile() is deprecated and no longer supports " | |
"NOT creating missing directories") | |
return self._stubber.fs.add_real_file(real_file_path, read_only=False) | |
def setUpPyfakefs(self): | |
"""Bind the file-related modules to the :py:class:`pyfakefs` fake file | |
system instead of the real file system. Also bind the fake `open()` | |
function, and on Python 2, the `file()` function. | |
Invoke this at the beginning of the `setUp()` method in your unit test | |
class. | |
""" | |
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: | |
self.addCleanup(lambda: sys.meta_path.pop(0)) | |
else: | |
sys.meta_path.pop(0) | |
def tearDownPyfakefs(self): | |
"""This method is deprecated and exists only for backward compatibility. | |
It does nothing. | |
""" | |
pass | |
class Patcher(object): | |
""" | |
Instantiate a stub creator to bind and un-bind the file-related modules to | |
the :py:mod:`pyfakefs` fake modules. | |
The arguments are explained in :py:class:`TestCase`. | |
:py:class:`Patcher` is used in :py:class:`TestCase`. :py:class:`Patcher` | |
also works as a context manager for PyTest:: | |
with Patcher(): | |
doStuff() | |
""" | |
SKIPMODULES = set([None, fake_filesystem, fake_filesystem_shutil, sys]) | |
'''Stub nothing that is imported within these modules. | |
`sys` is included to prevent `sys.path` from being stubbed with the fake | |
`os.path`. | |
''' | |
assert None in SKIPMODULES, "sys.modules contains 'None' values; must skip them." | |
HAS_PATHLIB = sys.version_info >= (3, 4) | |
IS_WINDOWS = sys.platform in ('win32', 'cygwin') | |
# To add py.test support per issue https://github.com/jmcgeheeiv/pyfakefs/issues/43, | |
# it appears that adding 'py', 'pytest', '_pytest' to SKIPNAMES will help | |
SKIPNAMES = set(['os', 'path', 'io', 'genericpath']) | |
if HAS_PATHLIB: | |
SKIPNAMES.add('pathlib') | |
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 {} | |
self._special_names['tempfile'] = {'os': '_os', 'io': '_io'} | |
if additional_skip_names is not None: | |
self._skipNames.update(additional_skip_names) | |
self._patchPath = patch_path | |
if not patch_path: | |
self._skipNames.discard('path') | |
self._skipNames.discard('genericpath') | |
# Attributes set by _findModules() | |
self._os_modules = set() | |
self._path_modules = set() | |
if self.HAS_PATHLIB: | |
self._pathlib_modules = set() | |
self._shutil_modules = set() | |
self._io_modules = set() | |
self._findModules() | |
assert None not in vars(self).values(), \ | |
"_findModules() missed the initialization of an instance variable" | |
# Attributes set by _refresh() | |
self._stubs = None | |
self.fs = None | |
self.fake_os = None | |
self.fake_path = None | |
if self.HAS_PATHLIB: | |
self.fake_pathlib = None | |
self.fake_shutil = None | |
self.fake_open = None | |
self.fake_io = None | |
# _isStale is set by tearDown(), reset by _refresh() | |
self._isStale = True | |
# HACK: fake temporary directory not created yet | |
self.__create_temp_dir = True | |
def __enter__(self): | |
"""Context manager for usage outside of fake_filesystem_unittest.TestCase. | |
Ensure that all patched modules are removed in case of an unhandled exception. | |
""" | |
self.setUp() | |
return self | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
self.tearDown() | |
def _findModules(self): | |
"""Find and cache all modules that import file system modules. | |
Later, `setUp()` will stub these with the fake file system | |
modules. | |
""" | |
for name, module in set(sys.modules.items()): | |
if (module in self.SKIPMODULES or | |
(not inspect.ismodule(module)) or | |
name.split('.')[0] in self._skipNames): | |
continue | |
# IMPORTANT TESTING NOTE: Whenever you add a new module below, test | |
# it by adding an attribute in fixtures/module_with_attributes.py | |
# and a test in fake_filesystem_unittest_test.py, class | |
# TestAttributesWithFakeModuleNames. | |
if inspect.ismodule(module.__dict__.get('os')): | |
self._os_modules.add((module, 'os')) | |
if self._patchPath and inspect.ismodule(module.__dict__.get('path')): | |
self._path_modules.add((module, 'path')) | |
if self.HAS_PATHLIB and inspect.ismodule(module.__dict__.get('pathlib')): | |
self._pathlib_modules.add((module, 'pathlib')) | |
if inspect.ismodule(module.__dict__.get('shutil')): | |
self._shutil_modules.add((module, 'shutil')) | |
if inspect.ismodule(module.__dict__.get('io')): | |
self._io_modules.add((module, 'io')) | |
if '__name__' in module.__dict__ and module.__name__ in self._special_names: | |
module_names = self._special_names[module.__name__] | |
if 'os' in module_names: | |
if inspect.ismodule(module.__dict__.get(module_names['os'])): | |
self._os_modules.add((module, module_names['os'])) | |
if self._patchPath and 'path' in module_names: | |
if inspect.ismodule(module.__dict__.get(module_names['path'])): | |
self._path_modules.add((module, module_names['path'])) | |
if self.HAS_PATHLIB and 'pathlib' in module_names: | |
if inspect.ismodule(module.__dict__.get(module_names['pathlib'])): | |
self._pathlib_modules.add((module, module_names['pathlib'])) | |
if 'io' in module_names: | |
if inspect.ismodule(module.__dict__.get(module_names['io'])): | |
self._io_modules.add((module, module_names['io'])) | |
def _refresh(self): | |
"""Renew the fake file system and set the _isStale flag to `False`.""" | |
if self._stubs is not None: | |
self._stubs.SmartUnsetAll() | |
self._stubs = mox3_stubout.StubOutForTesting() | |
self.fs = fake_filesystem.FakeFilesystem() | |
self.fake_os = fake_filesystem.FakeOsModule(self.fs) | |
self.fake_path = self.fake_os.path | |
if self.HAS_PATHLIB: | |
self.fake_pathlib = fake_pathlib.FakePathlibModule(self.fs) | |
self.fake_shutil = fake_filesystem_shutil.FakeShutilModule(self.fs) | |
self.fake_open = fake_filesystem.FakeFileOpen(self.fs) | |
self.fake_io = fake_filesystem.FakeIoModule(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.6 to 3.2: unlink is a class method of _TemporaryFileWrapper | |
tempfile._TemporaryFileWrapper.unlink = self.fake_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_os.unlink,) | |
# HACK: stub the tempfile._sanitize_params | |
tempfile._sanitize_params = lambda prefix, suffix, dir: self._sanitize_params(prefix, suffix, dir) | |
# HACK stub tempfile._sanitize_params | |
def _sanitize_params(self, prefix, suffix, dir): | |
"""Stub the tempfile._sanitize_params() method to | |
check if the temporal directory already exists | |
(and create if needed).""" | |
if self.__create_temp_dir: | |
try: | |
self.fs.CreateDirectory(tempfile.gettempdir()) | |
except OSError: | |
# temporal directory already exists | |
pass | |
finally: | |
self.__create_temp_dir = False | |
return original_sanitize_params(prefix, suffix, dir) | |
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. | |
""" | |
# HACK: create temporal directory later in order to achieve an empty | |
# initial fake filesystem | |
#temp_dir = tempfile.gettempdir() | |
self._findModules() | |
self._refresh() | |
assert None not in vars(self).values(), \ | |
"_findModules() missed the initialization of an instance variable" | |
if doctester is not None: | |
doctester.globs = self.replaceGlobs(doctester.globs) | |
if sys.version_info < (3,): | |
# file() was eliminated in Python3 | |
self._stubs.SmartSet(builtins, 'file', self.fake_open) | |
self._stubs.SmartSet(builtins, 'open', self.fake_open) | |
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, 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._io_modules: | |
self._stubs.SmartSet(module, attr, self.fake_io) | |
# the temp directory is assumed to exist at least in `tempfile1, | |
# so we create it here for convenience | |
# HACK: create temporal directory later in order to achieve an empty | |
# initial fake filesystem | |
#self.fs.CreateDirectory(temp_dir) | |
def replaceGlobs(self, globs_): | |
globs = globs_.copy() | |
if self._isStale: | |
self._refresh() | |
if 'os' in globs: | |
globs['os'] = fake_filesystem.FakeOsModule(self.fs) | |
if 'path' in globs: | |
fake_os = globs['os'] if 'os' in globs \ | |
else fake_filesystem.FakeOsModule(self.fs) | |
globs['path'] = fake_os.path | |
if 'shutil' in globs: | |
globs['shutil'] = fake_filesystem_shutil.FakeShutilModule(self.fs) | |
if 'io' in globs: | |
globs['io'] = fake_filesystem.FakeIoModule(self.fs) | |
return globs | |
def tearDown(self, doctester=None): | |
"""Clear the fake filesystem bindings created by `setUp()`.""" | |
self._isStale = True | |
self._stubs.SmartUnsetAll() | |
class DynamicPatcher(object): | |
"""A file loader that replaces file system related modules by their | |
fake implementation if they are loaded after calling `setupPyFakefs()`. | |
Implements the protocol needed for import hooks. | |
""" | |
def __init__(self, patcher): | |
self._patcher = patcher | |
self._patching = False | |
self.modules = { | |
'os': self._patcher.fake_os, | |
'os.path': self._patcher.fake_path, | |
'io': self._patcher.fake_io, | |
'shutil': self._patcher.fake_shutil | |
} | |
if sys.version_info >= (3, 4): | |
self.modules['pathlib'] = fake_pathlib.FakePathlibModule | |
# remove all modules that have to be patched from `sys.modules`, | |
# otherwise the find_... methods will not be called | |
for module in self.modules: | |
if self.needs_patch(module) and module in sys.modules: | |
del sys.modules[module] | |
def needs_patch(self, name): | |
"""Check if the module with the given name shall be replaced.""" | |
if self._patching or name not in self.modules: | |
return False | |
if (name in sys.modules and | |
type(sys.modules[name]) == self.modules[name]): | |
return False | |
return True | |
def find_spec(self, fullname, path, target=None): | |
"""Module finder for Python 3.""" | |
if self.needs_patch(fullname): | |
return ModuleSpec(fullname, self) | |
def find_module(self, fullname, path=None): | |
"""Module finder for Python 2.""" | |
if self.needs_patch(fullname): | |
return self | |
def load_module(self, fullname): | |
"""Replaces the module by its fake implementation.""" | |
# prevent re-entry via the finder | |
self._patching = True | |
importlib.import_module(fullname) | |
self._patching = False | |
# preserve the original module (currently not used) | |
sys.modules['original_' + fullname] = sys.modules[fullname] | |
# replace with fake implementation | |
sys.modules[fullname] = self.modules[fullname] | |
return self.modules[fullname] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
# | |
# Copyright 2014 Altera Corporation. All Rights Reserved. | |
# Copyright 2015-2017 John McGehee | |
# Author: John McGehee | |
# | |
# 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. | |
""" | |
Test the :py:class`pyfakefs.fake_filesystem_unittest.TestCase` base class. | |
""" | |
import io | |
import os | |
import glob | |
import shutil | |
import sys | |
from unittest import TestCase | |
from import_as_example import check_if_exists | |
from pyfakefs.fake_filesystem_unittest import Patcher | |
from pyfakefs import fake_filesystem_unittest | |
if sys.version_info >= (3, 4): | |
import pathlib | |
if sys.version_info < (2, 7): | |
import unittest2 as unittest | |
else: | |
import unittest | |
class TestPatcher(TestCase): | |
def testContextManager(self): | |
with Patcher() as patcher: | |
patcher.fs.CreateFile('/foo/bar', contents='test') | |
with open('/foo/bar') as f: | |
contents = f.read() | |
self.assertEqual('test', contents) | |
class TestPyfakefsUnittestBase(fake_filesystem_unittest.TestCase): | |
def setUp(self): | |
"""Set up the fake file system""" | |
self.setUpPyfakefs() | |
class TestPyfakefsUnittest(TestPyfakefsUnittestBase): # pylint: disable=R0904 | |
"""Test the `pyfakefs.fake_filesystem_unittest.TestCase` base class.""" | |
# HACK | |
def test_is_emtpy(self): | |
"""Tests that the initial fake filesystem is empty.""" | |
self.assertEqual( | |
self.fs.root.contents, {}, | |
f'The fake filesystem is not empty: {self.fs.root.contents}' | |
) | |
@unittest.skipIf(sys.version_info > (2,), "file() was removed in Python 3") | |
def test_file(self): | |
"""Fake `file()` function is bound""" | |
self.assertFalse(os.path.exists('/fake_file.txt')) | |
with file('/fake_file.txt', 'w') as f: | |
f.write("This test file was created using the file() function.\n") | |
self.assertTrue(self.fs.Exists('/fake_file.txt')) | |
with file('/fake_file.txt') as f: | |
content = f.read() | |
self.assertEqual(content, | |
'This test file was created using the file() function.\n') | |
def test_open(self): | |
"""Fake `open()` function is bound""" | |
self.assertFalse(os.path.exists('/fake_file.txt')) | |
with open('/fake_file.txt', 'w') as f: | |
f.write("This test file was created using the open() function.\n") | |
self.assertTrue(self.fs.Exists('/fake_file.txt')) | |
with open('/fake_file.txt') as f: | |
content = f.read() | |
self.assertEqual(content, | |
'This test file was created using the open() function.\n') | |
def test_io_open(self): | |
"""Fake io module is bound""" | |
self.assertFalse(os.path.exists('/fake_file.txt')) | |
with io.open('/fake_file.txt', 'w') as f: | |
f.write("This test file was created using the io.open() function.\n") | |
self.assertTrue(self.fs.Exists('/fake_file.txt')) | |
with open('/fake_file.txt') as f: | |
content = f.read() | |
self.assertEqual(content, | |
'This test file was created using the io.open() function.\n') | |
def test_os(self): | |
"""Fake os module is bound""" | |
self.assertFalse(self.fs.Exists('/test/dir1/dir2')) | |
os.makedirs('/test/dir1/dir2') | |
self.assertTrue(self.fs.Exists('/test/dir1/dir2')) | |
def test_glob(self): | |
"""Fake glob module is bound""" | |
is_windows = sys.platform.startswith('win') | |
self.assertEqual(glob.glob('/test/dir1/dir*'), | |
[]) | |
self.fs.CreateDirectory('/test/dir1/dir2a') | |
matching_paths = glob.glob('/test/dir1/dir*') | |
if is_windows: | |
self.assertEqual(matching_paths, [r'\test\dir1\dir2a']) | |
else: | |
self.assertEqual(matching_paths, ['/test/dir1/dir2a']) | |
self.fs.CreateDirectory('/test/dir1/dir2b') | |
matching_paths = sorted(glob.glob('/test/dir1/dir*')) | |
if is_windows: | |
self.assertEqual(matching_paths, [r'\test\dir1\dir2a', r'\test\dir1\dir2b']) | |
else: | |
self.assertEqual(matching_paths, ['/test/dir1/dir2a', '/test/dir1/dir2b']) | |
def test_shutil(self): | |
"""Fake shutil module is bound""" | |
self.fs.CreateDirectory('/test/dir1/dir2a') | |
self.fs.CreateDirectory('/test/dir1/dir2b') | |
self.assertTrue(self.fs.Exists('/test/dir1/dir2b')) | |
self.assertTrue(self.fs.Exists('/test/dir1/dir2a')) | |
shutil.rmtree('/test/dir1') | |
self.assertFalse(self.fs.Exists('/test/dir1')) | |
@unittest.skipIf(sys.version_info < (3, 4), "pathlib new in Python 3.4") | |
def test_fakepathlib(self): | |
with pathlib.Path('/fake_file.txt') as p: | |
with p.open('w') as f: | |
f.write('text') | |
is_windows = sys.platform.startswith('win') | |
if is_windows: | |
self.assertTrue(self.fs.Exists(r'\fake_file.txt')) | |
else: | |
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 | |
class TestAttributesWithFakeModuleNames(TestPyfakefsUnittestBase): | |
"""Test that module attributes with names like `path` or `io` are not | |
stubbed out. | |
""" | |
def testAttributes(self): | |
"""Attributes of module under test are not patched""" | |
global path | |
self.assertEqual(module_with_attributes.os, 'os attribute value') | |
self.assertEqual(module_with_attributes.path, 'path attribute value') | |
self.assertEqual(module_with_attributes.pathlib, 'pathlib attribute value') | |
self.assertEqual(module_with_attributes.shutil, 'shutil attribute value') | |
self.assertEqual(module_with_attributes.io, 'io attribute value') | |
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, | |
because it is faked by FakePathModule | |
""" | |
def __init__(self, methodName='runTest'): | |
super(TestPatchPathUnittestFailing, self).__init__(methodName, | |
patch_path=True) | |
@unittest.expectedFailure | |
def test_own_path_module(self): | |
self.assertEqual(2, path.floor(2.5)) | |
class TestPatchPathUnittestPassing(TestPyfakefsUnittestBase): | |
"""Tests the behavior with patch_path set to False: | |
An own path module (in this case an alias to math) can be imported and used | |
""" | |
def __init__(self, methodName='runTest'): | |
super(TestPatchPathUnittestPassing, self).__init__(methodName, | |
patch_path=False) | |
def test_own_path_module(self): | |
self.assertEqual(2, path.floor(2.5)) | |
@unittest.skipIf(sys.version_info < (2, 7), "No byte strings in Python 2.6") | |
class TestCopyOrAddRealFile(TestPyfakefsUnittestBase): | |
"""Tests the `fake_filesystem_unittest.TestCase.copyRealFile()` method. | |
Note that `copyRealFile()` is deprecated in favor of `FakeFilesystem.add_real_file()`. | |
""" | |
with open(__file__) as f: | |
real_string_contents = f.read() | |
with open(__file__, 'rb') as f: | |
real_byte_contents = f.read() | |
real_stat = os.stat(__file__) | |
@unittest.skipIf(sys.platform == 'darwin', 'Different copy behavior') | |
def testCopyRealFile(self): | |
'''Typical usage of deprecated copyRealFile()''' | |
# Use this file as the file to be copied to the fake file system | |
real_file_path = os.path.realpath(__file__) | |
fake_file = self.copyRealFile(real_file_path) | |
self.assertTrue('class TestCopyOrAddRealFile(TestPyfakefsUnittestBase)' | |
in self.real_string_contents, | |
'Verify real file string contents') | |
self.assertTrue(b'class TestCopyOrAddRealFile(TestPyfakefsUnittestBase)' | |
in self.real_byte_contents, | |
'Verify real file byte contents') | |
# note that real_string_contents may differ to fake_file.contents due to newline conversions in open() | |
self.assertEqual(fake_file.byte_contents, self.real_byte_contents) | |
self.assertEqual(oct(fake_file.st_mode), oct(self.real_stat.st_mode)) | |
self.assertEqual(fake_file.st_size, self.real_stat.st_size) | |
self.assertAlmostEqual(fake_file.st_ctime, self.real_stat.st_ctime, places=5) | |
self.assertAlmostEqual(fake_file.st_atime, self.real_stat.st_atime, places=5) | |
self.assertLess(fake_file.st_atime, self.real_stat.st_atime + 10) | |
self.assertAlmostEqual(fake_file.st_mtime, self.real_stat.st_mtime, places=5) | |
self.assertEqual(fake_file.st_uid, self.real_stat.st_uid) | |
self.assertEqual(fake_file.st_gid, self.real_stat.st_gid) | |
def testCopyRealFileDeprecatedArguments(self): | |
'''Deprecated copyRealFile() arguments''' | |
real_file_path = __file__ | |
self.assertFalse(self.fs.Exists(real_file_path)) | |
# Specify redundant fake file path | |
self.copyRealFile(real_file_path, real_file_path) | |
self.assertTrue(self.fs.Exists(real_file_path)) | |
# Test deprecated argument values | |
with self.assertRaises(ValueError): | |
self.copyRealFile(real_file_path, '/different/filename') | |
with self.assertRaises(ValueError): | |
self.copyRealFile(real_file_path, create_missing_dirs=False) | |
def testAddRealFile(self): | |
'''Add a real file to the fake file system to be read on demand''' | |
# this tests only the basic functionality inside a unit test, more thorough tests | |
# are done in fake_filesystem_test.RealFileSystemAccessTest | |
real_file_path = __file__ | |
fake_file = self.fs.add_real_file(real_file_path) | |
self.assertTrue(self.fs.Exists(real_file_path)) | |
self.assertIsNone(fake_file._byte_contents) | |
self.assertEqual(self.real_byte_contents, fake_file.byte_contents) | |
def testAddRealDirectory(self): | |
'''Add a real directory and the contained files to the fake file system to be read on demand''' | |
# this tests only the basic functionality inside a unit test, more thorough tests | |
# are done in fake_filesystem_test.RealFileSystemAccessTest | |
# Note: this test fails (add_real_directory raises) if 'genericpath' is not added to SKIPNAMES | |
real_dir_path = os.path.join(os.path.dirname(__file__), 'pyfakefs') | |
self.fs.add_real_directory(real_dir_path) | |
self.assertTrue(self.fs.Exists(real_dir_path)) | |
self.assertTrue(self.fs.Exists(os.path.join(real_dir_path, 'fake_filesystem.py'))) | |
if __name__ == "__main__": | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment