Skip to content

Commit c7494a9

Browse files
ericprejoshmoorejakirkham
authored
Add numpy encoder class for json.dumps (#933)
* Add numpy encoder class for json.dumps and add test * Use numbers instead of numpy module * Add entry to release note Co-authored-by: Josh Moore <[email protected]> Co-authored-by: jakirkham <[email protected]>
1 parent 18abb19 commit c7494a9

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

docs/release.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Bug fixes
1414
value when empty chunks are read back in.
1515
By :user:`Vyas Ramasubramani <vyasr>`; :issue:`965`.
1616

17+
* Add number encoder for ``json.dumps`` to support numpy intergers in
18+
``chunks`` arguments. By :user:`Eric Prestat <ericpre>` :issue:`697`.
19+
1720
.. _release_2.11.1:
1821

1922
2.11.1

zarr/tests/test_creation.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,8 @@ def test_create_read_only(zarr_version):
714714
assert z.read_only
715715
with pytest.raises(PermissionError):
716716
z[:] = 42
717+
718+
719+
def test_json_dumps_chunks_numpy_dtype():
720+
z = zeros((10,), chunks=(np.int64(2),))
721+
assert np.all(z[...] == 0)

zarr/tests/test_util.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
import numpy as np
55
import pytest
66

7-
from zarr.util import (all_equal, flatten, guess_chunks, human_readable_size, info_html_report,
8-
info_text_report, is_total_slice, normalize_chunks,
7+
from zarr.core import Array
8+
from zarr.util import (all_equal, flatten, guess_chunks, human_readable_size,
9+
info_html_report, info_text_report, is_total_slice,
10+
json_dumps, normalize_chunks,
911
normalize_dimension_separator,
1012
normalize_fill_value, normalize_order,
1113
normalize_resize_args, normalize_shape, retry_call,
@@ -238,3 +240,11 @@ def test_all_equal():
238240
# all_equal(None, *) always returns False
239241
assert not all_equal(None, np.array([None, None]))
240242
assert not all_equal(None, np.array([None, 10]))
243+
244+
245+
def test_json_dumps_numpy_dtype():
246+
assert json_dumps(np.int64(0)) == json_dumps(0)
247+
assert json_dumps(np.float32(0)) == json_dumps(float(0))
248+
# Check that we raise the error of the superclass for unsupported object
249+
with pytest.raises(TypeError):
250+
json_dumps(Array)

zarr/util.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,22 @@ def flatten(arg: Iterable) -> Iterable:
3333
}
3434

3535

36+
class NumberEncoder(json.JSONEncoder):
37+
38+
def default(self, o):
39+
# See json.JSONEncoder.default docstring for explanation
40+
# This is necessary to encode numpy dtype
41+
if isinstance(o, numbers.Integral):
42+
return int(o)
43+
if isinstance(o, numbers.Real):
44+
return float(o)
45+
return json.JSONEncoder.default(self, o)
46+
47+
3648
def json_dumps(o: Any) -> bytes:
3749
"""Write JSON in a consistent, human-readable way."""
3850
return json.dumps(o, indent=4, sort_keys=True, ensure_ascii=True,
39-
separators=(',', ': ')).encode('ascii')
51+
separators=(',', ': '), cls=NumberEncoder).encode('ascii')
4052

4153

4254
def json_loads(s: str) -> Dict[str, Any]:

0 commit comments

Comments
 (0)