From 7654f41a8fe0e794c584e22434811898c81458af Mon Sep 17 00:00:00 2001 From: Sri Charan Date: Wed, 7 Oct 2026 23:55:34 +0530 Subject: [PATCH] Fix fnmatch filtering under simulated Windows --- CHANGES.md | 3 +++ pyfakefs/fake_filesystem_unittest.py | 5 +++++ pyfakefs/tests/fake_filesystem_glob_test.py | 24 +++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index c40e7404..db2fb654 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,9 @@ The released versions correspond to PyPI releases. ### Fixes +* fixed `fnmatch.filter` and `glob.glob` missing uppercase names + when simulating Windows on a POSIX host + (see [#1345](https://github.com/pytest-dev/pyfakefs/issues/1345)) * fixed a crash if the stack limit was set to a low value (see [#1313](https://github.com/pytest-dev/pyfakefs/issues/1313)) * fixed `os.ftruncate` to inspect the `FakeFileWrapper` returned by diff --git a/pyfakefs/fake_filesystem_unittest.py b/pyfakefs/fake_filesystem_unittest.py index 22ce33d4..6a07d5be 100644 --- a/pyfakefs/fake_filesystem_unittest.py +++ b/pyfakefs/fake_filesystem_unittest.py @@ -38,6 +38,7 @@ import _io # type:ignore[import] import doctest +import fnmatch import functools import genericpath import glob @@ -1121,6 +1122,10 @@ def patch_modules(self) -> None: for name, modules in self.FS_MODULES.items(): for module, attr in modules: try: + # fnmatch.filter skips normcase when os.path is posixpath. + # The fake path module can use Windows case rules instead. + if module is fnmatch and name == "posixpath": + continue if not skip_prefixes or not module.__name__.startswith( skip_prefixes ): diff --git a/pyfakefs/tests/fake_filesystem_glob_test.py b/pyfakefs/tests/fake_filesystem_glob_test.py index 3747e8af..5e604809 100644 --- a/pyfakefs/tests/fake_filesystem_glob_test.py +++ b/pyfakefs/tests/fake_filesystem_glob_test.py @@ -15,12 +15,14 @@ """Test for glob using fake_filesystem.""" import contextlib +import fnmatch import glob import os import sys import unittest from pyfakefs import fake_filesystem_unittest +from pyfakefs.fake_filesystem import OSType class FakeGlobUnitTest(fake_filesystem_unittest.TestCase): @@ -86,6 +88,28 @@ def test_has_magic(self): self.assertTrue(glob.has_magic("[")) self.assertFalse(glob.has_magic("a")) + def test_fnmatch_filter_windows(self): + self.fs.os = OSType.WINDOWS + for pattern in ("*.txt", "*.TXT"): + with self.subTest(pattern=pattern): + self.assertEqual( + ["B.TXT"], fnmatch.filter(["B.TXT", "other.log"], pattern) + ) + self.assertEqual( + [b"B.TXT"], + fnmatch.filter([b"B.TXT", b"other.log"], pattern.encode()), + ) + + def test_glob_windows_case_insensitive(self): + self.fs.os = OSType.WINDOWS + self.fs.create_file(r"C:\d\B.TXT") + self.assertEqual([r"C:\d\B.TXT"], glob.glob(r"C:\d\*.txt")) + + def test_fnmatch_filter_linux_case_sensitive(self): + self.fs.os = OSType.LINUX + self.assertEqual([], fnmatch.filter(["B.TXT"], "*.txt")) + self.assertEqual(["B.TXT"], fnmatch.filter(["B.TXT"], "*.TXT")) + if __name__ == "__main__": unittest.main()