Skip to content
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

REF/DEPR: Deprecate AbstractMethodError #54408

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions pandas/core/arrays/_mixins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from __future__ import annotations

from abc import (
ABC,
abstractmethod,
)
from functools import wraps
from typing import (
TYPE_CHECKING,
Expand Down Expand Up @@ -28,7 +32,6 @@
TakeIndexer,
npt,
)
from pandas.errors import AbstractMethodError
from pandas.util._decorators import doc
from pandas.util._validators import (
validate_bool_kwarg,
Expand Down Expand Up @@ -88,7 +91,7 @@ def method(self, *args, **kwargs):
return cast(F, method)


class NDArrayBackedExtensionArray(NDArrayBacked, ExtensionArray):
class NDArrayBackedExtensionArray(NDArrayBacked, ExtensionArray, ABC):
"""
ExtensionArray that is backed by a single NumPy ndarray.
"""
Expand All @@ -107,9 +110,10 @@ def _box_func(self, x):
"""
return x

@abstractmethod
def _validate_scalar(self, value):
# used by NDArrayBackedExtensionIndex.insert
raise AbstractMethodError(self)
...

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

Expand Down
52 changes: 30 additions & 22 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
"""
from __future__ import annotations

from abc import (
ABC,
abstractmethod,
)
import operator
from typing import (
TYPE_CHECKING,
Expand All @@ -28,7 +32,6 @@
)
from pandas.compat import set_function_name
from pandas.compat.numpy import function as nv
from pandas.errors import AbstractMethodError
from pandas.util._decorators import (
Appender,
Substitution,
Expand Down Expand Up @@ -208,8 +211,8 @@ class ExtensionArray:

This class does not inherit from 'abc.ABCMeta' for performance reasons.
Methods and properties required by the interface raise
``pandas.errors.AbstractMethodError`` and no ``register`` method is
provided for registering virtual subclasses.
``NotImplementedError`` and no ``register`` method is provided for
registering virtual subclasses.

ExtensionArrays are limited to 1 dimension.

Expand Down Expand Up @@ -289,7 +292,7 @@ def _from_sequence(cls, scalars, *, dtype: Dtype | None = None, copy: bool = Fal
[4, 5]
Length: 2, dtype: Int64
"""
raise AbstractMethodError(cls)
raise NotImplementedError

@classmethod
def _from_sequence_of_strings(
Expand Down Expand Up @@ -320,7 +323,7 @@ def _from_sequence_of_strings(
[1, 2, 3]
Length: 3, dtype: Int64
"""
raise AbstractMethodError(cls)
raise NotImplementedError

@classmethod
def _from_factorized(cls, values, original):
Expand Down Expand Up @@ -349,7 +352,7 @@ def _from_factorized(cls, values, original):
[(0, 1], (1, 5]]
Length: 2, dtype: interval[int64, right]
"""
raise AbstractMethodError(cls)
raise NotImplementedError

# ------------------------------------------------------------------------
# Must be a Sequence
Expand Down Expand Up @@ -393,7 +396,7 @@ def __getitem__(self, item: PositionalIndexer) -> Self | Any:
For a boolean mask, return an instance of ``ExtensionArray``, filtered
to the values where ``item`` is True.
"""
raise AbstractMethodError(self)
raise NotImplementedError

def __setitem__(self, key, value) -> None:
"""
Expand Down Expand Up @@ -448,7 +451,7 @@ def __len__(self) -> int:
-------
length : int
"""
raise AbstractMethodError(self)
raise NotImplementedError

def __iter__(self) -> Iterator[Any]:
"""
Expand Down Expand Up @@ -490,7 +493,7 @@ def __eq__(self, other: object) -> ArrayLike: # type: ignore[override]
# return NotImplemented (to ensure that those objects are responsible for
# first unpacking the arrays, and then dispatch the operation to the
# underlying arrays)
raise AbstractMethodError(self)
raise NotImplementedError

# error: Signature of "__ne__" incompatible with supertype "object"
def __ne__(self, other: object) -> ArrayLike: # type: ignore[override]
Expand Down Expand Up @@ -550,7 +553,7 @@ def dtype(self) -> ExtensionDtype:
>>> pd.array([1, 2, 3]).dtype
Int64Dtype()
"""
raise AbstractMethodError(self)
raise NotImplementedError

@property
def shape(self) -> Shape:
Expand Down Expand Up @@ -599,7 +602,7 @@ def nbytes(self) -> int:
"""
# If this is expensive to compute, return an approximate lower bound
# on the number of bytes needed.
raise AbstractMethodError(self)
raise NotImplementedError

# ------------------------------------------------------------------------
# Additional Methods
Expand Down Expand Up @@ -711,7 +714,7 @@ def isna(self) -> np.ndarray | ExtensionArraySupportsAnyAll:
>>> arr.isna()
array([False, False, True, True])
"""
raise AbstractMethodError(self)
raise NotImplementedError

@property
def _hasna(self) -> bool:
Expand Down Expand Up @@ -1562,7 +1565,7 @@ def take(self, indices, allow_fill=False, fill_value=None):
# uses. In this case, your implementation is responsible for casting
# the user-facing type to the storage type, before using
# pandas.api.extensions.take
raise AbstractMethodError(self)
raise NotImplementedError

def copy(self) -> Self:
"""
Expand All @@ -1582,7 +1585,7 @@ def copy(self) -> Self:
[1, 2, 3]
Length: 3, dtype: Int64
"""
raise AbstractMethodError(self)
raise NotImplementedError

def view(self, dtype: Dtype | None = None) -> ArrayLike:
"""
Expand Down Expand Up @@ -1763,7 +1766,7 @@ def _concat_same_type(cls, to_concat: Sequence[Self]) -> Self:
# should allow "easy" concatenation (no upcasting needed), and result
# in a new ExtensionArray of the same dtype.
# Note: this strict behaviour is only guaranteed starting with pandas 1.1
raise AbstractMethodError(cls)
raise NotImplementedError

# The _can_hold_na attribute is set to True so that pandas internals
# will use the ExtensionDtype.na_value as the NA value in operations
Expand Down Expand Up @@ -2303,15 +2306,17 @@ def _groupby_op(
raise NotImplementedError


class ExtensionArraySupportsAnyAll(ExtensionArray):
class ExtensionArraySupportsAnyAll(ExtensionArray, ABC):
@abstractmethod
def any(self, *, skipna: bool = True) -> bool:
raise AbstractMethodError(self)
...

@abstractmethod
def all(self, *, skipna: bool = True) -> bool:
raise AbstractMethodError(self)
...


class ExtensionOpsMixin:
class ExtensionOpsMixin(ABC):
"""
A base class for linking the operators to their dunder names.

Expand All @@ -2323,8 +2328,9 @@ class ExtensionOpsMixin:
"""

@classmethod
@abstractmethod
def _create_arithmetic_method(cls, op):
raise AbstractMethodError(cls)
...

@classmethod
def _add_arithmetic_ops(cls) -> None:
Expand All @@ -2348,8 +2354,9 @@ def _add_arithmetic_ops(cls) -> None:
setattr(cls, "__rdivmod__", cls._create_arithmetic_method(roperator.rdivmod))

@classmethod
@abstractmethod
def _create_comparison_method(cls, op):
raise AbstractMethodError(cls)
...

@classmethod
def _add_comparison_ops(cls) -> None:
Expand All @@ -2361,8 +2368,9 @@ def _add_comparison_ops(cls) -> None:
setattr(cls, "__ge__", cls._create_comparison_method(operator.ge))

@classmethod
@abstractmethod
def _create_logical_method(cls, op):
raise AbstractMethodError(cls)
...

@classmethod
def _add_logical_ops(cls) -> None:
Expand Down
26 changes: 15 additions & 11 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from abc import abstractmethod
from datetime import (
datetime,
timedelta,
Expand Down Expand Up @@ -69,7 +70,6 @@
)
from pandas.compat.numpy import function as nv
from pandas.errors import (
AbstractMethodError,
InvalidComparison,
PerformanceWarning,
)
Expand Down Expand Up @@ -214,12 +214,14 @@ class DatetimeLikeArrayMixin( # type: ignore[misc]
def _can_hold_na(self) -> bool:
return True

@abstractmethod
def __init__(
self, data, dtype: Dtype | None = None, freq=None, copy: bool = False
) -> None:
raise AbstractMethodError(self)
...

@property
@abstractmethod
def _scalar_type(self) -> type[DatetimeLikeScalar]:
"""
The scalar associated with this datelike
Expand All @@ -228,8 +230,8 @@ def _scalar_type(self) -> type[DatetimeLikeScalar]:
* DatetimeArray : Timestamp
* TimedeltaArray : Timedelta
"""
raise AbstractMethodError(self)

@abstractmethod
def _scalar_from_string(self, value: str) -> DTScalarOrNaT:
"""
Construct a scalar type from a string.
Expand All @@ -248,8 +250,8 @@ def _scalar_from_string(self, value: str) -> DTScalarOrNaT:
This should call ``self._check_compatible_with`` before
unboxing the result.
"""
raise AbstractMethodError(self)

@abstractmethod
def _unbox_scalar(
self, value: DTScalarOrNaT
) -> np.int64 | np.datetime64 | np.timedelta64:
Expand All @@ -271,8 +273,8 @@ def _unbox_scalar(
>>> arr._unbox_scalar(arr[0])
numpy.datetime64('1970-01-01T00:00:00.000000000')
"""
raise AbstractMethodError(self)

@abstractmethod
def _check_compatible_with(self, other: DTScalarOrNaT) -> None:
"""
Verify that `self` and `other` are compatible.
Expand All @@ -291,15 +293,14 @@ def _check_compatible_with(self, other: DTScalarOrNaT) -> None:
------
Exception
"""
raise AbstractMethodError(self)

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

@abstractmethod
def _box_func(self, x):
"""
box function to get object from internal representation
"""
raise AbstractMethodError(self)

def _box_values(self, values) -> np.ndarray:
"""
Expand Down Expand Up @@ -329,6 +330,7 @@ def asi8(self) -> npt.NDArray[np.int64]:
# ----------------------------------------------------------------
# Rendering Methods

@abstractmethod
def _format_native_types(
self, *, na_rep: str | float = "NaT", date_format=None
) -> npt.NDArray[np.object_]:
Expand All @@ -339,7 +341,6 @@ def _format_native_types(
-------
ndarray[str]
"""
raise AbstractMethodError(self)

def _formatter(self, boxed: bool = False):
# TODO: Remove Datetime & DatetimeTZ formatters.
Expand Down Expand Up @@ -1154,8 +1155,9 @@ def _add_period(self, other: Period) -> PeriodArray:
parr = PeriodArray(i8vals, dtype=dtype)
return parr + self

@abstractmethod
def _add_offset(self, offset):
raise AbstractMethodError(self)
...

def _add_timedeltalike_scalar(self, other):
"""
Expand Down Expand Up @@ -1989,8 +1991,9 @@ def __init__(
type(self)._validate_frequency(self, freq)

@classmethod
@abstractmethod
def _validate_dtype(cls, values, dtype):
raise AbstractMethodError(cls)
...

@property
def freq(self):
Expand Down Expand Up @@ -2056,8 +2059,9 @@ def _validate_frequency(cls, index, freq, **kwargs):
) from err

@classmethod
@abstractmethod
def _generate_range(cls, start, end, periods, freq, *args, **kwargs) -> Self:
raise AbstractMethodError(cls)
...

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

Expand Down
5 changes: 2 additions & 3 deletions pandas/core/arrays/masked.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
IS64,
is_platform_windows,
)
from pandas.errors import AbstractMethodError
from pandas.util._decorators import doc
from pandas.util._validators import validate_fillna_kwargs

Expand Down Expand Up @@ -168,7 +167,7 @@ def _formatter(self, boxed: bool = False) -> Callable[[Any], str | None]:

@property
def dtype(self) -> BaseMaskedDtype:
raise AbstractMethodError(self)
raise NotImplementedError

@overload
def __getitem__(self, item: ScalarIndexer) -> Any:
Expand Down Expand Up @@ -253,7 +252,7 @@ def fillna(
def _coerce_to_array(
cls, values, *, dtype: DtypeObj, copy: bool = False
) -> tuple[np.ndarray, np.ndarray]:
raise AbstractMethodError(cls)
raise NotImplementedError

def _validate_setitem_value(self, value):
"""
Expand Down
Loading