@@ -99,7 +99,7 @@ class PathGlobber(_GlobberBase):
9999 @staticmethod
100100 def concat_path (path , text ):
101101 """Appends text to the given path."""
102- return path .with_segments (path . _raw_path + text )
102+ return path .with_segments (str ( path ) + text )
103103
104104
105105class PurePathBase :
@@ -112,9 +112,9 @@ class PurePathBase:
112112 """
113113
114114 __slots__ = (
115- # The `_raw_path ` slot store a joined string path . This is set in the
116- # `__init__()` method.
117- '_raw_path ' ,
115+ # The `_raw_paths ` slot stores unjoined string paths . This is set in
116+ # the `__init__()` method.
117+ '_raw_paths ' ,
118118
119119 # The '_resolving' slot stores a boolean indicating whether the path
120120 # is being processed by `PathBase.resolve()`. This prevents duplicate
@@ -124,11 +124,14 @@ class PurePathBase:
124124 parser = ParserBase ()
125125 _globber = PathGlobber
126126
127- def __init__ (self , path , * paths ):
128- self ._raw_path = self .parser .join (path , * paths ) if paths else path
129- if not isinstance (self ._raw_path , str ):
130- raise TypeError (
131- f"path should be a str, not { type (self ._raw_path ).__name__ !r} " )
127+ def __init__ (self , arg , * args ):
128+ paths = [arg ]
129+ paths .extend (args )
130+ for path in paths :
131+ if not isinstance (path , str ):
132+ raise TypeError (
133+ f"path should be a str, not { type (path ).__name__ !r} " )
134+ self ._raw_paths = paths
132135 self ._resolving = False
133136
134137 def with_segments (self , * pathsegments ):
@@ -141,7 +144,19 @@ def with_segments(self, *pathsegments):
141144 def __str__ (self ):
142145 """Return the string representation of the path, suitable for
143146 passing to system calls."""
144- return self ._raw_path
147+ paths = self ._raw_paths
148+ if len (paths ) == 1 :
149+ return paths [0 ]
150+ elif paths :
151+ # Join path segments from the initializer.
152+ path = self .parser .join (* paths )
153+ # Cache the joined path.
154+ paths .clear ()
155+ paths .append (path )
156+ return path
157+ else :
158+ paths .append ('' )
159+ return ''
145160
146161 def as_posix (self ):
147162 """Return the string representation of the path with forward (/)
@@ -166,7 +181,7 @@ def anchor(self):
166181 @property
167182 def name (self ):
168183 """The final path component, if any."""
169- return self .parser .split (self . _raw_path )[1 ]
184+ return self .parser .split (str ( self ) )[1 ]
170185
171186 @property
172187 def suffix (self ):
@@ -202,7 +217,7 @@ def with_name(self, name):
202217 split = self .parser .split
203218 if split (name )[0 ]:
204219 raise ValueError (f"Invalid name { name !r} " )
205- return self .with_segments (split (self . _raw_path )[0 ], name )
220+ return self .with_segments (split (str ( self ) )[0 ], name )
206221
207222 def with_stem (self , stem ):
208223 """Return a new path with the stem changed."""
@@ -242,17 +257,17 @@ def relative_to(self, other, *, walk_up=False):
242257 anchor0 , parts0 = self ._stack
243258 anchor1 , parts1 = other ._stack
244259 if anchor0 != anchor1 :
245- raise ValueError (f"{ self . _raw_path !r} and { other . _raw_path !r} have different anchors" )
260+ raise ValueError (f"{ str ( self ) !r} and { str ( other ) !r} have different anchors" )
246261 while parts0 and parts1 and parts0 [- 1 ] == parts1 [- 1 ]:
247262 parts0 .pop ()
248263 parts1 .pop ()
249264 for part in parts1 :
250265 if not part or part == '.' :
251266 pass
252267 elif not walk_up :
253- raise ValueError (f"{ self . _raw_path !r} is not in the subpath of { other . _raw_path !r} " )
268+ raise ValueError (f"{ str ( self ) !r} is not in the subpath of { str ( other ) !r} " )
254269 elif part == '..' :
255- raise ValueError (f"'..' segment in { other . _raw_path !r} cannot be walked" )
270+ raise ValueError (f"'..' segment in { str ( other ) !r} cannot be walked" )
256271 else :
257272 parts0 .append ('..' )
258273 return self .with_segments ('' , * reversed (parts0 ))
@@ -289,17 +304,17 @@ def joinpath(self, *pathsegments):
289304 paths) or a totally different path (if one of the arguments is
290305 anchored).
291306 """
292- return self .with_segments (self ._raw_path , * pathsegments )
307+ return self .with_segments (* self ._raw_paths , * pathsegments )
293308
294309 def __truediv__ (self , key ):
295310 try :
296- return self .with_segments (self ._raw_path , key )
311+ return self .with_segments (* self ._raw_paths , key )
297312 except TypeError :
298313 return NotImplemented
299314
300315 def __rtruediv__ (self , key ):
301316 try :
302- return self .with_segments (key , self ._raw_path )
317+ return self .with_segments (key , * self ._raw_paths )
303318 except TypeError :
304319 return NotImplemented
305320
@@ -311,7 +326,7 @@ def _stack(self):
311326 *parts* is a reversed list of parts following the anchor.
312327 """
313328 split = self .parser .split
314- path = self . _raw_path
329+ path = str ( self )
315330 parent , name = split (path )
316331 names = []
317332 while path != parent :
@@ -323,7 +338,7 @@ def _stack(self):
323338 @property
324339 def parent (self ):
325340 """The logical parent of the path."""
326- path = self . _raw_path
341+ path = str ( self )
327342 parent = self .parser .split (path )[0 ]
328343 if path != parent :
329344 parent = self .with_segments (parent )
@@ -335,7 +350,7 @@ def parent(self):
335350 def parents (self ):
336351 """A sequence of this path's logical parents."""
337352 split = self .parser .split
338- path = self . _raw_path
353+ path = str ( self )
339354 parent = split (path )[0 ]
340355 parents = []
341356 while path != parent :
@@ -347,7 +362,7 @@ def parents(self):
347362 def is_absolute (self ):
348363 """True if the path is absolute (has both a root and, if applicable,
349364 a drive)."""
350- return self .parser .isabs (self . _raw_path )
365+ return self .parser .isabs (str ( self ) )
351366
352367 @property
353368 def _pattern_str (self ):
0 commit comments