28
28
import asyncio
29
29
import math
30
30
from dataclasses import dataclass , replace
31
- from functools import cached_property , partial
32
- from typing import Any , Self , TypeVar
31
+ from functools import cached_property
32
+ from typing import Any , Self
33
33
from warnings import warn
34
34
35
35
import numpy as np
@@ -79,6 +79,18 @@ class _NumcodecsCodec(Metadata):
79
79
codec_name : str
80
80
codec_config : dict [str , JSON ]
81
81
82
+ def __init_subclass__ (cls , * , codec_name : str | None = None , ** kwargs ):
83
+ """To be used only when creating the actual public-facing codec class."""
84
+ super ().__init_subclass__ (** kwargs )
85
+ if codec_name is not None :
86
+ namespace = codec_name
87
+
88
+ cls_name = f"{ CODEC_PREFIX } { namespace } .{ cls .__name__ } "
89
+ cls .codec_name = f"{ CODEC_PREFIX } { namespace } "
90
+ cls .__doc__ = f"""
91
+ See :class:`{ cls_name } ` for more details and parameters.
92
+ """
93
+
82
94
def __init__ (self , ** codec_config : JSON ) -> None :
83
95
if not self .codec_name :
84
96
raise ValueError (
@@ -180,128 +192,55 @@ async def _encode_single(self, chunk_ndbuffer: NDBuffer, chunk_spec: ArraySpec)
180
192
return chunk_spec .prototype .buffer .from_bytes (out )
181
193
182
194
183
- T = TypeVar ("T" , bound = _NumcodecsCodec )
184
-
185
-
186
- def _add_docstring (cls : type [T ], ref_class_name : str ) -> type [T ]:
187
- cls .__doc__ = f"""
188
- See :class:`{ ref_class_name } ` for more details and parameters.
189
- """
190
- return cls
191
-
192
-
193
- def _add_docstring_wrapper (ref_class_name : str ) -> partial :
194
- return partial (_add_docstring , ref_class_name = ref_class_name )
195
-
196
-
197
- def _make_bytes_bytes_codec (codec_name : str , cls_name : str ) -> type [_NumcodecsBytesBytesCodec ]:
198
- # rename for class scope
199
- _codec_name = CODEC_PREFIX + codec_name
200
-
201
- class _Codec (_NumcodecsBytesBytesCodec ):
202
- codec_name = _codec_name
203
-
204
- def __init__ (self , ** codec_config : JSON ) -> None :
205
- super ().__init__ (** codec_config )
206
-
207
- _Codec .__name__ = cls_name
208
- return _Codec
209
-
210
-
211
- def _make_array_array_codec (codec_name : str , cls_name : str ) -> type [_NumcodecsArrayArrayCodec ]:
212
- # rename for class scope
213
- _codec_name = CODEC_PREFIX + codec_name
214
-
215
- class _Codec (_NumcodecsArrayArrayCodec ):
216
- codec_name = _codec_name
217
-
218
- def __init__ (self , ** codec_config : JSON ) -> None :
219
- super ().__init__ (** codec_config )
220
-
221
- _Codec .__name__ = cls_name
222
- return _Codec
223
-
224
-
225
- def _make_array_bytes_codec (codec_name : str , cls_name : str ) -> type [_NumcodecsArrayBytesCodec ]:
226
- # rename for class scope
227
- _codec_name = CODEC_PREFIX + codec_name
195
+ # bytes-to-bytes codecs
196
+ class Blosc (_NumcodecsBytesBytesCodec , codec_name = "blosc" ):
197
+ pass
228
198
229
- class _Codec (_NumcodecsArrayBytesCodec ):
230
- codec_name = _codec_name
231
199
232
- def __init__ ( self , ** codec_config : JSON ) -> None :
233
- super (). __init__ ( ** codec_config )
200
+ class LZ4 ( _NumcodecsBytesBytesCodec , codec_name = "lz4" ) :
201
+ pass
234
202
235
- _Codec .__name__ = cls_name
236
- return _Codec
237
203
204
+ class Zstd (_NumcodecsBytesBytesCodec , codec_name = "zstd" ):
205
+ pass
238
206
239
- def _make_checksum_codec (codec_name : str , cls_name : str ) -> type [_NumcodecsBytesBytesCodec ]:
240
- # rename for class scope
241
- _codec_name = CODEC_PREFIX + codec_name
242
207
243
- class _ChecksumCodec (_NumcodecsBytesBytesCodec ):
244
- codec_name = _codec_name
208
+ class Zlib (_NumcodecsBytesBytesCodec , codec_name = "zlib" ):
209
+ pass
245
210
246
- def __init__ (self , ** codec_config : JSON ) -> None :
247
- super ().__init__ (** codec_config )
248
211
249
- def compute_encoded_size ( self , input_byte_length : int , chunk_spec : ArraySpec ) -> int :
250
- return input_byte_length + 4 # pragma: no cover
212
+ class GZip ( _NumcodecsBytesBytesCodec , codec_name = "gzip" ) :
213
+ pass
251
214
252
- _ChecksumCodec .__name__ = cls_name
253
- return _ChecksumCodec
254
215
216
+ class BZ2 (_NumcodecsBytesBytesCodec , codec_name = "bz2" ):
217
+ pass
255
218
256
- # bytes-to-bytes codecs
257
- Blosc = _add_docstring (_make_bytes_bytes_codec ("blosc" , "Blosc" ), "numcodecs.blosc.Blosc" )
258
- LZ4 = _add_docstring (_make_bytes_bytes_codec ("lz4" , "LZ4" ), "numcodecs.lz4.LZ4" )
259
- Zstd = _add_docstring (_make_bytes_bytes_codec ("zstd" , "Zstd" ), "numcodecs.zstd.Zstd" )
260
- Zlib = _add_docstring (_make_bytes_bytes_codec ("zlib" , "Zlib" ), "numcodecs.zlib.Zlib" )
261
- GZip = _add_docstring (_make_bytes_bytes_codec ("gzip" , "GZip" ), "numcodecs.gzip.GZip" )
262
- BZ2 = _add_docstring (_make_bytes_bytes_codec ("bz2" , "BZ2" ), "numcodecs.bz2.BZ2" )
263
- LZMA = _add_docstring (_make_bytes_bytes_codec ("lzma" , "LZMA" ), "numcodecs.lzma.LZMA" )
264
219
220
+ class LZMA (_NumcodecsBytesBytesCodec , codec_name = "lzma" ):
221
+ pass
265
222
266
- @_add_docstring_wrapper ("numcodecs.shuffle.Shuffle" )
267
- class Shuffle (_NumcodecsBytesBytesCodec ):
268
- codec_name = f"{ CODEC_PREFIX } shuffle"
269
-
270
- def __init__ (self , ** codec_config : JSON ) -> None :
271
- super ().__init__ (** codec_config )
272
223
224
+ class Shuffle (_NumcodecsBytesBytesCodec , codec_name = "shuffle" ):
273
225
def evolve_from_array_spec (self , array_spec : ArraySpec ) -> Shuffle :
274
226
if self .codec_config .get ("elementsize" , None ) is None :
275
227
return Shuffle (** {** self .codec_config , "elementsize" : array_spec .dtype .itemsize })
276
228
return self # pragma: no cover
277
229
278
230
279
231
# array-to-array codecs ("filters")
280
- @_add_docstring_wrapper ("numcodecs.delta.Delta" )
281
- class Delta (_NumcodecsArrayArrayCodec ):
282
- codec_name = f"{ CODEC_PREFIX } delta"
283
-
284
- def __init__ (self , ** codec_config : dict [str , JSON ]) -> None :
285
- super ().__init__ (** codec_config )
286
-
232
+ class Delta (_NumcodecsArrayArrayCodec , codec_name = "delta" ):
287
233
def resolve_metadata (self , chunk_spec : ArraySpec ) -> ArraySpec :
288
234
if astype := self .codec_config .get ("astype" ):
289
235
return replace (chunk_spec , dtype = np .dtype (astype )) # type: ignore[call-overload]
290
236
return chunk_spec
291
237
292
238
293
- BitRound = _add_docstring (
294
- _make_array_array_codec ("bitround" , "BitRound" ), "numcodecs.bitround.BitRound"
295
- )
296
-
239
+ class BitRound (_NumcodecsArrayArrayCodec , codec_name = "bitround" ):
240
+ pass
297
241
298
- @_add_docstring_wrapper ("numcodecs.fixedscaleoffset.FixedScaleOffset" )
299
- class FixedScaleOffset (_NumcodecsArrayArrayCodec ):
300
- codec_name = f"{ CODEC_PREFIX } fixedscaleoffset"
301
-
302
- def __init__ (self , ** codec_config : JSON ) -> None :
303
- super ().__init__ (** codec_config )
304
242
243
+ class FixedScaleOffset (_NumcodecsArrayArrayCodec , codec_name = "fixedscaleoffset" ):
305
244
def resolve_metadata (self , chunk_spec : ArraySpec ) -> ArraySpec :
306
245
if astype := self .codec_config .get ("astype" ):
307
246
return replace (chunk_spec , dtype = np .dtype (astype )) # type: ignore[call-overload]
@@ -313,10 +252,7 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> FixedScaleOffset:
313
252
return self
314
253
315
254
316
- @_add_docstring_wrapper ("numcodecs.quantize.Quantize" )
317
- class Quantize (_NumcodecsArrayArrayCodec ):
318
- codec_name = f"{ CODEC_PREFIX } quantize"
319
-
255
+ class Quantize (_NumcodecsArrayArrayCodec , codec_name = "quantize" ):
320
256
def __init__ (self , ** codec_config : JSON ) -> None :
321
257
super ().__init__ (** codec_config )
322
258
@@ -326,13 +262,7 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> Quantize:
326
262
return self
327
263
328
264
329
- @_add_docstring_wrapper ("numcodecs.packbits.PackBits" )
330
- class PackBits (_NumcodecsArrayArrayCodec ):
331
- codec_name = f"{ CODEC_PREFIX } packbits"
332
-
333
- def __init__ (self , ** codec_config : JSON ) -> None :
334
- super ().__init__ (** codec_config )
335
-
265
+ class PackBits (_NumcodecsArrayArrayCodec , codec_name = "packbits" ):
336
266
def resolve_metadata (self , chunk_spec : ArraySpec ) -> ArraySpec :
337
267
return replace (
338
268
chunk_spec ,
@@ -345,13 +275,7 @@ def validate(self, *, dtype: np.dtype[Any], **_kwargs) -> None:
345
275
raise ValueError (f"Packbits filter requires bool dtype. Got { dtype } ." )
346
276
347
277
348
- @_add_docstring_wrapper ("numcodecs.astype.AsType" )
349
- class AsType (_NumcodecsArrayArrayCodec ):
350
- codec_name = f"{ CODEC_PREFIX } astype"
351
-
352
- def __init__ (self , ** codec_config : JSON ) -> None :
353
- super ().__init__ (** codec_config )
354
-
278
+ class AsType (_NumcodecsArrayArrayCodec , codec_name = "astype" ):
355
279
def resolve_metadata (self , chunk_spec : ArraySpec ) -> ArraySpec :
356
280
return replace (chunk_spec , dtype = np .dtype (self .codec_config ["encode_dtype" ])) # type: ignore[arg-type]
357
281
@@ -362,19 +286,39 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> AsType:
362
286
363
287
364
288
# bytes-to-bytes checksum codecs
365
- CRC32 = _add_docstring (_make_checksum_codec ("crc32" , "CRC32" ), "numcodecs.checksum32.CRC32" )
366
- CRC32C = _add_docstring (_make_checksum_codec ("crc32c" , "CRC32C" ), "numcodecs.checksum32.CRC32C" )
367
- Adler32 = _add_docstring (_make_checksum_codec ("adler32" , "Adler32" ), "numcodecs.checksum32.Adler32" )
368
- Fletcher32 = _add_docstring (
369
- _make_checksum_codec ("fletcher32" , "Fletcher32" ), "numcodecs.fletcher32.Fletcher32"
370
- )
371
- JenkinsLookup3 = _add_docstring (
372
- _make_checksum_codec ("jenkins_lookup3" , "JenkinsLookup3" ), "numcodecs.checksum32.JenkinsLookup3"
373
- )
289
+ class _NumcodecsChecksumCodec (_NumcodecsBytesBytesCodec ):
290
+ def compute_encoded_size (self , input_byte_length : int , chunk_spec : ArraySpec ) -> int :
291
+ return input_byte_length + 4 # pragma: no cover
292
+
293
+
294
+ class CRC32 (_NumcodecsChecksumCodec , codec_name = "crc32" ):
295
+ pass
296
+
297
+
298
+ class CRC32C (_NumcodecsChecksumCodec , codec_name = "crc32c" ):
299
+ pass
300
+
301
+
302
+ class Adler32 (_NumcodecsChecksumCodec , codec_name = "adler32" ):
303
+ pass
304
+
305
+
306
+ class Fletcher32 (_NumcodecsChecksumCodec , codec_name = "fletcher32" ):
307
+ pass
308
+
309
+
310
+ class JenkinsLookup3 (_NumcodecsChecksumCodec , codec_name = "jenkins_lookup3" ):
311
+ pass
312
+
374
313
375
314
# array-to-bytes codecs
376
- PCodec = _add_docstring (_make_array_bytes_codec ("pcodec" , "PCodec" ), "numcodecs.pcodec.PCodec" )
377
- ZFPY = _add_docstring (_make_array_bytes_codec ("zfpy" , "ZFPY" ), "numcodecs.zfpy.ZFPY" )
315
+ class PCodec (_NumcodecsArrayBytesCodec , codec_name = "pcodec" ):
316
+ pass
317
+
318
+
319
+ class ZFPY (_NumcodecsArrayBytesCodec , codec_name = "zfpy" ):
320
+ pass
321
+
378
322
379
323
__all__ = [
380
324
"BZ2" ,
0 commit comments