Skip to content

CLN: consistent signatures for equals methods #35636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 12, 2020
4 changes: 2 additions & 2 deletions pandas/_libs/sparse.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ cdef class IntIndex(SparseIndex):
if not monotonic:
raise ValueError("Indices must be strictly increasing")

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
if not isinstance(other, IntIndex):
return False

Expand Down Expand Up @@ -399,7 +399,7 @@ cdef class BlockIndex(SparseIndex):
if blengths[i] == 0:
raise ValueError(f'Zero-length block {i}')

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
if not isinstance(other, BlockIndex):
return False

Expand Down
14 changes: 10 additions & 4 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
without warning.
"""
import operator
from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union
from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union, cast

import numpy as np

Expand All @@ -20,7 +20,12 @@
from pandas.util._validators import validate_fillna_kwargs

from pandas.core.dtypes.cast import maybe_cast_to_extension_array
from pandas.core.dtypes.common import is_array_like, is_list_like, pandas_dtype
from pandas.core.dtypes.common import (
is_array_like,
is_dtype_equal,
is_list_like,
pandas_dtype,
)
from pandas.core.dtypes.dtypes import ExtensionDtype
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
from pandas.core.dtypes.missing import isna
Expand Down Expand Up @@ -742,7 +747,7 @@ def searchsorted(self, value, side="left", sorter=None):
arr = self.astype(object)
return arr.searchsorted(value, side=side, sorter=sorter)

def equals(self, other: "ExtensionArray") -> bool:
def equals(self, other: object) -> bool:
"""
Return if another array is equivalent to this array.

Expand All @@ -762,7 +767,8 @@ def equals(self, other: "ExtensionArray") -> bool:
"""
if not type(self) == type(other):
return False
elif not self.dtype == other.dtype:
other = cast(ExtensionArray, other)
if not is_dtype_equal(self.dtype, other.dtype):
return False
elif not len(self) == len(other):
return False
Expand Down
6 changes: 4 additions & 2 deletions pandas/core/arrays/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,7 @@ def _from_factorized(cls, uniques, original):
original.categories.take(uniques), dtype=original.dtype
)

def equals(self, other):
def equals(self, other: object) -> bool:
"""
Returns True if categorical arrays are equal.

Expand All @@ -2254,7 +2254,9 @@ def equals(self, other):
-------
bool
"""
if self.is_dtype_equal(other):
if not isinstance(other, Categorical):
return False
elif self.is_dtype_equal(other):
if self.categories.equals(other.categories):
# fastpath to avoid re-coding
other_codes = other._codes
Expand Down
4 changes: 3 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
Tuple,
Type,
Union,
cast,
)
import warnings
import weakref
Expand Down Expand Up @@ -1195,7 +1196,7 @@ def _indexed_same(self, other) -> bool:
self._get_axis(a).equals(other._get_axis(a)) for a in self._AXIS_ORDERS
)

def equals(self, other):
def equals(self, other: object) -> bool:
"""
Test whether two objects contain the same elements.

Expand Down Expand Up @@ -1275,6 +1276,7 @@ def equals(self, other):
"""
if not (isinstance(other, type(self)) or isinstance(self, type(other))):
return False
other = cast(NDFrame, other)
return self._mgr.equals(other._mgr)

# -------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4176,7 +4176,7 @@ def putmask(self, mask, value):
# coerces to object
return self.astype(object).putmask(mask, value)

def equals(self, other: Any) -> bool:
def equals(self, other: object) -> bool:
"""
Determine if two Index object are equal.

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def _is_dtype_compat(self, other) -> bool:

return other

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
"""
Determine if two CategoricalIndex objects contain the same elements.

Expand Down
6 changes: 3 additions & 3 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
is_scalar,
)
from pandas.core.dtypes.concat import concat_compat
from pandas.core.dtypes.generic import ABCIndex, ABCIndexClass, ABCSeries
from pandas.core.dtypes.generic import ABCIndex, ABCSeries

from pandas.core import algorithms
from pandas.core.arrays import DatetimeArray, PeriodArray, TimedeltaArray
Expand Down Expand Up @@ -130,14 +130,14 @@ def __array_wrap__(self, result, context=None):

# ------------------------------------------------------------------------

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
"""
Determines if two Index objects contain the same elements.
"""
if self.is_(other):
return True

if not isinstance(other, ABCIndexClass):
if not isinstance(other, Index):
return False
elif not isinstance(other, type(self)):
try:
Expand Down
7 changes: 4 additions & 3 deletions pandas/core/indexes/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,19 +1005,20 @@ def _format_space(self) -> str:
def argsort(self, *args, **kwargs) -> np.ndarray:
return np.lexsort((self.right, self.left))

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
"""
Determines if two IntervalIndex objects contain the same elements.
"""
if self.is_(other):
return True

# if we can coerce to an II
# then we can compare
# if we can coerce to an IntervalIndex then we can compare
Copy link
Member Author

@simonjayhawkins simonjayhawkins Aug 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from #33940

Index and Series are consistent when it comes to not being equal with other array-likes:

not necessarily in this PR, but is this behaviour consistent with other Index types

>>> x = np.linspace(0, 100, num=3)
>>> x
array([  0.,  50., 100.])
>>>
>>> idx = pd.IntervalIndex.from_breaks(x)
>>> idx
IntervalIndex([(0.0, 50.0], (50.0, 100.0]],
              closed='right',
              dtype='interval[float64]')
>>>
>>> arr = idx.values
>>> arr
<IntervalArray>
[(0.0, 50.0], (50.0, 100.0]]
Length: 2, closed: right, dtype: interval[float64]
>>>
>>> idx.equals(arr)
True
>>>
>>> arr.equals(idx)
False
>>>

if not isinstance(other, IntervalIndex):
if not is_interval_dtype(other):
return False
other = Index(other)
if not isinstance(other, IntervalIndex):
return False

return (
self.left.equals(other.left)
Expand Down
11 changes: 5 additions & 6 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3227,7 +3227,7 @@ def truncate(self, before=None, after=None):
verify_integrity=False,
)

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
"""
Determines if two MultiIndex objects have the same labeling information
(the levels themselves do not necessarily have to be the same)
Expand Down Expand Up @@ -3270,11 +3270,10 @@ def equals(self, other) -> bool:
np.asarray(other.levels[i]._values), other_codes, allow_fill=False
)

# since we use NaT both datetime64 and timedelta64
# we can have a situation where a level is typed say
# timedelta64 in self (IOW it has other values than NaT)
# but types datetime64 in other (where its all NaT)
# but these are equivalent
# since we use NaT both datetime64 and timedelta64 we can have a
# situation where a level is typed say timedelta64 in self (IOW it
# has other values than NaT) but types datetime64 in other (where
# its all NaT) but these are equivalent
if len(self_values) == 0 and len(other_values) == 0:
continue

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ def argsort(self, *args, **kwargs) -> np.ndarray:
else:
return np.arange(len(self) - 1, -1, -1)

def equals(self, other) -> bool:
def equals(self, other: object) -> bool:
"""
Determines if two Index objects contain the same elements.
"""
Expand Down
5 changes: 4 additions & 1 deletion pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,10 @@ def take(self, indexer, axis: int = 1, verify: bool = True, convert: bool = True
new_axis=new_labels, indexer=indexer, axis=axis, allow_dups=True
)

def equals(self, other: "BlockManager") -> bool:
def equals(self, other: object) -> bool:
if not isinstance(other, BlockManager):
return False

self_axes, other_axes = self.axes, other.axes
if len(self_axes) != len(other_axes):
return False
Expand Down