]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-103525: Improve exception message from `pathlib.PurePath()` (GH-103526)
authorBarney Gale <barney.gale@gmail.com>
Tue, 2 May 2023 18:08:19 +0000 (19:08 +0100)
committerGitHub <noreply@github.com>
Tue, 2 May 2023 18:08:19 +0000 (19:08 +0100)
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 <tjreedy@udel.edu>
Lib/pathlib.py
Lib/test/test_pathlib.py
Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst [new file with mode: 0644]

index f43f01ef41a97fafae4acd67b114c4a8daf689ab..8eb08949fa9b43108aa2b945c3a187ca6a92bc58 100644 (file)
@@ -300,18 +300,27 @@ class PurePath(object):
         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:
+                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 "
+                        "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):
@@ -620,7 +629,7 @@ class PurePath(object):
         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:
@@ -630,7 +639,7 @@ class PurePath(object):
 
     def __rtruediv__(self, key):
         try:
-            return type(self)(key, self._raw_path)
+            return type(self)(key, self)
         except TypeError:
             return NotImplemented
 
@@ -864,7 +873,7 @@ class Path(PurePath):
             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):
         """
index 76cfadeedcea845bcd9d2b0ebee7ee53f1e6cc3b..8b5b61a818bbbc947643c5f9901882744e8061c0 100644 (file)
@@ -81,9 +81,9 @@ class _BasePurePathTest(object):
                    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 (file)
index 0000000..1414cb0
--- /dev/null
@@ -0,0 +1,2 @@
+Fix misleading exception message when mixed ``str`` and ``bytes`` arguments
+are supplied to :class:`pathlib.PurePath` and :class:`~pathlib.Path`.