From ce5c938b6b467b0802c8b88aefde6be33c073f86 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 29 Aug 2023 16:52:35 +0200 Subject: [PATCH] gh-108638: Fix stat.filemode() when _stat is missing Change the pure Python implementation of stat.filemode() for unknown file type: use "?", as done by the _stat.filemode(). test_stat skips TestFilemodeCStat if the _stat extension is missing. --- Lib/stat.py | 10 ++++++++-- Lib/test/test_stat.py | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Lib/stat.py b/Lib/stat.py index fc024db3f4fbee..52cadbf04f6c88 100644 --- a/Lib/stat.py +++ b/Lib/stat.py @@ -126,6 +126,8 @@ def S_ISWHT(mode): _filemode_table = ( + # File type chars according to: + # http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h ((S_IFLNK, "l"), (S_IFSOCK, "s"), # Must appear before IFREG and IFDIR as IFSOCK == IFREG | IFDIR (S_IFREG, "-"), @@ -156,13 +158,17 @@ def S_ISWHT(mode): def filemode(mode): """Convert a file's mode to a string of the form '-rwxrwxrwx'.""" perm = [] - for table in _filemode_table: + for index, table in enumerate(_filemode_table): for bit, char in table: if mode & bit == bit: perm.append(char) break else: - perm.append("-") + if index == 0: + # Unknown filetype + perm.append("?") + else: + perm.append("-") return "".join(perm) diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 4ba37aed2dc9db..0eced2fcf98376 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -122,8 +122,11 @@ def test_mode(self): st_mode, modestr = self.get_mode() self.assertEqual(modestr, '-rwx------') self.assertS_IS("REG", st_mode) - self.assertEqual(self.statmod.S_IMODE(st_mode), + imode = self.statmod.S_IMODE(st_mode) + self.assertEqual(imode, self.statmod.S_IRWXU) + self.assertEqual(self.statmod.filemode(imode), + '?rwx------') os.chmod(TESTFN, 0o070) st_mode, modestr = self.get_mode() @@ -238,6 +241,7 @@ def test_file_attribute_constants(self): self.assertEqual(value, modvalue, key) +@unittest.skipIf(c_stat is None, 'need _stat extension') class TestFilemodeCStat(TestFilemode, unittest.TestCase): statmod = c_stat