@@ -275,9 +275,20 @@ def __reduce__(self):
275275 def _parse_parts (cls , parts ):
276276 if not parts :
277277 return '' , '' , []
278+ elif len (parts ) == 1 :
279+ path = os .fspath (parts [0 ])
280+ else :
281+ path = cls ._flavour .join (* parts )
278282 sep = cls ._flavour .sep
279283 altsep = cls ._flavour .altsep
280- path = cls ._flavour .join (* parts )
284+ if isinstance (path , str ):
285+ # Force-cast str subclasses to str (issue #21127)
286+ path = str (path )
287+ else :
288+ raise TypeError (
289+ "argument should be a str or an os.PathLike "
290+ "object where __fspath__ returns a str, "
291+ f"not { type (path ).__name__ !r} " )
281292 if altsep :
282293 path = path .replace (altsep , sep )
283294 drv , root , rel = cls ._flavour .splitroot (path )
@@ -288,32 +299,10 @@ def _parse_parts(cls, parts):
288299 parsed = [sys .intern (x ) for x in unfiltered_parsed if x and x != '.' ]
289300 return drv , root , parsed
290301
291- @classmethod
292- def _parse_args (cls , args ):
293- # This is useful when you don't want to create an instance, just
294- # canonicalize some constructor arguments.
295- parts = []
296- for a in args :
297- if isinstance (a , PurePath ):
298- parts += a ._parts
299- else :
300- a = os .fspath (a )
301- if isinstance (a , str ):
302- # Force-cast str subclasses to str (issue #21127)
303- parts .append (str (a ))
304- else :
305- raise TypeError (
306- "argument should be a str object or an os.PathLike "
307- "object returning str, not %r"
308- % type (a ))
309- return cls ._parse_parts (parts )
310-
311302 @classmethod
312303 def _from_parts (cls , args ):
313- # We need to call _parse_args on the instance, so as to get the
314- # right flavour.
315304 self = object .__new__ (cls )
316- drv , root , parts = self ._parse_args (args )
305+ drv , root , parts = self ._parse_parts (args )
317306 self ._drv = drv
318307 self ._root = root
319308 self ._parts = parts
@@ -572,7 +561,7 @@ def joinpath(self, *args):
572561 anchored).
573562 """
574563 drv1 , root1 , parts1 = self ._drv , self ._root , self ._parts
575- drv2 , root2 , parts2 = self ._parse_args (args )
564+ drv2 , root2 , parts2 = self ._parse_parts (args )
576565 if root2 :
577566 if not drv2 and drv1 :
578567 return self ._from_parsed_parts (drv1 , root2 , [drv1 + root2 ] + parts2 [1 :])
@@ -659,7 +648,7 @@ def match(self, path_pattern):
659648 return True
660649
661650# Can't subclass os.PathLike from PurePath and keep the constructor
662- # optimizations in PurePath._parse_args() .
651+ # optimizations in PurePath.__slots__ .
663652os .PathLike .register (PurePath )
664653
665654
@@ -704,11 +693,7 @@ def __new__(cls, *args, **kwargs):
704693 warnings ._deprecated ("pathlib.PurePath(**kwargs)" , msg , remove = (3 , 14 ))
705694 if cls is Path :
706695 cls = WindowsPath if os .name == 'nt' else PosixPath
707- self = cls ._from_parts (args )
708- if self ._flavour is not os .path :
709- raise NotImplementedError ("cannot instantiate %r on your system"
710- % (cls .__name__ ,))
711- return self
696+ return cls ._from_parts (args )
712697
713698 def _make_child_relpath (self , part ):
714699 # This is an optimization used for dir walking. `part` must be
@@ -1258,9 +1243,19 @@ class PosixPath(Path, PurePosixPath):
12581243 """
12591244 __slots__ = ()
12601245
1246+ if os .name == 'nt' :
1247+ def __new__ (cls , * args , ** kwargs ):
1248+ raise NotImplementedError (
1249+ f"cannot instantiate { cls .__name__ !r} on your system" )
1250+
12611251class WindowsPath (Path , PureWindowsPath ):
12621252 """Path subclass for Windows systems.
12631253
12641254 On a Windows system, instantiating a Path should return this object.
12651255 """
12661256 __slots__ = ()
1257+
1258+ if os .name != 'nt' :
1259+ def __new__ (cls , * args , ** kwargs ):
1260+ raise NotImplementedError (
1261+ f"cannot instantiate { cls .__name__ !r} on your system" )
0 commit comments