@@ -44,13 +44,13 @@ class ScalarMapJSON(TypedDict):
4444OutOfRangeMode = Literal ["clamp" , "wrap" ]
4545
4646
47- class ScalarMap (TypedDict ):
47+ class ScalarMap (TypedDict , total = False ):
4848 """
4949 The normalized, in-memory form of a scalar map.
5050 """
5151
52- encode : NotRequired [ Mapping [str | float | int , str | float | int ] ]
53- decode : NotRequired [ Mapping [str | float | int , str | float | int ] ]
52+ encode : Mapping [str | float | int , str | float | int ]
53+ decode : Mapping [str | float | int , str | float | int ]
5454
5555
5656def parse_scalar_map (obj : ScalarMapJSON | ScalarMap ) -> ScalarMap :
@@ -85,33 +85,18 @@ def parse_scalar_map(obj: ScalarMapJSON | ScalarMap) -> ScalarMap:
8585 _HAS_RUST_BACKEND = False
8686
8787
88- def _check_scalar_representable (
89- value : str | float ,
90- dtype : np .dtype , # type: ignore[type-arg]
91- direction : str ,
92- role : str ,
88+ def _check_representable (
89+ value : JSON ,
90+ zdtype : ZDType [TBaseDType , TBaseScalar ],
91+ label : str ,
9392) -> None :
94- """Raise ``ValueError`` if *value* cannot be represented in *dtype *."""
95- fval = float ( value )
96- is_integer_dtype = np . issubdtype ( dtype , np . integer )
97- if np . isnan ( fval ) and is_integer_dtype :
93+ """Raise ``ValueError`` if *value* cannot be parsed by *zdtype *."""
94+ try :
95+ zdtype . from_json_scalar ( value , zarr_format = 3 )
96+ except ( TypeError , ValueError , OverflowError ) as e :
9897 raise ValueError (
99- f"scalar_map { direction } { role } { value !r} is NaN, "
100- f"which is not representable in integer dtype { dtype } ."
101- )
102- if is_integer_dtype :
103- info = np .iinfo (dtype )
104- ival = int (fval )
105- if float (ival ) != fval :
106- raise ValueError (
107- f"scalar_map { direction } { role } { value !r} is not an integer, "
108- f"which is required for integer dtype { dtype } ."
109- )
110- if ival < info .min or ival > info .max :
111- raise ValueError (
112- f"scalar_map { direction } { role } { value !r} is out of range "
113- f"for dtype { dtype } [{ info .min } , { info .max } ]."
114- )
98+ f"{ label } { value !r} is not representable in dtype { zdtype .to_native_dtype ()} ."
99+ ) from e
115100
116101
117102# ---------------------------------------------------------------------------
@@ -215,28 +200,30 @@ def validate(
215200 raise ValueError ("out_of_range='wrap' is only valid for integer target types." )
216201
217202 if self .scalar_map is not None :
218- self ._validate_scalar_map (source_native , target_native )
203+ self ._validate_scalar_map (dtype , self . dtype )
219204
220205 def _validate_scalar_map (
221206 self ,
222- source_native : np . dtype , # type: ignore[type-arg]
223- target_native : np . dtype , # type: ignore[type-arg]
207+ source_zdtype : ZDType [ TBaseDType , TBaseScalar ],
208+ target_zdtype : ZDType [ TBaseDType , TBaseScalar ],
224209 ) -> None :
225210 """Validate that scalar map entries are compatible with source/target dtypes."""
226211 assert self .scalar_map is not None
227212 # For encode: keys are source values, values are target values.
228213 # For decode: keys are target values, values are source values.
229- direction_dtypes = {
230- "encode" : (source_native , target_native ),
231- "decode" : (target_native , source_native ),
214+ direction_dtypes : dict [
215+ str , tuple [ZDType [TBaseDType , TBaseScalar ], ZDType [TBaseDType , TBaseScalar ]]
216+ ] = {
217+ "encode" : (source_zdtype , target_zdtype ),
218+ "decode" : (target_zdtype , source_zdtype ),
232219 }
233- for direction , (key_dtype , val_dtype ) in direction_dtypes .items ():
220+ for direction , (key_zdtype , val_zdtype ) in direction_dtypes .items ():
234221 if direction not in self .scalar_map :
235222 continue
236223 sub_map = self .scalar_map [direction ] # type: ignore[literal-required]
237224 for k , v in sub_map .items ():
238- _check_scalar_representable (k , key_dtype , direction , " key" )
239- _check_scalar_representable (v , val_dtype , direction , " value" )
225+ _check_representable (k , key_zdtype , f"scalar_map { direction } key" )
226+ _check_representable (v , val_zdtype , f"scalar_map { direction } value" )
240227
241228 def _do_cast (
242229 self ,
0 commit comments