Skip to content

Commit

Permalink
Fix pure windows path behavior (#1011)
Browse files Browse the repository at this point in the history
* Hard-code path separators in `Pure*Path` classes
* Fixes #1006
  • Loading branch information
kurtmckee authored May 6, 2024
1 parent d11b848 commit d875151
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ The released versions correspond to PyPI releases.
* The usage of the `pathlib2` and `scandir` modules in pyfakefs is now deprecated.
They will now cause deprecation warnings if still used. Support for patching
these modules will be removed in pyfakefs 6.0.
* `PureWindowsPath` and `PurePosixPath` now use filesystem-independent path separators,
and their path-parsing behaviors are now consistent regardless of runtime platform
and/or faked filesystem customization (see [#1006](../../issues/1006)).

## [Version 5.4.1](https://pypi.python.org/pypi/pyfakefs/5.4.0) (2024-04-11)
Fixes a regression.
Expand Down
33 changes: 28 additions & 5 deletions pyfakefs/fake_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,38 @@ def init_module(filesystem):
# pylint: disable=protected-access
FakePath.filesystem = filesystem
if sys.version_info < (3, 12):
FakePathlibModule.PureWindowsPath._flavour = _FakeWindowsFlavour(filesystem)
FakePathlibModule.PurePosixPath._flavour = _FakePosixFlavour(filesystem)
FakePathlibModule.WindowsPath._flavour = _FakeWindowsFlavour(filesystem)
FakePathlibModule.PosixPath._flavour = _FakePosixFlavour(filesystem)

# Pure POSIX path separators must be filesystem-independent.
fake_pure_posix_flavour = _FakePosixFlavour(filesystem)
fake_pure_posix_flavour.sep = "/"
fake_pure_posix_flavour.altsep = None
FakePathlibModule.PurePosixPath._flavour = fake_pure_posix_flavour

# Pure Windows path separators must be filesystem-independent.
fake_pure_nt_flavour = _FakePosixFlavour(filesystem)
fake_pure_nt_flavour.sep = "\\"
fake_pure_nt_flavour.altsep = "/"
FakePathlibModule.PureWindowsPath._flavour = fake_pure_nt_flavour
else:
# in Python 3.12, the flavour is no longer an own class,
# but points to the os-specific path module (posixpath/ntpath)
fake_os = FakeOsModule(filesystem)
fake_path = fake_os.path
FakePathlibModule.PureWindowsPath._flavour = fake_path
FakePathlibModule.PurePosixPath._flavour = fake_path
FakePathlibModule.PosixPath._flavour = fake_os.path
FakePathlibModule.WindowsPath._flavour = fake_os.path

# Pure POSIX path separators must be filesystem independent.
fake_pure_posix_os = FakeOsModule(filesystem)
fake_pure_posix_os.path.sep = "/"
fake_pure_posix_os.path.altsep = None
FakePathlibModule.PurePosixPath._flavour = fake_pure_posix_os.path

# Pure Windows path separators must be filesystem independent.
fake_pure_nt_os = FakeOsModule(filesystem)
fake_pure_nt_os.path.sep = "\\"
fake_pure_nt_os.path.altsep = "/"
FakePathlibModule.PureWindowsPath._flavour = fake_pure_nt_os.path


def _wrap_strfunc(strfunc):
Expand Down
26 changes: 26 additions & 0 deletions pyfakefs/tests/fake_pathlib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1286,5 +1286,31 @@ def test_is_file_for_unreadable_dir_windows(self):
path.is_file()


class FakePathlibModulePurePathTest(unittest.TestCase):
def test_windows_pure_path_parsing(self):
"""Verify faked pure Windows paths use filesystem-independent separators."""

path = r"C:\Windows\cmd.exe"
self.assertEqual(
fake_pathlib.FakePathlibModule.PureWindowsPath(path).stem,
pathlib.PureWindowsPath(path).stem,
)

path = r"C:/Windows/cmd.exe"
self.assertEqual(
fake_pathlib.FakePathlibModule.PureWindowsPath(path).stem,
pathlib.PureWindowsPath(path).stem,
)

def test_posix_pure_path_parsing(self):
"""Verify faked pure POSIX paths use filesystem-independent separators."""

path = r"/bin/bash"
self.assertEqual(
fake_pathlib.FakePathlibModule.PurePosixPath(path).stem,
pathlib.PurePosixPath(path).stem,
)


if __name__ == "__main__":
unittest.main(verbosity=2)

0 comments on commit d875151

Please sign in to comment.