.. availability:: Unix, Windows.
-.. function:: chown(path, user=None, group=None)
+.. function:: chown(path, user=None, group=None, *, dir_fd=None, \
+ follow_symlinks=True)
Change owner *user* and/or *group* of the given *path*.
.. versionadded:: 3.3
+ .. versionchanged:: 3.13
+ Added *dir_fd* and *follow_symlinks* parameters.
+
.. function:: which(cmd, mode=os.F_OK | os.X_OK, path=None)
return _ntuple_diskusage(total, used, free)
-def chown(path, user=None, group=None):
+def chown(path, user=None, group=None, *, dir_fd=None, follow_symlinks=True):
"""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 dir_fd is set, it should be an open file descriptor to the directory to
+ be used as the root of *path* if it is relative.
+
+ If follow_symlinks is set to False and the last element of the path is a
+ symbolic link, chown will modify the link itself and not the file being
+ referenced by the link.
"""
sys.audit('shutil.chown', path, user, group)
if _group is None:
raise LookupError("no such group: {!r}".format(group))
- os.chown(path, _user, _group)
+ os.chown(path, _user, _group, dir_fd=dir_fd,
+ follow_symlinks=follow_symlinks)
def get_terminal_size(fallback=(80, 24)):
"""Get the size of the terminal window.
def test_chown(self):
dirname = self.mkdtemp()
filename = tempfile.mktemp(dir=dirname)
+ linkname = os.path.join(dirname, "chown_link")
write_file(filename, 'testing chown function')
+ os.symlink(filename, linkname)
with self.assertRaises(ValueError):
shutil.chown(filename)
gid = os.getgid()
def check_chown(path, uid=None, gid=None):
- s = os.stat(filename)
+ s = os.stat(path)
if uid is not None:
self.assertEqual(uid, s.st_uid)
if gid is not None:
shutil.chown(dirname, user, group)
check_chown(dirname, uid, gid)
+ dirfd = os.open(dirname, os.O_RDONLY)
+ self.addCleanup(os.close, dirfd)
+ basename = os.path.basename(filename)
+ baselinkname = os.path.basename(linkname)
+ shutil.chown(basename, uid, gid, dir_fd=dirfd)
+ check_chown(filename, uid, gid)
+ shutil.chown(basename, uid, dir_fd=dirfd)
+ check_chown(filename, uid)
+ shutil.chown(basename, group=gid, dir_fd=dirfd)
+ check_chown(filename, gid=gid)
+ shutil.chown(basename, uid, gid, dir_fd=dirfd, follow_symlinks=True)
+ check_chown(filename, uid, gid)
+ shutil.chown(basename, uid, gid, dir_fd=dirfd, follow_symlinks=False)
+ check_chown(filename, uid, gid)
+ shutil.chown(linkname, uid, follow_symlinks=True)
+ check_chown(filename, uid)
+ shutil.chown(baselinkname, group=gid, dir_fd=dirfd, follow_symlinks=False)
+ check_chown(filename, gid=gid)
+ shutil.chown(baselinkname, uid, gid, dir_fd=dirfd, follow_symlinks=True)
+ check_chown(filename, uid, gid)
+
+ with self.assertRaises(TypeError):
+ shutil.chown(filename, uid, dir_fd=dirname)
+
+ with self.assertRaises(FileNotFoundError):
+ shutil.chown('missingfile', uid, gid, dir_fd=dirfd)
+
+ with self.assertRaises(ValueError):
+ shutil.chown(filename, dir_fd=dirfd)
+
@support.requires_subprocess()
class TestWhich(BaseTest, unittest.TestCase):