From 1532ec8a4d8933829d01e2877084461a47ed6c39 Mon Sep 17 00:00:00 2001 From: TomNicholas Date: Thu, 22 Aug 2024 17:01:54 -0400 Subject: [PATCH 01/11] add tests for cubed --- xarray_array_testing/tests/test_cubed.py | 77 ++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 xarray_array_testing/tests/test_cubed.py diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py new file mode 100644 index 0000000..80b463f --- /dev/null +++ b/xarray_array_testing/tests/test_cubed.py @@ -0,0 +1,77 @@ +from typing import ContextManager +from contextlib import nullcontext + +import pytest +import hypothesis.strategies as st +from hypothesis import note +import numpy as np +import numpy.testing as npt + +from xarray_array_testing.base import DuckArrayTestMixin +from xarray_array_testing.creation import CreationTests +from xarray_array_testing.reduction import ReductionTests + +import cubed +import cubed.random + + +def cubed_random_array(shape: tuple[int], dtype: np.dtype) -> cubed.Array: + """ + Generates a random cubed array + + Supports integer and float dtypes. + """ + # TODO hypothesis doesn't like us using random inside strategies + rng = np.random.default_rng() + + if np.issubdtype(dtype, np.integer): + arr = rng.integers(low=0, high=+3, size=shape, dtype=dtype) + return cubed.from_array(arr) + else: + # TODO generate general chunking pattern + ca = cubed.random.random(size=shape, chunks=shape) + return cubed.array_api.astype(ca, dtype) + + +def random_cubed_arrays_fn( + *, shape: tuple[int, ...], dtype: np.dtype, +) -> st.SearchStrategy[cubed.Array]: + return st.builds(cubed_random_array, shape=st.just(shape), dtype=st.just(dtype)) + + +class CubedTestMixin(DuckArrayTestMixin): + @property + def xp(self) -> type[cubed.array_api]: + return cubed.array_api + + @property + def array_type(self) -> type[cubed.Array]: + return cubed.Array + + @staticmethod + def array_strategy_fn(*, shape, dtype) -> st.SearchStrategy[cubed.Array]: + return random_cubed_arrays_fn(shape=shape, dtype=dtype) + + @staticmethod + def assert_equal(a: cubed.Array, b: cubed.Array): + npt.assert_equal(a.compute(), b.compute()) + + + +class TestCreationCubed(CreationTests, CubedTestMixin): + pass + + +class TestReductionCubed(ReductionTests, CubedTestMixin): + @staticmethod + def expected_errors(op, **parameters) -> ContextManager: + var = parameters.get('variable') + + note(f"op = {op}") + note(f"dtype = {var.dtype}") + note(f"is_integer = {cubed.array_api.isdtype(var.dtype, 'integral')}") + + if op == 'mean' and cubed.array_api.isdtype(var.dtype, "integral") or var.dtype == np.dtype('float16'): + return pytest.raises(TypeError, match='Only real floating-point dtypes are allowed in mean') + else: + return nullcontext() From 9be6e3c2c94287cf030a8b29f756c4d45d15a616 Mon Sep 17 00:00:00 2001 From: TomNicholas Date: Thu, 22 Aug 2024 17:03:55 -0400 Subject: [PATCH 02/11] silence hypothesis health check warnings --- xarray_array_testing/creation.py | 3 ++- xarray_array_testing/reduction.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/xarray_array_testing/creation.py b/xarray_array_testing/creation.py index 291e082..32435a5 100644 --- a/xarray_array_testing/creation.py +++ b/xarray_array_testing/creation.py @@ -1,11 +1,12 @@ import hypothesis.strategies as st import xarray.testing.strategies as xrst -from hypothesis import given +from hypothesis import given, settings, HealthCheck from xarray_array_testing.base import DuckArrayTestMixin class CreationTests(DuckArrayTestMixin): + @settings(suppress_health_check=[HealthCheck.differing_executors]) @given(st.data()) def test_create_variable(self, data): variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) diff --git a/xarray_array_testing/reduction.py b/xarray_array_testing/reduction.py index 8e58949..6aa42ef 100644 --- a/xarray_array_testing/reduction.py +++ b/xarray_array_testing/reduction.py @@ -2,7 +2,7 @@ import hypothesis.strategies as st import xarray.testing.strategies as xrst -from hypothesis import given +from hypothesis import given, settings, HealthCheck, note from xarray_array_testing.base import DuckArrayTestMixin @@ -12,16 +12,22 @@ class ReductionTests(DuckArrayTestMixin): def expected_errors(op, **parameters): return nullcontext() + # TODO understand the differing executors health check error + @settings(suppress_health_check=[HealthCheck.differing_executors]) @given(st.data()) def test_variable_mean(self, data): variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) + note(f"note: {variable}") + with self.expected_errors("mean", variable=variable): actual = variable.mean().data expected = self.xp.mean(variable.data) - self.assert_equal(actual, expected) + assert isinstance(actual, self.array_type), type(actual) + self.assert_equal(actual, expected) + @settings(suppress_health_check=[HealthCheck.differing_executors]) @given(st.data()) def test_variable_prod(self, data): variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) @@ -30,4 +36,5 @@ def test_variable_prod(self, data): actual = variable.prod().data expected = self.xp.prod(variable.data) - self.assert_equal(actual, expected) + assert isinstance(actual, self.array_type), type(actual) + self.assert_equal(actual, expected) From df26fc763da78e23e049af3fa21c594effda6224 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:12:12 +0000 Subject: [PATCH 03/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray_array_testing/creation.py | 2 +- xarray_array_testing/reduction.py | 2 +- xarray_array_testing/tests/test_cubed.py | 32 ++++++++++++++---------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/xarray_array_testing/creation.py b/xarray_array_testing/creation.py index 32435a5..ebcd1be 100644 --- a/xarray_array_testing/creation.py +++ b/xarray_array_testing/creation.py @@ -1,6 +1,6 @@ import hypothesis.strategies as st import xarray.testing.strategies as xrst -from hypothesis import given, settings, HealthCheck +from hypothesis import HealthCheck, given, settings from xarray_array_testing.base import DuckArrayTestMixin diff --git a/xarray_array_testing/reduction.py b/xarray_array_testing/reduction.py index 6aa42ef..9e1b186 100644 --- a/xarray_array_testing/reduction.py +++ b/xarray_array_testing/reduction.py @@ -2,7 +2,7 @@ import hypothesis.strategies as st import xarray.testing.strategies as xrst -from hypothesis import given, settings, HealthCheck, note +from hypothesis import HealthCheck, given, note, settings from xarray_array_testing.base import DuckArrayTestMixin diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index 80b463f..b2f9da5 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -1,29 +1,28 @@ -from typing import ContextManager from contextlib import nullcontext +from typing import ContextManager -import pytest +import cubed +import cubed.random import hypothesis.strategies as st -from hypothesis import note import numpy as np import numpy.testing as npt +import pytest +from hypothesis import note from xarray_array_testing.base import DuckArrayTestMixin from xarray_array_testing.creation import CreationTests from xarray_array_testing.reduction import ReductionTests -import cubed -import cubed.random - def cubed_random_array(shape: tuple[int], dtype: np.dtype) -> cubed.Array: """ Generates a random cubed array - + Supports integer and float dtypes. """ # TODO hypothesis doesn't like us using random inside strategies rng = np.random.default_rng() - + if np.issubdtype(dtype, np.integer): arr = rng.integers(low=0, high=+3, size=shape, dtype=dtype) return cubed.from_array(arr) @@ -34,7 +33,9 @@ def cubed_random_array(shape: tuple[int], dtype: np.dtype) -> cubed.Array: def random_cubed_arrays_fn( - *, shape: tuple[int, ...], dtype: np.dtype, + *, + shape: tuple[int, ...], + dtype: np.dtype, ) -> st.SearchStrategy[cubed.Array]: return st.builds(cubed_random_array, shape=st.just(shape), dtype=st.just(dtype)) @@ -57,7 +58,6 @@ def assert_equal(a: cubed.Array, b: cubed.Array): npt.assert_equal(a.compute(), b.compute()) - class TestCreationCubed(CreationTests, CubedTestMixin): pass @@ -65,13 +65,19 @@ class TestCreationCubed(CreationTests, CubedTestMixin): class TestReductionCubed(ReductionTests, CubedTestMixin): @staticmethod def expected_errors(op, **parameters) -> ContextManager: - var = parameters.get('variable') + var = parameters.get("variable") note(f"op = {op}") note(f"dtype = {var.dtype}") note(f"is_integer = {cubed.array_api.isdtype(var.dtype, 'integral')}") - if op == 'mean' and cubed.array_api.isdtype(var.dtype, "integral") or var.dtype == np.dtype('float16'): - return pytest.raises(TypeError, match='Only real floating-point dtypes are allowed in mean') + if ( + op == "mean" + and cubed.array_api.isdtype(var.dtype, "integral") + or var.dtype == np.dtype("float16") + ): + return pytest.raises( + TypeError, match="Only real floating-point dtypes are allowed in mean" + ) else: return nullcontext() From 72fd4bf3b50dea5efab8d6b83158cb965f632992 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Fri, 23 Aug 2024 14:36:21 +0200 Subject: [PATCH 04/11] install `cubed` and `cubed-xarray` in ci --- ci/requirements/environment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/requirements/environment.yaml b/ci/requirements/environment.yaml index 51bdd94..6998d45 100644 --- a/ci/requirements/environment.yaml +++ b/ci/requirements/environment.yaml @@ -10,3 +10,5 @@ dependencies: - hypothesis - xarray - numpy + - cubed + - cubed-xarray From 376181c5a50a096c29e91194445bc4ac336cd9bc Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 11:59:11 +0200 Subject: [PATCH 05/11] actually pass in the right op --- xarray_array_testing/reduction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray_array_testing/reduction.py b/xarray_array_testing/reduction.py index 7528773..2b667bc 100644 --- a/xarray_array_testing/reduction.py +++ b/xarray_array_testing/reduction.py @@ -22,7 +22,7 @@ def test_variable_numerical_reduce(self, op, data): note(f"note: {variable}") - with self.expected_errors("mean", variable=variable): + with self.expected_errors(op, variable=variable): # compute using xr.Variable.() actual = getattr(variable, op)().data # compute using xp.(array) From 4610b309a16b1e2aa7e67d8ff1dc3d01a91e1eeb Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 11:59:23 +0200 Subject: [PATCH 06/11] create a more informative error message --- xarray_array_testing/reduction.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray_array_testing/reduction.py b/xarray_array_testing/reduction.py index 2b667bc..f3a3fb0 100644 --- a/xarray_array_testing/reduction.py +++ b/xarray_array_testing/reduction.py @@ -28,5 +28,7 @@ def test_variable_numerical_reduce(self, op, data): # compute using xp.(array) expected = getattr(self.xp, op)(variable.data) - assert isinstance(actual, self.array_type), type(actual) + assert isinstance( + actual, self.array_type + ), f"expected {self.array_type} but got {type(actual)}" self.assert_equal(actual, expected) From 77f08c8369a26fd52e135d61dbea78406ab613c5 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 12:00:41 +0200 Subject: [PATCH 07/11] use the proper import for `ContextManager` --- xarray_array_testing/tests/test_cubed.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index b2f9da5..8247194 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -1,5 +1,4 @@ -from contextlib import nullcontext -from typing import ContextManager +from contextlib import ContextManager, nullcontext import cubed import cubed.random From 6d77f30e617a7b0b7ae223753320610292e15eb6 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 12:01:04 +0200 Subject: [PATCH 08/11] simplify the dtype check --- xarray_array_testing/tests/test_cubed.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index 8247194..bf36842 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -66,14 +66,14 @@ class TestReductionCubed(ReductionTests, CubedTestMixin): def expected_errors(op, **parameters) -> ContextManager: var = parameters.get("variable") + xp = cubed.array_api + note(f"op = {op}") note(f"dtype = {var.dtype}") note(f"is_integer = {cubed.array_api.isdtype(var.dtype, 'integral')}") - if ( - op == "mean" - and cubed.array_api.isdtype(var.dtype, "integral") - or var.dtype == np.dtype("float16") + if op == "mean" and xp.isdtype( + var.dtype, ("integral", "complex floating", np.dtype("float16")) ): return pytest.raises( TypeError, match="Only real floating-point dtypes are allowed in mean" From 3b166943dec7318fad46b0192ef28ef1797741d1 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 12:01:20 +0200 Subject: [PATCH 09/11] skip `var` and `std` --- xarray_array_testing/tests/test_cubed.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index bf36842..6a7d89f 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -78,5 +78,7 @@ def expected_errors(op, **parameters) -> ContextManager: return pytest.raises( TypeError, match="Only real floating-point dtypes are allowed in mean" ) + elif op in {"var", "std"}: + pytest.skip(reason=f"cubed does not implement {op} yet") else: return nullcontext() From f97633dc47ce549d955231a7fcbcd63f421aa441 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 12:01:36 +0200 Subject: [PATCH 10/11] expect an error for `float16` That dtype is currently not part of the spec. --- xarray_array_testing/tests/test_cubed.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index 6a7d89f..a7ab65f 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -78,6 +78,10 @@ def expected_errors(op, **parameters) -> ContextManager: return pytest.raises( TypeError, match="Only real floating-point dtypes are allowed in mean" ) + elif xp.isdtype(var.dtype, np.dtype("float16")): + return pytest.raises( + TypeError, match="Only numeric dtypes are allowed in isnan" + ) elif op in {"var", "std"}: pytest.skip(reason=f"cubed does not implement {op} yet") else: From 3e66118809eaa74b3b9d287116b06f090e6ebdfc Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 28 Aug 2024 12:06:52 +0200 Subject: [PATCH 11/11] change the target version to 3.11 --- pyproject.toml | 2 +- xarray_array_testing/tests/test_cubed.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d387a6..cb66373 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ exclude = [ "__pycache__", "docs", ] -target-version = "py312" +target-version = "py311" extend-include = ["*.ipynb"] line-length = 100 diff --git a/xarray_array_testing/tests/test_cubed.py b/xarray_array_testing/tests/test_cubed.py index a7ab65f..066f05e 100644 --- a/xarray_array_testing/tests/test_cubed.py +++ b/xarray_array_testing/tests/test_cubed.py @@ -1,4 +1,5 @@ -from contextlib import ContextManager, nullcontext +from contextlib import AbstractContextManager as ContextManager +from contextlib import nullcontext import cubed import cubed.random pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy