From 6c1131e8dff2c701414f6d776a0548781367e3cd Mon Sep 17 00:00:00 2001 From: barneygale Date: Thu, 13 Apr 2023 19:40:50 +0100 Subject: [PATCH 1/2] GH-103525: Improve exception message from `pathlib.PurePath()` 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. --- Lib/pathlib.py | 34 +++++++++++-------- Lib/test/test_pathlib.py | 4 +-- ...-04-13-19-43-15.gh-issue-103525.uY4VYg.rst | 2 ++ 3 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 4ae1fae6f4b358..599df1953c1377 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -300,18 +300,24 @@ def __reduce__(self): return (self.__class__, self.parts) def __init__(self, *args): - if not args: - path = '' - elif len(args) == 1: - path = os.fspath(args[0]) + paths = [] + for arg in args: + if isinstance(arg, PurePath): + path = arg._raw_path + else: + path = os.fspath(arg) + if not isinstance(path, str): + raise TypeError( + "argument should be a str or an os.PathLike " + "object where __fspath__ returns a str, " + f"not {type(path).__name__!r}") + paths.append(path) + if len(paths) == 0: + self._raw_path = '' + elif len(paths) == 1: + self._raw_path = paths[0] else: - path = self._flavour.join(*args) - if not isinstance(path, str): - raise TypeError( - "argument should be a str or an os.PathLike " - "object where __fspath__ returns a str, " - f"not {type(path).__name__!r}") - self._raw_path = path + self._raw_path = self._flavour.join(*paths) @classmethod def _parse_path(cls, path): @@ -615,7 +621,7 @@ def joinpath(self, *args): paths) or a totally different path (if one of the arguments is anchored). """ - return self.__class__(self._raw_path, *args) + return self.__class__(self, *args) def __truediv__(self, key): try: @@ -625,7 +631,7 @@ def __truediv__(self, key): def __rtruediv__(self, key): try: - return type(self)(key, self._raw_path) + return type(self)(key, self) except TypeError: return NotImplemented @@ -859,7 +865,7 @@ def absolute(self): cwd = self._flavour.abspath(self.drive) else: cwd = os.getcwd() - return type(self)(cwd, self._raw_path) + return type(self)(cwd, self) def resolve(self, strict=False): """ diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 3c6da94d094610..85a7438cb27629 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -81,9 +81,9 @@ def test_bytes(self): r"where __fspath__ returns a str, not 'bytes'") with self.assertRaisesRegex(TypeError, message): P(b'a') - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, message): P(b'a', 'b') - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, message): P('a', b'b') with self.assertRaises(TypeError): P('a').joinpath(b'b') diff --git a/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst b/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst new file mode 100644 index 00000000000000..1414cb07dd9155 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst @@ -0,0 +1,2 @@ +Fix misleading exception message when mixed ``str`` and ``bytes`` arguments +are supplied to :class:`pathlib.PurePath` and :class:`~pathlib.Path`. From d24465e5af405aee956f7177ea1211ba3c27ca59 Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Thu, 13 Apr 2023 20:16:42 +0100 Subject: [PATCH 2/2] Update Lib/pathlib.py Co-authored-by: Terry Jan Reedy --- Lib/pathlib.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 599df1953c1377..8ef834e68d2d35 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -305,7 +305,10 @@ def __init__(self, *args): if isinstance(arg, PurePath): path = arg._raw_path else: - path = os.fspath(arg) + try: + path = os.fspath(arg) + except TypeError: + path = arg if not isinstance(path, str): raise TypeError( "argument should be a str or an os.PathLike "