1
1
from __future__ import annotations
2
2
3
3
from abc import abstractmethod
4
- from typing import TYPE_CHECKING , Optional
4
+ from typing import TYPE_CHECKING , Awaitable , Callable , Iterable , Optional , Tuple , TypeVar
5
5
6
6
import numpy as np
7
7
from zarr .v3 .abc .metadata import Metadata
8
8
9
- from zarr .v3 .common import ArraySpec
9
+ from zarr .v3 .common import ArraySpec , concurrent_map
10
10
from zarr .v3 .store import StorePath
11
11
12
12
18
18
RuntimeConfiguration ,
19
19
)
20
20
21
+ T = TypeVar ("T" )
22
+ U = TypeVar ("U" )
23
+
24
+
25
+ def noop_for_none (
26
+ func : Callable [[Optional [T ], ArraySpec , RuntimeConfiguration ], Awaitable [U ]]
27
+ ) -> Callable [[T , ArraySpec , RuntimeConfiguration ], Awaitable [U ]]:
28
+ async def wrap (
29
+ chunk : Optional [T ], chunk_spec : ArraySpec , runtime_configuration : RuntimeConfiguration
30
+ ) -> U :
31
+ if chunk is None :
32
+ return None
33
+ return await func (chunk , chunk_spec , runtime_configuration )
34
+
35
+ return wrap
36
+
21
37
22
38
class Codec (Metadata ):
23
39
is_fixed_size : bool
@@ -46,6 +62,20 @@ async def decode(
46
62
) -> np .ndarray :
47
63
pass
48
64
65
+ async def decode_batch (
66
+ self ,
67
+ chunk_arrays_and_specs : Iterable [Tuple [np .ndarray , ArraySpec ]],
68
+ runtime_configuration : RuntimeConfiguration ,
69
+ ) -> Iterable [np .ndarray ]:
70
+ return await concurrent_map (
71
+ [
72
+ (chunk_array , chunk_spec , runtime_configuration )
73
+ for chunk_array , chunk_spec in chunk_arrays_and_specs
74
+ ],
75
+ noop_for_none (self .decode ),
76
+ runtime_configuration .concurrency ,
77
+ )
78
+
49
79
@abstractmethod
50
80
async def encode (
51
81
self ,
@@ -55,17 +85,45 @@ async def encode(
55
85
) -> Optional [np .ndarray ]:
56
86
pass
57
87
88
+ async def encode_batch (
89
+ self ,
90
+ chunk_arrays_and_specs : Iterable [Tuple [Optional [np .ndarray ], ArraySpec ]],
91
+ runtime_configuration : RuntimeConfiguration ,
92
+ ) -> Iterable [Optional [np .ndarray ]]:
93
+ return await concurrent_map (
94
+ [
95
+ (chunk_array , chunk_spec , runtime_configuration )
96
+ for chunk_array , chunk_spec in chunk_arrays_and_specs
97
+ ],
98
+ noop_for_none (self .encode ),
99
+ runtime_configuration .concurrency ,
100
+ )
101
+
58
102
59
103
class ArrayBytesCodec (Codec ):
60
104
@abstractmethod
61
105
async def decode (
62
106
self ,
63
- chunk_array : BytesLike ,
107
+ chunk_bytes : BytesLike ,
64
108
chunk_spec : ArraySpec ,
65
109
runtime_configuration : RuntimeConfiguration ,
66
110
) -> np .ndarray :
67
111
pass
68
112
113
+ async def decode_batch (
114
+ self ,
115
+ chunk_bytes_and_specs : Iterable [Tuple [BytesLike , ArraySpec ]],
116
+ runtime_configuration : RuntimeConfiguration ,
117
+ ) -> Iterable [np .ndarray ]:
118
+ return await concurrent_map (
119
+ [
120
+ (chunk_bytes , chunk_spec , runtime_configuration )
121
+ for chunk_bytes , chunk_spec in chunk_bytes_and_specs
122
+ ],
123
+ noop_for_none (self .decode ),
124
+ runtime_configuration .concurrency ,
125
+ )
126
+
69
127
@abstractmethod
70
128
async def encode (
71
129
self ,
@@ -75,6 +133,20 @@ async def encode(
75
133
) -> Optional [BytesLike ]:
76
134
pass
77
135
136
+ async def encode_batch (
137
+ self ,
138
+ chunk_arrays_and_specs : Iterable [Tuple [Optional [np .ndarray ], ArraySpec ]],
139
+ runtime_configuration : RuntimeConfiguration ,
140
+ ) -> Iterable [Optional [BytesLike ]]:
141
+ return await concurrent_map (
142
+ [
143
+ (chunk_array , chunk_spec , runtime_configuration )
144
+ for chunk_array , chunk_spec in chunk_arrays_and_specs
145
+ ],
146
+ noop_for_none (self .encode ),
147
+ runtime_configuration .concurrency ,
148
+ )
149
+
78
150
79
151
class ArrayBytesCodecPartialDecodeMixin :
80
152
@abstractmethod
@@ -87,6 +159,20 @@ async def decode_partial(
87
159
) -> Optional [np .ndarray ]:
88
160
pass
89
161
162
+ async def decode_partial_batched (
163
+ self ,
164
+ batch_info : Iterable [Tuple [StorePath , SliceSelection , ArraySpec ]],
165
+ runtime_configuration : RuntimeConfiguration ,
166
+ ) -> Iterable [Optional [np .ndarray ]]:
167
+ return await concurrent_map (
168
+ [
169
+ (store_path , selection , chunk_spec , runtime_configuration )
170
+ for store_path , selection , chunk_spec in batch_info
171
+ ],
172
+ self .decode_partial ,
173
+ runtime_configuration .concurrency ,
174
+ )
175
+
90
176
91
177
class ArrayBytesCodecPartialEncodeMixin :
92
178
@abstractmethod
@@ -100,17 +186,45 @@ async def encode_partial(
100
186
) -> None :
101
187
pass
102
188
189
+ async def encode_partial_batched (
190
+ self ,
191
+ batch_info : Iterable [Tuple [StorePath , np .ndarray , SliceSelection , ArraySpec ]],
192
+ runtime_configuration : RuntimeConfiguration ,
193
+ ) -> None :
194
+ await concurrent_map (
195
+ [
196
+ (store_path , chunk_array , selection , chunk_spec , runtime_configuration )
197
+ for store_path , chunk_array , selection , chunk_spec in batch_info
198
+ ],
199
+ self .encode_partial ,
200
+ runtime_configuration .concurrency ,
201
+ )
202
+
103
203
104
204
class BytesBytesCodec (Codec ):
105
205
@abstractmethod
106
206
async def decode (
107
207
self ,
108
- chunk_array : BytesLike ,
208
+ chunk_bytes : BytesLike ,
109
209
chunk_spec : ArraySpec ,
110
210
runtime_configuration : RuntimeConfiguration ,
111
211
) -> BytesLike :
112
212
pass
113
213
214
+ async def decode_batch (
215
+ self ,
216
+ chunk_bytes_and_specs : Iterable [Tuple [BytesLike , ArraySpec ]],
217
+ runtime_configuration : RuntimeConfiguration ,
218
+ ) -> Iterable [BytesLike ]:
219
+ return await concurrent_map (
220
+ [
221
+ (chunk_bytes , chunk_spec , runtime_configuration )
222
+ for chunk_bytes , chunk_spec in chunk_bytes_and_specs
223
+ ],
224
+ noop_for_none (self .decode ),
225
+ runtime_configuration .concurrency ,
226
+ )
227
+
114
228
@abstractmethod
115
229
async def encode (
116
230
self ,
@@ -119,3 +233,17 @@ async def encode(
119
233
runtime_configuration : RuntimeConfiguration ,
120
234
) -> Optional [BytesLike ]:
121
235
pass
236
+
237
+ async def encode_batch (
238
+ self ,
239
+ chunk_bytes_and_specs : Iterable [Tuple [Optional [BytesLike ], ArraySpec ]],
240
+ runtime_configuration : RuntimeConfiguration ,
241
+ ) -> Iterable [Optional [BytesLike ]]:
242
+ return await concurrent_map (
243
+ [
244
+ (chunk_bytes , chunk_spec , runtime_configuration )
245
+ for chunk_bytes , chunk_spec in chunk_bytes_and_specs
246
+ ],
247
+ noop_for_none (self .encode ),
248
+ runtime_configuration .concurrency ,
249
+ )
0 commit comments