4343
4444DEFAULT_DTYPE  =  "float64" 
4545
46+ # Keep in sync with _replace_special_floats 
47+ SPECIAL_FLOATS_ENCODED  =  {
48+     "Infinity" : np .inf ,
49+     "-Infinity" : - np .inf ,
50+     "NaN" : np .nan ,
51+ }
52+ 
4653
4754def  parse_zarr_format (data : object ) ->  Literal [3 ]:
4855    if  data  ==  3 :
@@ -149,7 +156,7 @@ def default(self, o: object) -> Any:
149156                if  isinstance (out , complex ):
150157                    # python complex types are not JSON serializable, so we use the 
151158                    # serialization defined in the zarr v3 spec 
152-                     return  [out .real , out .imag ]
159+                     return  _replace_special_floats ( [out .real , out .imag ]) 
153160                elif  np .isnan (out ):
154161                    return  "NaN" 
155162                elif  np .isinf (out ):
@@ -447,8 +454,11 @@ def parse_fill_value(
447454    if  isinstance (fill_value , Sequence ) and  not  isinstance (fill_value , str ):
448455        if  data_type  in  (DataType .complex64 , DataType .complex128 ):
449456            if  len (fill_value ) ==  2 :
457+                 decoded_fill_value  =  tuple (
458+                     SPECIAL_FLOATS_ENCODED .get (value , value ) for  value  in  fill_value 
459+                 )
450460                # complex datatypes serialize to JSON arrays with two elements 
451-                 return  np_dtype .type (complex (* fill_value ))
461+                 return  np_dtype .type (complex (* decoded_fill_value ))
452462            else :
453463                msg  =  (
454464                    f"Got an invalid fill value for complex data type { data_type .value }  ." 
@@ -475,12 +485,20 @@ def parse_fill_value(
475485        pass 
476486    elif  fill_value  in  ["Infinity" , "-Infinity" ] and  not  np .isfinite (casted_value ):
477487        pass 
478-     elif  np_dtype .kind  in   "cf " :
488+     elif  np_dtype .kind  ==   "f " :
479489        # float comparison is not exact, especially when dtype <float64 
480-         # so we us  np.isclose for this comparison. 
490+         # so we use  np.isclose for this comparison. 
481491        # this also allows us to compare nan fill_values 
482492        if  not  np .isclose (fill_value , casted_value , equal_nan = True ):
483493            raise  ValueError (f"fill value { fill_value !r}   is not valid for dtype { data_type }  " )
494+     elif  np_dtype .kind  ==  "c" :
495+         # confusingly np.isclose(np.inf, np.inf + 0j) is False on numpy<2, so compare real and imag parts 
496+         # explicitly. 
497+         if  not  (
498+             np .isclose (np .real (fill_value ), np .real (casted_value ), equal_nan = True )
499+             and  np .isclose (np .imag (fill_value ), np .imag (casted_value ), equal_nan = True )
500+         ):
501+             raise  ValueError (f"fill value { fill_value !r}   is not valid for dtype { data_type }  " )
484502    else :
485503        if  fill_value  !=  casted_value :
486504            raise  ValueError (f"fill value { fill_value !r}   is not valid for dtype { data_type }  " )
0 commit comments