diff options
author | mrbean-bremen <hansemrbean@googlemail.com> | 2023-04-01 21:24:06 +0200 |
---|---|---|
committer | mrbean-bremen <mrbean-bremen@users.noreply.github.com> | 2023-04-03 19:09:39 +0200 |
commit | f3e90c0cc1a60e17e5fd219009259942e3ec3369 (patch) | |
tree | 9f1f83fbcbebd89af6afd2a18a75dcb2eaf44300 /pyfakefs | |
parent | c819a409053bcbe63670b86314a68c77c1eff1ac (diff) | |
download | pyfakefs-f3e90c0cc1a60e17e5fd219009259942e3ec3369.tar.gz |
Set the os.supports_xxx properties for the fake filesystem
- return the faked functions instead of the real ones
- fixes #799
Diffstat (limited to 'pyfakefs')
-rw-r--r-- | pyfakefs/fake_os.py | 47 | ||||
-rw-r--r-- | pyfakefs/fake_pathlib.py | 2 | ||||
-rw-r--r-- | pyfakefs/tests/fake_filesystem_shutil_test.py | 11 | ||||
-rw-r--r-- | pyfakefs/tests/fake_os_test.py | 59 | ||||
-rw-r--r-- | pyfakefs/tests/fake_pathlib_test.py | 2 |
5 files changed, 94 insertions, 27 deletions
diff --git a/pyfakefs/fake_os.py b/pyfakefs/fake_os.py index 0d638a5..912fd31 100644 --- a/pyfakefs/fake_os.py +++ b/pyfakefs/fake_os.py @@ -36,6 +36,7 @@ from typing import ( cast, AnyStr, TYPE_CHECKING, + Set, ) from pyfakefs.extra_packages import use_scandir @@ -146,6 +147,10 @@ class FakeOsModule: self.filesystem = filesystem self.os_module: Any = os self.path = FakePathModule(self.filesystem, self) + self._supports_follow_symlinks: Optional[Set] = None + self._supports_dir_fd: Optional[Set] = None + self._supports_effective_ids: Optional[Set] = None + self._supports_fd: Optional[Set] = None @property def devnull(self) -> str: @@ -890,8 +895,7 @@ class FakeOsModule: path = path if dir_fd is not None: # check if fd is supported for the built-in real function - real_fct = getattr(os, fct.__name__) - if real_fct not in self.supports_dir_fd: + if fct not in self.supports_dir_fd: raise NotImplementedError("dir_fd unavailable on this platform") if isinstance(path, int): raise ValueError( @@ -998,7 +1002,7 @@ class FakeOsModule: the link itself is queried instead of the linked object. """ if not follow_symlinks and ( - os.chmod not in os.supports_follow_symlinks or IS_PYPY + self.chmod not in self.supports_follow_symlinks or IS_PYPY ): raise NotImplementedError( "`follow_symlinks` for chmod() is not available " "on this system" @@ -1268,6 +1272,43 @@ class FakeOsModule: return written return 0 + def fake_functions(self, original_functions) -> Set: + functions = set() + for fn in original_functions: + if hasattr(self, fn.__name__): + functions.add(getattr(self, fn.__name__)) + else: + functions.add(fn) + return functions + + @property + def supports_follow_symlinks(self) -> Set[Callable]: + if self._supports_follow_symlinks is None: + self._supports_follow_symlinks = self.fake_functions( + self.os_module.supports_follow_symlinks + ) + return self._supports_follow_symlinks + + @property + def supports_dir_fd(self) -> Set[Callable]: + if self._supports_dir_fd is None: + self._supports_dir_fd = self.fake_functions(self.os_module.supports_dir_fd) + return self._supports_dir_fd + + @property + def supports_fd(self) -> Set[Callable]: + if self._supports_fd is None: + self._supports_fd = self.fake_functions(self.os_module.supports_fd) + return self._supports_fd + + @property + def supports_effective_ids(self) -> Set[Callable]: + if self._supports_effective_ids is None: + self._supports_effective_ids = self.fake_functions( + self.os_module.supports_effective_ids + ) + return self._supports_effective_ids + def __getattr__(self, name: str) -> Any: """Forwards any unfaked calls to the standard os module.""" return getattr(self.os_module, name) diff --git a/pyfakefs/fake_pathlib.py b/pyfakefs/fake_pathlib.py index 4f8ec6f..2291ddb 100644 --- a/pyfakefs/fake_pathlib.py +++ b/pyfakefs/fake_pathlib.py @@ -132,7 +132,7 @@ class _FakeAccessor(accessor): # type: ignore [valid-type, misc] if ( not kwargs["follow_symlinks"] - and os.os_module.chmod not in os.supports_follow_symlinks + and os.os_module.chmod not in os.os_module.supports_follow_symlinks ): raise NotImplementedError( "`follow_symlinks` for chmod() is not available " "on this system" diff --git a/pyfakefs/tests/fake_filesystem_shutil_test.py b/pyfakefs/tests/fake_filesystem_shutil_test.py index c99d464..e1bfab1 100644 --- a/pyfakefs/tests/fake_filesystem_shutil_test.py +++ b/pyfakefs/tests/fake_filesystem_shutil_test.py @@ -231,6 +231,17 @@ class FakeShutilModuleTest(RealFsTestCase): self.assertAlmostEqual(src_stat.st_atime, dst_stat.st_atime, places=2) self.assertAlmostEqual(src_stat.st_mtime, dst_stat.st_mtime, places=2) + def test_copystat_symlinks(self): + """Regression test for #799""" + self.skip_if_symlink_not_supported() + f = self.make_path("xyzzy") + self.create_file(f) + sym1 = self.make_path("sym1") + sym2 = self.make_path("sym2") + self.create_symlink(sym1, f) + self.create_symlink(sym2, f) + shutil.copystat(sym1, sym2, follow_symlinks=False) + def test_copy2(self): src_file = self.make_path("xyzzy") self.create_file(src_file) diff --git a/pyfakefs/tests/fake_os_test.py b/pyfakefs/tests/fake_os_test.py index d3727a1..e9294f6 100644 --- a/pyfakefs/tests/fake_os_test.py +++ b/pyfakefs/tests/fake_os_test.py @@ -2011,7 +2011,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase): self.createTestFile(path) link_path = self.make_path("link_to_some_file") self.create_symlink(link_path, path) - if os.chmod not in os.supports_follow_symlinks or IS_PYPY: + if self.os.chmod not in self.os.supports_follow_symlinks or IS_PYPY: with self.assertRaises(NotImplementedError): self.os.chmod(link_path, 0o6543, follow_symlinks=False) else: @@ -2866,6 +2866,21 @@ class FakeOsModuleTest(FakeOsModuleTestBase): with self.open(file_path) as f: self.assertEqual("0123456789", f.read()) + def test_capabilities(self): + """Make sure that the fake capabilities are the same as the real ones.""" + self.assertEqual( + self.os.stat in self.os.supports_follow_symlinks, + os.stat in os.supports_follow_symlinks, + ) + self.assertEqual(self.os.stat in self.os.supports_fd, os.stat in os.supports_fd) + self.assertEqual( + self.os.stat in self.os.supports_dir_fd, os.stat in os.supports_dir_fd + ) + self.assertEqual( + self.os.stat in self.os.supports_effective_ids, + os.stat in os.supports_effective_ids, + ) + class RealOsModuleTest(FakeOsModuleTest): def use_real_fs(self): @@ -4661,7 +4676,7 @@ class RealOsModuleWalkTest(FakeOsModuleWalkTest): class FakeOsModuleDirFdTest(FakeOsModuleTestBase): def setUp(self): super(FakeOsModuleDirFdTest, self).setUp() - self.os.supports_dir_fd = set() + self.os.supports_dir_fd.clear() self.filesystem.is_windows_fs = False self.filesystem.create_dir("/foo/bar") self.dir_fd = self.os.open("/foo", os.O_RDONLY) @@ -4675,7 +4690,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): self.os.F_OK, dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.access) + self.os.supports_dir_fd.add(self.os.access) self.assertTrue(self.os.access("baz", self.os.F_OK, dir_fd=self.dir_fd)) def test_chmod(self): @@ -4686,7 +4701,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): 0o6543, dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.chmod) + self.os.supports_dir_fd.add(self.os.chmod) self.os.chmod("baz", 0o6543, dir_fd=self.dir_fd) st = self.os.stat("/foo/baz") self.assert_mode_equal(0o6543, st.st_mode) @@ -4701,7 +4716,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): 101, dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.chown) + self.os.supports_dir_fd.add(self.os.chown) self.os.chown("baz", 100, 101, dir_fd=self.dir_fd) st = self.os.stat("/foo/baz") self.assertEqual(st[stat.ST_UID], 100) @@ -4715,7 +4730,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/bat", src_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.link) + self.os.supports_dir_fd.add(self.os.link) self.os.link("baz", "/bat", src_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/bat")) @@ -4727,7 +4742,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/bat", dst_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.link) + self.os.supports_dir_fd.add(self.os.link) self.os.link("/foo/baz", "bat", dst_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/bat")) @@ -4739,7 +4754,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/bat", dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.symlink) + self.os.supports_dir_fd.add(self.os.symlink) self.os.symlink("baz", "/bat", dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/bat")) @@ -4753,7 +4768,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/geo/metro/lemon/pie", dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.readlink) + self.os.supports_dir_fd.add(self.os.readlink) self.assertEqual( "/foo/baz", self.os.readlink("/geo/metro/lemon/pie", dir_fd=self.dir_fd), @@ -4761,13 +4776,13 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): def test_stat(self): self.assertRaises(NotImplementedError, self.os.stat, "baz", dir_fd=self.dir_fd) - self.os.supports_dir_fd.add(os.stat) + self.os.supports_dir_fd.add(self.os.stat) st = self.os.stat("baz", dir_fd=self.dir_fd) self.assertEqual(st.st_mode, 0o100666) def test_lstat(self): self.assertRaises(NotImplementedError, self.os.lstat, "baz", dir_fd=self.dir_fd) - self.os.supports_dir_fd.add(os.lstat) + self.os.supports_dir_fd.add(self.os.lstat) st = self.os.lstat("baz", dir_fd=self.dir_fd) self.assertEqual(st.st_mode, 0o100666) @@ -4775,13 +4790,13 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): self.assertRaises( NotImplementedError, self.os.mkdir, "newdir", dir_fd=self.dir_fd ) - self.os.supports_dir_fd.add(os.mkdir) + self.os.supports_dir_fd.add(self.os.mkdir) self.os.mkdir("newdir", dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/newdir")) def test_rmdir(self): self.assertRaises(NotImplementedError, self.os.rmdir, "bar", dir_fd=self.dir_fd) - self.os.supports_dir_fd.add(os.rmdir) + self.os.supports_dir_fd.add(self.os.rmdir) self.os.rmdir("bar", dir_fd=self.dir_fd) self.assertFalse(self.os.path.exists("/foo/bar")) @@ -4790,7 +4805,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): self.assertRaises( NotImplementedError, self.os.mknod, "newdir", dir_fd=self.dir_fd ) - self.os.supports_dir_fd.add(os.mknod) + self.os.supports_dir_fd.add(self.os.mknod) self.os.mknod("newdir", dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/newdir")) @@ -4802,7 +4817,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/foo/batz", src_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.rename) + self.os.supports_dir_fd.add(self.os.rename) self.os.rename("bar", "/foo/batz", src_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/batz")) @@ -4814,7 +4829,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/foo/batz", dst_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.rename) + self.os.supports_dir_fd.add(self.os.rename) self.os.rename("/foo/bar", "batz", dst_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/batz")) @@ -4826,7 +4841,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/foo/batz", src_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.rename) + self.os.supports_dir_fd.add(self.os.rename) self.os.replace("bar", "/foo/batz", src_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/batz")) @@ -4838,7 +4853,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): "/foo/batz", dst_dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.rename) + self.os.supports_dir_fd.add(self.os.rename) self.os.replace("/foo/bar", "batz", dst_dir_fd=self.dir_fd) self.assertTrue(self.os.path.exists("/foo/batz")) @@ -4846,7 +4861,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): self.assertRaises( NotImplementedError, self.os.remove, "baz", dir_fd=self.dir_fd ) - self.os.supports_dir_fd.add(os.remove) + self.os.supports_dir_fd.add(self.os.remove) self.os.remove("baz", dir_fd=self.dir_fd) self.assertFalse(self.os.path.exists("/foo/baz")) @@ -4854,7 +4869,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): self.assertRaises( NotImplementedError, self.os.unlink, "baz", dir_fd=self.dir_fd ) - self.os.supports_dir_fd.add(os.unlink) + self.os.supports_dir_fd.add(self.os.unlink) self.os.unlink("baz", dir_fd=self.dir_fd) self.assertFalse(self.os.path.exists("/foo/baz")) @@ -4866,7 +4881,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): (1, 2), dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.utime) + self.os.supports_dir_fd.add(self.os.utime) self.os.utime("baz", times=(1, 2), dir_fd=self.dir_fd) st = self.os.stat("/foo/baz") self.assertEqual(1, st.st_atime) @@ -4880,7 +4895,7 @@ class FakeOsModuleDirFdTest(FakeOsModuleTestBase): os.O_RDONLY, dir_fd=self.dir_fd, ) - self.os.supports_dir_fd.add(os.open) + self.os.supports_dir_fd.add(self.os.open) fd = self.os.open("baz", os.O_RDONLY, dir_fd=self.dir_fd) self.assertLess(0, fd) diff --git a/pyfakefs/tests/fake_pathlib_test.py b/pyfakefs/tests/fake_pathlib_test.py index 6cc7bd9..d487f32 100644 --- a/pyfakefs/tests/fake_pathlib_test.py +++ b/pyfakefs/tests/fake_pathlib_test.py @@ -402,7 +402,7 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase): self.skip_if_symlink_not_supported() file_stat = self.os.stat(self.file_path) link_stat = self.os.lstat(self.file_link_path) - if self.real_os.chmod not in os.supports_follow_symlinks or IS_PYPY: + if self.os.chmod not in self.os.supports_follow_symlinks or IS_PYPY: with self.assertRaises(NotImplementedError): self.path(self.file_link_path).chmod(0o444, follow_symlinks=False) else: |