Skip to content

Commit

Permalink
BUG: GH24011 - Rich comparisons of Timestamps now return NotImplement…
Browse files Browse the repository at this point in the history
…ed (#24021)
  • Loading branch information
AlexandreDecan authored and jreback committed Apr 5, 2019
1 parent 1a30601 commit a193df1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Backwards incompatible API changes

.. _whatsnew_0250.api_breaking.utc_offset_indexing:


Indexing with date strings with UTC offsets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -215,6 +216,7 @@ Other API Changes
- :class:`DatetimeTZDtype` will now standardize pytz timezones to a common timezone instance (:issue:`24713`)
- ``Timestamp`` and ``Timedelta`` scalars now implement the :meth:`to_numpy` method as aliases to :meth:`Timestamp.to_datetime64` and :meth:`Timedelta.to_timedelta64`, respectively. (:issue:`24653`)
- :meth:`Timestamp.strptime` will now rise a ``NotImplementedError`` (:issue:`25016`)
- Comparing :class:`Timestamp` with unsupported objects now returns :py:obj:`NotImplemented` instead of raising ``TypeError``. This implies that unsupported rich comparisons are delegated to the other object, and are now consistent with Python 3 behavior for ``datetime`` objects (:issue:`24011`)
- Bug in :meth:`DatetimeIndex.snap` which didn't preserving the ``name`` of the input :class:`Index` (:issue:`25575`)

.. _whatsnew_0250.deprecations:
Expand Down
17 changes: 2 additions & 15 deletions pandas/_libs/tslibs/timestamps.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -227,26 +227,13 @@ cdef class _Timestamp(datetime):
if is_datetime64_object(other):
other = Timestamp(other)
else:
if op == Py_EQ:
return False
elif op == Py_NE:
return True

# only allow ==, != ops
raise TypeError('Cannot compare type %r with type %r' %
(type(self).__name__,
type(other).__name__))
return NotImplemented
elif is_array(other):
# avoid recursion error GH#15183
return PyObject_RichCompare(np.array([self]), other, op)
return PyObject_RichCompare(other, self, reverse_ops[op])
else:
if op == Py_EQ:
return False
elif op == Py_NE:
return True
raise TypeError('Cannot compare type %r with type %r' %
(type(self).__name__, type(other).__name__))
return NotImplemented

self._assert_tzawareness_compat(other)
return cmp_scalar(self.value, ots.value, op)
Expand Down
30 changes: 30 additions & 0 deletions pandas/tests/scalar/timestamp/test_comparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,33 @@ def test_timestamp_compare_with_early_datetime(self):
assert stamp >= datetime(1600, 1, 1)
assert stamp < datetime(2700, 1, 1)
assert stamp <= datetime(2700, 1, 1)


def test_rich_comparison_with_unsupported_type():
# Comparisons with unsupported objects should return NotImplemented
# (it previously raised TypeError, see #24011)

class Inf(object):
def __lt__(self, o):
return False

def __le__(self, o):
return isinstance(o, Inf)

def __gt__(self, o):
return not isinstance(o, Inf)

def __ge__(self, o):
return True

def __eq__(self, o):
return isinstance(o, Inf)

inf = Inf()
timestamp = Timestamp('2018-11-30')

for left, right in [(inf, timestamp), (timestamp, inf)]:
assert left > right or left < right
assert left >= right or left <= right
assert not (left == right)
assert left != right

0 comments on commit a193df1

Please sign in to comment.