55import time
66from collections import defaultdict
77from contextlib import contextmanager
8- from typing import TYPE_CHECKING , Self
8+ from typing import TYPE_CHECKING , Any , Self
99
1010from zarr .abc .store import AccessMode , ByteRangeRequest , Store
1111from zarr .core .buffer import Buffer
@@ -57,17 +57,24 @@ def _default_handler(self) -> logging.Handler:
5757 return handler
5858
5959 @contextmanager
60- def log (self ) -> Generator [None , None , None ]:
60+ def log (self , hint : Any = "" ) -> Generator [None , None , None ]:
61+ """Context manager to log method calls
62+
63+ Each call to the wrapped store is logged to the configured logger and added to
64+ the counter dict.
65+ """
6166 method = inspect .stack ()[2 ].function
6267 op = f"{ type (self ._store ).__name__ } .{ method } "
68+ if hint :
69+ op += f"({ hint } )"
6370 self .logger .info (f"Calling { op } " )
6471 start_time = time .time ()
6572 try :
6673 self .counter [method ] += 1
6774 yield
6875 finally :
6976 end_time = time .time ()
70- self .logger .info (f"Finished { op } in { end_time - start_time :.2f} seconds " )
77+ self .logger .info (f"Finished { op } [ { end_time - start_time :.2f} s] " )
7178
7279 @property
7380 def supports_writes (self ) -> bool :
@@ -95,10 +102,15 @@ def _mode(self) -> AccessMode: # type: ignore[override]
95102 return self ._store ._mode
96103
97104 @property
98- def _is_open (self ) -> bool : # type: ignore[override]
105+ def _is_open (self ) -> bool :
99106 with self .log ():
100107 return self ._store ._is_open
101108
109+ @_is_open .setter
110+ def _is_open (self , value : bool ) -> None :
111+ with self .log (value ):
112+ self ._store ._is_open = value
113+
102114 async def _open (self ) -> None :
103115 with self .log ():
104116 return await self ._store ._open ()
@@ -122,7 +134,7 @@ def __repr__(self) -> str:
122134 return f"LoggingStore({ repr (self ._store )!r} )"
123135
124136 def __eq__ (self , other : object ) -> bool :
125- with self .log ():
137+ with self .log (other ):
126138 return self ._store == other
127139
128140 async def get (
@@ -131,56 +143,69 @@ async def get(
131143 prototype : BufferPrototype ,
132144 byte_range : tuple [int | None , int | None ] | None = None ,
133145 ) -> Buffer | None :
134- with self .log ():
146+ # docstring inherited
147+ with self .log (key ):
135148 return await self ._store .get (key = key , prototype = prototype , byte_range = byte_range )
136149
137150 async def get_partial_values (
138151 self ,
139152 prototype : BufferPrototype ,
140153 key_ranges : Iterable [tuple [str , ByteRangeRequest ]],
141154 ) -> list [Buffer | None ]:
142- with self .log ():
155+ # docstring inherited
156+ keys = "," .join ([k [0 ] for k in key_ranges ])
157+ with self .log (keys ):
143158 return await self ._store .get_partial_values (prototype = prototype , key_ranges = key_ranges )
144159
145160 async def exists (self , key : str ) -> bool :
146- with self .log ():
161+ # docstring inherited
162+ with self .log (key ):
147163 return await self ._store .exists (key )
148164
149165 async def set (self , key : str , value : Buffer ) -> None :
150- with self .log ():
166+ # docstring inherited
167+ with self .log (key ):
151168 return await self ._store .set (key = key , value = value )
152169
153170 async def set_if_not_exists (self , key : str , value : Buffer ) -> None :
154- with self .log ():
171+ # docstring inherited
172+ with self .log (key ):
155173 return await self ._store .set_if_not_exists (key = key , value = value )
156174
157175 async def delete (self , key : str ) -> None :
158- with self .log ():
176+ # docstring inherited
177+ with self .log (key ):
159178 return await self ._store .delete (key = key )
160179
161180 async def set_partial_values (
162181 self , key_start_values : Iterable [tuple [str , int , bytes | bytearray | memoryview ]]
163182 ) -> None :
164- with self .log ():
183+ # docstring inherited
184+ keys = "," .join ([k [0 ] for k in key_start_values ])
185+ with self .log (keys ):
165186 return await self ._store .set_partial_values (key_start_values = key_start_values )
166187
167188 async def list (self ) -> AsyncGenerator [str , None ]:
189+ # docstring inherited
168190 with self .log ():
169191 async for key in self ._store .list ():
170192 yield key
171193
172194 async def list_prefix (self , prefix : str ) -> AsyncGenerator [str , None ]:
173- with self .log ():
195+ # docstring inherited
196+ with self .log (prefix ):
174197 async for key in self ._store .list_prefix (prefix = prefix ):
175198 yield key
176199
177200 async def list_dir (self , prefix : str ) -> AsyncGenerator [str , None ]:
178- with self .log ():
201+ # docstring inherited
202+ with self .log (prefix ):
179203 async for key in self ._store .list_dir (prefix = prefix ):
180204 yield key
181205
182206 def with_mode (self , mode : AccessModeLiteral ) -> Self :
183- with self .log ():
207+ # docstring inherited
208+ with self .log (mode ):
184209 return type (self )(
185210 self ._store .with_mode (mode ),
186211 log_level = self .log_level ,
0 commit comments