@@ -309,6 +309,9 @@ def encode(self, variable: Variable, name: T_Name = None):
309
309
dtype = np .dtype (encoding .get ("dtype" , data .dtype ))
310
310
fv = encoding .get ("_FillValue" )
311
311
mv = encoding .get ("missing_value" )
312
+ # to properly handle _FillValue/missing_value below [a], [b]
313
+ # we need to check if unsigned data is written as signed data
314
+ unsigned = encoding .get ("_Unsigned" ) is not None
312
315
313
316
fv_exists = fv is not None
314
317
mv_exists = mv is not None
@@ -323,13 +326,19 @@ def encode(self, variable: Variable, name: T_Name = None):
323
326
324
327
if fv_exists :
325
328
# Ensure _FillValue is cast to same dtype as data's
326
- encoding ["_FillValue" ] = dtype .type (fv )
329
+ # [a] need to skip this if _Unsigned is available
330
+ if not unsigned :
331
+ encoding ["_FillValue" ] = dtype .type (fv )
327
332
fill_value = pop_to (encoding , attrs , "_FillValue" , name = name )
328
333
329
334
if mv_exists :
330
335
# try to use _FillValue, if it exists to align both values
331
336
# or use missing_value and ensure it's cast to same dtype as data's
332
- encoding ["missing_value" ] = attrs .get ("_FillValue" , dtype .type (mv ))
337
+ # [b] need to provide mv verbatim if _Unsigned is available
338
+ encoding ["missing_value" ] = attrs .get (
339
+ "_FillValue" ,
340
+ (dtype .type (mv ) if not unsigned else mv ),
341
+ )
333
342
fill_value = pop_to (encoding , attrs , "missing_value" , name = name )
334
343
335
344
# apply fillna
@@ -522,7 +531,6 @@ def encode(self, variable: Variable, name: T_Name = None) -> Variable:
522
531
def decode (self , variable : Variable , name : T_Name = None ) -> Variable :
523
532
if "_Unsigned" in variable .attrs :
524
533
dims , data , attrs , encoding = unpack_for_decoding (variable )
525
-
526
534
unsigned = pop_to (attrs , encoding , "_Unsigned" )
527
535
528
536
if data .dtype .kind == "i" :
0 commit comments