Skip to content

Commit e90bbd5

Browse files
committed
Add FakeFilesystem.os for more convenient OS setting
- the setter changes all needed attributes and resets the file system - reset now also resets pathlib to adapt the path separators - adapt documentation
1 parent a1bcc48 commit e90bbd5

File tree

4 files changed

+78
-7
lines changed

4 files changed

+78
-7
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The released versions correspond to PyPi releases.
99
* add possibility to patch `io.open_code` using the new argument
1010
`patch_open_code` (since Python 3.8)
1111
(see [#554](../../issues/554))
12+
* add possibility to set file system OS via `FakeFilesystem.os`
1213

1314
#### Fixes
1415
* fix handling of real files in combination with `home` if simulating

docs/usage.rst

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -675,8 +675,15 @@ Simulating other file systems
675675
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
676676
Pyfakefs supports Linux, MacOS and Windows operating systems. By default,
677677
the file system of the OS where the tests run is assumed, but it is possible
678-
to simulate other file systems to an extent. ``pyfakefs.FakeFilesystem`` has
679-
a few attributes that can be changed to simulate another file system:
678+
to simulate other file systems to some extent. To set a specific file
679+
system, you can change ``pyfakefs.FakeFilesystem.os`` to one of
680+
``OSType.LINUX``, ``OSType.MACOS`` and ``OSType.WINDOWS``. On doing so, the
681+
behavior of pyfakefs is adapted to the respective file system. Note that
682+
setting this causes the fake file system to be reset, so you should call it
683+
before adding any files.
684+
685+
Setting the ``os`` attributes changes a number of ``pyfakefs.FakeFilesystem``
686+
attributes, which can also be set separately if needed:
680687
681688
- ``is windows_fs`` - if ``True`` a Windows file system (NTFS) is assumed
682689
- ``is_macos`` - if ``True`` and ``is windows_fs`` is ``False``, the
@@ -694,11 +701,13 @@ The following test works both under Windows and Linux:
694701
695702
.. code:: python
696703
697-
def test_windows_paths(fs):
698-
fs.is_windows_fs = True
699-
path = "C:/foo/bar"
700-
assert os.path.splitdrive(path) == ("C:", "/foo/bar")
704+
from pyfakefs.fake_filesystem import OSType
701705
706+
def test_windows_paths(fs):
707+
fs.os = OSType.WINDOWS
708+
assert r"C:\foo\bar" == os.path.join('C:\\', 'foo', 'bar'))
709+
assert os.path.splitdrive(r"C:\foo\bar") == ("C:", r"\foo\bar")
710+
assert os.path.ismount("C:")
702711
703712
Troubleshooting
704713
---------------

pyfakefs/fake_filesystem.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@
158158
GROUP_ID = 1 if IS_WIN else os.getgid()
159159

160160

161+
class OSType(Enum):
162+
"""Defines the real or simulated OS of the underlying file system."""
163+
LINUX = "linux"
164+
MACOS = "macos"
165+
WINDOWS = "windows"
166+
167+
161168
class PatchMode(Enum):
162169
"""Defines if patching shall be on, off, or in automatic mode.
163170
Currently only used for `patch_open_code` option.
@@ -905,6 +912,24 @@ def __init__(self, path_separator=os.path.sep, total_size=None,
905912
def is_linux(self):
906913
return not self.is_windows_fs and not self.is_macos
907914

915+
@property
916+
def os(self):
917+
"""Return the real or simulated type of operating system."""
918+
return (OSType.WINDOWS if self.is_windows_fs else
919+
OSType.MACOS if self.is_macos else OSType.LINUX)
920+
921+
@os.setter
922+
def os(self, value):
923+
"""Set the simulated type of operating system underlying the fake
924+
file system."""
925+
self.is_windows_fs = value == OSType.WINDOWS
926+
self.is_macos = value == OSType.MACOS
927+
self.is_case_sensitive = value == OSType.LINUX
928+
self.path_separator = '\\' if value == OSType.WINDOWS else '/'
929+
self.alternative_path_separator = ('/' if value == OSType.WINDOWS
930+
else None)
931+
self.reset()
932+
908933
def reset(self, total_size=None):
909934
"""Remove all file system contents and reset the root."""
910935
self.root = FakeDirectory(self.path_separator, filesystem=self)
@@ -917,6 +942,8 @@ def reset(self, total_size=None):
917942
self.mount_points = {}
918943
self.add_mount_point(self.root.name, total_size)
919944
self._add_standard_streams()
945+
from pyfakefs import fake_pathlib
946+
fake_pathlib.init_module(self)
920947

921948
def pause(self):
922949
"""Pause the patching of the file system modules until `resume` is

pyfakefs/tests/fake_filesystem_unittest_test.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import pyfakefs.tests.import_as_example
3535
from pyfakefs import fake_filesystem_unittest, fake_filesystem
3636
from pyfakefs.extra_packages import pathlib
37+
from pyfakefs.fake_filesystem import OSType
3738
from pyfakefs.fake_filesystem_unittest import (
3839
Patcher, Pause, patchfs, PatchMode
3940
)
@@ -747,10 +748,10 @@ def test_run_module(self):
747748
class TestOtherFS(fake_filesystem_unittest.TestCase):
748749
def setUp(self):
749750
self.setUpPyfakefs()
750-
self.fs.is_windows_fs = os.name != 'nt'
751751

752752
def test_real_file_with_home(self):
753753
"""Regression test for #558"""
754+
self.fs.is_windows_fs = os.name != 'nt'
754755
self.fs.add_real_file(__file__)
755756
with open(__file__) as f:
756757
self.assertTrue(f.read())
@@ -762,6 +763,39 @@ def test_real_file_with_home(self):
762763
with open(__file__) as f:
763764
self.assertTrue(f.read())
764765

766+
def test_windows(self):
767+
self.fs.os = OSType.WINDOWS
768+
path = r'C:\foo\bar'
769+
self.assertEqual(path, os.path.join('C:\\', 'foo', 'bar'))
770+
self.assertEqual(('C:', r'\foo\bar'), os.path.splitdrive(path))
771+
self.fs.create_file(path)
772+
self.assertTrue(os.path.exists(path))
773+
self.assertTrue(os.path.exists(path.upper()))
774+
self.assertTrue(os.path.ismount(r'\\share\foo'))
775+
self.assertTrue(os.path.ismount(r'C:'))
776+
777+
def test_linux(self):
778+
self.fs.os = OSType.LINUX
779+
path = '/foo/bar'
780+
self.assertEqual(path, os.path.join('/', 'foo', 'bar'))
781+
self.assertEqual(('', 'C:/foo/bar'), os.path.splitdrive('C:/foo/bar'))
782+
self.fs.create_file(path)
783+
self.assertTrue(os.path.exists(path))
784+
self.assertFalse(os.path.exists(path.upper()))
785+
self.assertTrue(os.path.ismount('/'))
786+
self.assertFalse(os.path.ismount('//share/foo'))
787+
788+
def test_macos(self):
789+
self.fs.os = OSType.MACOS
790+
path = '/foo/bar'
791+
self.assertEqual(path, os.path.join('/', 'foo', 'bar'))
792+
self.assertEqual(('', 'C:/foo/bar'), os.path.splitdrive('C:/foo/bar'))
793+
self.fs.create_file(path)
794+
self.assertTrue(os.path.exists(path))
795+
self.assertTrue(os.path.exists(path.upper()))
796+
self.assertTrue(os.path.ismount('/'))
797+
self.assertFalse(os.path.ismount('//share/foo'))
798+
765799

766800
if __name__ == "__main__":
767801
unittest.main()

0 commit comments

Comments
 (0)