aboutsummaryrefslogtreecommitdiff
path: root/pyfakefs
diff options
context:
space:
mode:
authormrbean-bremen <hansemrbean@googlemail.com>2023-04-01 21:24:06 +0200
committermrbean-bremen <mrbean-bremen@users.noreply.github.com>2023-04-03 19:09:39 +0200
commitf3e90c0cc1a60e17e5fd219009259942e3ec3369 (patch)
tree9f1f83fbcbebd89af6afd2a18a75dcb2eaf44300 /pyfakefs
parentc819a409053bcbe63670b86314a68c77c1eff1ac (diff)
downloadpyfakefs-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.py47
-rw-r--r--pyfakefs/fake_pathlib.py2
-rw-r--r--pyfakefs/tests/fake_filesystem_shutil_test.py11
-rw-r--r--pyfakefs/tests/fake_os_test.py59
-rw-r--r--pyfakefs/tests/fake_pathlib_test.py2
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: