1111from zarr .core .buffer .core import default_buffer_prototype
1212from zarr .core .common import concurrent_map
1313from zarr .storage ._utils import (
14- _dereference_path ,
14+ _join_paths ,
1515 _normalize_byte_range_index ,
1616 normalize_path ,
1717 parse_store_url ,
@@ -700,7 +700,7 @@ def __init__(self, name: str | None = None, *, path: str = "", read_only: bool =
700700 self .path = normalize_path (path )
701701
702702 def __str__ (self ) -> str :
703- return _dereference_path ( f"memory://{ self ._name } " , self .path )
703+ return _join_paths ([ f"memory://{ self ._name } " , self .path ] )
704704
705705 def __repr__ (self ) -> str :
706706 return f"ManagedMemoryStore('{ self } ')"
@@ -792,7 +792,7 @@ async def get(
792792 ) -> Buffer | None :
793793 # docstring inherited
794794 return await super ().get (
795- _dereference_path ( self .path , key ), prototype = prototype , byte_range = byte_range
795+ _join_paths ([ self .path , key ] ), prototype = prototype , byte_range = byte_range
796796 )
797797
798798 async def get_partial_values (
@@ -801,26 +801,24 @@ async def get_partial_values(
801801 key_ranges : Iterable [tuple [str , ByteRequest | None ]],
802802 ) -> list [Buffer | None ]:
803803 # docstring inherited
804- key_ranges = [
805- (_dereference_path (self .path , key ), byte_range ) for key , byte_range in key_ranges
806- ]
804+ key_ranges = [(_join_paths ([self .path , key ]), byte_range ) for key , byte_range in key_ranges ]
807805 return await super ().get_partial_values (prototype , key_ranges )
808806
809807 async def exists (self , key : str ) -> bool :
810808 # docstring inherited
811- return await super ().exists (_dereference_path ( self .path , key ))
809+ return await super ().exists (_join_paths ([ self .path , key ] ))
812810
813811 async def set (self , key : str , value : Buffer , byte_range : tuple [int , int ] | None = None ) -> None :
814812 # docstring inherited
815- return await super ().set (_dereference_path ( self .path , key ), value , byte_range = byte_range )
813+ return await super ().set (_join_paths ([ self .path , key ] ), value , byte_range = byte_range )
816814
817815 async def set_if_not_exists (self , key : str , value : Buffer ) -> None :
818816 # docstring inherited
819- return await super ().set_if_not_exists (_dereference_path ( self .path , key ), value )
817+ return await super ().set_if_not_exists (_join_paths ([ self .path , key ] ), value )
820818
821819 async def delete (self , key : str ) -> None :
822820 # docstring inherited
823- return await super ().delete (_dereference_path ( self .path , key ))
821+ return await super ().delete (_join_paths ([ self .path , key ] ))
824822
825823 async def list (self ) -> AsyncIterator [str ]:
826824 # docstring inherited
@@ -831,16 +829,16 @@ async def list(self) -> AsyncIterator[str]:
831829
832830 async def list_prefix (self , prefix : str ) -> AsyncIterator [str ]:
833831 # docstring inherited
834- # Don't use _dereference_path here because it strips trailing slashes,
835- # which would break prefix matching (e.g., "fo/" vs "foo/" )
832+ # Manual concatenation instead of _join_paths because we need "path/"
833+ # as the prefix when prefix is empty (to list all keys under self.path )
836834 full_prefix = f"{ self .path } /{ prefix } " if self .path else prefix
837835 path_prefix = self .path + "/" if self .path else ""
838836 async for key in super ().list_prefix (full_prefix ):
839837 yield key .removeprefix (path_prefix )
840838
841839 async def list_dir (self , prefix : str ) -> AsyncIterator [str ]:
842840 # docstring inherited
843- full_prefix = _dereference_path ( self .path , prefix )
841+ full_prefix = _join_paths ([ self .path , prefix ] )
844842 async for key in super ().list_dir (full_prefix ):
845843 yield key
846844
0 commit comments