@@ -458,7 +458,7 @@ def iterdir(self) -> Iterator[Self]:
458458 _ , _ , name = name .removesuffix (sep ).rpartition (self .parser .sep )
459459 yield base .with_segments (str (base ), name )
460460
461- def __open_rb__ (self , buffering = - 1 ) -> BinaryIO :
461+ def __open_rb__ (self , buffering : int = - 1 ) -> BinaryIO :
462462 block_size = _buffering2blocksize ("wb" , buffering )
463463 kw = {}
464464 if block_size is not None :
@@ -470,14 +470,19 @@ def readlink(self) -> Self:
470470
471471 # --- WritablePath attributes -------------------------------------
472472
473- def symlink_to ( # type: ignore[override]
473+ def symlink_to (
474474 self ,
475- target : str | os . PathLike [ str ] | UPath ,
475+ target : ReadablePathLike ,
476476 target_is_directory : bool = False ,
477477 ) -> None :
478478 raise NotImplementedError
479479
480- def mkdir (self , mode = 0o777 , parents = False , exist_ok = False ) -> None :
480+ def mkdir (
481+ self ,
482+ mode : int = 0o777 ,
483+ parents : bool = False ,
484+ exist_ok : bool = False ,
485+ ) -> None :
481486 if parents and not exist_ok and self .exists ():
482487 raise FileExistsError (str (self ))
483488 try :
@@ -492,7 +497,7 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False) -> None:
492497 if not self .is_dir ():
493498 raise FileExistsError (str (self ))
494499
495- def __open_wb__ (self , buffering = - 1 ) -> BinaryIO :
500+ def __open_wb__ (self , buffering : int = - 1 ) -> BinaryIO :
496501 block_size = _buffering2blocksize ("wb" , buffering )
497502 kw = {}
498503 if block_size is not None :
@@ -504,7 +509,7 @@ def __open_wb__(self, buffering=-1) -> BinaryIO:
504509 @overload
505510 def open (
506511 self ,
507- mode : Literal ["r" , "w" , "a" ] = "r" ,
512+ mode : Literal ["r" , "w" , "a" ] = ... ,
508513 buffering : int = ...,
509514 encoding : str = ...,
510515 errors : str = ...,
@@ -515,18 +520,32 @@ def open(
515520 @overload
516521 def open (
517522 self ,
518- mode : Literal ["rb" , "wb" , "ab" ],
523+ mode : Literal ["rb" , "wb" , "ab" ] = ... ,
519524 buffering : int = ...,
520525 encoding : str = ...,
521526 errors : str = ...,
522527 newline : str = ...,
523528 ** fsspec_kwargs : Any ,
524529 ) -> BinaryIO : ...
525530
531+ @overload
532+ def open (
533+ self ,
534+ mode : str = ...,
535+ buffering : int = ...,
536+ encoding : str | None = ...,
537+ errors : str | None = ...,
538+ newline : str | None = ...,
539+ ** fsspec_kwargs : Any ,
540+ ) -> IO [Any ]: ...
541+
526542 def open (
527543 self ,
528544 mode : str = "r" ,
529- * args : Any ,
545+ buffering : int = UNSET_DEFAULT ,
546+ encoding : str | None = UNSET_DEFAULT ,
547+ errors : str | None = UNSET_DEFAULT ,
548+ newline : str | None = UNSET_DEFAULT ,
530549 ** fsspec_kwargs : Any ,
531550 ) -> IO [Any ]:
532551 """
@@ -549,19 +568,18 @@ def open(
549568 Additional options for the fsspec filesystem.
550569 """
551570 # match the signature of pathlib.Path.open()
552- for key , value in zip (["buffering" , "encoding" , "errors" , "newline" ], args ):
553- if key in fsspec_kwargs :
554- raise TypeError (
555- f"{ type (self ).__name__ } .open() got multiple values for '{ key } '"
556- )
557- fsspec_kwargs [key ] = value
558- # translate pathlib buffering to fs block_size
559- if "buffering" in fsspec_kwargs :
571+ if buffering is not UNSET_DEFAULT :
560572 if "block_size" in fsspec_kwargs :
561573 raise TypeError ("cannot specify both 'buffering' and 'block_size'" )
562- block_size = _buffering2blocksize (mode , fsspec_kwargs . pop ( " buffering" ) )
574+ block_size = _buffering2blocksize (mode , buffering )
563575 if block_size is not None :
564576 fsspec_kwargs .setdefault ("block_size" , block_size )
577+ if encoding is not UNSET_DEFAULT :
578+ fsspec_kwargs ["encoding" ] = encoding
579+ if errors is not UNSET_DEFAULT :
580+ fsspec_kwargs ["errors" ] = errors
581+ if newline is not UNSET_DEFAULT :
582+ fsspec_kwargs ["newline" ] = newline
565583 return self .fs .open (self .path , mode = mode , ** fsspec_kwargs )
566584
567585 # === pathlib.Path ================================================
@@ -807,6 +825,8 @@ def rename(
807825 ) -> Self :
808826 if isinstance (target , str ) and self .storage_options :
809827 target = UPath (target , ** self .storage_options )
828+ if target == self :
829+ return self
810830 target_protocol = get_upath_protocol (target )
811831 if target_protocol :
812832 if target_protocol != self .protocol :
@@ -826,7 +846,6 @@ def rename(
826846 if ".." in parent .parts or "." in parent .parts :
827847 parent = parent .resolve ()
828848 target_ = parent .joinpath (os .path .normpath (str (target )))
829- assert isinstance (target_ , type (self )), "identical protocols enforced above"
830849 if recursive is not UNSET_DEFAULT :
831850 kwargs ["recursive" ] = recursive
832851 if maxdepth is not UNSET_DEFAULT :
@@ -836,9 +855,9 @@ def rename(
836855 target_ .path ,
837856 ** kwargs ,
838857 )
839- return target_
858+ return self . with_segments ( target_ )
840859
841- def replace (self , target : str | os . PathLike [ str ] | UPath ) -> UPath :
860+ def replace (self , target : WritablePathLike ) -> Self :
842861 raise NotImplementedError # todo
843862
844863 @property
0 commit comments