From 49e418aeeb5d07337d97264dba604d5d23ae27fb Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 25 Oct 2021 11:07:15 -0700 Subject: [PATCH 1/2] BUG: np.timedelta64 + Period --- doc/source/whatsnew/v1.4.0.rst | 2 +- pandas/_libs/tslibs/period.pyx | 9 +++- pandas/tests/arithmetic/test_period.py | 4 ++ pandas/tests/scalar/period/test_period.py | 59 +++++------------------ 4 files changed, 25 insertions(+), 49 deletions(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 254a004a37c40..e7893e3eca08d 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -565,7 +565,7 @@ I/O Period ^^^^^^ -- +- Bug in adding a :class:`Period` object to a ``np.timedelta64`` object incorrectly raising ``TypeError`` (:issue:`??`) - Plotting diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 0998cb7b0c21e..dcf4323bc8755 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -4,6 +4,7 @@ cimport numpy as cnp from cpython.object cimport ( Py_EQ, Py_NE, + PyObject_RichCompare, PyObject_RichCompareBool, ) from numpy cimport ( @@ -1594,6 +1595,9 @@ cdef class _Period(PeriodMixin): PeriodDtypeBase _dtype BaseOffset freq + # higher than np.ndarray, np.matrix, np.timedelta64 + __array_priority__ = 100 + dayofweek = _Period.day_of_week dayofyear = _Period.day_of_year @@ -1652,7 +1656,10 @@ cdef class _Period(PeriodMixin): return PyObject_RichCompareBool(self.ordinal, other.ordinal, op) elif other is NaT: return _nat_scalar_rules[op] - return NotImplemented # TODO: ndarray[object]? + elif util.is_array(other): + # in particular ndarray[object]; see test_pi_cmp_period + return np.array([PyObject_RichCompare(self, x, op) for x in other]) + return NotImplemented def __hash__(self): return hash((self.ordinal, self.freqstr)) diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py index 7d215c940c031..287f3159c71b3 100644 --- a/pandas/tests/arithmetic/test_period.py +++ b/pandas/tests/arithmetic/test_period.py @@ -185,6 +185,10 @@ def test_pi_cmp_period(self): exp = idx.values < idx.values[10] tm.assert_numpy_array_equal(result, exp) + # Tests Period.__richcmp__ against ndarray[object, ndim=2] + result = idx.values.reshape(10, 2) < 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 = ( diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py index 9b2e0cac5de84..f1b8c1cfdd39b 100644 --- a/pandas/tests/scalar/period/test_period.py +++ b/pandas/tests/scalar/period/test_period.py @@ -1287,20 +1287,8 @@ def test_add_offset(self): msg = "Input has different freq|Input cannot be converted to Period" with pytest.raises(IncompatibleFrequency, match=msg): p + o - - if isinstance(o, np.timedelta64): - msg = "cannot use operands with types" - with pytest.raises(TypeError, match=msg): - o + p - else: - msg = "|".join( - [ - "Input has different freq", - "Input cannot be converted to Period", - ] - ) - with pytest.raises(IncompatibleFrequency, match=msg): - o + p + with pytest.raises(IncompatibleFrequency, match=msg): + o + p for freq in ["M", "2M", "3M"]: p = Period("2011-03", freq=freq) @@ -1329,14 +1317,8 @@ def test_add_offset(self): with pytest.raises(IncompatibleFrequency, match=msg): p + o - - if isinstance(o, np.timedelta64): - td_msg = "cannot use operands with types" - with pytest.raises(TypeError, match=td_msg): - o + p - else: - with pytest.raises(IncompatibleFrequency, match=msg): - o + p + with pytest.raises(IncompatibleFrequency, match=msg): + o + p # freq is Tick for freq in ["D", "2D", "3D"]: @@ -1352,14 +1334,11 @@ def test_add_offset(self): exp = Period("2011-04-03", freq=freq) assert p + np.timedelta64(2, "D") == exp - msg = "cannot use operands with types" - with pytest.raises(TypeError, match=msg): - np.timedelta64(2, "D") + p + assert np.timedelta64(2, "D") + p == exp exp = Period("2011-04-02", freq=freq) assert p + np.timedelta64(3600 * 24, "s") == exp - with pytest.raises(TypeError, match=msg): - np.timedelta64(3600 * 24, "s") + p + assert np.timedelta64(3600 * 24, "s") + p == exp exp = Period("2011-03-30", freq=freq) assert p + timedelta(-2) == exp @@ -1385,14 +1364,8 @@ def test_add_offset(self): ]: with pytest.raises(IncompatibleFrequency, match=msg): p + o - - if isinstance(o, np.timedelta64): - td_msg = "cannot use operands with types" - with pytest.raises(TypeError, match=td_msg): - o + p - else: - with pytest.raises(IncompatibleFrequency, match=msg): - o + p + with pytest.raises(IncompatibleFrequency, match=msg): + o + p for freq in ["H", "2H", "3H"]: p = Period("2011-04-01 09:00", freq=freq) @@ -1408,13 +1381,11 @@ def test_add_offset(self): msg = "cannot use operands with types" exp = Period("2011-04-01 12:00", freq=freq) assert p + np.timedelta64(3, "h") == exp - with pytest.raises(TypeError, match=msg): - np.timedelta64(3, "h") + p + assert np.timedelta64(3, "h") + p == exp exp = Period("2011-04-01 10:00", freq=freq) assert p + np.timedelta64(3600, "s") == exp - with pytest.raises(TypeError, match=msg): - np.timedelta64(3600, "s") + p + assert np.timedelta64(3600, "s") + p == exp exp = Period("2011-04-01 11:00", freq=freq) assert p + timedelta(minutes=120) == exp @@ -1440,14 +1411,8 @@ def test_add_offset(self): ]: with pytest.raises(IncompatibleFrequency, match=msg): p + o - - if isinstance(o, np.timedelta64): - td_msg = "cannot use operands with types" - with pytest.raises(TypeError, match=td_msg): - o + p - else: - with pytest.raises(IncompatibleFrequency, match=msg): - o + p + with pytest.raises(IncompatibleFrequency, match=msg): + o + p def test_sub_offset(self): # freq is DateOffset From 6a22bea2cd2b43d38114aac0ea229e69c581d974 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 25 Oct 2021 11:08:12 -0700 Subject: [PATCH 2/2] GH Ref --- doc/source/whatsnew/v1.4.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index e7893e3eca08d..fb7d9d77c8c79 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -565,7 +565,7 @@ I/O Period ^^^^^^ -- Bug in adding a :class:`Period` object to a ``np.timedelta64`` object incorrectly raising ``TypeError`` (:issue:`??`) +- Bug in adding a :class:`Period` object to a ``np.timedelta64`` object incorrectly raising ``TypeError`` (:issue:`44182`) - Plotting