Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite1990c0

Browse files
authored
Fix string integer parsing (#3489)
* fix: allow for intlike strings in json parsing* floatish strings* tests* float tests
1 parent48e7f4d commite1990c0

File tree

5 files changed

+152
-0
lines changed

5 files changed

+152
-0
lines changed

‎src/zarr/core/dtype/npy/common.py‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
IntishFloat=NewType("IntishFloat",float)
5959
"""A type for floats that represent integers, like 1.0 (but not 1.1)."""
6060

61+
IntishStr=NewType("IntishStr",str)
62+
"""A type for strings that represent integers, like "0" or "42"."""
63+
64+
FloatishStr=NewType("FloatishStr",str)
65+
"""A type for strings that represent floats, like "3.14" or "-2.5"."""
66+
6167
NumpyEndiannessStr=Literal[">","<","="]
6268
NUMPY_ENDIANNESS_STR:Final=">","<","="
6369

@@ -488,6 +494,59 @@ def check_json_intish_float(data: JSON) -> TypeGuard[IntishFloat]:
488494
returnisinstance(data,float)anddata.is_integer()
489495

490496

497+
defcheck_json_intish_str(data:JSON)->TypeGuard[IntishStr]:
498+
"""
499+
Check if a JSON value is a string that represents an integer, like "0", "42", or "-5".
500+
501+
Parameters
502+
----------
503+
data : JSON
504+
The JSON value to check.
505+
506+
Returns
507+
-------
508+
bool
509+
True if the data is a string representing an integer, False otherwise.
510+
"""
511+
ifnotisinstance(data,str):
512+
returnFalse
513+
514+
try:
515+
int(data)
516+
exceptValueError:
517+
returnFalse
518+
else:
519+
returnTrue
520+
521+
522+
defcheck_json_floatish_str(data:JSON)->TypeGuard[FloatishStr]:
523+
"""
524+
Check if a JSON value is a string that represents a float, like "3.14", "-2.5", or "0.0".
525+
526+
Note: This function is intended to be used AFTER check_json_float_v2/v3, so it only
527+
handles regular string representations that those functions don't cover.
528+
529+
Parameters
530+
----------
531+
data : JSON
532+
The JSON value to check.
533+
534+
Returns
535+
-------
536+
bool
537+
True if the data is a string representing a regular float, False otherwise.
538+
"""
539+
ifnotisinstance(data,str):
540+
returnFalse
541+
542+
try:
543+
float(data)
544+
exceptValueError:
545+
returnFalse
546+
else:
547+
returnTrue
548+
549+
491550
defcheck_json_str(data:JSON)->TypeGuard[str]:
492551
"""
493552
Check if a JSON value is a string.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
TFloatScalar_co,
2020
check_json_float_v2,
2121
check_json_float_v3,
22+
check_json_floatish_str,
2223
endianness_to_numpy_str,
2324
float_from_json_v2,
2425
float_from_json_v3,
@@ -270,13 +271,17 @@ def from_json_scalar(self, data: JSON, *, zarr_format: ZarrFormat) -> TFloatScal
270271
ifzarr_format==2:
271272
ifcheck_json_float_v2(data):
272273
returnself._cast_scalar_unchecked(float_from_json_v2(data))
274+
elifcheck_json_floatish_str(data):
275+
returnself._cast_scalar_unchecked(float(data))
273276
else:
274277
raiseTypeError(
275278
f"Invalid type:{data}. Expected a float or a special string encoding of a float."
276279
)
277280
elifzarr_format==3:
278281
ifcheck_json_float_v3(data):
279282
returnself._cast_scalar_unchecked(float_from_json_v3(data))
283+
elifcheck_json_floatish_str(data):
284+
returnself._cast_scalar_unchecked(float(data))
280285
else:
281286
raiseTypeError(
282287
f"Invalid type:{data}. Expected a float or a special string encoding of a float."

‎src/zarr/core/dtype/npy/int.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
fromzarr.core.dtype.npy.commonimport (
2727
check_json_int,
2828
check_json_intish_float,
29+
check_json_intish_str,
2930
endianness_to_numpy_str,
3031
get_endianness_from_numpy_dtype,
3132
)
@@ -209,6 +210,10 @@ def from_json_scalar(self, data: JSON, *, zarr_format: ZarrFormat) -> TIntScalar
209210
returnself._cast_scalar_unchecked(data)
210211
ifcheck_json_intish_float(data):
211212
returnself._cast_scalar_unchecked(int(data))
213+
214+
ifcheck_json_intish_str(data):
215+
returnself._cast_scalar_unchecked(int(data))
216+
212217
raiseTypeError(f"Invalid type:{data}. Expected an integer.")
213218

214219
defto_json_scalar(self,data:object,*,zarr_format:ZarrFormat)->int:

‎tests/test_dtype/test_npy/test_float.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,47 @@ class TestFloat64(_BaseTestFloat):
167167
("0x3ff0000000000000",1.0),
168168
)
169169
item_size_params= (Float64(),)
170+
171+
172+
deftest_check_json_floatish_str()->None:
173+
"""Test the check_json_floatish_str function."""
174+
fromzarr.core.dtype.npy.commonimportcheck_json_floatish_str
175+
176+
# Test valid string floats
177+
assertcheck_json_floatish_str("3.14")
178+
assertcheck_json_floatish_str("0.0")
179+
assertcheck_json_floatish_str("-2.5")
180+
assertcheck_json_floatish_str("1.0")
181+
182+
# Test invalid cases
183+
assertnotcheck_json_floatish_str("not_a_number")
184+
assertnotcheck_json_floatish_str("")
185+
assertnotcheck_json_floatish_str(3.14)# actual float, not string
186+
assertnotcheck_json_floatish_str(42)# int
187+
assertnotcheck_json_floatish_str(None)
188+
189+
# Test that special cases still work via float() conversion
190+
# (these will be handled by existing functions first in practice)
191+
assertcheck_json_floatish_str("NaN")
192+
assertcheck_json_floatish_str("Infinity")
193+
assertcheck_json_floatish_str("-Infinity")
194+
195+
196+
deftest_string_float_from_json_scalar()->None:
197+
"""Test that string representations of floats can be parsed by from_json_scalar."""
198+
# Test with Float32
199+
dtype_instance=Float32()
200+
result=dtype_instance.from_json_scalar("3.14",zarr_format=3)
201+
assertabs(result-np.float32(3.14))<1e-6
202+
assertisinstance(result,np.float32)
203+
204+
# Test other cases
205+
result=dtype_instance.from_json_scalar("0.0",zarr_format=3)
206+
assertresult==np.float32(0.0)
207+
208+
result=dtype_instance.from_json_scalar("-2.5",zarr_format=3)
209+
assertresult==np.float32(-2.5)
210+
211+
# Test that it works for v2 format too
212+
result=dtype_instance.from_json_scalar("1.5",zarr_format=2)
213+
assertresult==np.float32(1.5)

‎tests/test_dtype/test_npy/test_int.py‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,42 @@ class TestUInt64(BaseTestZDType):
281281
)
282282
invalid_scalar_params= ((UInt64(), {"set!"}), (UInt64(), ("tuple",)))
283283
item_size_params= (UInt64(),)
284+
285+
286+
deftest_check_json_intish_str()->None:
287+
"""Test the check_json_intish_str function."""
288+
fromzarr.core.dtype.npy.commonimportcheck_json_intish_str
289+
290+
# Test valid string integers
291+
assertcheck_json_intish_str("0")
292+
assertcheck_json_intish_str("42")
293+
assertcheck_json_intish_str("-5")
294+
assertcheck_json_intish_str("123")
295+
296+
# Test invalid cases
297+
assertnotcheck_json_intish_str("3.14")
298+
assertnotcheck_json_intish_str("not_a_number")
299+
assertnotcheck_json_intish_str("")
300+
assertnotcheck_json_intish_str(42)# actual int, not string
301+
assertnotcheck_json_intish_str(3.14)# float
302+
assertnotcheck_json_intish_str(None)
303+
304+
305+
deftest_string_integer_from_json_scalar()->None:
306+
"""Test that string representations of integers can be parsed by from_json_scalar."""
307+
# Test the specific reproducer case
308+
dtype_instance=Int32()
309+
result=dtype_instance.from_json_scalar("0",zarr_format=3)
310+
assertresult==np.int32(0)
311+
assertisinstance(result,np.int32)
312+
313+
# Test other cases
314+
result=dtype_instance.from_json_scalar("42",zarr_format=3)
315+
assertresult==np.int32(42)
316+
317+
result=dtype_instance.from_json_scalar("-5",zarr_format=3)
318+
assertresult==np.int32(-5)
319+
320+
# Test that it works for v2 format too
321+
result=dtype_instance.from_json_scalar("123",zarr_format=2)
322+
assertresult==np.int32(123)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp