mirror of
https://github.com/p2p-ld/numpydantic.git
synced 2024-11-14 02:34:28 +00:00
finish replacing interface tests with new helper system
This commit is contained in:
parent
3356738e42
commit
5d4f03a8a9
7 changed files with 150 additions and 183 deletions
|
@ -31,6 +31,53 @@ else:
|
|||
YES_PIPE = False
|
||||
|
||||
|
||||
def merged_product(
|
||||
*args: Sequence[ValidationCase],
|
||||
) -> Generator[ValidationCase, None, None]:
|
||||
"""
|
||||
Generator for the product of the iterators of validation cases,
|
||||
merging each tuple, and respecting if they should be :meth:`.ValidationCase.skip`
|
||||
or not.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
shape_cases = [
|
||||
ValidationCase(shape=(10, 10, 10), passes=True, id="valid shape"),
|
||||
ValidationCase(shape=(10, 10), passes=False, id="missing dimension"),
|
||||
]
|
||||
dtype_cases = [
|
||||
ValidationCase(dtype=float, passes=True, id="float"),
|
||||
ValidationCase(dtype=int, passes=False, id="int"),
|
||||
]
|
||||
|
||||
iterator = merged_product(shape_cases, dtype_cases))
|
||||
next(iterator)
|
||||
# ValidationCase(
|
||||
# shape=(10, 10, 10),
|
||||
# dtype=float,
|
||||
# passes=True,
|
||||
# id="valid shape-float"
|
||||
# )
|
||||
next(iterator)
|
||||
# ValidationCase(
|
||||
# shape=(10, 10, 10),
|
||||
# dtype=int,
|
||||
# passes=False,
|
||||
# id="valid shape-int"
|
||||
# )
|
||||
|
||||
|
||||
"""
|
||||
iterator = product(*args)
|
||||
for case_tuple in iterator:
|
||||
case = merge_cases(case_tuple)
|
||||
if case.skip():
|
||||
continue
|
||||
yield case
|
||||
|
||||
|
||||
class BasicModel(BaseModel):
|
||||
x: int
|
||||
|
||||
|
@ -58,7 +105,6 @@ FLOAT: TypeAlias = NDArray[Shape["*, *, *"], Float]
|
|||
STRING: TypeAlias = NDArray[Shape["*, *, *"], str]
|
||||
MODEL: TypeAlias = NDArray[Shape["*, *, *"], BasicModel]
|
||||
UNION_TYPE: TypeAlias = NDArray[Shape["*, *, *"], Union[np.uint32, np.float32]]
|
||||
UNION_PIPE: TypeAlias = NDArray[Shape["*, *, *"], np.uint32 | np.float32]
|
||||
|
||||
SHAPE_CASES = (
|
||||
ValidationCase(shape=(10, 10, 10), passes=True, id="valid shape"),
|
||||
|
@ -135,6 +181,8 @@ DTYPE_CASES = [
|
|||
|
||||
|
||||
if YES_PIPE:
|
||||
UNION_PIPE: TypeAlias = NDArray[Shape["*, *, *"], np.uint32 | np.float32]
|
||||
|
||||
DTYPE_CASES.extend(
|
||||
[
|
||||
ValidationCase(
|
||||
|
@ -178,50 +226,3 @@ _INTERFACE_CASES = [
|
|||
ZarrNestedCase,
|
||||
VideoCase,
|
||||
]
|
||||
|
||||
|
||||
def merged_product(
|
||||
*args: Sequence[ValidationCase],
|
||||
) -> Generator[ValidationCase, None, None]:
|
||||
"""
|
||||
Generator for the product of the iterators of validation cases,
|
||||
merging each tuple, and respecting if they should be :meth:`.ValidationCase.skip`
|
||||
or not.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
shape_cases = [
|
||||
ValidationCase(shape=(10, 10, 10), passes=True, id="valid shape"),
|
||||
ValidationCase(shape=(10, 10), passes=False, id="missing dimension"),
|
||||
]
|
||||
dtype_cases = [
|
||||
ValidationCase(dtype=float, passes=True, id="float"),
|
||||
ValidationCase(dtype=int, passes=False, id="int"),
|
||||
]
|
||||
|
||||
iterator = merged_product(shape_cases, dtype_cases))
|
||||
next(iterator)
|
||||
# ValidationCase(
|
||||
# shape=(10, 10, 10),
|
||||
# dtype=float,
|
||||
# passes=True,
|
||||
# id="valid shape-float"
|
||||
# )
|
||||
next(iterator)
|
||||
# ValidationCase(
|
||||
# shape=(10, 10, 10),
|
||||
# dtype=int,
|
||||
# passes=False,
|
||||
# id="valid shape-int"
|
||||
# )
|
||||
|
||||
|
||||
"""
|
||||
iterator = product(*args)
|
||||
for case_tuple in iterator:
|
||||
case = merge_cases(case_tuple)
|
||||
if case.skip():
|
||||
continue
|
||||
yield case
|
||||
|
|
|
@ -46,9 +46,16 @@ class InterfaceCase(ABC):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[NDArrayType]:
|
||||
"""
|
||||
Make an array from a shape and dtype, and a path if needed
|
||||
|
||||
Args:
|
||||
shape: shape of the array
|
||||
dtype: dtype of the array
|
||||
path: Path, if needed to generate on disk
|
||||
array: Rather than passing shape and dtype, pass a literal arraylike thing
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -19,7 +19,7 @@ from numpydantic.interface import (
|
|||
ZarrInterface,
|
||||
)
|
||||
from numpydantic.testing.helpers import InterfaceCase
|
||||
from numpydantic.types import DtypeType
|
||||
from numpydantic.types import DtypeType, NDArrayType
|
||||
|
||||
|
||||
class NumpyCase(InterfaceCase):
|
||||
|
@ -33,8 +33,11 @@ class NumpyCase(InterfaceCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> np.ndarray:
|
||||
if issubclass(dtype, BaseModel):
|
||||
if array is not None:
|
||||
return np.array(array, dtype=dtype)
|
||||
elif issubclass(dtype, BaseModel):
|
||||
return np.full(shape=shape, fill_value=dtype(x=1))
|
||||
else:
|
||||
return np.zeros(shape=shape, dtype=dtype)
|
||||
|
@ -59,6 +62,7 @@ class HDF5Case(_HDF5MetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[H5ArrayPath]:
|
||||
if cls.skip(shape, dtype):
|
||||
return None
|
||||
|
@ -67,7 +71,9 @@ class HDF5Case(_HDF5MetaCase):
|
|||
array_path = "/" + "_".join([str(s) for s in shape]) + "__" + dtype.__name__
|
||||
generator = np.random.default_rng()
|
||||
|
||||
if dtype is str:
|
||||
if array is not None:
|
||||
data = np.array(array, dtype=dtype)
|
||||
elif dtype is str:
|
||||
data = generator.random(shape).astype(bytes)
|
||||
elif dtype is datetime:
|
||||
data = np.empty(shape, dtype="S32")
|
||||
|
@ -91,13 +97,16 @@ class HDF5CompoundCase(_HDF5MetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[H5ArrayPath]:
|
||||
if cls.skip(shape, dtype):
|
||||
return None
|
||||
|
||||
hdf5_file = path / "h5f.h5"
|
||||
array_path = "/" + "_".join([str(s) for s in shape]) + "__" + dtype.__name__
|
||||
if dtype is str:
|
||||
if array is not None:
|
||||
data = np.array(array, dtype=dtype)
|
||||
elif dtype is str:
|
||||
dt = np.dtype([("data", np.dtype("S10")), ("extra", "i8")])
|
||||
data = np.array([("hey", 0)] * np.prod(shape), dtype=dt).reshape(shape)
|
||||
elif dtype is datetime:
|
||||
|
@ -128,7 +137,10 @@ class DaskCase(InterfaceCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> da.Array:
|
||||
if array is not None:
|
||||
return da.array(array, dtype=dtype, chunks=-1)
|
||||
if issubclass(dtype, BaseModel):
|
||||
return da.full(shape=shape, fill_value=dtype(x=1), chunks=-1)
|
||||
else:
|
||||
|
@ -142,7 +154,7 @@ class _ZarrMetaCase(InterfaceCase):
|
|||
|
||||
@classmethod
|
||||
def skip(cls, shape: Tuple[int, ...], dtype: DtypeType) -> bool:
|
||||
return not issubclass(dtype, BaseModel)
|
||||
return issubclass(dtype, BaseModel)
|
||||
|
||||
|
||||
class ZarrCase(_ZarrMetaCase):
|
||||
|
@ -154,8 +166,12 @@ class ZarrCase(_ZarrMetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[zarr.Array]:
|
||||
return zarr.zeros(shape=shape, dtype=dtype)
|
||||
if array is not None:
|
||||
return zarr.array(array, dtype=dtype, chunks=-1)
|
||||
else:
|
||||
return zarr.zeros(shape=shape, dtype=dtype)
|
||||
|
||||
|
||||
class ZarrDirCase(_ZarrMetaCase):
|
||||
|
@ -167,9 +183,13 @@ class ZarrDirCase(_ZarrMetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[zarr.Array]:
|
||||
store = zarr.DirectoryStore(str(path / "array.zarr"))
|
||||
return zarr.zeros(shape=shape, dtype=dtype, store=store)
|
||||
if array is not None:
|
||||
return zarr.array(array, dtype=dtype, store=store, chunks=-1)
|
||||
else:
|
||||
return zarr.zeros(shape=shape, dtype=dtype, store=store)
|
||||
|
||||
|
||||
class ZarrZipCase(_ZarrMetaCase):
|
||||
|
@ -181,9 +201,13 @@ class ZarrZipCase(_ZarrMetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[zarr.Array]:
|
||||
store = zarr.ZipStore(str(path / "array.zarr"), mode="w")
|
||||
return zarr.zeros(shape=shape, dtype=dtype, store=store)
|
||||
if array is not None:
|
||||
return zarr.array(array, dtype=dtype, store=store, chunks=-1)
|
||||
else:
|
||||
return zarr.zeros(shape=shape, dtype=dtype, store=store)
|
||||
|
||||
|
||||
class ZarrNestedCase(_ZarrMetaCase):
|
||||
|
@ -195,11 +219,15 @@ class ZarrNestedCase(_ZarrMetaCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> ZarrArrayPath:
|
||||
file = str(path / "nested.zarr")
|
||||
root = zarr.open(file, mode="w")
|
||||
subpath = "a/b/c"
|
||||
_ = root.zeros(subpath, shape=shape, dtype=dtype)
|
||||
if array is not None:
|
||||
_ = root.array(subpath, array, dtype=dtype)
|
||||
else:
|
||||
_ = root.zeros(subpath, shape=shape, dtype=dtype)
|
||||
return ZarrArrayPath(file=file, path=subpath)
|
||||
|
||||
|
||||
|
@ -214,10 +242,15 @@ class VideoCase(InterfaceCase):
|
|||
shape: Tuple[int, ...] = (10, 10),
|
||||
dtype: DtypeType = float,
|
||||
path: Optional[Path] = None,
|
||||
array: Optional[NDArrayType] = None,
|
||||
) -> Optional[Path]:
|
||||
if cls.skip(shape, dtype):
|
||||
return None
|
||||
|
||||
if array is not None:
|
||||
array = np.ndarray(shape, dtype=np.uint8)
|
||||
shape = array.shape
|
||||
|
||||
is_color = len(shape) == 4
|
||||
frames = shape[0]
|
||||
frame_shape = shape[1:]
|
||||
|
@ -232,13 +265,16 @@ class VideoCase(InterfaceCase):
|
|||
)
|
||||
|
||||
for i in range(frames):
|
||||
# make fresh array every time bc opencv eats them
|
||||
array = np.zeros(frame_shape, dtype=np.uint8)
|
||||
if not is_color:
|
||||
array[i, i] = i
|
||||
if array is not None:
|
||||
frame = array[i]
|
||||
else:
|
||||
array[i, i, :] = i
|
||||
writer.write(array)
|
||||
# make fresh array every time bc opencv eats them
|
||||
frame = np.zeros(frame_shape, dtype=np.uint8)
|
||||
if not is_color:
|
||||
frame[i, i] = i
|
||||
else:
|
||||
frame[i, i, :] = i
|
||||
writer.write(frame)
|
||||
writer.release()
|
||||
return video_path
|
||||
|
||||
|
|
5
tests/fixtures/generation.py
vendored
5
tests/fixtures/generation.py
vendored
|
@ -7,7 +7,6 @@ import zarr
|
|||
|
||||
from numpydantic.interface.hdf5 import H5ArrayPath
|
||||
from numpydantic.interface.zarr import ZarrArrayPath
|
||||
from numpydantic.testing import ValidationCase
|
||||
from numpydantic.testing.interfaces import HDF5Case, HDF5CompoundCase, VideoCase
|
||||
|
||||
|
||||
|
@ -57,8 +56,8 @@ def avi_video(tmp_output_dir_func) -> Callable[[Tuple[int, int], int, bool], Pat
|
|||
shape = (frames, *shape)
|
||||
if is_color:
|
||||
shape = (*shape, 3)
|
||||
return VideoCase.array_from_case(
|
||||
ValidationCase(shape=shape, dtype=np.uint8), tmp_output_dir_func
|
||||
return VideoCase.make_array(
|
||||
shape=shape, dtype=np.uint8, path=tmp_output_dir_func
|
||||
)
|
||||
|
||||
return _make_video
|
||||
|
|
|
@ -5,13 +5,11 @@ from typing import Any
|
|||
import h5py
|
||||
import numpy as np
|
||||
import pytest
|
||||
from pydantic import BaseModel, ValidationError
|
||||
from pydantic import BaseModel
|
||||
|
||||
from numpydantic import NDArray, Shape
|
||||
from numpydantic.exceptions import DtypeError, ShapeError
|
||||
from numpydantic.interface import H5Interface
|
||||
from numpydantic.interface.hdf5 import H5ArrayPath, H5Proxy
|
||||
from numpydantic.testing.helpers import ValidationCase
|
||||
from numpydantic.testing.interfaces import HDF5Case, HDF5CompoundCase
|
||||
|
||||
pytestmark = pytest.mark.hdf5
|
||||
|
@ -27,35 +25,24 @@ def hdf5_cases(request):
|
|||
return request.param
|
||||
|
||||
|
||||
def hdf5_array_case(
|
||||
case: ValidationCase, array_func, compound: bool = False
|
||||
) -> H5ArrayPath:
|
||||
"""
|
||||
Args:
|
||||
case:
|
||||
array_func: ( the function returned from the `hdf5_array` fixture )
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
if issubclass(case.dtype, BaseModel):
|
||||
pytest.skip("hdf5 cant support arbitrary python objects")
|
||||
return array_func(case.shape, case.dtype, compound)
|
||||
|
||||
|
||||
def _test_hdf5_case(case: ValidationCase, array_func, compound: bool = False) -> None:
|
||||
array = hdf5_array_case(case, array_func, compound)
|
||||
if case.passes:
|
||||
case.model(array=array)
|
||||
else:
|
||||
with pytest.raises((ValidationError, DtypeError, ShapeError)):
|
||||
case.model(array=array)
|
||||
|
||||
|
||||
def test_hdf5_enabled():
|
||||
assert H5Interface.enabled()
|
||||
|
||||
|
||||
@pytest.mark.shape
|
||||
def test_hdf5_shape(shape_cases, hdf5_cases):
|
||||
shape_cases.interface = hdf5_cases
|
||||
if shape_cases.skip():
|
||||
pytest.skip()
|
||||
shape_cases.validate_case()
|
||||
|
||||
|
||||
@pytest.mark.dtype
|
||||
def test_hdf5_dtype(dtype_cases, hdf5_cases):
|
||||
dtype_cases.interface = hdf5_cases
|
||||
dtype_cases.validate_case()
|
||||
|
||||
|
||||
def test_hdf5_check(interface_type):
|
||||
if interface_type[1] is H5Interface:
|
||||
assert H5Interface.check(interface_type[0])
|
||||
|
@ -82,20 +69,6 @@ def test_hdf5_check_not_hdf5(tmp_path):
|
|||
assert not H5Interface.check(spec)
|
||||
|
||||
|
||||
@pytest.mark.shape
|
||||
def test_hdf5_shape(shape_cases, hdf5_cases):
|
||||
shape_cases.interface = hdf5_cases
|
||||
if shape_cases.skip():
|
||||
pytest.skip()
|
||||
shape_cases.validate_case()
|
||||
|
||||
|
||||
@pytest.mark.dtype
|
||||
def test_hdf5_dtype(dtype_cases, hdf5_cases):
|
||||
dtype_cases.interface = hdf5_cases
|
||||
dtype_cases.validate_case()
|
||||
|
||||
|
||||
def test_hdf5_dataset_not_exists(hdf5_array, model_blank):
|
||||
array = hdf5_array()
|
||||
with pytest.raises(ValueError) as e:
|
||||
|
|
|
@ -1,37 +1,21 @@
|
|||
import numpy as np
|
||||
import pytest
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
from numpydantic.exceptions import DtypeError, ShapeError
|
||||
from numpydantic.testing.helpers import ValidationCase
|
||||
from numpydantic.testing.cases import NumpyCase
|
||||
|
||||
pytestmark = pytest.mark.numpy
|
||||
|
||||
|
||||
def numpy_array(case: ValidationCase) -> np.ndarray:
|
||||
if issubclass(case.dtype, BaseModel):
|
||||
return np.full(shape=case.shape, fill_value=case.dtype(x=1))
|
||||
else:
|
||||
return np.zeros(shape=case.shape, dtype=case.dtype)
|
||||
|
||||
|
||||
def _test_np_case(case: ValidationCase):
|
||||
array = numpy_array(case)
|
||||
if case.passes:
|
||||
case.model(array=array)
|
||||
else:
|
||||
with pytest.raises((ValidationError, DtypeError, ShapeError)):
|
||||
case.model(array=array)
|
||||
|
||||
|
||||
@pytest.mark.shape
|
||||
def test_numpy_shape(shape_cases):
|
||||
_test_np_case(shape_cases)
|
||||
shape_cases.interface = NumpyCase
|
||||
shape_cases.validate_case()
|
||||
|
||||
|
||||
@pytest.mark.dtype
|
||||
def test_numpy_dtype(dtype_cases):
|
||||
_test_np_case(dtype_cases)
|
||||
dtype_cases.interface = NumpyCase
|
||||
dtype_cases.validate_case()
|
||||
|
||||
|
||||
def test_numpy_coercion(model_blank):
|
||||
|
|
|
@ -1,58 +1,21 @@
|
|||
import json
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
import zarr
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
from numpydantic.exceptions import DtypeError, ShapeError
|
||||
from numpydantic.interface import ZarrInterface
|
||||
from numpydantic.interface.zarr import ZarrArrayPath
|
||||
from numpydantic.testing.helpers import ValidationCase
|
||||
from numpydantic.testing.cases import ZarrCase, ZarrDirCase, ZarrNestedCase, ZarrZipCase
|
||||
from numpydantic.testing.helpers import InterfaceCase
|
||||
|
||||
pytestmark = pytest.mark.zarr
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def dir_array(tmp_output_dir_func) -> zarr.DirectoryStore:
|
||||
store = zarr.DirectoryStore(tmp_output_dir_func / "array.zarr")
|
||||
return store
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def zip_array(tmp_output_dir_func) -> zarr.ZipStore:
|
||||
store = zarr.ZipStore(tmp_output_dir_func / "array.zip", mode="w")
|
||||
return store
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def nested_dir_array(tmp_output_dir_func) -> zarr.NestedDirectoryStore:
|
||||
store = zarr.NestedDirectoryStore(tmp_output_dir_func / "nested")
|
||||
return store
|
||||
|
||||
|
||||
def _zarr_array(case: ValidationCase, store) -> zarr.core.Array:
|
||||
if issubclass(case.dtype, BaseModel):
|
||||
pytest.skip(
|
||||
"Zarr can't handle objects properly at the moment, "
|
||||
"see https://github.com/zarr-developers/zarr-python/issues/2081"
|
||||
)
|
||||
# return zarr.full(
|
||||
# shape=case.shape,
|
||||
# fill_value=case.dtype(x=1),
|
||||
# dtype=object,
|
||||
# object_codec=Pickle(),
|
||||
# )
|
||||
else:
|
||||
return zarr.zeros(shape=case.shape, dtype=case.dtype, store=store)
|
||||
|
||||
|
||||
def _test_zarr_case(case: ValidationCase, store):
|
||||
array = _zarr_array(case, store)
|
||||
if case.passes:
|
||||
case.model(array=array)
|
||||
else:
|
||||
with pytest.raises((ValidationError, DtypeError, ShapeError)):
|
||||
case.model(array=array)
|
||||
@pytest.fixture(
|
||||
params=[ZarrCase, ZarrZipCase, ZarrDirCase, ZarrNestedCase],
|
||||
)
|
||||
def zarr_case(request) -> InterfaceCase:
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
|
@ -86,13 +49,17 @@ def test_zarr_check(interface_type):
|
|||
|
||||
|
||||
@pytest.mark.shape
|
||||
def test_zarr_shape(store, shape_cases):
|
||||
_test_zarr_case(shape_cases, store)
|
||||
def test_zarr_shape(shape_cases, zarr_case):
|
||||
shape_cases.interface = zarr_case
|
||||
shape_cases.validate_case()
|
||||
|
||||
|
||||
@pytest.mark.dtype
|
||||
def test_zarr_dtype(dtype_cases, store):
|
||||
_test_zarr_case(dtype_cases, store)
|
||||
def test_zarr_dtype(dtype_cases, zarr_case):
|
||||
dtype_cases.interface = zarr_case
|
||||
if dtype_cases.skip():
|
||||
pytest.skip()
|
||||
dtype_cases.validate_case()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("array", ["zarr_nested_array", "zarr_array"])
|
||||
|
@ -126,7 +93,7 @@ def test_zarr_array_path_from_iterable(zarr_array):
|
|||
@pytest.mark.serialization
|
||||
@pytest.mark.parametrize("dump_array", [True, False])
|
||||
@pytest.mark.parametrize("roundtrip", [True, False])
|
||||
def test_zarr_to_json(store, model_blank, roundtrip, dump_array):
|
||||
def test_zarr_to_json(zarr_case, model_blank, roundtrip, dump_array, tmp_path):
|
||||
expected_fields = (
|
||||
"Type",
|
||||
"Data type",
|
||||
|
@ -136,9 +103,9 @@ def test_zarr_to_json(store, model_blank, roundtrip, dump_array):
|
|||
"Store type",
|
||||
"hexdigest",
|
||||
)
|
||||
lol_array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
lol_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=int)
|
||||
|
||||
array = zarr.array(lol_array, store=store)
|
||||
array = zarr_case.make_array(array=lol_array, dtype=int, path=tmp_path)
|
||||
instance = model_blank(array=array)
|
||||
|
||||
context = {"dump_array": dump_array}
|
||||
|
@ -148,7 +115,7 @@ def test_zarr_to_json(store, model_blank, roundtrip, dump_array):
|
|||
|
||||
if roundtrip:
|
||||
if dump_array:
|
||||
assert as_json["value"] == lol_array
|
||||
assert np.array_equal(as_json["value"], lol_array)
|
||||
else:
|
||||
if as_json.get("file", False):
|
||||
assert "array" not in as_json
|
||||
|
@ -158,4 +125,4 @@ def test_zarr_to_json(store, model_blank, roundtrip, dump_array):
|
|||
assert len(as_json["info"]["hexdigest"]) == 40
|
||||
|
||||
else:
|
||||
assert as_json == lol_array
|
||||
assert np.array_equal(as_json, lol_array)
|
||||
|
|
Loading…
Reference in a new issue