diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 4f07b9f6040d24..740f49cc6329e3 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -421,7 +421,8 @@ Directory and files operations .. 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*. @@ -436,6 +437,8 @@ Directory and files operations .. 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) diff --git a/Lib/shutil.py b/Lib/shutil.py index 94b09509008b0b..3bb7822ce4e95b 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1442,11 +1442,19 @@ def disk_usage(path): 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 not None, it should be a file descriptor open to a directory; + path will then be relative to that directory. + dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + + If follow_symlinks is not set and path is a symbolic link, the owner of the + symlink will be changed instead of the file it points to. """ sys.audit('shutil.chown', path, user, group) @@ -1472,7 +1480,8 @@ def chown(path, user=None, group=None): 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. diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 60e88d57b2b23d..79f9f7efb1b24a 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2107,6 +2107,7 @@ def test_disk_usage(self): def test_chown(self): dirname = self.mkdtemp() filename = tempfile.mktemp(dir=dirname) + dirfd = os.open(dirname, os.O_RDONLY) write_file(filename, 'testing chown function') with self.assertRaises(ValueError): @@ -2128,7 +2129,7 @@ def test_chown(self): 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: @@ -2142,6 +2143,17 @@ def check_chown(path, uid=None, gid=None): check_chown(filename, uid) shutil.chown(filename, group=gid) check_chown(filename, gid=gid) + shutil.chown(os.path.basename(filename), uid, gid, dir_fd=dirfd) + check_chown(filename, uid, gid) + shutil.chown(os.path.basename(filename), user=uid, dir_fd=dirfd) + check_chown(filename, uid) + shutil.chown(os.path.basename(filename), group=gid, dir_fd=dirfd) + check_chown(filename, gid=gid) + + with self.assertRaises(FileNotFoundError): + shutil.chown('invalid-file', user=uid, dir_fd=dirfd) + shutil.chown('invalid-file', group=gid, dir_fd=dirfd) + shutil.chown('invalid-file', user=uid, group=gid, dir_fd=dirfd) shutil.chown(dirname, uid, gid) check_chown(dirname, uid, gid) @@ -2149,8 +2161,14 @@ def check_chown(path, uid=None, gid=None): check_chown(dirname, uid) shutil.chown(dirname, user=uid) check_chown(dirname, uid) + shutil.chown(dirname, user=uid, follow_symlinks=True) + check_chown(dirname, uid) shutil.chown(dirname, group=gid) check_chown(dirname, gid=gid) + shutil.chown(dirname, group=gid, follow_symlinks=True) + check_chown(dirname, gid=gid) + shutil.chown(dirname, user=uid, group=gid, follow_symlinks=True) + check_chown(dirname, uid=uid, gid=gid) try: user = pwd.getpwuid(uid)[0] diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-21-18-11-23.gh-issue-62308.-TEHIG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-21-18-11-23.gh-issue-62308.-TEHIG.rst new file mode 100644 index 00000000000000..9c4e03c06c4eea --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-21-18-11-23.gh-issue-62308.-TEHIG.rst @@ -0,0 +1 @@ +Added the *dir_fd* & *follow_symlinks* parameters to :func:`shutil.chown`.