2020
2121
2222def _get (
23- path : str , prototype : BufferPrototype , byte_range : tuple [int | None , int | None ] | None
23+ path : Path , prototype : BufferPrototype , byte_range : tuple [int | None , int | None ] | None
2424) -> Buffer :
2525 """
2626 Fetch a contiguous region of bytes from a file.
@@ -35,7 +35,6 @@ def _get(
3535 and the second value specifies the total number of bytes to read. If the total value is
3636 `None`, then the entire file after the first byte will be read.
3737 """
38- target = Path (path )
3938 if byte_range is not None :
4039 if byte_range [0 ] is None :
4140 start = 0
@@ -44,8 +43,8 @@ def _get(
4443
4544 end = (start + byte_range [1 ]) if byte_range [1 ] is not None else None
4645 else :
47- return prototype .buffer .from_bytes (target .read_bytes ())
48- with target .open ("rb" ) as f :
46+ return prototype .buffer .from_bytes (path .read_bytes ())
47+ with path .open ("rb" ) as f :
4948 size = f .seek (0 , io .SEEK_END )
5049 if start is not None :
5150 if start >= 0 :
@@ -105,13 +104,15 @@ class LocalStore(Store):
105104 supports_deletes : bool = True
106105 supports_partial_writes : bool = True
107106 supports_listing : bool = True
107+ _path : Path
108108
109109 def __init__ (self , path : Path | str , * , mode : AccessModeLiteral = "r" ) -> None :
110110 super ().__init__ (mode = mode , path = str (path ))
111+ self ._path = Path (self .path )
111112
112113 async def _open (self ) -> None :
113114 if not self .mode .readonly :
114- Path ( self .path ) .mkdir (parents = True , exist_ok = True )
115+ self ._path .mkdir (parents = True , exist_ok = True )
115116 return await super ()._open ()
116117
117118 async def clear (self ) -> None :
@@ -156,7 +157,7 @@ async def get(
156157 if not self ._is_open :
157158 await self ._open ()
158159
159- path = os . path . join ( self .path , key )
160+ path = self ._path / key
160161
161162 try :
162163 return await asyncio .to_thread (_get , path , prototype , byte_range )
@@ -172,7 +173,7 @@ async def get_partial_values(
172173 args = []
173174 for key , byte_range in key_ranges :
174175 assert isinstance (key , str )
175- path = os . path . join ( self .path , key )
176+ path = self ._path / key
176177 args .append ((_get , path , prototype , byte_range ))
177178 return await concurrent_map (args , asyncio .to_thread , limit = None ) # TODO: fix limit
178179
@@ -194,7 +195,7 @@ async def _set(self, key: str, value: Buffer, exclusive: bool = False) -> None:
194195 assert isinstance (key , str )
195196 if not isinstance (value , Buffer ):
196197 raise TypeError ("LocalStore.set(): `value` must a Buffer instance" )
197- path = Path ( self .path ) / key
198+ path = self ._path / key
198199 await asyncio .to_thread (_put , path , value , start = None , exclusive = exclusive )
199200
200201 async def set_partial_values (
@@ -212,15 +213,15 @@ async def set_partial_values(
212213 async def delete (self , key : str ) -> None :
213214 # docstring inherited
214215 self ._check_writable ()
215- path = Path ( self .path ) / key
216+ path = self ._path / key
216217 if path .is_dir (): # TODO: support deleting directories? shutil.rmtree?
217218 shutil .rmtree (path )
218219 else :
219220 await asyncio .to_thread (path .unlink , True ) # Q: we may want to raise if path is missing
220221
221222 async def exists (self , key : str ) -> bool :
222223 # docstring inherited
223- path = Path ( self .path ) / key
224+ path = self ._path / key
224225 return await asyncio .to_thread (path .is_file )
225226
226227 async def list (self ) -> AsyncGenerator [str , None ]:
@@ -232,21 +233,21 @@ async def list(self) -> AsyncGenerator[str, None]:
232233 """
233234 # TODO: just invoke list_prefix with the prefix "/"
234235 to_strip = self .path + "/"
235- for p in Path ( self .path ) .rglob ("*" ):
236+ for p in self ._path .rglob ("*" ):
236237 if p .is_file ():
237238 yield str (p .relative_to (to_strip ))
238239
239240 async def list_prefix (self , prefix : str ) -> AsyncGenerator [str , None ]:
240241 # docstring inherited
241242 to_strip = os .path .join (self .path , prefix )
242- for p in (Path ( self .path ) / prefix ).rglob ("*" ):
243+ for p in (self ._path / prefix ).rglob ("*" ):
243244 if p .is_file ():
244245 yield str (p .relative_to (to_strip ))
245246
246247 async def list_dir (self , prefix : str ) -> AsyncGenerator [str , None ]:
247248 # docstring inherited
248249 base = os .path .join (self .path , prefix )
249- to_strip = str ( base ) + "/"
250+ to_strip = base + "/"
250251
251252 try :
252253 key_iter = Path (base ).iterdir ()
0 commit comments