]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-108638: Fix stat.filemode() when _stat is missing (#108639)
authorVictor Stinner <vstinner@python.org>
Tue, 29 Aug 2023 15:46:46 +0000 (17:46 +0200)
committerGitHub <noreply@github.com>
Tue, 29 Aug 2023 15:46:46 +0000 (15:46 +0000)
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
Lib/test/test_stat.py

index fc024db3f4fbeeb903272363ee2bad19de0e635b..52cadbf04f6c88b754d8926fa3ba18c9d6c49fd4 100644 (file)
@@ -126,6 +126,8 @@ SF_SNAPSHOT  = 0x00200000  # file is a snapshot file
 
 
 _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 @@ _filemode_table = (
 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)
 
 
index 4ba37aed2dc9db3469f618538c94b9da355a4b15..0eced2fcf98376e416c4f0966250846898702228 100644 (file)
@@ -122,8 +122,11 @@ class TestFilemode:
             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 @@ class TestFilemode:
             self.assertEqual(value, modvalue, key)
 
 
+@unittest.skipIf(c_stat is None, 'need _stat extension')
 class TestFilemodeCStat(TestFilemode, unittest.TestCase):
     statmod = c_stat