diff --git a/CHANGES.md b/CHANGES.md index dffd917d..fdba89f5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,8 @@ The released versions correspond to PyPi releases. (see [#707](../../issues/707)) * return the expected type from `fcntl.ioctl` and `fcntl.fcntl` calls if `arg` is of type `byte`; the call itself does nothing as before +* do not skip filesystem modules by name to allow using own modules with + the same name (see [#707](../../issues/707)) ## [Version 4.6.3](https://pypi.python.org/pypi/pyfakefs/4.6.3) (2022-07-20) diff --git a/pyfakefs/fake_filesystem_unittest.py b/pyfakefs/fake_filesystem_unittest.py index aaebc645..6d62ac00 100644 --- a/pyfakefs/fake_filesystem_unittest.py +++ b/pyfakefs/fake_filesystem_unittest.py @@ -35,10 +35,14 @@ pyfakefs by simply changing their base class from `:py:class`unittest.TestCase` to `:py:class`pyfakefs.fake_filesystem_unittest.TestCase`. """ +import _io # type:ignore [import] import doctest import functools +import genericpath import inspect +import io import linecache +import os import shutil import sys import tempfile @@ -366,8 +370,6 @@ class Patcher: '''Stub nothing that is imported within these modules. `sys` is included to prevent `sys.path` from being stubbed with the fake `os.path`. - The `pytest` and `py` modules are used by pytest and have to access the - real file system. The `linecache` module is used to read the test file in case of test failure to get traceback information before test tear down. In order to make sure that reading the test file is not faked, @@ -376,8 +378,21 @@ class Patcher: ''' SKIPMODULES = { None, fake_filesystem, fake_filesystem_shutil, - sys, linecache, tokenize + sys, linecache, tokenize, os, io, _io, genericpath, os.path } + if sys.platform == 'win32': + import nt # type:ignore [import] + import ntpath + SKIPMODULES.add(nt) + SKIPMODULES.add(ntpath) + else: + import posix + import posixpath + import fcntl + SKIPMODULES.add(posix) + SKIPMODULES.add(posixpath) + SKIPMODULES.add(fcntl) + # caches all modules that do not have file system modules or function # to speed up _find_modules CACHED_MODULES: Set[ModuleType] = set() @@ -391,8 +406,7 @@ class Patcher: IS_WINDOWS = sys.platform in ('win32', 'cygwin') - SKIPNAMES = {'os', 'path', 'io', 'genericpath', 'fcntl', - OS_MODULE, PATH_MODULE} + SKIPNAMES: Set[str] = set() # hold values from last call - if changed, the cache has to be invalidated PATCHED_MODULE_NAMES: Set[str] = set() diff --git a/pyfakefs/pytest_tests/io.py b/pyfakefs/pytest_tests/io.py new file mode 100644 index 00000000..5d622f1e --- /dev/null +++ b/pyfakefs/pytest_tests/io.py @@ -0,0 +1,14 @@ +""" +This is a test case for pyfakefs issue #708. +It tests the usage of an own module with the same name as a patched filesystem +module, the content is taken from the issue. +""" + + +class InputStream: + def __init__(self, name): + self.name = name + + def read(self): + with open(self.name, 'r') as f: + return f.readline() diff --git a/pyfakefs/pytest_tests/pytest_plugin_test.py b/pyfakefs/pytest_tests/pytest_plugin_test.py index 5632ff6b..04741f61 100644 --- a/pyfakefs/pytest_tests/pytest_plugin_test.py +++ b/pyfakefs/pytest_tests/pytest_plugin_test.py @@ -3,6 +3,7 @@ import tempfile from pyfakefs.fake_filesystem_unittest import Pause +import pyfakefs.pytest_tests.io def test_fs_fixture(fs): @@ -50,3 +51,12 @@ def test_pause_resume_contextmanager(fs): assert os.path.exists(real_temp_file.name) assert not os.path.exists(real_temp_file.name) assert os.path.exists(fake_temp_file.name) + + +def test_use_own_io_module(fs): + filepath = 'foo.txt' + with open(filepath, 'w') as f: + f.write('bar') + + stream = pyfakefs.pytest_tests.io.InputStream(filepath) + assert stream.read() == 'bar'