From 2ab022817332fd4a73119e7b223f7e2105b814aa Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 08:33:31 +0100 Subject: [PATCH 01/10] fix: Period.__eq__ numpy scalar --- pandas/tests/arithmetic/test_period.py | 4 ++++ pandas/tests/scalar/period/test_period.py | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py index d7cb314743e86..020f64ba16cdb 100644 --- a/pandas/tests/arithmetic/test_period.py +++ b/pandas/tests/arithmetic/test_period.py @@ -189,6 +189,10 @@ def test_pi_cmp_period(self): result = idx.values.reshape(10, 2) < idx[10] tm.assert_numpy_array_equal(result, exp.reshape(10, 2)) + # Tests Period.__richcmp__ against ndarray[object, ndim=0] + result = idx < np.array(idx[10]) + tm.assert_numpy_array_equal(result, exp.reshape(10, 2)) + # TODO: moved from test_datetime64; de-duplicate with version below def test_parr_cmp_period_scalar2(self, box_with_array): xbox = get_expected_box(box_with_array) diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index f1b8c1cfdd39b..87188a43338c7 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1148,6 +1148,15 @@ def test_period_cmp_nat(self): assert not left <= right assert not left >= right + def test_comparison_numpy_scalar(self): + p = Period("2000-01", "M") + zerodim = np.array(0) + scalar = np.int_(0) + + for left, right in ((p, zerodim), (zerodim, p), (p, scalar), (scalar, p)): + assert not left == right + assert (left == right) is np.bool_(False) + class TestArithmetic: def test_sub_delta(self): From 024dc78b36a4bc2180dd087a15f7276501e3bf14 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 08:38:22 +0100 Subject: [PATCH 02/10] fix test --- pandas/tests/arithmetic/test_period.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py index 020f64ba16cdb..41c2cb2cc4f1e 100644 --- a/pandas/tests/arithmetic/test_period.py +++ b/pandas/tests/arithmetic/test_period.py @@ -191,7 +191,7 @@ def test_pi_cmp_period(self): # Tests Period.__richcmp__ against ndarray[object, ndim=0] result = idx < np.array(idx[10]) - tm.assert_numpy_array_equal(result, exp.reshape(10, 2)) + tm.assert_numpy_array_equal(result, exp) # TODO: moved from test_datetime64; de-duplicate with version below def test_parr_cmp_period_scalar2(self, box_with_array): From 1bc17edcf5ddf57c9715b24c619da401c1828c52 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 08:46:22 +0100 Subject: [PATCH 03/10] update code --- pandas/_libs/tslibs/period.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 337876d610c5e..fa36ff32c72e7 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1656,7 +1656,7 @@ cdef class _Period(PeriodMixin): return PyObject_RichCompareBool(self.ordinal, other.ordinal, op) elif other is NaT: return _nat_scalar_rules[op] - elif util.is_array(other): + elif util.is_array(other) and not np.ndim(other) == 0: # in particular ndarray[object]; see test_pi_cmp_period return np.array([PyObject_RichCompare(self, x, op) for x in other]) return NotImplemented From 32e1883b964a0fad2492250225ad438cf80dbc59 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 10:29:52 +0100 Subject: [PATCH 04/10] fix tests --- pandas/tests/scalar/period/test_period.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index 87188a43338c7..7588c99a838d9 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1148,14 +1148,15 @@ def test_period_cmp_nat(self): assert not left <= right assert not left >= right - def test_comparison_numpy_scalar(self): + @pytest.mark.parametrize( + "scalar, expected", ((np.array(0), np.bool_(False)), (np.int_(0), False)) + ) + def test_comparison_numpy_scalar(self, scalar, expected): p = Period("2000-01", "M") - zerodim = np.array(0) - scalar = np.int_(0) - for left, right in ((p, zerodim), (zerodim, p), (p, scalar), (scalar, p)): + for left, right in ((p, scalar), (scalar, p)): assert not left == right - assert (left == right) is np.bool_(False) + assert (left == right) is expected class TestArithmetic: From 6c05457240b388a3916340766adf7885c84e1e9d Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 12:06:14 +0100 Subject: [PATCH 05/10] fix test again --- pandas/tests/scalar/period/test_period.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index 7588c99a838d9..90f5d65339bc7 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1148,15 +1148,12 @@ def test_period_cmp_nat(self): assert not left <= right assert not left >= right - @pytest.mark.parametrize( - "scalar, expected", ((np.array(0), np.bool_(False)), (np.int_(0), False)) - ) - def test_comparison_numpy_scalar(self, scalar, expected): + @pytest.mark.parametrize("scalar", (np.array(0), np.int_(0))) + def test_comparison_numpy_scalar(self, scalar): p = Period("2000-01", "M") for left, right in ((p, scalar), (scalar, p)): - assert not left == right - assert (left == right) is expected + assert (left == right) is False class TestArithmetic: From 6592e9731680580261b70af6bd9278aa0e956b2e Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 12:07:02 +0100 Subject: [PATCH 06/10] clean code --- pandas/_libs/tslibs/period.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index fa36ff32c72e7..88aa11e6e6394 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1656,7 +1656,7 @@ cdef class _Period(PeriodMixin): return PyObject_RichCompareBool(self.ordinal, other.ordinal, op) elif other is NaT: return _nat_scalar_rules[op] - elif util.is_array(other) and not np.ndim(other) == 0: + elif util.is_array(other) and np.ndim(other) > 0: # in particular ndarray[object]; see test_pi_cmp_period return np.array([PyObject_RichCompare(self, x, op) for x in other]) return NotImplemented From 784d2e8420b53885f5aea83cf2b7dbaa5bb397d2 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 12:39:45 +0100 Subject: [PATCH 07/10] handle p == np.array(p) --- pandas/_libs/tslibs/period.pyx | 9 ++++++--- pandas/tests/scalar/period/test_period.py | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 88aa11e6e6394..c00aff78d40ee 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1656,9 +1656,12 @@ cdef class _Period(PeriodMixin): return PyObject_RichCompareBool(self.ordinal, other.ordinal, op) elif other is NaT: return _nat_scalar_rules[op] - elif util.is_array(other) and np.ndim(other) > 0: - # in particular ndarray[object]; see test_pi_cmp_period - return np.array([PyObject_RichCompare(self, x, op) for x in other]) + elif util.is_array(other): + if np.ndim(other) > 0: + # in particular ndarray[object]; see test_pi_cmp_period + return np.array([PyObject_RichCompare(self, x, op) for x in other]) + else: + return PyObject_RichCompare(self, other.item(), op) return NotImplemented def __hash__(self): diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index 90f5d65339bc7..f7c117466422e 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1148,12 +1148,15 @@ def test_period_cmp_nat(self): assert not left <= right assert not left >= right - @pytest.mark.parametrize("scalar", (np.array(0), np.int_(0))) - def test_comparison_numpy_scalar(self, scalar): + @pytest.mark.parametrize( + "scalar, expected", + ((np.array(0), False), (np.int_(0), False), (Period("2000-01", "M"), True)), + ) + def test_comparison_numpy_scalar(self, scalar, expected): p = Period("2000-01", "M") for left, right in ((p, scalar), (scalar, p)): - assert (left == right) is False + assert (left == right) is expected class TestArithmetic: From f8e89f1629512b66e2837854a076e672f5bbeee2 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 2 Nov 2021 12:46:53 +0100 Subject: [PATCH 08/10] linting --- pandas/_libs/tslibs/period.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index c00aff78d40ee..3c3c7357df1ab 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1658,10 +1658,10 @@ cdef class _Period(PeriodMixin): return _nat_scalar_rules[op] elif util.is_array(other): if np.ndim(other) > 0: - # in particular ndarray[object]; see test_pi_cmp_period - return np.array([PyObject_RichCompare(self, x, op) for x in other]) + # in particular ndarray[object]; see test_pi_cmp_period + return np.array([PyObject_RichCompare(self, x, op) for x in other]) else: - return PyObject_RichCompare(self, other.item(), op) + return PyObject_RichCompare(self, other.item(), op) return NotImplemented def __hash__(self): From 9a2db3bf9a8b3185e315ced0b88843d015207369 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Wed, 3 Nov 2021 22:30:07 +0100 Subject: [PATCH 09/10] use cnp.PyArray_IsZeroDim --- pandas/_libs/tslibs/period.pyx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 3c3c7357df1ab..f594e0a8bdafd 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1657,11 +1657,12 @@ cdef class _Period(PeriodMixin): elif other is NaT: return _nat_scalar_rules[op] elif util.is_array(other): - if np.ndim(other) > 0: + # GH#44285 + if cnp.PyArray_IsZeroDim(other): + return PyObject_RichCompare(self, other.item(), op) + else: # in particular ndarray[object]; see test_pi_cmp_period return np.array([PyObject_RichCompare(self, x, op) for x in other]) - else: - return PyObject_RichCompare(self, other.item(), op) return NotImplemented def __hash__(self): From e0fa7061e76c64f9e77cad05a364c9de4f3534d5 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Wed, 3 Nov 2021 22:32:20 +0100 Subject: [PATCH 10/10] only test zerodim_arr --- pandas/tests/scalar/period/test_period.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index f7c117466422e..cd1bf21753249 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1149,14 +1149,14 @@ def test_period_cmp_nat(self): assert not left >= right @pytest.mark.parametrize( - "scalar, expected", - ((np.array(0), False), (np.int_(0), False), (Period("2000-01", "M"), True)), + "zerodim_arr, expected", + ((np.array(0), False), (np.array(Period("2000-01", "M")), True)), ) - def test_comparison_numpy_scalar(self, scalar, expected): + def test_comparison_numpy_zerodim_arr(self, zerodim_arr, expected): p = Period("2000-01", "M") - for left, right in ((p, scalar), (scalar, p)): - assert (left == right) is expected + assert (p == zerodim_arr) is expected + assert (zerodim_arr == p) is expected class TestArithmetic: