Skip to content

gh-108638: Fix stat.filemode() when _stat is missing #108639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Lib/stat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, "-"),
Expand Down Expand Up @@ -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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if index == 0:
if not perm:

And you can remove index.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, feel free to write a follow-up PR if you want, sadly you reviewed the change just after it got merged automatically. I have not preference between enumerate() + if index == 0 and not perm.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_stat.filemode() and stat.filemode() implementations are very different. I tried to write a minimum fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so there is a _stat.filemode()? I noticed that the Python implementation always use constants defined in Python, even if they are overwritten by _stat later. I was not sure whether this is good or bad. On one hand, the original use case was for tar files, which can came from other systems. On other hand, it should work with local files.

# Unknown filetype
perm.append("?")
else:
perm.append("-")
return "".join(perm)


Expand Down
6 changes: 5 additions & 1 deletion Lib/test/test_stat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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

Expand Down