Skip to content

Commit fa61ed8

Browse files
abishop1990Cipher
andauthored
fix: BaseFloat._check_scalar rejects invalid string values (#3586) (#3762)
* fix: BaseFloat._check_scalar rejects invalid string values (#3586) BaseFloat._check_scalar returned True for all strings because the FloatLike type union includes str. This allowed invalid strings like 'not valid' to pass the check and then raise a confusing ValueError in _cast_scalar_unchecked instead of the expected TypeError. Fix _check_scalar to validate string inputs by attempting conversion: - Valid float strings (e.g. 'NaN', 'inf', '-inf', '1.5') return True - Invalid strings (e.g. 'not valid') return False, causing cast_scalar to raise TypeError as expected Add test cases for invalid string inputs to invalid_scalar_params. Fixes #3586 * style: fix ruff formatting and TRY300 in _check_scalar --------- Co-authored-by: Cipher <cipher@openclaw.ai>
1 parent 1cb1cce commit fa61ed8

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/zarr/core/dtype/npy/float.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@ def _check_scalar(self, data: object) -> TypeGuard[FloatLike]:
201201
TypeGuard[FloatLike]
202202
True if the input is a valid scalar value, False otherwise.
203203
"""
204+
if isinstance(data, str):
205+
# Only accept strings that are valid float representations (e.g. "NaN", "inf").
206+
# Plain strings that cannot be converted should return False so that cast_scalar
207+
# raises TypeError rather than a confusing ValueError.
208+
try:
209+
self.to_native_dtype().type(data)
210+
except (ValueError, OverflowError):
211+
return False
212+
else:
213+
return True
204214
return isinstance(data, FloatLike)
205215

206216
def _cast_scalar_unchecked(self, data: FloatLike) -> TFloatScalar_co:

tests/test_dtype/test_npy/test_float.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ class TestFloat16(_BaseTestFloat):
6565
(Float16(), -1.0, np.float16(-1.0)),
6666
(Float16(), "NaN", np.float16("NaN")),
6767
)
68-
invalid_scalar_params = ((Float16(), {"set!"}),)
68+
invalid_scalar_params = (
69+
(Float16(), {"set!"}),
70+
(Float16(), "not_a_float"),
71+
)
6972
hex_string_params = (("0x7fc0", np.nan), ("0x7fc1", np.nan), ("0x3c00", 1.0))
7073
item_size_params = (Float16(),)
7174

@@ -113,7 +116,10 @@ class TestFloat32(_BaseTestFloat):
113116
(Float32(), -1.0, np.float32(-1.0)),
114117
(Float32(), "NaN", np.float32("NaN")),
115118
)
116-
invalid_scalar_params = ((Float32(), {"set!"}),)
119+
invalid_scalar_params = (
120+
(Float32(), {"set!"}),
121+
(Float32(), "not_a_float"),
122+
)
117123
hex_string_params = (("0x7fc00000", np.nan), ("0x7fc00001", np.nan), ("0x3f800000", 1.0))
118124
item_size_params = (Float32(),)
119125

@@ -160,7 +166,10 @@ class TestFloat64(_BaseTestFloat):
160166
(Float64(), -1.0, np.float64(-1.0)),
161167
(Float64(), "NaN", np.float64("NaN")),
162168
)
163-
invalid_scalar_params = ((Float64(), {"set!"}),)
169+
invalid_scalar_params = (
170+
(Float64(), {"set!"}),
171+
(Float64(), "not_a_float"),
172+
)
164173
hex_string_params = (
165174
("0x7ff8000000000000", np.nan),
166175
("0x7ff8000000000001", np.nan),

0 commit comments

Comments
 (0)