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