Skip to content

Commit 9dbd123

Browse files
gh-123084: Turn shutil.ExecError into a deprecated alias of RuntimeError (#123125)
1 parent f88c14d commit 9dbd123

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

Doc/deprecations/pending-removal-in-3.16.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ Pending Removal in Python 3.16
88
* :mod:`symtable`:
99
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
1010
(Contributed by Bénédikt Tran in :gh:`119698`.)
11+
12+
* :mod:`shutil`: Deprecate :class:`!shutil.ExecError`, which hasn't
13+
been raised by any :mod:`!shutil` function since Python 3.4. It's
14+
now an alias for :exc:`RuntimeError`.
15+

Lib/shutil.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
5858
"copytree", "move", "rmtree", "Error", "SpecialFileError",
59-
"ExecError", "make_archive", "get_archive_formats",
59+
"make_archive", "get_archive_formats",
6060
"register_archive_format", "unregister_archive_format",
6161
"get_unpack_formats", "register_unpack_format",
6262
"unregister_unpack_format", "unpack_archive",
@@ -74,8 +74,6 @@ class SpecialFileError(OSError):
7474
"""Raised when trying to do a kind of operation (e.g. copying) which is
7575
not supported on a special file (e.g. a named pipe)"""
7676

77-
class ExecError(OSError):
78-
"""Raised when a command could not be executed"""
7977

8078
class ReadError(OSError):
8179
"""Raised when an archive cannot be read"""
@@ -1582,3 +1580,15 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
15821580
if _access_check(name, mode):
15831581
return name
15841582
return None
1583+
1584+
def __getattr__(name):
1585+
if name == "ExecError":
1586+
import warnings
1587+
warnings._deprecated(
1588+
"shutil.ExecError",
1589+
f"{warnings._DEPRECATED_MSG}; it "
1590+
"isn't raised by any shutil function.",
1591+
remove=(3, 16)
1592+
)
1593+
return RuntimeError
1594+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

Lib/test/test_shutil.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3393,7 +3393,7 @@ def test_module_all_attribute(self):
33933393
self.assertTrue(hasattr(shutil, '__all__'))
33943394
target_api = ['copyfileobj', 'copyfile', 'copymode', 'copystat',
33953395
'copy', 'copy2', 'copytree', 'move', 'rmtree', 'Error',
3396-
'SpecialFileError', 'ExecError', 'make_archive',
3396+
'SpecialFileError', 'make_archive',
33973397
'get_archive_formats', 'register_archive_format',
33983398
'unregister_archive_format', 'get_unpack_formats',
33993399
'register_unpack_format', 'unregister_unpack_format',
@@ -3402,6 +3402,8 @@ def test_module_all_attribute(self):
34023402
if hasattr(os, 'statvfs') or os.name == 'nt':
34033403
target_api.append('disk_usage')
34043404
self.assertEqual(set(shutil.__all__), set(target_api))
3405+
with self.assertWarns(DeprecationWarning):
3406+
from shutil import ExecError
34053407

34063408

34073409
if __name__ == '__main__':
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Deprecate :class:`!shutil.ExecError`, which hasn't been
2+
raised by any :mod:`shutil` function since Python 3.4. It's
3+
now an alias for :exc:`RuntimeError`.
4+

0 commit comments

Comments
 (0)