From 2bb829e90bbcf32034f2bc54a6cd337efe51eb01 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Sun, 10 Jan 2021 15:39:27 +0100 Subject: [PATCH 1/3] Allow NumPy ufuncs to work with `np.ndarray` outputs where operations are clearly defined Fixes #213 --- CHANGELOG.md | 5 +++++ fletcher/base.py | 18 ++++++++++++++++++ tests/test_pandas_integration.py | 12 ++++++++++++ 3 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index adf531ea..a3e411d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ Starting with 0.5, we will follow the following versioning scheme: * We bump MINOR on breaking changes. * We increase PATCH otherwise. +0.7.2 (2021-01-XX) +------------------ + +* Allow NumPy ufuncs to work with `np.ndarray` outputs where operations are clearly defined (i.e. the fletcher array has no nulls). + 0.7.1 (2020-12-29) ------------------ diff --git a/fletcher/base.py b/fletcher/base.py index 6a7c1f2b..71f01a64 100644 --- a/fletcher/base.py +++ b/fletcher/base.py @@ -547,6 +547,24 @@ def __array_ufunc__(self, ufunc, method: str, *inputs, **kwargs): ) if len(inputs) != 2: raise NotImplementedError("Only ufuncs with a second input are supported") + if "out" in kwargs: + out = kwargs.pop("out") + if len(out) == 1: + out_array = out[0] + if isinstance(out_array, np.ndarray) and self.data.null_count == 0: + self_as_np = np.asarray(self) + mapped_inputs = [self_as_np if i is self else i for i in inputs] + return self_as_np.__array_ufunc__( + ufunc, method, *mapped_inputs, **kwargs + ) + else: + raise NotImplementedError( + "Currently ufuncs with outputs are only supported for arrays without missings" + ) + else: + raise NotImplementedError( + "Currently ufuncs only support a single output" + ) if len(kwargs) > 0: raise NotImplementedError("ufuncs with kwargs aren't supported") if isinstance(inputs[0], FletcherBaseArray): diff --git a/tests/test_pandas_integration.py b/tests/test_pandas_integration.py index 3b4ce016..368e9828 100644 --- a/tests/test_pandas_integration.py +++ b/tests/test_pandas_integration.py @@ -278,3 +278,15 @@ def test_setitem_chunked_int_index(indices, test_array_chunked): ser[integer_index] = ["int", "index"] assert ser[indices[0]] == "int" assert ser[indices[1]] == "index" + + +def test_numpy_ufunc_with_keyword(fletcher_array): + # https://github.com/xhochy/fletcher/issues/213 + + x = fletcher_array([0]) + y = np.array([False]) + + # Test without in-place storage + y | (x == 1) + # Test with in-place storage + y |= x == 1 From e49830848973541272bf38fe641c21b21a75f564 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Sun, 17 Jan 2021 20:05:31 +0100 Subject: [PATCH 2/3] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3e411d2..536ad7c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ Starting with 0.5, we will follow the following versioning scheme: * We bump MINOR on breaking changes. * We increase PATCH otherwise. -0.7.2 (2021-01-XX) +0.7.2 (2021-01-17) ------------------ * Allow NumPy ufuncs to work with `np.ndarray` outputs where operations are clearly defined (i.e. the fletcher array has no nulls). From f913dd14cf63118b991626e817e6c8deeb0733f6 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Sun, 17 Jan 2021 20:24:05 +0100 Subject: [PATCH 3/3] Implement dtype.itemsize --- fletcher/base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fletcher/base.py b/fletcher/base.py index 71f01a64..1015d8f5 100644 --- a/fletcher/base.py +++ b/fletcher/base.py @@ -209,6 +209,10 @@ def name(self) -> str: """ return str(self) + @property + def itemsize(self) -> int: + return self.arrow_dtype.bit_width + @property def _is_boolean(self): return pa.types.is_boolean(self.arrow_dtype)