Skip to content

Commit 8611e7b

Browse files
GH-103525: Improve exception message from pathlib.PurePath() (GH-103526)
Check that arguments are strings before calling `os.path.join()`. Also improve performance of `PurePath(PurePath(...))` while we're in the area: we now use the *unnormalized* string path of such arguments. Co-authored-by: Terry Jan Reedy <[email protected]>
1 parent d81ca7e commit 8611e7b

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

Lib/pathlib.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -300,18 +300,27 @@ def __reduce__(self):
300300
return (self.__class__, self.parts)
301301

302302
def __init__(self, *args):
303-
if not args:
304-
path = ''
305-
elif len(args) == 1:
306-
path = os.fspath(args[0])
303+
paths = []
304+
for arg in args:
305+
if isinstance(arg, PurePath):
306+
path = arg._raw_path
307+
else:
308+
try:
309+
path = os.fspath(arg)
310+
except TypeError:
311+
path = arg
312+
if not isinstance(path, str):
313+
raise TypeError(
314+
"argument should be a str or an os.PathLike "
315+
"object where __fspath__ returns a str, "
316+
f"not {type(path).__name__!r}")
317+
paths.append(path)
318+
if len(paths) == 0:
319+
self._raw_path = ''
320+
elif len(paths) == 1:
321+
self._raw_path = paths[0]
307322
else:
308-
path = self._flavour.join(*args)
309-
if not isinstance(path, str):
310-
raise TypeError(
311-
"argument should be a str or an os.PathLike "
312-
"object where __fspath__ returns a str, "
313-
f"not {type(path).__name__!r}")
314-
self._raw_path = path
323+
self._raw_path = self._flavour.join(*paths)
315324

316325
@classmethod
317326
def _parse_path(cls, path):
@@ -620,7 +629,7 @@ def joinpath(self, *args):
620629
paths) or a totally different path (if one of the arguments is
621630
anchored).
622631
"""
623-
return self.__class__(self._raw_path, *args)
632+
return self.__class__(self, *args)
624633

625634
def __truediv__(self, key):
626635
try:
@@ -630,7 +639,7 @@ def __truediv__(self, key):
630639

631640
def __rtruediv__(self, key):
632641
try:
633-
return type(self)(key, self._raw_path)
642+
return type(self)(key, self)
634643
except TypeError:
635644
return NotImplemented
636645

@@ -864,7 +873,7 @@ def absolute(self):
864873
cwd = self._flavour.abspath(self.drive)
865874
else:
866875
cwd = os.getcwd()
867-
return type(self)(cwd, self._raw_path)
876+
return type(self)(cwd, self)
868877

869878
def resolve(self, strict=False):
870879
"""

Lib/test/test_pathlib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ def test_bytes(self):
8181
r"where __fspath__ returns a str, not 'bytes'")
8282
with self.assertRaisesRegex(TypeError, message):
8383
P(b'a')
84-
with self.assertRaises(TypeError):
84+
with self.assertRaisesRegex(TypeError, message):
8585
P(b'a', 'b')
86-
with self.assertRaises(TypeError):
86+
with self.assertRaisesRegex(TypeError, message):
8787
P('a', b'b')
8888
with self.assertRaises(TypeError):
8989
P('a').joinpath(b'b')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix misleading exception message when mixed ``str`` and ``bytes`` arguments
2+
are supplied to :class:`pathlib.PurePath` and :class:`~pathlib.Path`.

0 commit comments

Comments
 (0)