@@ -402,27 +402,38 @@ def __init__(
402402 ** args0 ._chain .nest ().storage_options ,
403403 ** storage_options ,
404404 }
405- str_args0 = str ( args0 )
405+ str_args0 = args0 . __vfspath__ ( )
406406
407407 else :
408408 if hasattr (args0 , "__fspath__" ) and args0 .__fspath__ is not None :
409409 str_args0 = args0 .__fspath__ ()
410+ elif hasattr (args0 , "__vfspath__" ) and args0 .__vfspath__ is not None :
411+ str_args0 = args0 .__vfspath__ ()
412+ elif isinstance (args0 , str ):
413+ str_args0 = args0
410414 else :
411- str_args0 = str (args0 )
415+ raise TypeError (
416+ "argument should be a UPath, str, "
417+ f"or support __vfspath__ or __fspath__, not { type (args0 )!r} "
418+ )
412419 storage_options = type (self )._parse_storage_options (
413420 str_args0 , protocol , storage_options
414421 )
415- if len (args ) > 1 :
416- str_args0 = WrappedFileSystemFlavour .from_protocol (protocol ).join (
417- str_args0 , * args [1 :]
418- )
419422 else :
420423 str_args0 = "."
421424
422425 segments = chain_parser .unchain (
423426 str_args0 , {"protocol" : protocol , ** storage_options }
424427 )
425- self ._chain = Chain .from_list (segments )
428+ chain = Chain .from_list (segments )
429+ if len (args ) > 1 :
430+ chain = chain .replace (
431+ path = WrappedFileSystemFlavour .from_protocol (protocol ).join (
432+ chain .active_path ,
433+ * args [1 :],
434+ )
435+ )
436+ self ._chain = chain
426437 self ._chain_parser = chain_parser
427438 self ._raw_urlpaths = args
428439 self ._relative_base = None
@@ -638,9 +649,6 @@ def with_segments(self, *pathsegments: JoinablePathLike) -> Self:
638649 return new_instance
639650
640651 def __str__ (self ) -> str :
641- return self .__vfspath__ ()
642-
643- def __vfspath__ (self ) -> str :
644652 if self ._relative_base is not None :
645653 active_path = self ._chain .active_path
646654 stripped_base = self .parser .strip_protocol (
@@ -658,10 +666,19 @@ def __vfspath__(self) -> str:
658666 else :
659667 return self ._chain_parser .chain (self ._chain .to_list ())[0 ]
660668
669+ def __vfspath__ (self ) -> str :
670+ if self ._relative_base is not None :
671+ return self .__str__ ()
672+ else :
673+ return self .path
674+
661675 def __repr__ (self ) -> str :
676+ cls_name = type (self ).__name__
677+ path = self .__vfspath__ ()
662678 if self ._relative_base is not None :
663- return f"<relative { type (self ).__name__ } { str (self )!r} >"
664- return f"{ type (self ).__name__ } ({ self .path !r} , protocol={ self ._protocol !r} )"
679+ return f"<relative { cls_name } { path !r} >"
680+ else :
681+ return f"{ cls_name } ({ path !r} , protocol={ self ._protocol !r} )"
665682
666683 # === JoinablePath overrides ======================================
667684
@@ -704,9 +721,9 @@ def with_name(self, name: str) -> Self:
704721 split = self .parser .split
705722 if self .parser .sep in name : # `split(name)[0]`
706723 raise ValueError (f"Invalid name { name !r} " )
707- path = str ( self )
708- path = path .removesuffix (split (path )[1 ]) + name
709- return self .with_segments (path )
724+ _path = self . __vfspath__ ( )
725+ _path = _path .removesuffix (split (_path )[1 ]) + name
726+ return self .with_segments (_path )
710727
711728 @property
712729 def anchor (self ) -> str :
@@ -780,7 +797,7 @@ def iterdir(self) -> Iterator[Self]:
780797 continue
781798 # only want the path name with iterdir
782799 _ , _ , name = name .removesuffix (sep ).rpartition (self .parser .sep )
783- yield base .with_segments (str ( base ) , name )
800+ yield base .with_segments (base . path , name )
784801
785802 def __open_reader__ (self ) -> BinaryIO :
786803 return self .fs .open (self .path , mode = "rb" )
@@ -1045,7 +1062,7 @@ def glob(
10451062 self = self .absolute ()
10461063 path_pattern = self .joinpath (pattern ).path
10471064 sep = self .parser .sep
1048- base = self .fs . _strip_protocol ( self . path )
1065+ base = self .path
10491066 for name in self .fs .glob (path_pattern ):
10501067 name = name .removeprefix (base ).removeprefix (sep )
10511068 yield self .joinpath (name )
@@ -1075,7 +1092,7 @@ def rglob(
10751092 if _FSSPEC_HAS_WORKING_GLOB :
10761093 r_path_pattern = self .joinpath ("**" , pattern ).path
10771094 sep = self .parser .sep
1078- base = self .fs . _strip_protocol ( self . path )
1095+ base = self .path
10791096 for name in self .fs .glob (r_path_pattern ):
10801097 name = name .removeprefix (base ).removeprefix (sep )
10811098 yield self .joinpath (name )
@@ -1084,7 +1101,7 @@ def rglob(
10841101 path_pattern = self .joinpath (pattern ).path
10851102 r_path_pattern = self .joinpath ("**" , pattern ).path
10861103 sep = self .parser .sep
1087- base = self .fs . _strip_protocol ( self . path )
1104+ base = self .path
10881105 seen = set ()
10891106 for p in (path_pattern , r_path_pattern ):
10901107 for name in self .fs .glob (p ):
@@ -1134,7 +1151,7 @@ def __eq__(self, other: object) -> bool:
11341151 return False
11351152
11361153 return (
1137- self .path == other .path
1154+ self .__vfspath__ () == other .__vfspath__ ()
11381155 and self .protocol == other .protocol
11391156 and self .storage_options == other .storage_options
11401157 )
@@ -1145,29 +1162,27 @@ def __hash__(self) -> int:
11451162 Note: in the future, if hash collisions become an issue, we
11461163 can add `fsspec.utils.tokenize(storage_options)`
11471164 """
1148- if self ._relative_base is not None :
1149- return hash ((self .protocol , str (self )))
1150- return hash ((self .protocol , self .path ))
1165+ return hash ((self .protocol , self .__vfspath__ ()))
11511166
11521167 def __lt__ (self , other : object ) -> bool :
11531168 if not isinstance (other , UPath ) or self .parser is not other .parser :
11541169 return NotImplemented
1155- return self .path < other .path
1170+ return self .__vfspath__ () < other .__vfspath__ ()
11561171
11571172 def __le__ (self , other : object ) -> bool :
11581173 if not isinstance (other , UPath ) or self .parser is not other .parser :
11591174 return NotImplemented
1160- return self .path <= other .path
1175+ return self .__vfspath__ () <= other .__vfspath__ ()
11611176
11621177 def __gt__ (self , other : object ) -> bool :
11631178 if not isinstance (other , UPath ) or self .parser is not other .parser :
11641179 return NotImplemented
1165- return self .path > other .path
1180+ return self .__vfspath__ () > other .__vfspath__ ()
11661181
11671182 def __ge__ (self , other : object ) -> bool :
11681183 if not isinstance (other , UPath ) or self .parser is not other .parser :
11691184 return NotImplemented
1170- return self .path >= other .path
1185+ return self .__vfspath__ () >= other .__vfspath__ ()
11711186
11721187 def resolve (self , strict : bool = False ) -> Self :
11731188 if self ._relative_base is not None :
0 commit comments