Skip to content

Commit a0afe8e

Browse files
committed
Automatically reset filesystem on changing os
- now done on changing is_windows_fs or is_macos
1 parent c640ddc commit a0afe8e

File tree

6 files changed

+53
-50
lines changed

6 files changed

+53
-50
lines changed

.github/workflows/pythonpackage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
strategy:
1010
matrix:
1111
os: [ubuntu-latest]
12-
python-version: [3.9]
12+
python-version: ["3.10"]
1313
steps:
1414
- uses: actions/checkout@v2
1515
- name: Set up Python ${{ matrix.python-version }}

CHANGES.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,17 @@ The released versions correspond to PyPi releases.
33

44
## Unreleased
55

6+
### Changes
7+
* automatically reset filesystem on changing `is_windows_fs` or `is_macos`
8+
(see [#692](../../issues/692)) - ensures better upwards compatibility in
9+
most cases
10+
11+
:warning: Make sure you write to the filesystem _after_ you change
12+
`is_windows_fs` or `is_macos`, otherwise the changes will be lost.
13+
14+
615
### Fixes
7-
* fixed regression: `os.exists` returned `True` for any root drive path under Windows
16+
* fixed regression: `os.path.exists` returned `True` for any root drive path under Windows
817

918
## [Version 4.6.2](https://pypi.python.org/pypi/pyfakefs/4.6.2) (2022-07-14)
1019
Patch release that fixes an error in the previous patch.

pyfakefs/fake_filesystem.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -933,14 +933,16 @@ def __init__(self, path_separator: str = os.path.sep,
933933
# Windows fs on non-Windows systems and vice verse;
934934
# is it used to support drive letters, UNC paths and some other
935935
# Windows-specific features
936-
self.is_windows_fs = sys.platform == 'win32'
936+
self._is_windows_fs = sys.platform == 'win32'
937937

938938
# can be used to test some MacOS-specific behavior under other systems
939-
self.is_macos = sys.platform == 'darwin'
939+
self._is_macos = sys.platform == 'darwin'
940940

941941
# is_case_sensitive can be used to test pyfakefs for case-sensitive
942942
# file systems on non-case-sensitive systems and vice verse
943-
self.is_case_sensitive = not (self.is_windows_fs or self.is_macos)
943+
self.is_case_sensitive: bool = (
944+
not (self.is_windows_fs or self._is_macos)
945+
)
944946

945947
self.root = FakeDirectory(self.path_separator, filesystem=self)
946948
self._cwd = ''
@@ -955,8 +957,8 @@ def __init__(self, path_separator: str = os.path.sep,
955957
# A heap containing all free positions in self.open_files list
956958
self._free_fd_heap: List[int] = []
957959
# last used numbers for inodes (st_ino) and devices (st_dev)
958-
self.last_ino = 0
959-
self.last_dev = 0
960+
self.last_ino: int = 0
961+
self.last_dev: int = 0
960962
self.mount_points: Dict[AnyString, Dict] = OrderedDict()
961963
self._add_root_mount_point(total_size)
962964
self._add_standard_streams()
@@ -969,6 +971,28 @@ def __init__(self, path_separator: str = os.path.sep,
969971
def is_linux(self) -> bool:
970972
return not self.is_windows_fs and not self.is_macos
971973

974+
@property
975+
def is_windows_fs(self) -> bool:
976+
return self._is_windows_fs
977+
978+
@is_windows_fs.setter
979+
def is_windows_fs(self, value: bool) -> None:
980+
if self._is_windows_fs != value:
981+
self._is_windows_fs = value
982+
self.reset()
983+
FakePathModule.reset(self)
984+
985+
@property
986+
def is_macos(self) -> bool:
987+
return self._is_macos
988+
989+
@is_macos.setter
990+
def is_macos(self, value: bool) -> None:
991+
if self._is_macos != value:
992+
self._is_macos = value
993+
self.reset()
994+
FakePathModule.reset(self)
995+
972996
@property
973997
def cwd(self) -> str:
974998
"""Return the current working directory of the fake filesystem."""
@@ -1009,8 +1033,8 @@ def os(self) -> OSType:
10091033
def os(self, value: OSType) -> None:
10101034
"""Set the simulated type of operating system underlying the fake
10111035
file system."""
1012-
self.is_windows_fs = value == OSType.WINDOWS
1013-
self.is_macos = value == OSType.MACOS
1036+
self._is_windows_fs = value == OSType.WINDOWS
1037+
self._is_macos = value == OSType.MACOS
10141038
self.is_case_sensitive = value == OSType.LINUX
10151039
self.path_separator = '\\' if value == OSType.WINDOWS else '/'
10161040
self.alternative_path_separator = ('/' if value == OSType.WINDOWS
@@ -2311,7 +2335,8 @@ def lresolve(self, path: AnyPath) -> FakeFile:
23112335
return (parent_obj.get_entry(to_string(child_name)) if child_name
23122336
else parent_obj)
23132337
except KeyError:
2314-
self.raise_os_error(errno.ENOENT, path_str)
2338+
pass
2339+
raise OSError(errno.ENOENT, path_str)
23152340

23162341
def add_object(self, file_path: AnyStr, file_object: AnyFile) -> None:
23172342
"""Add a fake file or directory into the filesystem at file_path.

pyfakefs/tests/fake_filesystem_test.py

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ def test_path(self):
6767

6868
def test_path_with_drive(self):
6969
self.filesystem.is_windows_fs = True
70-
self.filesystem.reset()
7170
dir_path = 'C:/foo/bar/baz'
7271
self.filesystem.create_dir(dir_path)
7372
dir_object = self.filesystem.get_object(dir_path)
@@ -83,7 +82,6 @@ def test_path_after_chdir(self):
8382

8483
def test_path_after_chdir_with_drive(self):
8584
self.filesystem.is_windows_fs = True
86-
self.filesystem.reset()
8785
dir_path = 'C:/foo/bar/baz'
8886
self.filesystem.create_dir(dir_path)
8987
self.os.chdir(dir_path)
@@ -124,11 +122,9 @@ def test_leave_file_unchanged_if_size_is_equal_to_current_size(self):
124122
def test_set_contents_to_dir_raises(self):
125123
# Regression test for #276
126124
self.filesystem.is_windows_fs = True
127-
self.filesystem.reset()
128125
with self.raises_os_error(errno.EISDIR):
129126
self.fake_dir.set_contents('a')
130127
self.filesystem.is_windows_fs = False
131-
self.filesystem.reset()
132128
with self.raises_os_error(errno.EISDIR):
133129
self.fake_dir.set_contents('a')
134130

@@ -320,7 +316,6 @@ def test_add_object_to_root(self):
320316

321317
def test_windows_root_dir_name(self):
322318
self.filesystem.is_windows_fs = True
323-
self.filesystem.reset()
324319
self.assertEqual('C:/', self.filesystem.root_dir_name)
325320
self.filesystem.cwd = 'E:/foo'
326321
self.assertEqual('E:/', self.filesystem.root_dir_name)
@@ -333,7 +328,6 @@ def test_exists_added_file(self):
333328

334329
def test_exists_relative_path_posix(self):
335330
self.filesystem.is_windows_fs = False
336-
self.filesystem.reset()
337331
self.filesystem.create_file('/a/b/file_one')
338332
self.filesystem.create_file('/a/c/file_two')
339333
self.assertTrue(self.filesystem.exists('a/b/../c/file_two'))
@@ -351,7 +345,6 @@ def test_exists_relative_path_posix(self):
351345
def test_exists_relative_path_windows(self):
352346
self.filesystem.is_windows_fs = True
353347
self.filesystem.is_macos = False
354-
self.filesystem.reset()
355348
self.filesystem.create_file('/a/b/file_one')
356349
self.filesystem.create_file('/a/c/file_two')
357350
self.assertTrue(self.filesystem.exists('a/b/../c/file_two'))
@@ -400,15 +393,13 @@ def test_add_object_to_child(self):
400393

401394
def test_add_object_to_regular_file_error_posix(self):
402395
self.filesystem.is_windows_fs = False
403-
self.filesystem.reset()
404396
self.filesystem.add_object(
405397
self.filesystem.root_dir_name, self.fake_file)
406398
with self.raises_os_error(errno.ENOTDIR):
407399
self.filesystem.add_object(self.fake_file.name, self.fake_file)
408400

409401
def test_add_object_to_regular_file_error_windows(self):
410402
self.filesystem.is_windows_fs = True
411-
self.filesystem.reset()
412403
self.filesystem.add_object(self.root_name, self.fake_file)
413404
with self.raises_os_error(errno.ENOENT):
414405
self.filesystem.add_object(self.fake_file.name, self.fake_file)
@@ -520,7 +511,6 @@ def test_create_directory_already_exists_error(self):
520511

521512
def test_create_file_in_read_only_directory_raises_in_posix(self):
522513
self.filesystem.is_windows_fs = False
523-
self.filesystem.reset()
524514
dir_path = '/foo/bar'
525515
self.filesystem.create_dir(dir_path, perm_bits=0o555)
526516
file_path = dir_path + '/baz'
@@ -534,7 +524,6 @@ def test_create_file_in_read_only_directory_raises_in_posix(self):
534524

535525
def test_create_file_in_read_only_directory_possible_in_windows(self):
536526
self.filesystem.is_windows_fs = True
537-
self.filesystem.reset()
538527
dir_path = 'C:/foo/bar'
539528
self.filesystem.create_dir(dir_path, perm_bits=0o555)
540529
file_path = dir_path + '/baz'
@@ -657,12 +646,10 @@ def check_lresolve_object(self):
657646

658647
def test_lresolve_object_windows(self):
659648
self.filesystem.is_windows_fs = True
660-
self.filesystem.reset()
661649
self.check_lresolve_object()
662650

663651
def test_lresolve_object_posix(self):
664652
self.filesystem.is_windows_fs = False
665-
self.filesystem.reset()
666653
self.check_lresolve_object()
667654

668655
def check_directory_access_on_file(self, error_subtype):
@@ -674,12 +661,10 @@ def check_directory_access_on_file(self, error_subtype):
674661

675662
def test_directory_access_on_file_windows(self):
676663
self.filesystem.is_windows_fs = True
677-
self.filesystem.reset()
678664
self.check_directory_access_on_file(errno.ENOENT)
679665

680666
def test_directory_access_on_file_posix(self):
681667
self.filesystem.is_windows_fs = False
682-
self.filesystem.reset()
683668
self.check_directory_access_on_file(errno.ENOTDIR)
684669

685670
def test_pickle_fs(self):
@@ -753,7 +738,6 @@ def test_getsize(self):
753738

754739
def test_getsize_with_looping_symlink(self):
755740
self.filesystem.is_windows_fs = False
756-
self.filesystem.reset()
757741
dir_path = '/foo/bar'
758742
self.filesystem.create_dir(dir_path)
759743
link_path = dir_path + "/link"
@@ -891,7 +875,6 @@ def setUp(self):
891875
def check_abspath(self, is_windows):
892876
# the implementation differs in Windows and Posix, so test both
893877
self.filesystem.is_windows_fs = is_windows
894-
self.filesystem.reset()
895878
filename = 'foo'
896879
abspath = self.filesystem.root_dir_name + filename
897880
self.filesystem.create_file(abspath)
@@ -909,7 +892,6 @@ def test_abspath_posix(self):
909892
def check_abspath_bytes(self, is_windows):
910893
"""abspath should return a consistent representation of a file."""
911894
self.filesystem.is_windows_fs = is_windows
912-
self.filesystem.reset()
913895
filename = b'foo'
914896
abspath = self.filesystem.root_dir_name.encode() + filename
915897
self.filesystem.create_file(abspath)
@@ -943,21 +925,18 @@ def test_abspath_deals_with_relative_non_root_path(self):
943925

944926
def test_abs_path_with_drive_component(self):
945927
self.filesystem.is_windows_fs = True
946-
self.filesystem.reset()
947928
self.filesystem.cwd = 'C:!foo'
948929
self.assertEqual('C:!foo!bar', self.path.abspath('bar'))
949930
self.assertEqual('C:!foo!bar', self.path.abspath('C:bar'))
950931
self.assertEqual('C:!foo!bar', self.path.abspath('!foo!bar'))
951932

952933
def test_isabs_with_drive_component(self):
953934
self.filesystem.is_windows_fs = False
954-
self.filesystem.reset()
955935
self.assertFalse(self.path.isabs('C:!foo'))
956936
self.assertFalse(self.path.isabs(b'C:!foo'))
957937
self.assertTrue(self.path.isabs('!'))
958938
self.assertTrue(self.path.isabs(b'!'))
959939
self.filesystem.is_windows_fs = True
960-
self.filesystem.reset()
961940
self.assertTrue(self.path.isabs('C:!foo'))
962941
self.assertTrue(self.path.isabs(b'C:!foo'))
963942
self.assertTrue(self.path.isabs('!'))
@@ -981,7 +960,6 @@ def test_relpath(self):
981960

982961
def test_realpath_vs_abspath(self):
983962
self.filesystem.is_windows_fs = False
984-
self.filesystem.reset()
985963
self.filesystem.create_file('!george!washington!bridge')
986964
self.filesystem.create_symlink('!first!president',
987965
'!george!washington')
@@ -1049,7 +1027,6 @@ def test_lexists(self):
10491027

10501028
def test_dirname_with_drive(self):
10511029
self.filesystem.is_windows_fs = True
1052-
self.filesystem.reset()
10531030
self.assertEqual('c:!foo',
10541031
self.path.dirname('c:!foo!bar'))
10551032
self.assertEqual(b'c:!',
@@ -1201,7 +1178,6 @@ def test_ismount(self):
12011178

12021179
def test_ismount_with_drive_letters(self):
12031180
self.filesystem.is_windows_fs = True
1204-
self.filesystem.reset()
12051181
self.assertTrue(self.path.ismount('!'))
12061182
self.assertTrue(self.path.ismount('c:!'))
12071183
self.assertFalse(self.path.ismount('c:'))
@@ -1212,7 +1188,6 @@ def test_ismount_with_drive_letters(self):
12121188

12131189
def test_ismount_with_unc_paths(self):
12141190
self.filesystem.is_windows_fs = True
1215-
self.filesystem.reset()
12161191
self.assertTrue(self.path.ismount('!!a!'))
12171192
self.assertTrue(self.path.ismount('!!a!b'))
12181193
self.assertTrue(self.path.ismount('!!a!b!'))
@@ -1287,7 +1262,6 @@ def test_ignores_up_level_references_starting_from_root(self):
12871262
self.assertEqual(
12881263
'|', self.filesystem.normpath('|..|..|foo|bar|..|..|'))
12891264
self.filesystem.is_windows_fs = False # not an UNC path
1290-
self.filesystem.reset()
12911265
self.assertEqual('|', self.filesystem.normpath('||..|.|..||'))
12921266

12931267
def test_conserves_up_level_references_starting_from_current_dir(self):
@@ -1398,7 +1372,6 @@ def test_normalize_case(self):
13981372

13991373
def test_normalize_case_for_drive(self):
14001374
self.filesystem.is_windows_fs = True
1401-
self.filesystem.reset()
14021375
self.filesystem.create_file('C:/Foo/Bar')
14031376
self.assertEqual('C:/Foo/Bar',
14041377
self.filesystem._original_path('c:/foo/bar'))
@@ -1465,7 +1438,6 @@ def setUp(self):
14651438
self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!')
14661439
self.filesystem.alternative_path_separator = '^'
14671440
self.filesystem.is_windows_fs = True
1468-
self.filesystem.reset()
14691441

14701442
def test_initial_value(self):
14711443
filesystem = fake_filesystem.FakeFilesystem()
@@ -1870,15 +1842,13 @@ def test_disk_size_on_unlimited_disk(self):
18701842

18711843
def test_disk_size_on_auto_mounted_drive_on_file_creation(self):
18721844
self.fs.is_windows_fs = True
1873-
self.fs.reset()
18741845
# drive d: shall be auto-mounted and the used size adapted
18751846
self.fs.create_file('d:!foo!bar', st_size=100)
18761847
self.fs.set_disk_usage(total_size=1000, path='d:')
18771848
self.assertEqual(self.fs.get_disk_usage('d:!foo').free, 900)
18781849

18791850
def test_disk_size_on_auto_mounted_drive_on_directory_creation(self):
18801851
self.fs.is_windows_fs = True
1881-
self.fs.reset()
18821852
self.fs.create_dir('d:!foo!bar')
18831853
self.fs.create_file('d:!foo!bar!baz', st_size=100)
18841854
self.fs.create_file('d:!foo!baz', st_size=100)
@@ -1943,40 +1913,42 @@ class MountPointTest(TestCase):
19431913
def setUp(self):
19441914
self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!',
19451915
total_size=100)
1946-
self.add_mount_points()
19471916

19481917
def add_mount_points(self):
19491918
self.filesystem.add_mount_point('!foo')
19501919
self.filesystem.add_mount_point('!bar')
19511920
self.filesystem.add_mount_point('!foo!baz')
19521921

19531922
def test_that_new_mount_points_get_new_device_number(self):
1923+
self.add_mount_points()
19541924
self.assertEqual(1, self.filesystem.get_object('!').st_dev)
19551925
self.assertEqual(2, self.filesystem.get_object('!foo').st_dev)
19561926
self.assertEqual(3, self.filesystem.get_object('!bar').st_dev)
19571927
self.assertEqual(4, self.filesystem.get_object('!foo!baz').st_dev)
19581928

19591929
def test_that_new_directories_get_correct_device_number(self):
1930+
self.add_mount_points()
19601931
self.assertEqual(1, self.filesystem.create_dir('!foo1!bar').st_dev)
19611932
self.assertEqual(2, self.filesystem.create_dir('!foo!bar').st_dev)
19621933
self.assertEqual(4,
19631934
self.filesystem.create_dir('!foo!baz!foo!bar').st_dev)
19641935

19651936
def test_that_new_files_get_correct_device_number(self):
1937+
self.add_mount_points()
19661938
self.assertEqual(1, self.filesystem.create_file('!foo1!bar').st_dev)
19671939
self.assertEqual(2, self.filesystem.create_file('!foo!bar').st_dev)
19681940
self.assertEqual(4, self.filesystem.create_file(
19691941
'!foo!baz!foo!bar').st_dev)
19701942

19711943
def test_that_mount_point_cannot_be_added_twice(self):
1944+
self.add_mount_points()
19721945
with self.raises_os_error(errno.EEXIST):
19731946
self.filesystem.add_mount_point('!foo')
19741947
with self.raises_os_error(errno.EEXIST):
19751948
self.filesystem.add_mount_point('!foo!')
19761949

19771950
def test_that_drives_are_auto_mounted(self):
19781951
self.filesystem.is_windows_fs = True
1979-
self.filesystem.reset()
19801952
self.add_mount_points()
19811953
self.filesystem.create_dir('d:!foo!bar')
19821954
self.filesystem.create_file('d:!foo!baz')
@@ -1988,7 +1960,6 @@ def test_that_drives_are_auto_mounted(self):
19881960

19891961
def test_that_drives_are_auto_mounted_case_insensitive(self):
19901962
self.filesystem.is_windows_fs = True
1991-
self.filesystem.reset()
19921963
self.add_mount_points()
19931964
self.filesystem.is_case_sensitive = False
19941965
self.filesystem.create_dir('D:!foo!bar')
@@ -2000,7 +1971,6 @@ def test_that_drives_are_auto_mounted_case_insensitive(self):
20001971

20011972
def test_that_unc_paths_are_auto_mounted(self):
20021973
self.filesystem.is_windows_fs = True
2003-
self.filesystem.reset()
20041974
self.add_mount_points()
20051975
self.filesystem.create_dir('!!foo!bar!baz')
20061976
self.filesystem.create_file('!!foo!bar!bip!bop')

0 commit comments

Comments
 (0)