diff --git a/python/cudf/cudf/core/frame.py b/python/cudf/cudf/core/frame.py index 0fd7848c7d1..3d36d3bd893 100644 --- a/python/cudf/cudf/core/frame.py +++ b/python/cudf/cudf/core/frame.py @@ -46,6 +46,7 @@ ) from cudf.core.column_accessor import ColumnAccessor from cudf.core.join import Merge, MergeSemi +from cudf.core.mixins import BinaryOperand from cudf.core.window import Rolling from cudf.utils import ioutils from cudf.utils.docutils import copy_docstring @@ -97,7 +98,7 @@ } -class Frame: +class Frame(BinaryOperand): """A collection of Column objects with an optional index. Parameters @@ -114,6 +115,8 @@ class Frame: _index: Optional[cudf.core.index.BaseIndex] _names: Optional[List] + _VALID_BINARY_OPERATIONS = BinaryOperand._SUPPORTED_BINARY_OPERATIONS + def __init__(self, data=None, index=None): if data is None: data = {} @@ -3555,13 +3558,7 @@ def _unaryop(self, op): ) def _binaryop( - self, - other: T, - fn: str, - fill_value: Any = None, - reflect: bool = False, - *args, - **kwargs, + self, other: T, op: str, fill_value: Any = None, *args, **kwargs, ) -> Frame: """Perform a binary operation between two frames. @@ -3569,15 +3566,11 @@ def _binaryop( ---------- other : Frame The second operand. - fn : str + op : str The operation to perform. fill_value : Any, default None The value to replace null values with. If ``None``, nulls are not filled before the operation. - reflect : bool, default False - If ``True``, swap the order of the operands. See - https://docs.python.org/3/reference/datamodel.html#object.__ror__ - for more information on when this is necessary. Returns ------- @@ -3617,6 +3610,7 @@ def _colwise_binop( A dict of columns constructed from the result of performing the requested operation on the operands. """ + fn = fn[2:-2] # Now actually perform the binop on the columns in left and right. output = {} @@ -3899,83 +3893,12 @@ def dot(self, other, reflect=False): return cudf.DataFrame(result) return result.item() - # Binary arithmetic operations. - def __add__(self, other): - return self._binaryop(other, "add") - - def __radd__(self, other): - return self._binaryop(other, "add", reflect=True) - - def __sub__(self, other): - return self._binaryop(other, "sub") - - def __rsub__(self, other): - return self._binaryop(other, "sub", reflect=True) - def __matmul__(self, other): return self.dot(other) def __rmatmul__(self, other): return self.dot(other, reflect=True) - def __mul__(self, other): - return self._binaryop(other, "mul") - - def __rmul__(self, other): - return self._binaryop(other, "mul", reflect=True) - - def __mod__(self, other): - return self._binaryop(other, "mod") - - def __rmod__(self, other): - return self._binaryop(other, "mod", reflect=True) - - def __pow__(self, other): - return self._binaryop(other, "pow") - - def __rpow__(self, other): - return self._binaryop(other, "pow", reflect=True) - - def __floordiv__(self, other): - return self._binaryop(other, "floordiv") - - def __rfloordiv__(self, other): - return self._binaryop(other, "floordiv", reflect=True) - - def __truediv__(self, other): - return self._binaryop(other, "truediv") - - def __rtruediv__(self, other): - return self._binaryop(other, "truediv", reflect=True) - - def __and__(self, other): - return self._binaryop(other, "and") - - def __or__(self, other): - return self._binaryop(other, "or") - - def __xor__(self, other): - return self._binaryop(other, "xor") - - # Binary rich comparison operations. - def __eq__(self, other): - return self._binaryop(other, "eq") - - def __ne__(self, other): - return self._binaryop(other, "ne") - - def __lt__(self, other): - return self._binaryop(other, "lt") - - def __le__(self, other): - return self._binaryop(other, "le") - - def __gt__(self, other): - return self._binaryop(other, "gt") - - def __ge__(self, other): - return self._binaryop(other, "ge") - # Unary logical operators def __neg__(self): return -1 * self @@ -5185,7 +5108,7 @@ def add(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "add", fill_value) + return self._binaryop(other, "__add__", fill_value) @annotate("FRAME_RADD", color="green", domain="cudf_python") def radd(self, other, axis, level=None, fill_value=None): @@ -5265,7 +5188,7 @@ def radd(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "add", fill_value, reflect=True) + return self._binaryop(other, "__radd__", fill_value) @annotate("FRAME_SUBTRACT", color="green", domain="cudf_python") def subtract(self, other, axis, level=None, fill_value=None): @@ -5346,7 +5269,7 @@ def subtract(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "sub", fill_value) + return self._binaryop(other, "__sub__", fill_value) sub = subtract @@ -5432,7 +5355,7 @@ def rsub(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "sub", fill_value, reflect=True) + return self._binaryop(other, "__rsub__", fill_value) @annotate("FRAME_MULTIPLY", color="green", domain="cudf_python") def multiply(self, other, axis, level=None, fill_value=None): @@ -5515,7 +5438,7 @@ def multiply(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "mul", fill_value) + return self._binaryop(other, "__mul__", fill_value) mul = multiply @@ -5602,7 +5525,7 @@ def rmul(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "mul", fill_value, reflect=True) + return self._binaryop(other, "__rmul__", fill_value) @annotate("FRAME_MOD", color="green", domain="cudf_python") def mod(self, other, axis, level=None, fill_value=None): @@ -5673,7 +5596,7 @@ def mod(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "mod", fill_value) + return self._binaryop(other, "__mod__", fill_value) @annotate("FRAME_RMOD", color="green", domain="cudf_python") def rmod(self, other, axis, level=None, fill_value=None): @@ -5756,7 +5679,7 @@ def rmod(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "mod", fill_value, reflect=True) + return self._binaryop(other, "__rmod__", fill_value) @annotate("FRAME_POW", color="green", domain="cudf_python") def pow(self, other, axis, level=None, fill_value=None): @@ -5836,7 +5759,7 @@ def pow(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "pow", fill_value) + return self._binaryop(other, "__pow__", fill_value) @annotate("FRAME_RPOW", color="green", domain="cudf_python") def rpow(self, other, axis, level=None, fill_value=None): @@ -5916,7 +5839,7 @@ def rpow(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "pow", fill_value, reflect=True) + return self._binaryop(other, "__rpow__", fill_value) @annotate("FRAME_FLOORDIV", color="green", domain="cudf_python") def floordiv(self, other, axis, level=None, fill_value=None): @@ -5996,7 +5919,7 @@ def floordiv(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "floordiv", fill_value) + return self._binaryop(other, "__floordiv__", fill_value) @annotate("FRAME_RFLOORDIV", color="green", domain="cudf_python") def rfloordiv(self, other, axis, level=None, fill_value=None): @@ -6093,7 +6016,7 @@ def rfloordiv(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "floordiv", fill_value, reflect=True) + return self._binaryop(other, "__rfloordiv__", fill_value) @annotate("FRAME_TRUEDIV", color="green", domain="cudf_python") def truediv(self, other, axis, level=None, fill_value=None): @@ -6178,7 +6101,7 @@ def truediv(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "truediv", fill_value) + return self._binaryop(other, "__truediv__", fill_value) # Alias for truediv div = truediv @@ -6272,7 +6195,7 @@ def rtruediv(self, other, axis, level=None, fill_value=None): if level is not None: raise NotImplementedError("level parameter is not supported yet.") - return self._binaryop(other, "truediv", fill_value, reflect=True) + return self._binaryop(other, "__rtruediv__", fill_value) # Alias for rtruediv rdiv = rtruediv @@ -6350,7 +6273,7 @@ def eq(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ return self._binaryop( - other=other, fn="eq", fill_value=fill_value, can_reindex=True + other=other, op="__eq__", fill_value=fill_value, can_reindex=True ) @annotate("FRAME_NE", color="green", domain="cudf_python") @@ -6426,7 +6349,7 @@ def ne(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ # noqa: E501 return self._binaryop( - other=other, fn="ne", fill_value=fill_value, can_reindex=True + other=other, op="__ne__", fill_value=fill_value, can_reindex=True ) @annotate("FRAME_LT", color="green", domain="cudf_python") @@ -6502,7 +6425,7 @@ def lt(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ # noqa: E501 return self._binaryop( - other=other, fn="lt", fill_value=fill_value, can_reindex=True + other=other, op="__lt__", fill_value=fill_value, can_reindex=True ) @annotate("FRAME_LE", color="green", domain="cudf_python") @@ -6578,7 +6501,7 @@ def le(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ # noqa: E501 return self._binaryop( - other=other, fn="le", fill_value=fill_value, can_reindex=True + other=other, op="__le__", fill_value=fill_value, can_reindex=True ) @annotate("FRAME_GT", color="green", domain="cudf_python") @@ -6654,7 +6577,7 @@ def gt(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ # noqa: E501 return self._binaryop( - other=other, fn="gt", fill_value=fill_value, can_reindex=True + other=other, op="__gt__", fill_value=fill_value, can_reindex=True ) @annotate("FRAME_GE", color="green", domain="cudf_python") @@ -6730,7 +6653,7 @@ def ge(self, other, axis="columns", level=None, fill_value=None): dtype: bool """ # noqa: E501 return self._binaryop( - other=other, fn="ge", fill_value=fill_value, can_reindex=True + other=other, op="__ge__", fill_value=fill_value, can_reindex=True ) def nunique(self, method: builtins.str = "sort", dropna: bool = True): diff --git a/python/cudf/cudf/core/index.py b/python/cudf/cudf/core/index.py index 5aab834d452..343ba33ece1 100644 --- a/python/cudf/cudf/core/index.py +++ b/python/cudf/cudf/core/index.py @@ -52,6 +52,7 @@ from cudf.core.column.string import StringMethods as StringMethods from cudf.core.dtypes import IntervalDtype from cudf.core.frame import Frame +from cudf.core.mixins import BinaryOperand from cudf.core.single_column_frame import SingleColumnFrame from cudf.utils.docutils import copy_docstring from cudf.utils.dtypes import find_common_type @@ -122,7 +123,7 @@ def _index_from_columns( return _index_from_data(dict(zip(range(len(columns)), columns)), name=name) -class RangeIndex(BaseIndex): +class RangeIndex(BaseIndex, BinaryOperand): """ Immutable Index implementing a monotonic integer range. @@ -155,6 +156,8 @@ class RangeIndex(BaseIndex): RangeIndex(start=1, stop=10, step=1, name='a') """ + _VALID_BINARY_OPERATIONS = BinaryOperand._SUPPORTED_BINARY_OPERATIONS + _range: range def __init__( @@ -698,43 +701,16 @@ def _apply_boolean_mask(self, boolean_mask): [self._values.apply_boolean_mask(boolean_mask)], [self.name] ) + def _binaryop(self, other, op: str): + return self._as_int64()._binaryop(other, op=op) + # Patch in all binops and unary ops, which bypass __getattr__ on the instance # and prevent the above overload from working. -for binop in ( - "__add__", - "__radd__", - "__sub__", - "__rsub__", - "__mod__", - "__rmod__", - "__pow__", - "__rpow__", - "__floordiv__", - "__rfloordiv__", - "__truediv__", - "__rtruediv__", - "__and__", - "__or__", - "__xor__", - "__eq__", - "__ne__", - "__lt__", - "__le__", - "__gt__", - "__ge__", -): - setattr( - RangeIndex, - binop, - lambda self, other, op=binop: getattr(self._as_int64(), op)(other), - ) - - for unaop in ("__neg__", "__pos__", "__abs__"): setattr( RangeIndex, - binop, + unaop, lambda self, op=unaop: getattr(self._as_int64(), op)(), ) @@ -814,19 +790,15 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): return NotImplemented def _binaryop( - self, - other: T, - fn: str, - fill_value: Any = None, - reflect: bool = False, - *args, - **kwargs, + self, other: T, op: str, fill_value: Any = None, *args, **kwargs, ) -> SingleColumnFrame: - # Specialize binops to generate the appropriate output index type. + reflect = self._is_reflected_op(op) + if reflect: + op = op[:2] + op[3:] operands = self._make_operands_for_binop(other, fill_value, reflect) if operands is NotImplemented: return NotImplemented - ret = _index_from_data(self._colwise_binop(operands, fn)) + ret = _index_from_data(self._colwise_binop(operands, op)) # pandas returns numpy arrays when the outputs are boolean. We # explicitly _do not_ use isinstance here: we want only boolean diff --git a/python/cudf/cudf/core/indexed_frame.py b/python/cudf/cudf/core/indexed_frame.py index 3ae0a838873..331457d17ae 100644 --- a/python/cudf/cudf/core/indexed_frame.py +++ b/python/cudf/cudf/core/indexed_frame.py @@ -1697,21 +1697,23 @@ def last(self, offset): def _binaryop( self, other: Any, - fn: str, + op: str, fill_value: Any = None, - reflect: bool = False, can_reindex: bool = False, *args, **kwargs, ): + reflect = self._is_reflected_op(op) + if reflect: + op = op[:2] + op[3:] operands, out_index = self._make_operands_and_index_for_binop( - other, fn, fill_value, reflect, can_reindex + other, op, fill_value, reflect, can_reindex ) if operands is NotImplemented: return NotImplemented return self._from_data( - ColumnAccessor(type(self)._colwise_binop(operands, fn)), + ColumnAccessor(type(self)._colwise_binop(operands, op)), index=out_index, ) diff --git a/python/cudf/cudf/core/mixins/__init__.py b/python/cudf/cudf/core/mixins/__init__.py index cecf4c1c7ed..dd3dcd6d388 100644 --- a/python/cudf/cudf/core/mixins/__init__.py +++ b/python/cudf/cudf/core/mixins/__init__.py @@ -1,5 +1,6 @@ # Copyright (c) 2022, NVIDIA CORPORATION. from .reductions import Reducible +from .binops import BinaryOperand -__all__ = ["Reducible"] +__all__ = ["Reducible", "BinaryOperand"] diff --git a/python/cudf/cudf/core/mixins/binops.py b/python/cudf/cudf/core/mixins/binops.py new file mode 100644 index 00000000000..773b47b62b2 --- /dev/null +++ b/python/cudf/cudf/core/mixins/binops.py @@ -0,0 +1,56 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. + +from .mixin_factory import _create_delegating_mixin + +BinaryOperand = _create_delegating_mixin( + "BinaryOperand", + "Mixin encapsulating binary operations.", + "BINARY_OPERATION", + "_binaryop", + { + # Numeric operations. + "__add__", + "__sub__", + "__mul__", + "__matmul__", + "__truediv__", + "__floordiv__", + "__mod__", + # "__divmod__", # Not yet implemented + "__pow__", + # "__lshift__", # Not yet implemented + # "__rshift__", # Not yet implemented + "__and__", + "__xor__", + "__or__", + # Reflected numeric operations. + "__radd__", + "__rsub__", + "__rmul__", + "__rmatmul__", + "__rtruediv__", + "__rfloordiv__", + "__rmod__", + # "__rdivmod__", # Not yet implemented + "__rpow__", + # "__rlshift__", # Not yet implemented + # "__rrshift__", # Not yet implemented + "__rand__", + "__rxor__", + "__ror__", + # Rich comparison operations. + "__lt__", + "__le__", + "__eq__", + "__ne__", + "__gt__", + "__ge__", + }, +) + + +def _is_reflected_op(op): + return op[2] == "r" and op != "__rshift__" + + +BinaryOperand._is_reflected_op = staticmethod(_is_reflected_op) diff --git a/python/cudf/cudf/core/mixins/binops.pyi b/python/cudf/cudf/core/mixins/binops.pyi new file mode 100644 index 00000000000..45093cd04d4 --- /dev/null +++ b/python/cudf/cudf/core/mixins/binops.pyi @@ -0,0 +1,88 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. + +from typing import Set + +class BinaryOperand: + _SUPPORTED_BINARY_OPERATIONS: Set + + def __add__(self, other): + ... + + def __sub__(self, other): + ... + + def __mul__(self, other): + ... + + def __truediv__(self, other): + ... + + def __floordiv__(self, other): + ... + + def __mod__(self, other): + ... + + def __pow__(self, other): + ... + + def __and__(self, other): + ... + + def __xor__(self, other): + ... + + def __or__(self, other): + ... + + def __radd__(self, other): + ... + + def __rsub__(self, other): + ... + + def __rmul__(self, other): + ... + + def __rtruediv__(self, other): + ... + + def __rfloordiv__(self, other): + ... + + def __rmod__(self, other): + ... + + def __rpow__(self, other): + ... + + def __rand__(self, other): + ... + + def __rxor__(self, other): + ... + + def __ror__(self, other): + ... + + def __lt__(self, other): + ... + + def __le__(self, other): + ... + + def __eq__(self, other): + ... + + def __ne__(self, other): + ... + + def __gt__(self, other): + ... + + def __ge__(self, other): + ... + + @staticmethod + def _is_reflected_op(op) -> bool: + ... diff --git a/python/cudf/cudf/core/mixins/mixin_factory.py b/python/cudf/cudf/core/mixins/mixin_factory.py index ecb18f61830..7bbb299d643 100644 --- a/python/cudf/cudf/core/mixins/mixin_factory.py +++ b/python/cudf/cudf/core/mixins/mixin_factory.py @@ -86,14 +86,18 @@ def _should_define_operation(cls, operation, base_operation_name): # At this point we know that the class has the operation defined but it # also overrides the base operation. Since this function is called before # the operation is defined on the current class, we know that it inherited - # the operation from a parent. We therefore have two possibilities: + # the operation from a parent. We therefore have three possibilities: # 1. A parent class manually defined the operation. That override takes # precedence even if the current class defined the base operation. # 2. A parent class has an auto-generated operation, i.e. it is of type # Operation and was created by OperationMixin.__init_subclass__. The # current class must override it so that its base operation is used # rather than the parent's base operation. + # 3. The method is defined for all classes, i.e. it is a method of object. for base_cls in cls.__mro__: + # We always override methods defined for object. + if base_cls is object: + return True # The first attribute in the MRO is the one that will be used. if operation in base_cls.__dict__: return isinstance(base_cls.__dict__[operation], Operation) @@ -216,6 +220,7 @@ def __init_subclass__(cls): # Only add the valid set of operations for a particular class. valid_operations = set() for base_cls in cls.__mro__: + # Check for sentinel indicating that all operations are valid. valid_operations |= getattr(base_cls, validity_attr, set()) invalid_operations = valid_operations - supported_operations @@ -251,9 +256,8 @@ def _operation(self, op: str, *args, **kwargs): ) setattr(OperationMixin, base_operation_name, _operation) - # This attribute is set in case lookup is convenient at a later point, but - # it is not strictly necessary since `supported_operations` is part of the - # closure associated with the class's creation. + # Making this attribute available makes it easy for subclasses to indicate + # that all supported operations for this mixin are valid. setattr(OperationMixin, supported_attr, supported_operations) return OperationMixin diff --git a/python/cudf/cudf/core/mixins/reductions.pyi b/python/cudf/cudf/core/mixins/reductions.pyi index 600f30e9372..3769b7c360e 100644 --- a/python/cudf/cudf/core/mixins/reductions.pyi +++ b/python/cudf/cudf/core/mixins/reductions.pyi @@ -1,8 +1,10 @@ # Copyright (c) 2022, NVIDIA CORPORATION. -from __future__ import annotations +from typing import Set class Reducible: + _SUPPORTED_REDUCTIONS: Set + def sum(self): ... diff --git a/python/cudf/cudf/core/scalar.py b/python/cudf/cudf/core/scalar.py index 134b94bf0f2..1c81803ed98 100644 --- a/python/cudf/cudf/core/scalar.py +++ b/python/cudf/cudf/core/scalar.py @@ -10,6 +10,7 @@ from cudf.core.column.column import ColumnBase from cudf.core.dtypes import ListDtype, StructDtype from cudf.core.index import BaseIndex +from cudf.core.mixins import BinaryOperand from cudf.core.series import Series from cudf.utils.dtypes import ( get_allowed_combinations_for_operator, @@ -17,7 +18,7 @@ ) -class Scalar: +class Scalar(BinaryOperand): """ A GPU-backed scalar object with NumPy scalar like properties May be used in binary operations against other scalars, cuDF @@ -57,6 +58,8 @@ class Scalar: The data type """ + _VALID_BINARY_OPERATIONS = BinaryOperand._SUPPORTED_BINARY_OPERATIONS + def __init__(self, value, dtype=None): self._host_value = None @@ -211,69 +214,8 @@ def __float__(self): def __bool__(self): return bool(self.value) - # Scalar Binary Operations - def __add__(self, other): - return self._scalar_binop(other, "__add__") - - def __radd__(self, other): - return self._scalar_binop(other, "__radd__") - - def __sub__(self, other): - return self._scalar_binop(other, "__sub__") - - def __rsub__(self, other): - return self._scalar_binop(other, "__rsub__") - - def __mul__(self, other): - return self._scalar_binop(other, "__mul__") - - def __rmul__(self, other): - return self._scalar_binop(other, "__rmul__") - - def __truediv__(self, other): - return self._scalar_binop(other, "__truediv__") - - def __floordiv__(self, other): - return self._scalar_binop(other, "__floordiv__") - - def __rtruediv__(self, other): - return self._scalar_binop(other, "__rtruediv__") - - def __mod__(self, other): - return self._scalar_binop(other, "__mod__") - - def __divmod__(self, other): - return self._scalar_binop(other, "__divmod__") - - def __and__(self, other): - return self._scalar_binop(other, "__and__") - - def __xor__(self, other): - return self._scalar_binop(other, "__or__") - - def __pow__(self, other): - return self._scalar_binop(other, "__pow__") - - def __gt__(self, other): - return self._scalar_binop(other, "__gt__") - - def __lt__(self, other): - return self._scalar_binop(other, "__lt__") - - def __ge__(self, other): - return self._scalar_binop(other, "__ge__") - - def __le__(self, other): - return self._scalar_binop(other, "__le__") - - def __eq__(self, other): - return self._scalar_binop(other, "__eq__") - - def __ne__(self, other): - return self._scalar_binop(other, "__ne__") - def __round__(self, n): - return self._scalar_binop(n, "__round__") + return self._binaryop(n, "__round__") # Scalar Unary Operations def __abs__(self): @@ -330,7 +272,7 @@ def _binop_result_dtype_or_error(self, other, op): return cudf.dtype(out_dtype) - def _scalar_binop(self, other, op): + def _binaryop(self, other, op: str): if isinstance(other, (ColumnBase, Series, BaseIndex, np.ndarray)): # dispatch to column implementation return NotImplemented diff --git a/python/cudf/cudf/core/series.py b/python/cudf/cudf/core/series.py index ec87fcdb066..fffce27c89a 100644 --- a/python/cudf/cudf/core/series.py +++ b/python/cudf/cudf/core/series.py @@ -1245,21 +1245,21 @@ def logical_and(self, other): "Series.logical_and is deprecated and will be removed.", FutureWarning, ) - return self._binaryop(other, "l_and").astype(np.bool_) + return self._binaryop(other, "__l_and__").astype(np.bool_) def remainder(self, other): warnings.warn( "Series.remainder is deprecated and will be removed.", FutureWarning, ) - return self._binaryop(other, "mod") + return self._binaryop(other, "__mod__") def logical_or(self, other): warnings.warn( "Series.logical_or is deprecated and will be removed.", FutureWarning, ) - return self._binaryop(other, "l_or").astype(np.bool_) + return self._binaryop(other, "__l_or__").astype(np.bool_) def logical_not(self): warnings.warn( diff --git a/python/cudf/cudf/utils/utils.py b/python/cudf/cudf/utils/utils.py index 4dadfede866..315da4d8dd6 100644 --- a/python/cudf/cudf/utils/utils.py +++ b/python/cudf/cudf/utils/utils.py @@ -24,12 +24,6 @@ _EQUALITY_OPS = { - "eq", - "ne", - "lt", - "gt", - "le", - "ge", "__eq__", "__ne__", "__lt__",