]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-123084: Turn `shutil.ExecError` into a deprecated alias of `RuntimeError` (#123125)
authorPeter Bierma <zintensitydev@gmail.com>
Wed, 21 Aug 2024 00:39:24 +0000 (20:39 -0400)
committerGitHub <noreply@github.com>
Wed, 21 Aug 2024 00:39:24 +0000 (00:39 +0000)
Doc/deprecations/pending-removal-in-3.16.rst
Lib/shutil.py
Lib/test/test_shutil.py
Misc/NEWS.d/next/Library/2024-08-18-08-25-32.gh-issue-123084.rf8izX.rst [new file with mode: 0644]

index 10cb5e424a623b4f1088346f7eb93c99a89e2126..de134f8e2ee9d36e1d27586dd3549b060e848967 100644 (file)
@@ -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`.
+
index 72b2d834dc387e34d79806f599f388fc363ad151..6037092a5e09f29657ecbc4e7844681866a029b9 100644 (file)
@@ -56,7 +56,7 @@ _WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
 
 __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}")
index c770be21b41c2ba9d358e4308335139a7551bf80..80e1d73b6b2aab4714122ab09bb313c5fce816e9 100644 (file)
@@ -3393,7 +3393,7 @@ class PublicAPITests(unittest.TestCase):
         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 @@ class PublicAPITests(unittest.TestCase):
         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 (file)
index 0000000..eb01d66
--- /dev/null
@@ -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`.
+