https://github.com/python/cpython/commit/8974a63f5ee0557e14db97eb1284a5dd8c49f8f7
commit: 8974a63f5ee0557e14db97eb1284a5dd8c49f8f7
branch: main
author: tahia <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-04-22T18:23:36Z
summary:

bpo-18108: Adding dir_fd and follow_symlinks keyword args to shutil.chown 
(GH-15811)

* Adding dir_fd and follow_symlinks keyword args to shutil.chown
* Extending test_shutil.TestShutil.test_chown to include new kwargs
* Updating shutil.chown documentation

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Berker Peksag <[email protected]>
Co-authored-by: Zachary Ware <[email protected]>

files:
A Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst
M Doc/library/shutil.rst
M Doc/whatsnew/3.13.rst
M Lib/shutil.py
M Lib/test/test_shutil.py

diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index 4f07b9f6040d24..8e5828c789e4e2 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,9 @@ 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/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 5be562030b507b..c04dc924d1efa5 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -594,6 +594,10 @@ os.path
   exactly one (back)slash to be absolute.
   (Contributed by Barney Gale and Jon Foster in :gh:`44626`.)
 
+* Add support of *dir_fd* and *follow_symlinks* keyword arguments in
+  :func:`shutil.chown`.
+  (Contributed by Berker Peksag and Tahia K in :gh:`62308`)
+
 pathlib
 -------
 
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 94b09509008b0b..910d6b6c63ac08 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -1442,11 +1442,18 @@ 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 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)
 
@@ -1472,7 +1479,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 3aa0ec6952339b..5b0aac67a0adeb 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -2212,7 +2212,9 @@ def test_disk_usage(self):
     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)
@@ -2233,7 +2235,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:
@@ -2269,6 +2271,36 @@ def check_chown(path, uid=None, gid=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):
diff --git a/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst 
b/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst
new file mode 100644
index 00000000000000..70ff76a0c920be
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst
@@ -0,0 +1 @@
+:func:`shutil.chown` now supports *dir_fd* and *follow_symlinks* keyword 
arguments.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to