(original) (raw)

changeset: 72039:d1fd0f0f8e68 parent: 72037:e3be2941c834 user: Sandro Tosi sandro.tosi@gmail.com date: Mon Aug 22 23:28:27 2011 +0200 files: Doc/library/os.rst Doc/library/shutil.rst Lib/shutil.py Lib/test/test_shutil.py Misc/NEWS description: #12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names. diff -r e3be2941c834 -r d1fd0f0f8e68 Doc/library/os.rst --- a/Doc/library/os.rst Mon Aug 22 20:31:11 2011 +0300 +++ b/Doc/library/os.rst Mon Aug 22 23:28:27 2011 +0200 @@ -1530,6 +1530,9 @@ 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. + See :func:`shutil.chown` for a higher-level function that accepts names in + addition to numeric ids. + Availability: Unix. diff -r e3be2941c834 -r d1fd0f0f8e68 Doc/library/shutil.rst --- a/Doc/library/shutil.rst Mon Aug 22 20:31:11 2011 +0300 +++ b/Doc/library/shutil.rst Mon Aug 22 23:28:27 2011 +0200 @@ -183,6 +183,20 @@ 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 This exception collects exceptions that are raised during a multi-file diff -r e3be2941c834 -r d1fd0f0f8e68 Lib/shutil.py --- a/Lib/shutil.py Mon Aug 22 20:31:11 2011 +0300 +++ b/Lib/shutil.py Mon Aug 22 23:28:27 2011 +0200 @@ -790,3 +790,34 @@ total, free = nt._getdiskusage(path) used = total - 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) diff -r e3be2941c834 -r d1fd0f0f8e68 Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py Mon Aug 22 20:31:11 2011 +0300 +++ b/Lib/test/test_shutil.py Mon Aug 22 23:28:27 2011 +0200 @@ -712,6 +712,65 @@ self.assertGreaterEqual(usage.total, usage.used) 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): diff -r e3be2941c834 -r d1fd0f0f8e68 Misc/NEWS --- a/Misc/NEWS Mon Aug 22 20:31:11 2011 +0300 +++ b/Misc/NEWS Mon Aug 22 23:28:27 2011 +0200 @@ -1144,6 +1144,9 @@ - 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 ----- /sandro.tosi@gmail.com