From 72ebc5dd62a5664978c458f893672a3f36cda2a5 Mon Sep 17 00:00:00 2001 From: Pietro Battiston Date: Tue, 14 Aug 2018 11:33:01 +0200 Subject: [PATCH] CLN: remove broken Index.__inv__, add Index.__invert__ closes #22335 --- doc/source/whatsnew/v0.24.0.txt | 3 ++- pandas/core/indexes/base.py | 4 ++-- pandas/tests/test_arithmetic.py | 37 ++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 9b70bda82e247..db5045b55a2b8 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -614,6 +614,8 @@ Indexing - Fixed ``DataFrame[np.nan]`` when columns are non-unique (:issue:`21428`) - Bug when indexing :class:`DatetimeIndex` with nanosecond resolution dates and timezones (:issue:`11679`) - Bug where indexing with a Numpy array containing negative values would mutate the indexer (:issue:`21867`) +- Method :meth:`Index.__inv__` was suppressed, as it provided the same functionality as :meth:`Index.__neg__` rather than what its name suggested; :meth:`Index.__invert__` was added instead, and the ``~`` operator now works (analogously as for :class:`Series`) (:issue:`21688`) +- Missing ^^^^^^^ @@ -688,4 +690,3 @@ Other - :meth: `~pandas.io.formats.style.Styler.background_gradient` now also supports tablewise application (in addition to rowwise and columnwise) with ``axis=None`` (:issue:`15204`) - - -- diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index bfa669a0ca164..7b90faeeefd26 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4689,7 +4689,7 @@ def _add_numeric_methods_disabled(cls): cls.__neg__ = make_invalid_op('__neg__') cls.__pos__ = make_invalid_op('__pos__') cls.__abs__ = make_invalid_op('__abs__') - cls.__inv__ = make_invalid_op('__inv__') + cls.__invert__ = make_invalid_op('__invert__') def _maybe_update_attributes(self, attrs): """ Update Index attributes (e.g. freq) depending on op """ @@ -4786,7 +4786,7 @@ def _evaluate_numeric_unary(self): cls.__neg__ = _make_evaluate_unary(operator.neg, '__neg__') cls.__pos__ = _make_evaluate_unary(operator.pos, '__pos__') cls.__abs__ = _make_evaluate_unary(np.abs, '__abs__') - cls.__inv__ = _make_evaluate_unary(lambda x: -x, '__inv__') + cls.__invert__ = _make_evaluate_unary(np.invert, '__invert__') @classmethod def _add_numeric_methods(cls): diff --git a/pandas/tests/test_arithmetic.py b/pandas/tests/test_arithmetic.py index 30d69e243c446..546e8b0357670 100644 --- a/pandas/tests/test_arithmetic.py +++ b/pandas/tests/test_arithmetic.py @@ -15,7 +15,7 @@ from pandas._libs.tslibs import IncompatibleFrequency from pandas import ( timedelta_range, - Timedelta, Timestamp, NaT, Series, TimedeltaIndex, DatetimeIndex, + Timedelta, Timestamp, NaT, Series, Index, TimedeltaIndex, DatetimeIndex, DataFrame) @@ -73,6 +73,41 @@ def box_df_fail(request): return request.param +# ------------------------------------------------------------------ +# Numeric types Arithmetic Operations + +class TestNumericOps(object): + + @pytest.mark.parametrize('opname', ['neg', 'pos', 'abs', 'inv', 'invert']) + @pytest.mark.parametrize('dtype', [int, float, object]) + def test_numeric_unary_ops(self, box, dtype, opname): + # GH 22335 + data = [-2, 0, 4, 5] + obj = box(data, dtype=dtype) + + def call_method(): + return getattr(obj, '__{}__'.format(opname))() + + if opname == 'inv': + # GH 22335 - 'inv' was wrong and was removed + pytest.raises(AttributeError, call_method) + return + if opname == 'invert' and dtype is float: + # inversion of floats is undefined + pytest.raises(TypeError, call_method) + return + if dtype in (object, bool) and isinstance(obj, Index): + # GH 16873 - numeric operations on 'object' dtype might be removed + # from NDFrames as well + pytest.raises(TypeError, call_method) + return + + result = call_method() + library_op = getattr(operator, opname) + expected = box([library_op(i) for i in data], dtype=dtype) + tm.assert_equal(result, expected) + + # ------------------------------------------------------------------ # Timedelta64[ns] dtype Comparisons