@@ -209,6 +209,12 @@ class PurePath:
209
209
# in the `__init__()` method.
210
210
'_raw_paths' ,
211
211
212
+ # The `_raw_path_cached` slot stores a joined but unnormalized string
213
+ # path. This is set in the `__init__()` method or `_raw_path`
214
+ # property. It's returned from `__fspath__()`, and used as the basis
215
+ # for the normalized path parts (see following slots).
216
+ '_raw_path_cached' ,
217
+
212
218
# The `_drv`, `_root` and `_tail_cached` slots store parsed and
213
219
# normalized parts of the path. They are set when any of the `drive`,
214
220
# `root` or `_tail` properties are accessed for the first time. The
@@ -273,19 +279,6 @@ def _parse_path(cls, path):
273
279
parsed = [sys .intern (str (x )) for x in rel .split (sep ) if x and x != '.' ]
274
280
return drv , root , parsed
275
281
276
- def _load_parts (self ):
277
- paths = self ._raw_paths
278
- if len (paths ) == 0 :
279
- path = ''
280
- elif len (paths ) == 1 :
281
- path = paths [0 ]
282
- else :
283
- path = self .pathmod .join (* paths )
284
- drv , root , tail = self ._parse_path (path )
285
- self ._drv = drv
286
- self ._root = root
287
- self ._tail_cached = tail
288
-
289
282
def _from_parsed_parts (self , drv , root , tail ):
290
283
path_str = self ._format_parsed_parts (drv , root , tail )
291
284
path = self .with_segments (path_str )
@@ -321,13 +314,22 @@ def as_posix(self):
321
314
def __repr__ (self ):
322
315
return "{}({!r})" .format (self .__class__ .__name__ , self .as_posix ())
323
316
317
+ @property
318
+ def _raw_path (self ):
319
+ """The joined (but unnormalized) string path."""
320
+ try :
321
+ return self ._raw_path_cached
322
+ except AttributeError :
323
+ self ._raw_path_cached = self .pathmod .join (* self ._raw_paths )
324
+ return self ._raw_path_cached
325
+
324
326
@property
325
327
def drive (self ):
326
328
"""The drive prefix (letter or UNC path), if any."""
327
329
try :
328
330
return self ._drv
329
331
except AttributeError :
330
- self ._load_parts ( )
332
+ self ._drv , self . _root , self . _tail_cached = self . _parse_path ( self . _raw_path )
331
333
return self ._drv
332
334
333
335
@property
@@ -336,15 +338,15 @@ def root(self):
336
338
try :
337
339
return self ._root
338
340
except AttributeError :
339
- self ._load_parts ( )
341
+ self ._drv , self . _root , self . _tail_cached = self . _parse_path ( self . _raw_path )
340
342
return self ._root
341
343
342
344
@property
343
345
def _tail (self ):
344
346
try :
345
347
return self ._tail_cached
346
348
except AttributeError :
347
- self ._load_parts ( )
349
+ self ._drv , self . _root , self . _tail_cached = self . _parse_path ( self . _raw_path )
348
350
return self ._tail_cached
349
351
350
352
@property
@@ -605,6 +607,10 @@ def __init__(self, *args):
605
607
f"not { type (path ).__name__ !r} " )
606
608
paths .append (path )
607
609
self ._raw_paths = paths
610
+ if len (paths ) == 1 :
611
+ self ._raw_path_cached = paths [0 ]
612
+ elif len (paths ) == 0 :
613
+ self ._raw_path_cached = ''
608
614
self ._resolving = False
609
615
610
616
def __reduce__ (self ):
@@ -613,12 +619,12 @@ def __reduce__(self):
613
619
return (self .__class__ , self .parts )
614
620
615
621
def __fspath__ (self ):
616
- return str ( self )
622
+ return self . _raw_path
617
623
618
624
def __bytes__ (self ):
619
625
"""Return the bytes representation of the path. This is only
620
626
recommended to use under Unix."""
621
- return os .fsencode (self )
627
+ return os .fsencode (str ( self ) )
622
628
623
629
@property
624
630
def _str_normcase (self ):
0 commit comments