mirror of https://github.com/python/cpython
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
This commit is contained in:
parent
6f2a683a0c
commit
d902a14dd0
|
@ -1530,6 +1530,9 @@ Files and Directories
|
||||||
Change the owner and group id of *path* to the numeric *uid* and *gid*. To leave
|
Change the owner and group id of *path* to the numeric *uid* and *gid*. To leave
|
||||||
one of the ids unchanged, set it to -1.
|
one of the ids unchanged, set it to -1.
|
||||||
|
|
||||||
|
See :func:`shutil.chown` for a higher-level function that accepts names in
|
||||||
|
addition to numeric ids.
|
||||||
|
|
||||||
Availability: Unix.
|
Availability: Unix.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,20 @@ Directory and files operations
|
||||||
|
|
||||||
Availability: Unix, Windows.
|
Availability: Unix, Windows.
|
||||||
|
|
||||||
|
.. function:: chown(path, user=None, group=None)
|
||||||
|
|
||||||
|
Change owner *user* and/or *group* of the given *path*.
|
||||||
|
|
||||||
|
*user* can be a system user name or a uid; the same applies to *group*. At
|
||||||
|
least one argument is required.
|
||||||
|
|
||||||
|
See also :func:`os.chown`, the underlying function.
|
||||||
|
|
||||||
|
Availability: Unix.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. exception:: Error
|
.. exception:: Error
|
||||||
|
|
||||||
This exception collects exceptions that are raised during a multi-file
|
This exception collects exceptions that are raised during a multi-file
|
||||||
|
|
|
@ -790,3 +790,34 @@ elif os.name == 'nt':
|
||||||
total, free = nt._getdiskusage(path)
|
total, free = nt._getdiskusage(path)
|
||||||
used = total - free
|
used = total - free
|
||||||
return _ntuple_diskusage(total, used, free)
|
return _ntuple_diskusage(total, used, free)
|
||||||
|
|
||||||
|
def chown(path, user=None, group=None):
|
||||||
|
"""Change owner user and group of the given path.
|
||||||
|
|
||||||
|
user and group can be the uid/gid or the user/group names, and in that case,
|
||||||
|
they are converted to their respective uid/gid.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if user is None and group is None:
|
||||||
|
raise ValueError("user and/or group must be set")
|
||||||
|
|
||||||
|
_user = user
|
||||||
|
_group = group
|
||||||
|
|
||||||
|
# -1 means don't change it
|
||||||
|
if user is None:
|
||||||
|
_user = -1
|
||||||
|
# user can either be an int (the uid) or a string (the system username)
|
||||||
|
elif isinstance(user, str):
|
||||||
|
_user = _get_uid(user)
|
||||||
|
if _user is None:
|
||||||
|
raise LookupError("no such user: {!r}".format(user))
|
||||||
|
|
||||||
|
if group is None:
|
||||||
|
_group = -1
|
||||||
|
elif not isinstance(group, int):
|
||||||
|
_group = _get_gid(group)
|
||||||
|
if _group is None:
|
||||||
|
raise LookupError("no such group: {!r}".format(group))
|
||||||
|
|
||||||
|
os.chown(path, _user, _group)
|
||||||
|
|
|
@ -712,6 +712,65 @@ class TestShutil(unittest.TestCase):
|
||||||
self.assertGreaterEqual(usage.total, usage.used)
|
self.assertGreaterEqual(usage.total, usage.used)
|
||||||
self.assertGreater(usage.total, usage.free)
|
self.assertGreater(usage.total, usage.free)
|
||||||
|
|
||||||
|
@unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
|
||||||
|
@unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown')
|
||||||
|
def test_chown(self):
|
||||||
|
|
||||||
|
# cleaned-up automatically by TestShutil.tearDown method
|
||||||
|
dirname = self.mkdtemp()
|
||||||
|
filename = tempfile.mktemp(dir=dirname)
|
||||||
|
write_file(filename, 'testing chown function')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
shutil.chown(filename)
|
||||||
|
|
||||||
|
with self.assertRaises(LookupError):
|
||||||
|
shutil.chown(filename, user='non-exising username')
|
||||||
|
|
||||||
|
with self.assertRaises(LookupError):
|
||||||
|
shutil.chown(filename, group='non-exising groupname')
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
shutil.chown(filename, b'spam')
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
shutil.chown(filename, 3.14)
|
||||||
|
|
||||||
|
uid = os.getuid()
|
||||||
|
gid = os.getgid()
|
||||||
|
|
||||||
|
def check_chown(path, uid=None, gid=None):
|
||||||
|
s = os.stat(filename)
|
||||||
|
if uid is not None:
|
||||||
|
self.assertEqual(uid, s.st_uid)
|
||||||
|
if gid is not None:
|
||||||
|
self.assertEqual(gid, s.st_gid)
|
||||||
|
|
||||||
|
shutil.chown(filename, uid, gid)
|
||||||
|
check_chown(filename, uid, gid)
|
||||||
|
shutil.chown(filename, uid)
|
||||||
|
check_chown(filename, uid)
|
||||||
|
shutil.chown(filename, user=uid)
|
||||||
|
check_chown(filename, uid)
|
||||||
|
shutil.chown(filename, group=gid)
|
||||||
|
check_chown(filename, gid)
|
||||||
|
|
||||||
|
shutil.chown(dirname, uid, gid)
|
||||||
|
check_chown(dirname, uid, gid)
|
||||||
|
shutil.chown(dirname, uid)
|
||||||
|
check_chown(dirname, uid)
|
||||||
|
shutil.chown(dirname, user=uid)
|
||||||
|
check_chown(dirname, uid)
|
||||||
|
shutil.chown(dirname, group=gid)
|
||||||
|
check_chown(dirname, gid)
|
||||||
|
|
||||||
|
user = pwd.getpwuid(uid)[0]
|
||||||
|
group = grp.getgrgid(gid)[0]
|
||||||
|
shutil.chown(filename, user, group)
|
||||||
|
check_chown(filename, uid, gid)
|
||||||
|
shutil.chown(dirname, user, group)
|
||||||
|
check_chown(dirname, uid, gid)
|
||||||
|
|
||||||
|
|
||||||
class TestMove(unittest.TestCase):
|
class TestMove(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -1144,6 +1144,9 @@ Library
|
||||||
|
|
||||||
- Issue #9347: Fix formatting for tuples in argparse type= error messages.
|
- Issue #9347: Fix formatting for tuples in argparse type= error messages.
|
||||||
|
|
||||||
|
- Issue #12191: Added shutil.chown() to change user and/or group owner of a
|
||||||
|
given path also specifying their names.
|
||||||
|
|
||||||
Build
|
Build
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue