Skip to content

Commit b62a760

Browse files
authored
gh-108638: Fix stat.filemode() when _stat is missing (#108639)
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.
1 parent 7659128 commit b62a760

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

Lib/stat.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ def S_ISWHT(mode):
126126

127127

128128
_filemode_table = (
129+
# File type chars according to:
130+
# http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h
129131
((S_IFLNK, "l"),
130132
(S_IFSOCK, "s"), # Must appear before IFREG and IFDIR as IFSOCK == IFREG | IFDIR
131133
(S_IFREG, "-"),
@@ -156,13 +158,17 @@ def S_ISWHT(mode):
156158
def filemode(mode):
157159
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
158160
perm = []
159-
for table in _filemode_table:
161+
for index, table in enumerate(_filemode_table):
160162
for bit, char in table:
161163
if mode & bit == bit:
162164
perm.append(char)
163165
break
164166
else:
165-
perm.append("-")
167+
if index == 0:
168+
# Unknown filetype
169+
perm.append("?")
170+
else:
171+
perm.append("-")
166172
return "".join(perm)
167173

168174

Lib/test/test_stat.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,11 @@ def test_mode(self):
122122
st_mode, modestr = self.get_mode()
123123
self.assertEqual(modestr, '-rwx------')
124124
self.assertS_IS("REG", st_mode)
125-
self.assertEqual(self.statmod.S_IMODE(st_mode),
125+
imode = self.statmod.S_IMODE(st_mode)
126+
self.assertEqual(imode,
126127
self.statmod.S_IRWXU)
128+
self.assertEqual(self.statmod.filemode(imode),
129+
'?rwx------')
127130

128131
os.chmod(TESTFN, 0o070)
129132
st_mode, modestr = self.get_mode()
@@ -238,6 +241,7 @@ def test_file_attribute_constants(self):
238241
self.assertEqual(value, modvalue, key)
239242

240243

244+
@unittest.skipIf(c_stat is None, 'need _stat extension')
241245
class TestFilemodeCStat(TestFilemode, unittest.TestCase):
242246
statmod = c_stat
243247

0 commit comments

Comments
 (0)