https://github.com/python/cpython/commit/9dbd12375561a393eaec4b21ee4ac568a407cdb0
commit: 9dbd12375561a393eaec4b21ee4ac568a407cdb0
branch: main
author: Peter Bierma <[email protected]>
committer: barneygale <[email protected]>
date: 2024-08-21T00:39:24Z
summary:
gh-123084: Turn `shutil.ExecError` into a deprecated alias of `RuntimeError`
(#123125)
files:
A Misc/NEWS.d/next/Library/2024-08-18-08-25-32.gh-issue-123084.rf8izX.rst
M Doc/deprecations/pending-removal-in-3.16.rst
M Lib/shutil.py
M Lib/test/test_shutil.py
diff --git a/Doc/deprecations/pending-removal-in-3.16.rst
b/Doc/deprecations/pending-removal-in-3.16.rst
index 10cb5e424a623b..de134f8e2ee9d3 100644
--- a/Doc/deprecations/pending-removal-in-3.16.rst
+++ b/Doc/deprecations/pending-removal-in-3.16.rst
@@ -8,3 +8,8 @@ Pending Removal in Python 3.16
* :mod:`symtable`:
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
(Contributed by Bénédikt Tran in :gh:`119698`.)
+
+* :mod:`shutil`: Deprecate :class:`!shutil.ExecError`, which hasn't
+ been raised by any :mod:`!shutil` function since Python 3.4. It's
+ now an alias for :exc:`RuntimeError`.
+
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 72b2d834dc387e..6037092a5e09f2 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -56,7 +56,7 @@
__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
"copytree", "move", "rmtree", "Error", "SpecialFileError",
- "ExecError", "make_archive", "get_archive_formats",
+ "make_archive", "get_archive_formats",
"register_archive_format", "unregister_archive_format",
"get_unpack_formats", "register_unpack_format",
"unregister_unpack_format", "unpack_archive",
@@ -74,8 +74,6 @@ class SpecialFileError(OSError):
"""Raised when trying to do a kind of operation (e.g. copying) which is
not supported on a special file (e.g. a named pipe)"""
-class ExecError(OSError):
- """Raised when a command could not be executed"""
class ReadError(OSError):
"""Raised when an archive cannot be read"""
@@ -1582,3 +1580,15 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
if _access_check(name, mode):
return name
return None
+
+def __getattr__(name):
+ if name == "ExecError":
+ import warnings
+ warnings._deprecated(
+ "shutil.ExecError",
+ f"{warnings._DEPRECATED_MSG}; it "
+ "isn't raised by any shutil function.",
+ remove=(3, 16)
+ )
+ return RuntimeError
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index c770be21b41c2b..80e1d73b6b2aab 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -3393,7 +3393,7 @@ def test_module_all_attribute(self):
self.assertTrue(hasattr(shutil, '__all__'))
target_api = ['copyfileobj', 'copyfile', 'copymode', 'copystat',
'copy', 'copy2', 'copytree', 'move', 'rmtree', 'Error',
- 'SpecialFileError', 'ExecError', 'make_archive',
+ 'SpecialFileError', 'make_archive',
'get_archive_formats', 'register_archive_format',
'unregister_archive_format', 'get_unpack_formats',
'register_unpack_format', 'unregister_unpack_format',
@@ -3402,6 +3402,8 @@ def test_module_all_attribute(self):
if hasattr(os, 'statvfs') or os.name == 'nt':
target_api.append('disk_usage')
self.assertEqual(set(shutil.__all__), set(target_api))
+ with self.assertWarns(DeprecationWarning):
+ from shutil import ExecError
if __name__ == '__main__':
diff --git
a/Misc/NEWS.d/next/Library/2024-08-18-08-25-32.gh-issue-123084.rf8izX.rst
b/Misc/NEWS.d/next/Library/2024-08-18-08-25-32.gh-issue-123084.rf8izX.rst
new file mode 100644
index 00000000000000..eb01d66d98aef6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-08-18-08-25-32.gh-issue-123084.rf8izX.rst
@@ -0,0 +1,4 @@
+Deprecate :class:`!shutil.ExecError`, which hasn't been
+raised by any :mod:`shutil` function since Python 3.4. It's
+now an alias for :exc:`RuntimeError`.
+
_______________________________________________
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]