diff --git a/src/zarr/core/dtype/npy/float.py b/src/zarr/core/dtype/npy/float.py index 0be2cbca9b..2a23cb429d 100644 --- a/src/zarr/core/dtype/npy/float.py +++ b/src/zarr/core/dtype/npy/float.py @@ -201,6 +201,16 @@ def _check_scalar(self, data: object) -> TypeGuard[FloatLike]: TypeGuard[FloatLike] True if the input is a valid scalar value, False otherwise. """ + if isinstance(data, str): + # Only accept strings that are valid float representations (e.g. "NaN", "inf"). + # Plain strings that cannot be converted should return False so that cast_scalar + # raises TypeError rather than a confusing ValueError. + try: + self.to_native_dtype().type(data) + except (ValueError, OverflowError): + return False + else: + return True return isinstance(data, FloatLike) def _cast_scalar_unchecked(self, data: FloatLike) -> TFloatScalar_co: diff --git a/tests/test_dtype/test_npy/test_float.py b/tests/test_dtype/test_npy/test_float.py index 1bbcbbc81f..8d8e768263 100644 --- a/tests/test_dtype/test_npy/test_float.py +++ b/tests/test_dtype/test_npy/test_float.py @@ -65,7 +65,10 @@ class TestFloat16(_BaseTestFloat): (Float16(), -1.0, np.float16(-1.0)), (Float16(), "NaN", np.float16("NaN")), ) - invalid_scalar_params = ((Float16(), {"set!"}),) + invalid_scalar_params = ( + (Float16(), {"set!"}), + (Float16(), "not_a_float"), + ) hex_string_params = (("0x7fc0", np.nan), ("0x7fc1", np.nan), ("0x3c00", 1.0)) item_size_params = (Float16(),) @@ -113,7 +116,10 @@ class TestFloat32(_BaseTestFloat): (Float32(), -1.0, np.float32(-1.0)), (Float32(), "NaN", np.float32("NaN")), ) - invalid_scalar_params = ((Float32(), {"set!"}),) + invalid_scalar_params = ( + (Float32(), {"set!"}), + (Float32(), "not_a_float"), + ) hex_string_params = (("0x7fc00000", np.nan), ("0x7fc00001", np.nan), ("0x3f800000", 1.0)) item_size_params = (Float32(),) @@ -160,7 +166,10 @@ class TestFloat64(_BaseTestFloat): (Float64(), -1.0, np.float64(-1.0)), (Float64(), "NaN", np.float64("NaN")), ) - invalid_scalar_params = ((Float64(), {"set!"}),) + invalid_scalar_params = ( + (Float64(), {"set!"}), + (Float64(), "not_a_float"), + ) hex_string_params = ( ("0x7ff8000000000000", np.nan), ("0x7ff8000000000001", np.nan),