]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-102828: emit deprecation warning for onerror arg to shutil.rmtree (#102850)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Tue, 21 Mar 2023 11:08:46 +0000 (11:08 +0000)
committerGitHub <noreply@github.com>
Tue, 21 Mar 2023 11:08:46 +0000 (11:08 +0000)
Doc/whatsnew/3.12.rst
Lib/shutil.py
Lib/tempfile.py
Lib/test/test_shutil.py

index af52c7cb670c61b0029a3a9ea68de215e9a59d88..b7c956d7f7845614194abb107b8b46028a0c4dba 100644 (file)
@@ -339,7 +339,8 @@ shutil
 
 * :func:`shutil.rmtree` now accepts a new argument *onexc* which is an
   error handler like *onerror* but which expects an exception instance
-  rather than a *(typ, val, tb)* triplet. *onerror* is deprecated.
+  rather than a *(typ, val, tb)* triplet. *onerror* is deprecated and
+  will be removed in Python 3.14.
   (Contributed by Irit Katriel in :gh:`102828`.)
 
 
@@ -503,8 +504,8 @@ Deprecated
   fields are deprecated. Use :data:`sys.last_exc` instead.
   (Contributed by Irit Katriel in :gh:`102778`.)
 
-* The *onerror* argument of :func:`shutil.rmtree` is deprecated. Use *onexc*
-  instead. (Contributed by Irit Katriel in :gh:`102828`.)
+* The *onerror* argument of :func:`shutil.rmtree` is deprecated as will be removed
+  in Python 3.14. Use *onexc* instead. (Contributed by Irit Katriel in :gh:`102828`.)
 
 
 Pending Removal in Python 3.13
@@ -586,6 +587,9 @@ Pending Removal in Python 3.14
   functions that have been deprecated since Python 2 but only gained a
   proper :exc:`DeprecationWarning` in 3.12. Remove them in 3.14.
 
+* The *onerror* argument of :func:`shutil.rmtree` is deprecated in 3.12,
+  and will be removed in 3.14.
+
 Pending Removal in Future Versions
 ----------------------------------
 
index 89a7ac72d98357e97bf4e9e2ef674627bfeadffd..b0576407e02ffbd478056e23d21d0cc3eebb3d74 100644 (file)
@@ -10,6 +10,7 @@ import stat
 import fnmatch
 import collections
 import errno
+import warnings
 
 try:
     import zlib
@@ -692,6 +693,11 @@ def rmtree(path, ignore_errors=False, onerror=None, *, onexc=None, dir_fd=None):
     onerror is deprecated and only remains for backwards compatibility.
     If both onerror and onexc are set, onerror is ignored and onexc is used.
     """
+
+    if onerror is not None:
+        warnings.warn("onerror argument is deprecated, use onexc instead",
+                      DeprecationWarning)
+
     sys.audit("shutil.rmtree", path, dir_fd)
     if ignore_errors:
         def onexc(*args):
index bb18d60db0d9198679fbdb5e0379af7f85192a7f..cf06092f826bcc352436eedb3da4d43e2337dc7b 100644 (file)
@@ -864,8 +864,8 @@ class TemporaryDirectory:
 
     @classmethod
     def _rmtree(cls, name, ignore_errors=False):
-        def onerror(func, path, exc_info):
-            if issubclass(exc_info[0], PermissionError):
+        def onexc(func, path, exc):
+            if isinstance(exc, PermissionError):
                 def resetperms(path):
                     try:
                         _os.chflags(path, 0)
@@ -885,13 +885,13 @@ class TemporaryDirectory:
                         cls._rmtree(path, ignore_errors=ignore_errors)
                 except FileNotFoundError:
                     pass
-            elif issubclass(exc_info[0], FileNotFoundError):
+            elif isinstance(exc, FileNotFoundError):
                 pass
             else:
                 if not ignore_errors:
                     raise
 
-        _shutil.rmtree(name, onerror=onerror)
+        _shutil.rmtree(name, onexc=onexc)
 
     @classmethod
     def _cleanup(cls, name, warn_message, ignore_errors=False):
index 89d65af3bc5b2b1c8a458e909f4c15fe4ad52408..1c0589ced9ea89164916569f14d395994b3b6f02 100644 (file)
@@ -23,6 +23,7 @@ from shutil import (make_archive,
                     unregister_unpack_format, get_unpack_formats,
                     SameFileError, _GiveupOnFastCopy)
 import tarfile
+import warnings
 import zipfile
 try:
     import posix
@@ -207,7 +208,8 @@ class TestRmTree(BaseTest, unittest.TestCase):
         errors = []
         def onerror(*args):
             errors.append(args)
-        shutil.rmtree(link, onerror=onerror)
+        with self.assertWarns(DeprecationWarning):
+            shutil.rmtree(link, onerror=onerror)
         self.assertEqual(len(errors), 1)
         self.assertIs(errors[0][0], os.path.islink)
         self.assertEqual(errors[0][1], link)
@@ -268,7 +270,8 @@ class TestRmTree(BaseTest, unittest.TestCase):
         errors = []
         def onerror(*args):
             errors.append(args)
-        shutil.rmtree(link, onerror=onerror)
+        with self.assertWarns(DeprecationWarning):
+            shutil.rmtree(link, onerror=onerror)
         self.assertEqual(len(errors), 1)
         self.assertIs(errors[0][0], os.path.islink)
         self.assertEqual(errors[0][1], link)
@@ -337,7 +340,8 @@ class TestRmTree(BaseTest, unittest.TestCase):
         errors = []
         def onerror(*args):
             errors.append(args)
-        shutil.rmtree(filename, onerror=onerror)
+        with self.assertWarns(DeprecationWarning):
+            shutil.rmtree(filename, onerror=onerror)
         self.assertEqual(len(errors), 2)
         self.assertIs(errors[0][0], os.scandir)
         self.assertEqual(errors[0][1], filename)
@@ -406,7 +410,8 @@ class TestRmTree(BaseTest, unittest.TestCase):
         self.addCleanup(os.chmod, self.child_file_path, old_child_file_mode)
         self.addCleanup(os.chmod, self.child_dir_path, old_child_dir_mode)
 
-        shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror)
+        with self.assertWarns(DeprecationWarning):
+            shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror)
         # Test whether onerror has actually been called.
         self.assertEqual(self.errorState, 3,
                          "Expected call to onerror function did not happen.")
@@ -532,7 +537,8 @@ class TestRmTree(BaseTest, unittest.TestCase):
         self.addCleanup(os.chmod, self.child_file_path, old_child_file_mode)
         self.addCleanup(os.chmod, self.child_dir_path, old_child_dir_mode)
 
-        shutil.rmtree(TESTFN, onerror=onerror, onexc=onexc)
+        with self.assertWarns(DeprecationWarning):
+            shutil.rmtree(TESTFN, onerror=onerror, onexc=onexc)
         self.assertTrue(onexc_called)
         self.assertFalse(onerror_called)