@@ -275,9 +275,20 @@ def __reduce__(self):
275
275
def _parse_parts (cls , parts ):
276
276
if not parts :
277
277
return '' , '' , []
278
+ elif len (parts ) == 1 :
279
+ path = os .fspath (parts [0 ])
280
+ else :
281
+ path = cls ._flavour .join (* parts )
278
282
sep = cls ._flavour .sep
279
283
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} " )
281
292
if altsep :
282
293
path = path .replace (altsep , sep )
283
294
drv , root , rel = cls ._flavour .splitroot (path )
@@ -288,32 +299,10 @@ def _parse_parts(cls, parts):
288
299
parsed = [sys .intern (x ) for x in unfiltered_parsed if x and x != '.' ]
289
300
return drv , root , parsed
290
301
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
-
311
302
@classmethod
312
303
def _from_parts (cls , args ):
313
- # We need to call _parse_args on the instance, so as to get the
314
- # right flavour.
315
304
self = object .__new__ (cls )
316
- drv , root , parts = self ._parse_args (args )
305
+ drv , root , parts = self ._parse_parts (args )
317
306
self ._drv = drv
318
307
self ._root = root
319
308
self ._parts = parts
@@ -572,7 +561,7 @@ def joinpath(self, *args):
572
561
anchored).
573
562
"""
574
563
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 )
576
565
if root2 :
577
566
if not drv2 and drv1 :
578
567
return self ._from_parsed_parts (drv1 , root2 , [drv1 + root2 ] + parts2 [1 :])
@@ -659,7 +648,7 @@ def match(self, path_pattern):
659
648
return True
660
649
661
650
# Can't subclass os.PathLike from PurePath and keep the constructor
662
- # optimizations in PurePath._parse_args() .
651
+ # optimizations in PurePath.__slots__ .
663
652
os .PathLike .register (PurePath )
664
653
665
654
@@ -704,11 +693,7 @@ def __new__(cls, *args, **kwargs):
704
693
warnings ._deprecated ("pathlib.PurePath(**kwargs)" , msg , remove = (3 , 14 ))
705
694
if cls is Path :
706
695
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 )
712
697
713
698
def _make_child_relpath (self , part ):
714
699
# This is an optimization used for dir walking. `part` must be
@@ -1258,9 +1243,19 @@ class PosixPath(Path, PurePosixPath):
1258
1243
"""
1259
1244
__slots__ = ()
1260
1245
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
+
1261
1251
class WindowsPath (Path , PureWindowsPath ):
1262
1252
"""Path subclass for Windows systems.
1263
1253
1264
1254
On a Windows system, instantiating a Path should return this object.
1265
1255
"""
1266
1256
__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