diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 610463ec3422b..df34c78f4408e 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1082,7 +1082,6 @@ Other API Changes has an improved ``KeyError`` message, and will not fail on duplicate column names with ``drop=True``. (:issue:`22484`) - Slicing a single row of a DataFrame with multiple ExtensionArrays of the same type now preserves the dtype, rather than coercing to object (:issue:`22784`) - :class:`DateOffset` attribute `_cacheable` and method `_should_cache` have been removed (:issue:`23118`) -- Comparing :class:`Timedelta` to be less or greater than unknown types now raises a ``TypeError`` instead of returning ``False`` (:issue:`20829`) - :meth:`Categorical.searchsorted`, when supplied a scalar value to search for, now returns a scalar instead of an array (:issue:`23466`). - :meth:`Categorical.searchsorted` now raises a ``KeyError`` rather that a ``ValueError``, if a searched for key is not found in its categories (:issue:`23466`). - :meth:`Index.hasnans` and :meth:`Series.hasnans` now always return a python boolean. Previously, a python or a numpy boolean could be returned, depending on circumstances (:issue:`23294`). diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index b0bead2f66ce4..0167f78a4efca 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -770,12 +770,26 @@ cdef class _Timedelta(timedelta): if is_timedelta64_object(other): other = Timedelta(other) else: - return NotImplemented + if op == Py_EQ: + return False + elif op == Py_NE: + return True + # only allow ==, != ops + raise TypeError('Cannot compare type {cls} with ' + 'type {other}' + .format(cls=type(self).__name__, + other=type(other).__name__)) if util.is_array(other): return PyObject_RichCompare(np.array([self]), other, op) return PyObject_RichCompare(other, self, reverse_ops[op]) else: - return NotImplemented + if op == Py_EQ: + return False + elif op == Py_NE: + return True + raise TypeError('Cannot compare type {cls} with type {other}' + .format(cls=type(self).__name__, + other=type(other).__name__)) return cmp_scalar(self.value, ots.value, op) diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 477c8aa4c3b0d..db0c848eaeb4b 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -44,10 +44,8 @@ def test_ops_error_str(self): with pytest.raises(TypeError): left + right - # GH 20829: python 2 comparison naturally does not raise TypeError - if compat.PY3: - with pytest.raises(TypeError): - left > right + with pytest.raises(TypeError): + left > right assert not left == right assert left != right @@ -107,9 +105,12 @@ def test_compare_timedelta_ndarray(self): expected = np.array([False, False]) tm.assert_numpy_array_equal(result, expected) + @pytest.mark.skip(reason="GH#20829 is reverted until after 0.24.0") def test_compare_custom_object(self): - """Make sure non supported operations on Timedelta returns NonImplemented - and yields to other operand (GH20829).""" + """ + Make sure non supported operations on Timedelta returns NonImplemented + and yields to other operand (GH#20829). + """ class CustomClass(object): def __init__(self, cmp_result=None): @@ -139,11 +140,7 @@ def __gt__(self, other): assert t == CustomClass(cmp_result=True) - @pytest.mark.skipif(compat.PY2, - reason="python 2 does not raise TypeError for \ - comparisons of different types") - @pytest.mark.parametrize("val", [ - "string", 1]) + @pytest.mark.parametrize("val", ["string", 1]) def test_compare_unknown_type(self, val): # GH20829 t = Timedelta('1s')