11import os
22from configparser import ConfigParser
33from pathlib import PurePath
4- from typing import Dict , Tuple , Union
4+ from typing import Dict , Optional , Tuple , Union
55
66from megfile .lib .compat import fspath
77from megfile .lib .url import get_url_scheme
8- from megfile .utils import classproperty
8+ from megfile .utils import cached_classproperty
99
1010from .errors import ProtocolExistsError , ProtocolNotFoundError
1111from .interfaces import BasePath , BaseURIPath , PathLike
@@ -54,15 +54,15 @@ def __init__(self, path: Union[PathLike, int], *other_paths: PathLike):
5454 self .path = str (pathlike )
5555 self .pathlike = pathlike
5656
57- @classproperty
57+ @cached_classproperty
5858 def _aliases (cls ) -> Dict [str , Dict [str , str ]]:
5959 config_path = os .path .expanduser (aliases_config )
60- aliases = _load_aliases_config (config_path )
61- setattr (cls , "_aliases" , aliases )
62- return aliases
60+ return _load_aliases_config (config_path )
6361
64- @staticmethod
65- def _extract_protocol (path : Union [PathLike , int ]) -> Tuple [str , Union [str , int ]]:
62+ @classmethod
63+ def _extract_protocol (
64+ cls , path : Union [PathLike , int ]
65+ ) -> Tuple [str , Union [str , int ]]:
6666 if isinstance (path , int ):
6767 protocol = "file"
6868 path_without_protocol = path
@@ -74,27 +74,26 @@ def _extract_protocol(path: Union[PathLike, int]) -> Tuple[str, Union[str, int]]
7474 else :
7575 path_without_protocol = path [len (protocol ) + 3 :]
7676 elif isinstance (path , (BaseURIPath , SmartPath )):
77- protocol = path .protocol
78- path_without_protocol = str (path )
77+ return str (path .protocol ), str (path )
7978 elif isinstance (path , (PurePath , BasePath )):
80- protocol , path_without_protocol = SmartPath ._extract_protocol (fspath (path ))
79+ return SmartPath ._extract_protocol (fspath (path ))
8180 else :
8281 raise ProtocolNotFoundError ("protocol not found: %r" % path )
83- return protocol , path_without_protocol
84-
85- @classmethod
86- def _create_pathlike (cls , path : Union [PathLike , int ]) -> BaseURIPath :
87- protocol , path_without_protocol = cls ._extract_protocol (path )
8882 aliases : Dict [str , Dict [str , str ]] = cls ._aliases # pyre-ignore[9]
8983 if protocol in aliases :
9084 protocol = aliases [protocol ]["protocol" ]
91- path = protocol + "://" + str (path_without_protocol )
85+ path = "%s://%s" % (protocol , path_without_protocol )
86+ return protocol , path
87+
88+ @classmethod
89+ def _create_pathlike (cls , path : Union [PathLike , int ]) -> BaseURIPath :
90+ protocol , unaliased_path = cls ._extract_protocol (path )
9291 if protocol .startswith ("s3+" ):
9392 protocol = "s3"
9493 if protocol not in cls ._registered_protocols :
9594 raise ProtocolNotFoundError ("protocol %r not found: %r" % (protocol , path ))
9695 path_class = cls ._registered_protocols [protocol ]
97- return path_class (path )
96+ return path_class (unaliased_path )
9897
9998 @classmethod
10099 def register (cls , path_class , override_ok : bool = False ):
@@ -137,7 +136,6 @@ def register(cls, path_class, override_ok: bool = False):
137136 joinpath = _bind_function ("joinpath" )
138137 abspath = _bind_function ("abspath" )
139138 realpath = _bind_function ("realpath" )
140- relpath = _bind_function ("relpath" )
141139 is_absolute = _bind_function ("is_absolute" )
142140 is_mount = _bind_function ("is_mount" )
143141 md5 = _bind_function ("md5" )
@@ -150,6 +148,16 @@ def protocol(self) -> str:
150148 def from_uri (cls , path : str ):
151149 return cls (path )
152150
151+ def relpath (self , start : Optional [str ] = None ) -> str :
152+ """Return the relative path of given path
153+
154+ :param start: Given start directory
155+ :returns: Relative path from start
156+ """
157+ if start is not None :
158+ _ , start = SmartPath ._extract_protocol (fspath (start ))
159+ return self .pathlike .relpath (start = start )
160+
153161 as_uri = _bind_function ("as_uri" )
154162 as_posix = _bind_function ("as_posix" )
155163 __lt__ = _bind_function ("__lt__" )
@@ -170,7 +178,6 @@ def from_uri(cls, path: str):
170178 is_mount = _bind_function ("is_mount" )
171179 abspath = _bind_function ("abspath" )
172180 realpath = _bind_function ("realpath" )
173- relpath = _bind_function ("relpath" )
174181 iterdir = _bind_function ("iterdir" )
175182 cwd = _bind_function ("cwd" )
176183 home = _bind_function ("home" )
0 commit comments