@@ -143,6 +143,7 @@ class MockEnvCodecPipeline(CodecPipeline):
143143 assert get_pipeline_class (reload_config = True ) == MockEnvCodecPipeline
144144
145145
146+ @pytest .mark .filterwarnings ("error" )
146147@pytest .mark .parametrize ("store" , ["local" , "memory" ], indirect = ["store" ])
147148def test_config_codec_implementation (store : Store ) -> None :
148149 # has default value
@@ -156,24 +157,29 @@ async def _encode_single(
156157 ) -> CodecOutput | None :
157158 _mock .call ()
158159
159- config .set ({"codecs.blosc" : fully_qualified_name (MockBloscCodec )})
160160 register_codec ("blosc" , MockBloscCodec )
161- assert get_codec_class ("blosc" ) == MockBloscCodec
162-
163- # test if codec is used
164- arr = Array .create (
165- store = store ,
166- shape = (100 ,),
167- chunks = (10 ,),
168- zarr_format = 3 ,
169- dtype = "i4" ,
170- codecs = [BytesCodec (), {"name" : "blosc" , "configuration" : {}}],
171- )
172- arr [:] = range (100 )
173- _mock .call .assert_called ()
161+ with config .set ({"codecs.blosc" : fully_qualified_name (MockBloscCodec )}):
162+ assert get_codec_class ("blosc" ) == MockBloscCodec
163+
164+ # test if codec is used
165+ arr = Array .create (
166+ store = store ,
167+ shape = (100 ,),
168+ chunks = (10 ,),
169+ zarr_format = 3 ,
170+ dtype = "i4" ,
171+ codecs = [BytesCodec (), {"name" : "blosc" , "configuration" : {}}],
172+ )
173+ arr [:] = range (100 )
174+ _mock .call .assert_called ()
175+
176+ # test set codec with environment variable
177+ class NewBloscCodec (BloscCodec ):
178+ pass
174179
175- with mock .patch .dict (os .environ , {"ZARR_CODECS__BLOSC" : fully_qualified_name (BloscCodec )}):
176- assert get_codec_class ("blosc" , reload_config = True ) == BloscCodec
180+ register_codec ("blosc" , NewBloscCodec )
181+ with mock .patch .dict (os .environ , {"ZARR_CODECS__BLOSC" : fully_qualified_name (NewBloscCodec )}):
182+ assert get_codec_class ("blosc" , reload_config = True ) == NewBloscCodec
177183
178184
179185@pytest .mark .parametrize ("store" , ["local" , "memory" ], indirect = ["store" ])
@@ -183,18 +189,17 @@ def test_config_ndbuffer_implementation(store: Store) -> None:
183189
184190 # set custom ndbuffer with TestNDArrayLike implementation
185191 register_ndbuffer (NDBufferUsingTestNDArrayLike )
186- config .set ({"ndbuffer" : fully_qualified_name (NDBufferUsingTestNDArrayLike )})
187- assert get_ndbuffer_class () == NDBufferUsingTestNDArrayLike
188- arr = Array .create (
189- store = store ,
190- shape = (100 ,),
191- chunks = (10 ,),
192- zarr_format = 3 ,
193- dtype = "i4" ,
194- )
195- got = arr [:]
196- print (type (got ))
197- assert isinstance (got , TestNDArrayLike )
192+ with config .set ({"ndbuffer" : fully_qualified_name (NDBufferUsingTestNDArrayLike )}):
193+ assert get_ndbuffer_class () == NDBufferUsingTestNDArrayLike
194+ arr = Array .create (
195+ store = store ,
196+ shape = (100 ,),
197+ chunks = (10 ,),
198+ zarr_format = 3 ,
199+ dtype = "i4" ,
200+ )
201+ got = arr [:]
202+ assert isinstance (got , TestNDArrayLike )
198203
199204
200205def test_config_buffer_implementation () -> None :
@@ -208,27 +213,53 @@ def test_config_buffer_implementation() -> None:
208213 arr [:] = np .arange (100 )
209214
210215 register_buffer (TestBuffer )
211- config .set ({"buffer" : fully_qualified_name (TestBuffer )})
212- assert get_buffer_class () == TestBuffer
213-
214- # no error using TestBuffer
215- data = np .arange (100 )
216- arr [:] = np .arange (100 )
217- assert np .array_equal (arr [:], data )
218-
219- data2d = np .arange (1000 ).reshape (100 , 10 )
220- arr_sharding = zeros (
221- shape = (100 , 10 ),
222- store = StoreExpectingTestBuffer (),
223- codecs = [ShardingCodec (chunk_shape = (10 , 10 ))],
224- )
225- arr_sharding [:] = data2d
226- assert np .array_equal (arr_sharding [:], data2d )
216+ with config .set ({"buffer" : fully_qualified_name (TestBuffer )}):
217+ assert get_buffer_class () == TestBuffer
227218
228- arr_Crc32c = zeros (
229- shape = (100 , 10 ),
230- store = StoreExpectingTestBuffer (),
231- codecs = [BytesCodec (), Crc32cCodec ()],
232- )
233- arr_Crc32c [:] = data2d
234- assert np .array_equal (arr_Crc32c [:], data2d )
219+ # no error using TestBuffer
220+ data = np .arange (100 )
221+ arr [:] = np .arange (100 )
222+ assert np .array_equal (arr [:], data )
223+
224+ data2d = np .arange (1000 ).reshape (100 , 10 )
225+ arr_sharding = zeros (
226+ shape = (100 , 10 ),
227+ store = StoreExpectingTestBuffer (),
228+ codecs = [ShardingCodec (chunk_shape = (10 , 10 ))],
229+ )
230+ arr_sharding [:] = data2d
231+ assert np .array_equal (arr_sharding [:], data2d )
232+
233+ arr_Crc32c = zeros (
234+ shape = (100 , 10 ),
235+ store = StoreExpectingTestBuffer (),
236+ codecs = [BytesCodec (), Crc32cCodec ()],
237+ )
238+ arr_Crc32c [:] = data2d
239+ assert np .array_equal (arr_Crc32c [:], data2d )
240+
241+
242+ @pytest .mark .filterwarnings ("error" )
243+ def test_warning_on_missing_codec_config () -> None :
244+ class NewCodec (BytesCodec ):
245+ pass
246+
247+ class NewCodec2 (BytesCodec ):
248+ pass
249+
250+ # error if codec is not registered
251+ with pytest .raises (KeyError ):
252+ get_codec_class ("missing_codec" )
253+
254+ # no warning if only one implementation is available
255+ register_codec ("new_codec" , NewCodec )
256+ get_codec_class ("new_codec" )
257+
258+ # warning because multiple implementations are available but none is selected in the config
259+ register_codec ("new_codec" , NewCodec2 )
260+ with pytest .warns (UserWarning ):
261+ get_codec_class ("new_codec" )
262+
263+ # no warning if multiple implementations are available and one is selected in the config
264+ with config .set ({"codecs.new_codec" : fully_qualified_name (NewCodec )}):
265+ get_codec_class ("new_codec" )
0 commit comments