From 2cb09076fd47f9ed8c517f078d0d7853ca160b7a Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Fri, 20 Sep 2024 18:28:38 -0700 Subject: [PATCH] add ability to dump proxy classes to arrays, tests for doing so and json dumping --- src/numpydantic/interface/hdf5.py | 9 +++++++- src/numpydantic/interface/video.py | 4 ++++ tests/test_interface/conftest.py | 4 ++-- tests/test_interface/test_interfaces.py | 30 +++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/numpydantic/interface/hdf5.py b/src/numpydantic/interface/hdf5.py index 20cec0d..3696a6f 100644 --- a/src/numpydantic/interface/hdf5.py +++ b/src/numpydantic/interface/hdf5.py @@ -134,10 +134,17 @@ class H5Proxy: else: return obj.dtype[self.field] + def __array__(self) -> np.ndarray: + """To a numpy array""" + with h5py.File(self.file, "r") as h5f: + obj = h5f.get(self.path) + return obj[:] + def __getattr__(self, item: str): with h5py.File(self.file, "r") as h5f: obj = h5f.get(self.path) - return getattr(obj, item) + val = getattr(obj, item) + return val def __getitem__( self, item: Union[int, slice, Tuple[Union[int, slice], ...]] diff --git a/src/numpydantic/interface/video.py b/src/numpydantic/interface/video.py index f64457b..1660545 100644 --- a/src/numpydantic/interface/video.py +++ b/src/numpydantic/interface/video.py @@ -137,6 +137,10 @@ class VideoProxy: slice_ = slice(0, slice_.stop, slice_.step) return slice_ + def __array__(self) -> np.ndarray: + """Whole video as a numpy array""" + return self[:] + def __getitem__(self, item: Union[int, slice, tuple]) -> np.ndarray: if isinstance(item, int): # want a single frame diff --git a/tests/test_interface/conftest.py b/tests/test_interface/conftest.py index 63bdc4a..7e6f767 100644 --- a/tests/test_interface/conftest.py +++ b/tests/test_interface/conftest.py @@ -1,6 +1,6 @@ import pytest -from typing import Tuple, Callable +from typing import Callable, Tuple, Type import numpy as np import dask.array as da import zarr @@ -32,7 +32,7 @@ from numpydantic import interface, NDArray "video", ], ) -def interface_type(request) -> Tuple[NDArray, interface.Interface]: +def interface_type(request) -> Tuple[NDArray, Type[interface.Interface]]: """ Test cases for each interface's ``check`` method - each input should match the provided interface and that interface only diff --git a/tests/test_interface/test_interfaces.py b/tests/test_interface/test_interfaces.py index 36308c9..3b1370a 100644 --- a/tests/test_interface/test_interfaces.py +++ b/tests/test_interface/test_interfaces.py @@ -2,6 +2,10 @@ Tests that should be applied to all interfaces """ +from typing import Callable +import numpy as np +from numpydantic.interface import Interface + def test_interface_revalidate(all_interfaces): """ @@ -10,3 +14,29 @@ def test_interface_revalidate(all_interfaces): See: https://github.com/p2p-ld/numpydantic/pull/14 """ _ = type(all_interfaces)(array=all_interfaces.array) + + +def test_interface_rematch(interface_type): + """ + All interfaces should match the results of the object they return after validation + """ + array, interface = interface_type + if isinstance(array, Callable): + array = array() + + assert Interface.match(interface().validate(array)) is interface + + +def test_interface_to_numpy_array(all_interfaces): + """ + All interfaces should be able to have the output of their validation stage + coerced to a numpy array with np.array() + """ + _ = np.array(all_interfaces.array) + + +def test_interface_dump_json(all_interfaces): + """ + All interfaces should be able to dump to json + """ + all_interfaces.model_dump_json()