File tree 4 files changed +20
-2
lines changed
4 files changed +20
-2
lines changed Original file line number Diff line number Diff line change @@ -12,6 +12,12 @@ The released versions correspond to PyPI releases.
12
12
* the default for `FakeFilesystem.shuffle_listdir_results` will change to `True` to reflect
13
13
the real filesystem behavior
14
14
15
+ ## Unreleased
16
+
17
+ ### Fixes
18
+ * fixed handling of dynamic imports from code in the fake filesystem in Python > 3.11
19
+ (see [#1121](../../issues/1121))
20
+
15
21
## [Version 5.8.0](https://pypi.python.org/pypi/pyfakefs/5.8.0) (2025-03-11)
16
22
Adds preliminary support for Python 3.14.
17
23
Original file line number Diff line number Diff line change @@ -86,6 +86,7 @@ def open(
86
86
newline : Optional [str ] = None ,
87
87
closefd : bool = True ,
88
88
opener : Optional [Callable ] = None ,
89
+ is_fake_open_code : bool = False ,
89
90
) -> Union [AnyFileWrapper , IO [Any ]]:
90
91
"""Redirect the call to FakeFileOpen.
91
92
See FakeFileOpen.call() for description.
@@ -101,6 +102,7 @@ def open(
101
102
newline ,
102
103
closefd ,
103
104
opener ,
105
+ is_fake_open_code ,
104
106
)
105
107
106
108
if sys .version_info >= (3 , 8 ):
@@ -118,7 +120,7 @@ def open_code(self, path):
118
120
and self .filesystem .exists (path )
119
121
or patch_mode == PatchMode .ON
120
122
):
121
- return self .open (path , mode = "rb" )
123
+ return self .open (path , mode = "rb" , is_fake_open_code = True )
122
124
# mostly this is used for compiled code -
123
125
# don't patch these, as the files are probably in the real fs
124
126
return self ._io_module .open_code (path )
Original file line number Diff line number Diff line change @@ -82,11 +82,14 @@ def fake_open(
82
82
newline : Optional [str ] = None ,
83
83
closefd : bool = True ,
84
84
opener : Optional [Callable ] = None ,
85
+ is_fake_open_code : bool = False ,
85
86
) -> Union [AnyFileWrapper , IO [Any ]]:
86
87
"""Redirect the call to FakeFileOpen.
87
88
See FakeFileOpen.call() for description.
88
89
"""
89
- if is_called_from_skipped_module (
90
+ # We don't need to check this if we are in an `open_code` call
91
+ # from a faked file (and this might cause recursions in `linecache`)
92
+ if not is_fake_open_code and is_called_from_skipped_module (
90
93
skip_names = skip_names ,
91
94
case_sensitive = filesystem .is_case_sensitive ,
92
95
check_open_code = sys .version_info >= (3 , 12 ),
Original file line number Diff line number Diff line change @@ -848,6 +848,13 @@ def test_exec_module_in_fake_fs(self):
848
848
self .import_foo ()
849
849
assert stdout .getvalue () == "hello\n "
850
850
851
+ def test_dynamic_import (self ):
852
+ # regression test for #1121
853
+ self .fs .create_file ("/foo.py" )
854
+ self .fs .create_file ("/bar.py" , contents = "import foo" )
855
+ sys .path .insert (0 , "" )
856
+ import foo # noqa
857
+
851
858
852
859
class TestOtherFS (fake_filesystem_unittest .TestCase ):
853
860
def setUp (self ):
You can’t perform that action at this time.
0 commit comments