PurePosixPath('setup.py')
Each element of *pathsegments* can be either a string representing a
- path segment, an object implementing the :class:`os.PathLike` interface
- which returns a string, or another path object::
+ path segment, or an object implementing the :class:`os.PathLike` interface
+ where the :meth:`~os.PathLike.__fspath__` method returns a string,
+ such as another path object::
>>> PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar')
path = cls._flavour.join(*parts)
sep = cls._flavour.sep
altsep = cls._flavour.altsep
+ if isinstance(path, str):
+ # Force-cast str subclasses to str (issue #21127)
+ path = str(path)
+ else:
+ raise TypeError(
+ "argument should be a str or an os.PathLike "
+ "object where __fspath__ returns a str, "
+ f"not {type(path).__name__!r}")
if altsep:
path = path.replace(altsep, sep)
drv, root, rel = cls._flavour.splitroot(path)
parsed = [sys.intern(x) for x in unfiltered_parsed if x and x != '.']
return drv, root, parsed
- @classmethod
- def _parse_args(cls, args):
- # This is useful when you don't want to create an instance, just
- # canonicalize some constructor arguments.
- parts = []
- for a in args:
- if isinstance(a, PurePath):
- parts += a._parts
- else:
- a = os.fspath(a)
- if isinstance(a, str):
- # Force-cast str subclasses to str (issue #21127)
- parts.append(str(a))
- else:
- raise TypeError(
- "argument should be a str object or an os.PathLike "
- "object returning str, not %r"
- % type(a))
- return cls._parse_parts(parts)
-
@classmethod
def _from_parts(cls, args):
- # We need to call _parse_args on the instance, so as to get the
- # right flavour.
self = object.__new__(cls)
- drv, root, parts = self._parse_args(args)
+ drv, root, parts = self._parse_parts(args)
self._drv = drv
self._root = root
self._parts = parts
anchored).
"""
drv1, root1, parts1 = self._drv, self._root, self._parts
- drv2, root2, parts2 = self._parse_args(args)
+ drv2, root2, parts2 = self._parse_parts(args)
if root2:
if not drv2 and drv1:
return self._from_parsed_parts(drv1, root2, [drv1 + root2] + parts2[1:])
return True
# Can't subclass os.PathLike from PurePath and keep the constructor
-# optimizations in PurePath._parse_args().
+# optimizations in PurePath.__slots__.
os.PathLike.register(PurePath)
self.assertEqual(P(P('a'), P('b')), P('a/b'))
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
+ def test_bytes(self):
+ P = self.cls
+ message = (r"argument should be a str or an os\.PathLike object "
+ r"where __fspath__ returns a str, not 'bytes'")
+ with self.assertRaisesRegex(TypeError, message):
+ P(b'a')
+ with self.assertRaises(TypeError):
+ P(b'a', 'b')
+ with self.assertRaises(TypeError):
+ P('a', b'b')
+ with self.assertRaises(TypeError):
+ P('a').joinpath(b'b')
+ with self.assertRaises(TypeError):
+ P('a') / b'b'
+ with self.assertRaises(TypeError):
+ b'a' / P('b')
+ with self.assertRaises(TypeError):
+ P('a').match(b'b')
+ with self.assertRaises(TypeError):
+ P('a').relative_to(b'b')
+ with self.assertRaises(TypeError):
+ P('a').with_name(b'b')
+ with self.assertRaises(TypeError):
+ P('a').with_stem(b'b')
+ with self.assertRaises(TypeError):
+ P('a').with_suffix(b'b')
+
def _check_str_subclass(self, *args):
# Issue #21127: it should be possible to construct a PurePath object
# from a str subclass instance, and it then gets converted to