Skip to content

Commit

Permalink
pythonGH-110109: Fix misleading pathlib._abc.PurePathBase repr (pyt…
Browse files Browse the repository at this point in the history
…hon#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.
  • Loading branch information
barneygale authored and kulikjak committed Jan 22, 2024
1 parent abdec6c commit 01f0e4d
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 15 deletions.
3 changes: 3 additions & 0 deletions Lib/pathlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def __reduce__(self):
# 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)

Expand Down
3 changes: 0 additions & 3 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,6 @@ def as_posix(self):
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."""
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_pathlib/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ def test_pickling_common(self):
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')
Expand Down
13 changes: 1 addition & 12 deletions Lib/test/test_pathlib/test_pathlib_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def test_magic_methods(self):
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__)
Expand Down Expand Up @@ -227,18 +228,6 @@ def test_as_posix_common(self):
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'))
Expand Down

0 comments on commit 01f0e4d

Please sign in to comment.