From b11da34f736f4e71096c1b710e446677981e8722 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Tue, 10 Aug 2021 16:31:34 -0500 Subject: [PATCH] BUG: Remove logical object ufuncs with bool output While this makes sense, the implementation here does not actually work. It is very difficult to actually reach it, but if reached it just crashes the process, so remove it. (I am not actually sure why the input needs to be object already here, that seems to be an issue with the current dispatcher/promotion special casing object a bit oddly.) --- numpy/core/code_generators/generate_umath.py | 4 +--- numpy/core/tests/test_ufunc.py | 21 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 9e94f9cccc47..d567b2eb9aaf 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -489,7 +489,6 @@ def english_upper(s): 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalAnd'), - TD(O, f='npy_ObjectLogicalAnd', out='?'), ), 'logical_not': Ufunc(1, 1, None, @@ -497,7 +496,6 @@ def english_upper(s): None, TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalNot'), - TD(O, f='npy_ObjectLogicalNot', out='?'), ), 'logical_or': Ufunc(2, 1, False_, @@ -505,13 +503,13 @@ def english_upper(s): 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalOr'), - TD(O, f='npy_ObjectLogicalOr', out='?'), ), 'logical_xor': Ufunc(2, 1, False_, docstrings.get('numpy.core.umath.logical_xor'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?'), + # TODO: using obj.logical_xor() seems pretty much useless: TD(P, f='logical_xor'), ), 'maximum': diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index a47f1df49871..401428ba6252 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -2029,6 +2029,27 @@ def test_NotImplemented_not_returned(self): assert_raises(TypeError, f, a, b) assert_raises(TypeError, f, c, a) + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or]) # logical_xor object loop is bad + @pytest.mark.parametrize("signature", + [(None, None, object), (object, None, None), + (None, object, None)]) + def test_logical_ufuncs_object_signatures(self, ufunc, signature): + a = np.array([True, None, False], dtype=object) + res = ufunc(a, a, signature=signature) + assert res.dtype == object + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + @pytest.mark.parametrize("signature", + [(bool, None, object), (object, None, bool), + (None, object, bool)]) + def test_logical_ufuncs_mixed_object_signatures(self, ufunc, signature): + # Most mixed signatures fail (except those with bool out, e.g. `OO->?`) + a = np.array([True, None, False]) + with pytest.raises(TypeError): + ufunc(a, a, signature=signature) + def test_reduce_noncontig_output(self): # Check that reduction deals with non-contiguous output arrays # appropriately.