]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-110109: Fix misleading `pathlib._abc.PurePathBase` repr (#113376)
authorBarney Gale <barney.gale@gmail.com>
Fri, 22 Dec 2023 15:11:16 +0000 (15:11 +0000)
committerGitHub <noreply@github.com>
Fri, 22 Dec 2023 15:11:16 +0000 (15:11 +0000)
`PurePathBase.__repr__()` produces a string like `MyPath('/foo')`. This
repr is incorrect/misleading when a subclass's `__init__()` method is
customized, which I expect to be the very common.

This commit moves the `__repr__()` method to `PurePath`, leaving
`PurePathBase` with the default `object` repr.

No user-facing changes because the `pathlib._abc` module remains private.

Lib/pathlib/__init__.py
Lib/pathlib/_abc.py
Lib/test/test_pathlib/test_pathlib.py
Lib/test/test_pathlib/test_pathlib_abc.py

index b020d2db350da86420ec944376fe7d8614eb01a6..4a8bee601225ed901a56f612423462a203b50f9b 100644 (file)
@@ -99,6 +99,9 @@ class PurePath(_abc.PurePathBase):
         # when pickling related paths.
         return (self.__class__, self.parts)
 
+    def __repr__(self):
+        return "{}({!r})".format(self.__class__.__name__, self.as_posix())
+
     def __fspath__(self):
         return str(self)
 
index 4808d0e61f70380b7d7c16d1fff4b8f37355b689..fc4b6443448a5d30b5cedaed5ab54672a2a649e1 100644 (file)
@@ -282,9 +282,6 @@ class PurePathBase:
         slashes."""
         return str(self).replace(self.pathmod.sep, '/')
 
-    def __repr__(self):
-        return "{}({!r})".format(self.__class__.__name__, self.as_posix())
-
     @property
     def drive(self):
         """The drive prefix (letter or UNC path), if any."""
index 00cfdd37e568a657ce6f0b66d30287b8af4383c3..d55ccd9e255fcc1e3b9cb7d7da10a5ba4be47d96 100644 (file)
@@ -69,6 +69,18 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
             self.assertEqual(hash(pp), hash(p))
             self.assertEqual(str(pp), str(p))
 
+    def test_repr_common(self):
+        for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
+            with self.subTest(pathstr=pathstr):
+                p = self.cls(pathstr)
+                clsname = p.__class__.__name__
+                r = repr(p)
+                # The repr() is in the form ClassName("forward-slashes path").
+                self.assertTrue(r.startswith(clsname + '('), r)
+                self.assertTrue(r.endswith(')'), r)
+                inner = r[len(clsname) + 1 : -1]
+                self.assertEqual(eval(inner), p.as_posix())
+
     def test_fspath_common(self):
         P = self.cls
         p = P('a/b')
index a272973d9c1d61a1a7d67614f1866f28c4707a40..6748def91a1e6e8abec0b6c54163877c1a74d244 100644 (file)
@@ -31,6 +31,7 @@ class PurePathBaseTest(unittest.TestCase):
         self.assertFalse(hasattr(P, '__fspath__'))
         self.assertFalse(hasattr(P, '__bytes__'))
         self.assertIs(P.__reduce__, object.__reduce__)
+        self.assertIs(P.__repr__, object.__repr__)
         self.assertIs(P.__hash__, object.__hash__)
         self.assertIs(P.__eq__, object.__eq__)
         self.assertIs(P.__lt__, object.__lt__)
@@ -227,18 +228,6 @@ class DummyPurePathTest(unittest.TestCase):
             self.assertEqual(P(pathstr).as_posix(), pathstr)
         # Other tests for as_posix() are in test_equivalences().
 
-    def test_repr_common(self):
-        for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
-            with self.subTest(pathstr=pathstr):
-                p = self.cls(pathstr)
-                clsname = p.__class__.__name__
-                r = repr(p)
-                # The repr() is in the form ClassName("forward-slashes path").
-                self.assertTrue(r.startswith(clsname + '('), r)
-                self.assertTrue(r.endswith(')'), r)
-                inner = r[len(clsname) + 1 : -1]
-                self.assertEqual(eval(inner), p.as_posix())
-
     def test_eq_common(self):
         P = self.cls
         self.assertEqual(P('a/b'), P('a/b'))