66
77import asyncio
88from dataclasses import dataclass
9- from typing import TYPE_CHECKING , Callable , Literal , Self , TypeGuard , overload
9+ from typing import TYPE_CHECKING , Literal , Self , TypeGuard , overload
1010
11- import numcodecs
12- import numcodecs .registry as numcodecs_registry
1311import numpy as np
1412from typing_extensions import Protocol , runtime_checkable
1513
3129
3230BufferOrNDArray = Buffer | np .ndarray [tuple [int , ...], np .dtype [np .generic ]] | NDArrayLike
3331
32+
3433def get_numcodec_class (name : str ) -> type [Numcodec ]:
3534 """Obtain a numcodec codec class by name.
3635
@@ -52,6 +51,8 @@ def get_numcodec_class(name: str) -> type[Numcodec]:
5251 Zlib(level=1)
5352
5453 """
54+ import numcodecs .registry as numcodecs_registry
55+
5556 cls = numcodecs_registry .codec_registry .get (name )
5657 if cls is None and name in numcodecs_registry .entries :
5758 cls = numcodecs_registry .entries [name ].load ()
@@ -60,9 +61,6 @@ def get_numcodec_class(name: str) -> type[Numcodec]:
6061 return cls
6162 raise KeyError (name )
6263
63- def resolve_numcodec (config : CodecJSON_V2 [str ]) -> Numcodec :
64- return numcodecs .get_codec (config ) # type: ignore[no-any-return]
65-
6664
6765@runtime_checkable
6866class Numcodec (Protocol ):
@@ -83,25 +81,26 @@ def get_config(self) -> CodecJSON_V2[str]: ...
8381 @classmethod
8482 def from_config (cls , config : CodecJSON_V2 [str ]) -> Self : ...
8583
84+
8685def is_numcodec_cls (obj : object ) -> TypeGuard [type [Numcodec ]]:
8786 """
8887 Check if the given object implements the Numcodec protocol. Because the @runtime_checkable
8988 decorator does not allow issubclass checks for protocols with non-method members (i.e., attributes),
9089 we need to manually check for the presence of the required attributes and methods.
9190 """
9291 return (
93- isinstance (obj , type ) and
94- hasattr (obj , "codec_id" ) and
95- isinstance (obj .codec_id , str ) and
96- hasattr (obj , "encode" ) and
97- callable (obj .encode ) and
98- hasattr (obj , "decode" ) and
99- callable (obj .decode ) and
100- hasattr (obj , "get_config" ) and
101- callable (obj .get_config ) and
102- hasattr (obj , "from_config" ) and
103- callable (obj .from_config )
104- )
92+ isinstance (obj , type )
93+ and hasattr (obj , "codec_id" )
94+ and isinstance (obj .codec_id , str )
95+ and hasattr (obj , "encode" )
96+ and callable (obj .encode )
97+ and hasattr (obj , "decode" )
98+ and callable (obj .decode )
99+ and hasattr (obj , "get_config" )
100+ and callable (obj .get_config )
101+ and hasattr (obj , "from_config" )
102+ and callable (obj .from_config )
103+ )
105104
106105
107106@dataclass (frozen = True , kw_only = True )
@@ -113,9 +112,7 @@ def to_json(self, zarr_format: Literal[2]) -> CodecJSON_V2[str]: ...
113112 @overload
114113 def to_json (self , zarr_format : Literal [3 ]) -> NamedConfig [str , BaseConfig ]: ...
115114
116- def to_json (
117- self , zarr_format : ZarrFormat
118- ) -> CodecJSON_V2 [str ] | NamedConfig [str , BaseConfig ]:
115+ def to_json (self , zarr_format : ZarrFormat ) -> CodecJSON_V2 [str ] | NamedConfig [str , BaseConfig ]:
119116 if zarr_format == 2 :
120117 return self .codec .get_config ()
121118 elif zarr_format == 3 :
@@ -126,7 +123,9 @@ def to_json(
126123
127124 @classmethod
128125 def _from_json_v2 (cls , data : CodecJSON ) -> Self :
129- return cls (codec = resolve_numcodec (data )) # type: ignore[arg-type]
126+ raise NotADirectoryError (
127+ "This class does not support creating instances from JSON data for Zarr format 2."
128+ )
130129
131130 @classmethod
132131 def _from_json_v3 (cls , data : CodecJSON ) -> Self :
@@ -137,7 +136,6 @@ def _from_json_v3(cls, data: CodecJSON) -> Self:
137136 def compute_encoded_size (self , input_byte_length : int , chunk_spec : ArraySpec ) -> int :
138137 raise NotImplementedError
139138
140-
141139 def to_array_array (self ) -> NumcodecsArrayArrayCodec :
142140 """
143141 Use the ``_codec`` attribute to create a NumcodecsArrayArrayCodec.
0 commit comments