* :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`.)
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
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
----------------------------------
@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)
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):
unregister_unpack_format, get_unpack_formats,
SameFileError, _GiveupOnFastCopy)
import tarfile
+import warnings
import zipfile
try:
import posix
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)
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)
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)
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.")
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)