https://github.com/python/cpython/commit/7146f1894638130940944d4808dae7d144d46227
commit: 7146f1894638130940944d4808dae7d144d46227
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
date: 2024-12-12T17:39:24Z
summary:

GH-127807: pathlib ABCs: remove `PathBase._unsupported_msg()` (#127855)

This method helped us customise the `UnsupportedOperation` message
depending on the type. But we're aiming to make `PathBase` a proper ABC
soon, so `NotImplementedError` is the right exception to raise there.

files:
M Lib/pathlib/__init__.py
M Lib/pathlib/_abc.py
M Lib/pathlib/_local.py
M Lib/test/test_pathlib/test_pathlib.py
M Lib/test/test_pathlib/test_pathlib_abc.py

diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py
index 5da3acd31997e5..ec1bac9ef49350 100644
--- a/Lib/pathlib/__init__.py
+++ b/Lib/pathlib/__init__.py
@@ -5,8 +5,6 @@
 operating systems.
 """
 
-from pathlib._abc import *
 from pathlib._local import *
 
-__all__ = (_abc.__all__ +
-           _local.__all__)
+__all__ = _local.__all__
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py
index b10aba85132332..b4560295300c28 100644
--- a/Lib/pathlib/_abc.py
+++ b/Lib/pathlib/_abc.py
@@ -20,15 +20,6 @@
 from pathlib._os import copyfileobj
 
 
-__all__ = ["UnsupportedOperation"]
-
-
-class UnsupportedOperation(NotImplementedError):
-    """An exception that is raised when an unsupported operation is attempted.
-    """
-    pass
-
-
 @functools.cache
 def _is_case_sensitive(parser):
     return parser.normcase('Aa') == 'Aa'
@@ -353,8 +344,8 @@ class PathBase(PurePathBase):
 
     This class provides dummy implementations for many methods that derived
     classes can override selectively; the default implementations raise
-    UnsupportedOperation. The most basic methods, such as stat() and open(),
-    directly raise UnsupportedOperation; these basic methods are called by
+    NotImplementedError. The most basic methods, such as stat() and open(),
+    directly raise NotImplementedError; these basic methods are called by
     other methods such as is_dir() and read_text().
 
     The Path class derives this class to implement local filesystem paths.
@@ -363,16 +354,12 @@ class PathBase(PurePathBase):
     """
     __slots__ = ()
 
-    @classmethod
-    def _unsupported_msg(cls, attribute):
-        return f"{cls.__name__}.{attribute} is unsupported"
-
     def stat(self, *, follow_symlinks=True):
         """
         Return the result of the stat() system call on this path, like
         os.stat() does.
         """
-        raise UnsupportedOperation(self._unsupported_msg('stat()'))
+        raise NotImplementedError
 
     # Convenience functions for querying the stat results
 
@@ -448,7 +435,7 @@ def open(self, mode='r', buffering=-1, encoding=None,
         Open the file pointed to by this path and return a file object, as
         the built-in open() function does.
         """
-        raise UnsupportedOperation(self._unsupported_msg('open()'))
+        raise NotImplementedError
 
     def read_bytes(self):
         """
@@ -498,7 +485,7 @@ def iterdir(self):
         The children are yielded in arbitrary order, and the
         special entries '.' and '..' are not included.
         """
-        raise UnsupportedOperation(self._unsupported_msg('iterdir()'))
+        raise NotImplementedError
 
     def _glob_selector(self, parts, case_sensitive, recurse_symlinks):
         if case_sensitive is None:
@@ -575,14 +562,14 @@ def readlink(self):
         """
         Return the path to which the symbolic link points.
         """
-        raise UnsupportedOperation(self._unsupported_msg('readlink()'))
+        raise NotImplementedError
 
     def symlink_to(self, target, target_is_directory=False):
         """
         Make this path a symlink pointing to the target path.
         Note the order of arguments (link, target) is the reverse of 
os.symlink.
         """
-        raise UnsupportedOperation(self._unsupported_msg('symlink_to()'))
+        raise NotImplementedError
 
     def _symlink_to_target_of(self, link):
         """
@@ -595,7 +582,7 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False):
         """
         Create a new directory at this given path.
         """
-        raise UnsupportedOperation(self._unsupported_msg('mkdir()'))
+        raise NotImplementedError
 
     # Metadata keys supported by this path type.
     _readable_metadata = _writable_metadata = frozenset()
@@ -604,13 +591,13 @@ def _read_metadata(self, keys=None, *, 
follow_symlinks=True):
         """
         Returns path metadata as a dict with string keys.
         """
-        raise UnsupportedOperation(self._unsupported_msg('_read_metadata()'))
+        raise NotImplementedError
 
     def _write_metadata(self, metadata, *, follow_symlinks=True):
         """
         Sets path metadata from the given dict with string keys.
         """
-        raise UnsupportedOperation(self._unsupported_msg('_write_metadata()'))
+        raise NotImplementedError
 
     def _copy_metadata(self, target, *, follow_symlinks=True):
         """
@@ -687,7 +674,7 @@ def _delete(self):
         """
         Delete this file or directory (including all sub-directories).
         """
-        raise UnsupportedOperation(self._unsupported_msg('_delete()'))
+        raise NotImplementedError
 
     def move(self, target):
         """
diff --git a/Lib/pathlib/_local.py b/Lib/pathlib/_local.py
index 0dfe9d2390ecff..b933dd512eeb28 100644
--- a/Lib/pathlib/_local.py
+++ b/Lib/pathlib/_local.py
@@ -21,15 +21,22 @@
 
 from pathlib._os import (copyfile, file_metadata_keys, read_file_metadata,
                          write_file_metadata)
-from pathlib._abc import UnsupportedOperation, PurePathBase, PathBase
+from pathlib._abc import PurePathBase, PathBase
 
 
 __all__ = [
+    "UnsupportedOperation",
     "PurePath", "PurePosixPath", "PureWindowsPath",
     "Path", "PosixPath", "WindowsPath",
     ]
 
 
+class UnsupportedOperation(NotImplementedError):
+    """An exception that is raised when an unsupported operation is attempted.
+    """
+    pass
+
+
 class _PathParents(Sequence):
     """This object provides sequence-like access to the logical ancestors
     of a path.  Don't try to construct it yourself."""
@@ -527,10 +534,6 @@ class Path(PathBase, PurePath):
     """
     __slots__ = ()
 
-    @classmethod
-    def _unsupported_msg(cls, attribute):
-        return f"{cls.__name__}.{attribute} is unsupported on this system"
-
     def __new__(cls, *args, **kwargs):
         if cls is Path:
             cls = WindowsPath if os.name == 'nt' else PosixPath
@@ -817,7 +820,8 @@ def owner(self, *, follow_symlinks=True):
             """
             Return the login name of the file owner.
             """
-            raise UnsupportedOperation(self._unsupported_msg('owner()'))
+            f = f"{type(self).__name__}.owner()"
+            raise UnsupportedOperation(f"{f} is unsupported on this system")
 
     if grp:
         def group(self, *, follow_symlinks=True):
@@ -831,7 +835,8 @@ def group(self, *, follow_symlinks=True):
             """
             Return the group name of the file gid.
             """
-            raise UnsupportedOperation(self._unsupported_msg('group()'))
+            f = f"{type(self).__name__}.group()"
+            raise UnsupportedOperation(f"{f} is unsupported on this system")
 
     if hasattr(os, "readlink"):
         def readlink(self):
@@ -839,6 +844,13 @@ def readlink(self):
             Return the path to which the symbolic link points.
             """
             return self.with_segments(os.readlink(self))
+    else:
+        def readlink(self):
+            """
+            Return the path to which the symbolic link points.
+            """
+            f = f"{type(self).__name__}.readlink()"
+            raise UnsupportedOperation(f"{f} is unsupported on this system")
 
     def touch(self, mode=0o666, exist_ok=True):
         """
@@ -989,6 +1001,14 @@ def symlink_to(self, target, target_is_directory=False):
             Note the order of arguments (link, target) is the reverse of 
os.symlink.
             """
             os.symlink(target, self, target_is_directory)
+    else:
+        def symlink_to(self, target, target_is_directory=False):
+            """
+            Make this path a symlink pointing to the target path.
+            Note the order of arguments (link, target) is the reverse of 
os.symlink.
+            """
+            f = f"{type(self).__name__}.symlink_to()"
+            raise UnsupportedOperation(f"{f} is unsupported on this system")
 
     if os.name == 'nt':
         def _symlink_to_target_of(self, link):
@@ -1013,7 +1033,8 @@ def hardlink_to(self, target):
 
             Note the order of arguments (self, target) is the reverse of 
os.link's.
             """
-            raise UnsupportedOperation(self._unsupported_msg('hardlink_to()'))
+            f = f"{type(self).__name__}.hardlink_to()"
+            raise UnsupportedOperation(f"{f} is unsupported on this system")
 
     def expanduser(self):
         """ Return a new path with expanded ~ and ~user constructs
diff --git a/Lib/test/test_pathlib/test_pathlib.py 
b/Lib/test/test_pathlib/test_pathlib.py
index b57ef420bfcbcd..68bff2cf0d511e 100644
--- a/Lib/test/test_pathlib/test_pathlib.py
+++ b/Lib/test/test_pathlib/test_pathlib.py
@@ -63,6 +63,14 @@ def needs_symlinks(fn):
     _tests_needing_symlinks.add(fn.__name__)
     return fn
 
+
+
+class UnsupportedOperationTest(unittest.TestCase):
+    def test_is_notimplemented(self):
+        self.assertTrue(issubclass(pathlib.UnsupportedOperation, 
NotImplementedError))
+        self.assertTrue(isinstance(pathlib.UnsupportedOperation(), 
NotImplementedError))
+
+
 #
 # Tests for the pure classes.
 #
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py 
b/Lib/test/test_pathlib/test_pathlib_abc.py
index d770b87dc6a104..e230dd188799a5 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -5,7 +5,7 @@
 import stat
 import unittest
 
-from pathlib._abc import UnsupportedOperation, PurePathBase, PathBase
+from pathlib._abc import PurePathBase, PathBase
 from pathlib._types import Parser
 import posixpath
 
@@ -27,11 +27,6 @@ def needs_windows(fn):
     return fn
 
 
-class UnsupportedOperationTest(unittest.TestCase):
-    def test_is_notimplemented(self):
-        self.assertTrue(issubclass(UnsupportedOperation, NotImplementedError))
-        self.assertTrue(isinstance(UnsupportedOperation(), 
NotImplementedError))
-
 #
 # Tests for the pure classes.
 #
@@ -1294,10 +1289,9 @@ def test_is_absolute_windows(self):
 class PathBaseTest(PurePathBaseTest):
     cls = PathBase
 
-    def test_unsupported_operation(self):
-        P = self.cls
+    def test_not_implemented_error(self):
         p = self.cls('')
-        e = UnsupportedOperation
+        e = NotImplementedError
         self.assertRaises(e, p.stat)
         self.assertRaises(e, p.exists)
         self.assertRaises(e, p.is_dir)

_______________________________________________
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]

Reply via email to