Skip to content

Commit 718cec9

Browse files
authored
ENH: Implement Index.__invert__ (#45006)
1 parent e50d077 commit 718cec9

File tree

8 files changed

+46
-9
lines changed

8 files changed

+46
-9
lines changed

pandas/_libs/tslibs/timedeltas.pyx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1401,7 +1401,6 @@ class Timedelta(_Timedelta):
14011401
# Arithmetic Methods
14021402
# TODO: Can some of these be defined in the cython class?
14031403

1404-
__inv__ = _op_unary_method(lambda x: -x, '__inv__')
14051404
__neg__ = _op_unary_method(lambda x: -x, '__neg__')
14061405
__pos__ = _op_unary_method(lambda x: x, '__pos__')
14071406
__abs__ = _op_unary_method(lambda x: abs(x), '__abs__')

pandas/core/indexes/base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6638,10 +6638,9 @@ def __neg__(self):
66386638
def __pos__(self):
66396639
return self._unary_method(operator.pos)
66406640

6641-
def __inv__(self):
6642-
# TODO: why not operator.inv?
6643-
# TODO: __inv__ vs __invert__?
6644-
return self._unary_method(lambda x: -x)
6641+
def __invert__(self):
6642+
# GH#8875
6643+
return self._unary_method(operator.inv)
66456644

66466645
# --------------------------------------------------------------------
66476646
# Reductions

pandas/core/indexes/multi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3804,7 +3804,7 @@ def drop_duplicates(self, keep: str | bool = "first") -> MultiIndex:
38043804
__neg__ = make_invalid_op("__neg__")
38053805
__pos__ = make_invalid_op("__pos__")
38063806
__abs__ = make_invalid_op("__abs__")
3807-
__inv__ = make_invalid_op("__inv__")
3807+
__invert__ = make_invalid_op("__invert__")
38083808

38093809

38103810
def _lexsort_depth(codes: list[np.ndarray], nlevels: int) -> int:

pandas/tests/frame/test_unary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
class TestDataFrameUnaryOperators:
11-
# __pos__, __neg__, __inv__
11+
# __pos__, __neg__, __invert__
1212

1313
@pytest.mark.parametrize(
1414
"df,expected",

pandas/tests/indexes/common.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,30 @@ def test_append_preserves_dtype(self, simple_index):
740740
alt = index.take(list(range(N)) * 2)
741741
tm.assert_index_equal(result, alt, check_exact=True)
742742

743+
def test_inv(self, simple_index):
744+
idx = simple_index
745+
746+
if idx.dtype.kind in ["i", "u"]:
747+
res = ~idx
748+
expected = Index(~idx.values, name=idx.name)
749+
tm.assert_index_equal(res, expected)
750+
751+
# check that we are matching Series behavior
752+
res2 = ~Series(idx)
753+
# TODO(2.0): once we preserve dtype, check_dtype can be True
754+
tm.assert_series_equal(res2, Series(expected), check_dtype=False)
755+
else:
756+
if idx.dtype.kind == "f":
757+
msg = "ufunc 'invert' not supported for the input types"
758+
else:
759+
msg = "bad operand"
760+
with pytest.raises(TypeError, match=msg):
761+
~idx
762+
763+
# check that we get the same behavior with Series
764+
with pytest.raises(TypeError, match=msg):
765+
~Series(idx)
766+
743767

744768
class NumericBase(Base):
745769
"""

pandas/tests/indexes/multi/test_compat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_numeric_compat(idx):
2727
1 // idx
2828

2929

30-
@pytest.mark.parametrize("method", ["all", "any"])
30+
@pytest.mark.parametrize("method", ["all", "any", "__invert__"])
3131
def test_logical_compat(idx, method):
3232
msg = f"cannot perform {method}"
3333

pandas/tests/scalar/timedelta/test_timedelta.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@
2525

2626

2727
class TestTimedeltaUnaryOps:
28+
def test_invert(self):
29+
td = Timedelta(10, unit="d")
30+
31+
msg = "bad operand type for unary ~"
32+
with pytest.raises(TypeError, match=msg):
33+
~td
34+
35+
# check this matches pytimedelta and timedelta64
36+
with pytest.raises(TypeError, match=msg):
37+
~(td.to_pytimedelta())
38+
39+
umsg = "ufunc 'invert' not supported for the input types"
40+
with pytest.raises(TypeError, match=umsg):
41+
~(td.to_timedelta64())
42+
2843
def test_unary_ops(self):
2944
td = Timedelta(10, unit="d")
3045

pandas/tests/series/test_unary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
class TestSeriesUnaryOps:
8-
# __neg__, __pos__, __inv__
8+
# __neg__, __pos__, __invert__
99

1010
def test_neg(self):
1111
ser = tm.makeStringSeries()

0 commit comments

Comments
 (0)