|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import warnings |
3 | 4 | from typing import TYPE_CHECKING, cast, overload |
4 | 5 |
|
5 | 6 | if TYPE_CHECKING: |
@@ -349,12 +350,25 @@ def parse_fill_value( |
349 | 350 |
|
350 | 351 | # Cast the fill_value to the given dtype |
351 | 352 | try: |
352 | | - casted_value = np.dtype(dtype).type(fill_value) |
| 353 | + # This warning filter can be removed after Zarr supports numpy>=2.0 |
| 354 | + # The warning is saying that the future behavior of out of bounds casting will be to raise |
| 355 | + # an OverflowError. In the meantime, we allow overflow and catch cases where |
| 356 | + # fill_value != casted_value below. |
| 357 | + with warnings.catch_warnings(): |
| 358 | + warnings.filterwarnings("ignore", category=DeprecationWarning) |
| 359 | + casted_value = np.dtype(dtype).type(fill_value) |
353 | 360 | except (ValueError, OverflowError, TypeError) as e: |
354 | 361 | raise ValueError(f"fill value {fill_value!r} is not valid for dtype {dtype}") from e |
355 | 362 | # Check if the value is still representable by the dtype |
356 | | - if fill_value != casted_value and not (np.isnan(fill_value) and np.isnan(casted_value)): |
357 | | - raise ValueError(f"fill value {fill_value!r} is not valid for dtype {dtype}") |
| 363 | + if dtype.kind == "f": |
| 364 | + # float comparison is not exact, especially when dtype <float64 |
| 365 | + # so we us np.isclose for this comparison. |
| 366 | + # this also allows us to compare nan fill_values |
| 367 | + if not np.isclose(fill_value, casted_value, equal_nan=True): |
| 368 | + raise ValueError(f"fill value {fill_value!r} is not valid for dtype {dtype}") |
| 369 | + else: |
| 370 | + if fill_value != casted_value: |
| 371 | + raise ValueError(f"fill value {fill_value!r} is not valid for dtype {dtype}") |
358 | 372 |
|
359 | 373 | return casted_value |
360 | 374 |
|
|
0 commit comments