Skip to content

Commit a93ff6e

Browse files
barneygaleaisk
authored andcommitted
pythonGH-110109: Fix misleading pathlib._abc.PurePathBase repr (python#113376)
`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.
1 parent f956371 commit a93ff6e

File tree

4 files changed

+16
-15
lines changed

4 files changed

+16
-15
lines changed

Lib/pathlib/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def __reduce__(self):
9999
# when pickling related paths.
100100
return (self.__class__, self.parts)
101101

102+
def __repr__(self):
103+
return "{}({!r})".format(self.__class__.__name__, self.as_posix())
104+
102105
def __fspath__(self):
103106
return str(self)
104107

Lib/pathlib/_abc.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,6 @@ def as_posix(self):
282282
slashes."""
283283
return str(self).replace(self.pathmod.sep, '/')
284284

285-
def __repr__(self):
286-
return "{}({!r})".format(self.__class__.__name__, self.as_posix())
287-
288285
@property
289286
def drive(self):
290287
"""The drive prefix (letter or UNC path), if any."""

Lib/test/test_pathlib/test_pathlib.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ def test_pickling_common(self):
6969
self.assertEqual(hash(pp), hash(p))
7070
self.assertEqual(str(pp), str(p))
7171

72+
def test_repr_common(self):
73+
for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
74+
with self.subTest(pathstr=pathstr):
75+
p = self.cls(pathstr)
76+
clsname = p.__class__.__name__
77+
r = repr(p)
78+
# The repr() is in the form ClassName("forward-slashes path").
79+
self.assertTrue(r.startswith(clsname + '('), r)
80+
self.assertTrue(r.endswith(')'), r)
81+
inner = r[len(clsname) + 1 : -1]
82+
self.assertEqual(eval(inner), p.as_posix())
83+
7284
def test_fspath_common(self):
7385
P = self.cls
7486
p = P('a/b')

Lib/test/test_pathlib/test_pathlib_abc.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def test_magic_methods(self):
3131
self.assertFalse(hasattr(P, '__fspath__'))
3232
self.assertFalse(hasattr(P, '__bytes__'))
3333
self.assertIs(P.__reduce__, object.__reduce__)
34+
self.assertIs(P.__repr__, object.__repr__)
3435
self.assertIs(P.__hash__, object.__hash__)
3536
self.assertIs(P.__eq__, object.__eq__)
3637
self.assertIs(P.__lt__, object.__lt__)
@@ -227,18 +228,6 @@ def test_as_posix_common(self):
227228
self.assertEqual(P(pathstr).as_posix(), pathstr)
228229
# Other tests for as_posix() are in test_equivalences().
229230

230-
def test_repr_common(self):
231-
for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
232-
with self.subTest(pathstr=pathstr):
233-
p = self.cls(pathstr)
234-
clsname = p.__class__.__name__
235-
r = repr(p)
236-
# The repr() is in the form ClassName("forward-slashes path").
237-
self.assertTrue(r.startswith(clsname + '('), r)
238-
self.assertTrue(r.endswith(')'), r)
239-
inner = r[len(clsname) + 1 : -1]
240-
self.assertEqual(eval(inner), p.as_posix())
241-
242231
def test_eq_common(self):
243232
P = self.cls
244233
self.assertEqual(P('a/b'), P('a/b'))

0 commit comments

Comments
 (0)