Skip to content

Commit ef5ad65

Browse files
committed
fix _can_hold_na case
1 parent db83ead commit ef5ad65

File tree

1 file changed

+46
-20
lines changed

1 file changed

+46
-20
lines changed

pandas/core/indexes/base.py

+46-20
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
FrozenSet,
1010
Hashable,
1111
List,
12-
NewType,
1312
Optional,
1413
Sequence,
1514
Tuple,
@@ -24,13 +23,16 @@
2423
from pandas._libs import algos as libalgos, index as libindex, lib
2524
import pandas._libs.join as libjoin
2625
from pandas._libs.lib import is_datetime_array, no_default
27-
from pandas._libs.tslibs import IncompatibleFrequency, OutOfBoundsDatetime, Timestamp
26+
from pandas._libs.tslibs import OutOfBoundsDatetime, Timestamp
27+
from pandas._libs.tslibs.period import IncompatibleFrequency
2828
from pandas._libs.tslibs.timezones import tz_compare
2929
from pandas._typing import AnyArrayLike, Dtype, DtypeObj, Label
30+
from pandas.compat import set_function_name
3031
from pandas.compat.numpy import function as nv
3132
from pandas.errors import DuplicateLabelError, InvalidIndexError
3233
from pandas.util._decorators import Appender, cache_readonly, doc
3334

35+
from pandas.core.dtypes import concat as _concat
3436
from pandas.core.dtypes.cast import (
3537
maybe_cast_to_integer_array,
3638
validate_numeric_casting,
@@ -66,6 +68,7 @@
6668
from pandas.core.dtypes.concat import concat_compat
6769
from pandas.core.dtypes.generic import (
6870
ABCCategorical,
71+
ABCDataFrame,
6972
ABCDatetimeIndex,
7073
ABCMultiIndex,
7174
ABCPandasArray,
@@ -76,7 +79,7 @@
7679
)
7780
from pandas.core.dtypes.missing import array_equivalent, isna
7881

79-
from pandas.core import missing, ops
82+
from pandas.core import ops
8083
from pandas.core.accessor import CachedAccessor
8184
import pandas.core.algorithms as algos
8285
from pandas.core.arrays import Categorical, ExtensionArray
@@ -85,6 +88,7 @@
8588
import pandas.core.common as com
8689
from pandas.core.indexers import deprecate_ndim_indexing
8790
from pandas.core.indexes.frozen import FrozenList
91+
import pandas.core.missing as missing
8892
from pandas.core.ops import get_op_result_name
8993
from pandas.core.ops.invalid import make_invalid_op
9094
from pandas.core.sorting import ensure_key_mapped, nargsort
@@ -118,10 +122,24 @@
118122
str_t = str
119123

120124

121-
_o_dtype = np.dtype(object)
125+
def _make_arithmetic_op(op, cls):
126+
def index_arithmetic_method(self, other):
127+
if isinstance(other, (ABCSeries, ABCDataFrame, ABCTimedeltaIndex)):
128+
return NotImplemented
129+
130+
from pandas import Series
131+
132+
result = op(Series(self), other)
133+
if isinstance(result, tuple):
134+
return (Index(result[0]), Index(result[1]))
135+
return Index(result)
122136

137+
name = f"__{op.__name__}__"
138+
return set_function_name(index_arithmetic_method, name, cls)
123139

124-
_Identity = NewType("_Identity", object)
140+
141+
_o_dtype = np.dtype(object)
142+
_Identity = object
125143

126144

127145
def _new_Index(cls, d):
@@ -220,7 +238,7 @@ def _outer_indexer(self, left, right):
220238

221239
_typ = "index"
222240
_data: Union[ExtensionArray, np.ndarray]
223-
_id: _Identity
241+
_id = None
224242
_name: Label = None
225243
# MultiIndex.levels previously allowed setting the index name. We
226244
# don't allow this anymore, and raise if it happens rather than
@@ -435,9 +453,8 @@ def _simple_new(cls, values, name: Label = None):
435453
result._index_data = values
436454
result._name = name
437455
result._cache = {}
438-
result._reset_identity()
439456

440-
return result
457+
return result._reset_identity()
441458

442459
@cache_readonly
443460
def _constructor(self):
@@ -541,16 +558,15 @@ def is_(self, other) -> bool:
541558
--------
542559
Index.identical : Works like ``Index.is_`` but also checks metadata.
543560
"""
544-
try:
545-
return self._id is other._id
546-
except AttributeError:
547-
return False
561+
# use something other than None to be clearer
562+
return self._id is getattr(other, "_id", Ellipsis) and self._id is not None
548563

549-
def _reset_identity(self) -> None:
564+
def _reset_identity(self):
550565
"""
551566
Initializes or resets ``_id`` attribute with new object.
552567
"""
553-
self._id = _Identity(object())
568+
self._id = _Identity()
569+
return self
554570

555571
def _cleanup(self):
556572
self._engine.clear_mapping()
@@ -4207,7 +4223,7 @@ def _concat(self, to_concat, name):
42074223
"""
42084224
to_concat = [x._values if isinstance(x, Index) else x for x in to_concat]
42094225

4210-
result = concat_compat(to_concat)
4226+
result = _concat.concat_compat(to_concat)
42114227
return Index(result, name=name)
42124228

42134229
def putmask(self, mask, value):
@@ -5363,12 +5379,22 @@ def _cmp_method(self, other, op):
53635379
"""
53645380
Wrapper used to dispatch comparison operations.
53655381
"""
5366-
if self.is_(other):
5382+
from .multi import MultiIndex
5383+
5384+
if self.is_(other) and not isinstance(self, MultiIndex):
53675385
# short-circuit when other is same as self
5368-
if op in (operator.eq, operator.le, operator.ge):
5369-
return np.ones(self.shape, dtype=bool)
5370-
elif op in (operator.ne, operator.lt, operator.gt):
5371-
return np.zeros(self.shape, dtype=bool)
5386+
bool_arr_type, na_bool = {
5387+
operator.eq: (np.ones, False),
5388+
operator.le: (np.ones, False),
5389+
operator.ge: (np.ones, False),
5390+
operator.ne: (np.zeros, True),
5391+
operator.lt: (np.zeros, True),
5392+
operator.gt: (np.zeros, True),
5393+
}[op]
5394+
bool_arr = bool_arr_type(self.shape, dtype=bool)
5395+
if self._can_hold_na:
5396+
bool_arr[isna(self)] = na_bool
5397+
return bool_arr
53725398

53735399
if isinstance(other, (np.ndarray, Index, ABCSeries, ExtensionArray)):
53745400
if len(self) != len(other):

0 commit comments

Comments
 (0)