Skip to content

Commit

Permalink
#14807: move undocumented tarfile.filemode() to stat.filemode(). Add …
Browse files Browse the repository at this point in the history
…tarfile.filemode alias with deprecation warning.
  • Loading branch information
giampaolo committed May 15, 2012
1 parent 41829e8 commit ffa1d0b
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 43 deletions.
11 changes: 10 additions & 1 deletion Doc/library/stat.rst
Expand Up @@ -104,6 +104,16 @@ Example::
if __name__ == '__main__':
walktree(sys.argv[1], visitfile)

An additional utility function is provided to covert a file's mode in a human
readable string:

.. function:: filemode(mode)

Convert a file's mode to a string of the form '-rwxrwxrwx'.

.. versionadded:: 3.3


All the variables below are simply symbolic indexes into the 10-tuple returned
by :func:`os.stat`, :func:`os.fstat` or :func:`os.lstat`.

Expand Down Expand Up @@ -344,4 +354,3 @@ The following flags can be used in the *flags* argument of :func:`os.chflags`:
The file is a snapshot file.

See the \*BSD or Mac OS systems man page :manpage:`chflags(2)` for more information.

8 changes: 8 additions & 0 deletions Doc/whatsnew/3.3.rst
Expand Up @@ -1177,6 +1177,14 @@ ssl

(Contributed by Colin Marc in :issue:`14204`)

stat
----

- The undocumented tarfile.filemode function has been moved to
:func:`stat.filemode`. It can be used to convert a file's mode to a string of
the form '-rwxrwxrwx'.

(Contributed by Giampaolo Rodolà in :issue:`14807`)

sys
---
Expand Down
40 changes: 40 additions & 0 deletions Lib/stat.py
Expand Up @@ -107,3 +107,43 @@ def S_ISSOCK(mode):
SF_APPEND = 0x00040000 # file may only be appended to
SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted
SF_SNAPSHOT = 0x00200000 # file is a snapshot file


_filemode_table = (
((S_IFLNK, "l"),
(S_IFREG, "-"),
(S_IFBLK, "b"),
(S_IFDIR, "d"),
(S_IFCHR, "c"),
(S_IFIFO, "p")),

((S_IRUSR, "r"),),
((S_IWUSR, "w"),),
((S_IXUSR|S_ISUID, "s"),
(S_ISUID, "S"),
(S_IXUSR, "x")),

((S_IRGRP, "r"),),
((S_IWGRP, "w"),),
((S_IXGRP|S_ISGID, "s"),
(S_ISGID, "S"),
(S_IXGRP, "x")),

((S_IROTH, "r"),),
((S_IWOTH, "w"),),
((S_IXOTH|S_ISVTX, "t"),
(S_ISVTX, "T"),
(S_IXOTH, "x"))
)

def filemode(mode):
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
perm = []
for table in _filemode_table:
for bit, char in table:
if mode & bit == bit:
perm.append(char)
break
else:
perm.append("-")
return "".join(perm)
48 changes: 7 additions & 41 deletions Lib/tarfile.py
Expand Up @@ -274,47 +274,13 @@ def copyfileobj(src, dst, length=None):
dst.write(buf)
return

filemode_table = (
((S_IFLNK, "l"),
(S_IFREG, "-"),
(S_IFBLK, "b"),
(S_IFDIR, "d"),
(S_IFCHR, "c"),
(S_IFIFO, "p")),

((TUREAD, "r"),),
((TUWRITE, "w"),),
((TUEXEC|TSUID, "s"),
(TSUID, "S"),
(TUEXEC, "x")),

((TGREAD, "r"),),
((TGWRITE, "w"),),
((TGEXEC|TSGID, "s"),
(TSGID, "S"),
(TGEXEC, "x")),

((TOREAD, "r"),),
((TOWRITE, "w"),),
((TOEXEC|TSVTX, "t"),
(TSVTX, "T"),
(TOEXEC, "x"))
)

def filemode(mode):
"""Convert a file's mode to a string of the form
-rwxrwxrwx.
Used by TarFile.list()
"""
perm = []
for table in filemode_table:
for bit, char in table:
if mode & bit == bit:
perm.append(char)
break
else:
perm.append("-")
return "".join(perm)
"""Deprecated in this location; use stat.filemode."""
import warnings
warnings.warn("deprecated in favor of stat.filemode",
DeprecationWarning, 2)
return stat.filemode(mode)


class TarError(Exception):
"""Base exception."""
Expand Down Expand Up @@ -1891,7 +1857,7 @@ def list(self, verbose=True):

for tarinfo in self:
if verbose:
print(filemode(tarinfo.mode), end=' ')
print(stat.filemode(tarinfo.mode), end=' ')
print("%s/%s" % (tarinfo.uname or tarinfo.uid,
tarinfo.gname or tarinfo.gid), end=' ')
if tarinfo.ischr() or tarinfo.isblk():
Expand Down
55 changes: 55 additions & 0 deletions Lib/test/test_stat.py
@@ -0,0 +1,55 @@
import unittest
import os
import stat
from test.support import TESTFN, run_unittest


def get_mode(fname=TESTFN):
return stat.filemode(os.lstat(fname).st_mode)


class TestFilemode(unittest.TestCase):

def setUp(self):
try:
os.remove(TESTFN)
except OSError:
try:
os.rmdir(TESTFN)
except OSError:
pass
tearDown = setUp

def test_mode(self):
with open(TESTFN, 'w'):
pass
os.chmod(TESTFN, 0o700)
self.assertEqual(get_mode(), '-rwx------')
os.chmod(TESTFN, 0o070)
self.assertEqual(get_mode(), '----rwx---')
os.chmod(TESTFN, 0o007)
self.assertEqual(get_mode(), '-------rwx')
os.chmod(TESTFN, 0o444)
self.assertEqual(get_mode(), '-r--r--r--')

def test_directory(self):
os.mkdir(TESTFN)
os.chmod(TESTFN, 0o700)
self.assertEqual(get_mode(), 'drwx------')

@unittest.skipUnless(hasattr(os, 'symlink'), 'os.symlink not available')
def test_link(self):
os.symlink(os.getcwd(), TESTFN)
self.assertEqual(get_mode(), 'lrwxrwxrwx')

@unittest.skipUnless(hasattr(os, 'mkfifo'), 'os.mkfifo not available')
def test_fifo(self):
os.mkfifo(TESTFN, 0o700)
self.assertEqual(get_mode(), 'prwx------')


def test_main():
run_unittest(TestFilemode)

if __name__ == '__main__':
test_main()
5 changes: 4 additions & 1 deletion Misc/NEWS
Expand Up @@ -31,10 +31,13 @@ Core and Builtins
Library
-------

- Issue 14807: move undocumented tarfile.filemode() to stat.filemode() and add
doc entry. Add tarfile.filemode alias with deprecation warning.

- Issue #13815: TarFile.extractfile() now returns io.BufferedReader objects.

- Issue #14532: Add a secure_compare() helper to the hmac module, to mitigate
timing attacks. Patch by Jon Oberheide.
timing attacks. Patch by Jon Oberheide.

- Add importlib.util.resolve_name().

Expand Down

0 comments on commit ffa1d0b

Please sign in to comment.