Skip to content

CLN: remove keep_null_freq in ops #30221

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 7 commits into from
Dec 12, 2019
Merged
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
3 changes: 2 additions & 1 deletion pandas/core/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ def wrapper(left, right):
res_name = get_op_result_name(left, right)

lvalues = extract_array(left, extract_numpy=True)
result = arithmetic_op(lvalues, right, op, str_rep)
rvalues = extract_array(right, extract_numpy=True)
result = arithmetic_op(lvalues, rvalues, op, str_rep)

return _construct_result(left, result, index=left.index, name=res_name)

Expand Down
23 changes: 4 additions & 19 deletions pandas/core/ops/array_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,14 @@
)
from pandas.core.dtypes.generic import (
ABCDatetimeArray,
ABCDatetimeIndex,
ABCExtensionArray,
ABCIndex,
ABCIndexClass,
ABCSeries,
ABCTimedeltaArray,
ABCTimedeltaIndex,
)
from pandas.core.dtypes.missing import isna, notna

from pandas.core.construction import extract_array
from pandas.core.ops import missing
from pandas.core.ops.dispatch import dispatch_to_extension_op, should_extension_dispatch
from pandas.core.ops.invalid import invalid_comparison
Expand Down Expand Up @@ -178,22 +175,10 @@ def arithmetic_op(

from pandas.core.ops import maybe_upcast_for_op

keep_null_freq = isinstance(
right,
(
ABCDatetimeIndex,
ABCDatetimeArray,
ABCTimedeltaIndex,
ABCTimedeltaArray,
Timestamp,
),
)

# NB: We assume that extract_array has already been called on `left`, but
# cannot make the same assumption about `right`. This is because we need
# to define `keep_null_freq` before calling extract_array on it.
# NB: We assume that extract_array has already been called
# on `left` and `right`.
lvalues = left
rvalues = extract_array(right, extract_numpy=True)
rvalues = right

rvalues = maybe_upcast_for_op(rvalues, lvalues.shape)

Expand All @@ -203,7 +188,7 @@ def arithmetic_op(
# TimedeltaArray, DatetimeArray, and Timestamp are included here
# because they have `freq` attribute which is handled correctly
# by dispatch_to_extension_op.
res_values = dispatch_to_extension_op(op, lvalues, rvalues, keep_null_freq)
res_values = dispatch_to_extension_op(op, lvalues, rvalues)

else:
with np.errstate(all="ignore"):
Expand Down
25 changes: 2 additions & 23 deletions pandas/core/ops/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import numpy as np

from pandas.errors import NullFrequencyError

from pandas.core.dtypes.common import (
is_datetime64_dtype,
is_extension_array_dtype,
Expand Down Expand Up @@ -97,10 +95,7 @@ def should_series_dispatch(left, right, op):


def dispatch_to_extension_op(
op,
left: Union[ABCExtensionArray, np.ndarray],
right: Any,
keep_null_freq: bool = False,
op, left: Union[ABCExtensionArray, np.ndarray], right: Any,
):
"""
Assume that left or right is a Series backed by an ExtensionArray,
Expand All @@ -111,9 +106,6 @@ def dispatch_to_extension_op(
op : binary operator
left : ExtensionArray or np.ndarray
right : object
keep_null_freq : bool, default False
Whether to re-raise a NullFrequencyError unchanged, as opposed to
catching and raising TypeError.

Returns
-------
Expand All @@ -131,20 +123,7 @@ def dispatch_to_extension_op(

# The op calls will raise TypeError if the op is not defined
# on the ExtensionArray

try:
res_values = op(left, right)
except NullFrequencyError:
# DatetimeIndex and TimedeltaIndex with freq == None raise ValueError
# on add/sub of integers (or int-like). We re-raise as a TypeError.
if keep_null_freq:
# TODO: remove keep_null_freq after Timestamp+int deprecation
# GH#22535 is enforced
raise
raise TypeError(
"incompatible type for a datetime/timedelta "
"operation [{name}]".format(name=op.__name__)
)
res_values = op(left, right)
return res_values


Expand Down
1 change: 1 addition & 0 deletions pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -1844,6 +1844,7 @@ def test_dt64_mul_div_numeric_invalid(self, one, dt64_series):
with pytest.raises(TypeError, match=msg):
one / dt64_series

# TODO: parametrize over box
@pytest.mark.parametrize("op", ["__add__", "__radd__", "__sub__", "__rsub__"])
@pytest.mark.parametrize("tz", [None, "Asia/Tokyo"])
def test_dt64_series_add_intlike(self, tz, op):
Expand Down
52 changes: 52 additions & 0 deletions pandas/tests/arithmetic/test_timedelta64.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,58 @@ def test_td64arr_add_sub_numeric_arr_invalid(self, box_with_array, vec, dtype):
with pytest.raises(TypeError):
vector - tdser

# TODO: parameterize over box and de-duplicate
def test_tdi_add_sub_int(self, one):
# Variants of `one` for #19012, deprecated GH#22535
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
msg = "Addition/subtraction of integers"

with pytest.raises(TypeError, match=msg):
rng + one
with pytest.raises(TypeError, match=msg):
rng += one
with pytest.raises(TypeError, match=msg):
rng - one
with pytest.raises(TypeError, match=msg):
rng -= one

# TODO: parameterize over box and de-duplicate
@pytest.mark.parametrize("box", [np.array, pd.Index])
def test_tdi_add_sub_integer_array(self, box):
# GH#19959, deprecated GH#22535
rng = timedelta_range("1 days 09:00:00", freq="H", periods=3)
other = box([4, 3, 2])
msg = "Addition/subtraction of integers and integer-arrays"

with pytest.raises(TypeError, match=msg):
rng + other

with pytest.raises(TypeError, match=msg):
other + rng

with pytest.raises(TypeError, match=msg):
rng - other

with pytest.raises(TypeError, match=msg):
other - rng

# TODO: parameterize over box and de-duplicate
@pytest.mark.parametrize("box", [np.array, pd.Index])
def test_tdi_addsub_integer_array_no_freq(self, box):
# GH#19959
tdi = TimedeltaIndex(["1 Day", "NaT", "3 Hours"])
other = box([14, -1, 16])
msg = "Addition/subtraction of integers"

with pytest.raises(TypeError, match=msg):
tdi + other
with pytest.raises(TypeError, match=msg):
other + tdi
with pytest.raises(TypeError, match=msg):
tdi - other
with pytest.raises(TypeError, match=msg):
other - tdi

# ------------------------------------------------------------------
# Operations with timedelta-like others

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import pandas.util.testing as tm


class TestDatetimeIndexArithmetic:
class TestDatetimeIndexShift:

# -------------------------------------------------------------
# DatetimeIndex.shift is used in integer addition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pandas.util.testing as tm


class TestPeriodIndexArithmetic:
class TestPeriodIndexShift:
# ---------------------------------------------------------------
# PeriodIndex.shift is used by __add__ and __sub__

Expand Down
55 changes: 0 additions & 55 deletions pandas/tests/indexes/timedeltas/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,61 +97,6 @@ def test_shift_no_freq(self):
with pytest.raises(NullFrequencyError):
tdi.shift(2)

# -------------------------------------------------------------
# Binary operations TimedeltaIndex and integer

def test_tdi_add_sub_int(self, one):
# Variants of `one` for #19012, deprecated GH#22535
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
msg = "Addition/subtraction of integers"

with pytest.raises(TypeError, match=msg):
rng + one
with pytest.raises(TypeError, match=msg):
rng += one
with pytest.raises(TypeError, match=msg):
rng - one
with pytest.raises(TypeError, match=msg):
rng -= one

# -------------------------------------------------------------
# __add__/__sub__ with integer arrays

@pytest.mark.parametrize("box", [np.array, pd.Index])
def test_tdi_add_sub_integer_array(self, box):
# GH#19959, deprecated GH#22535
rng = timedelta_range("1 days 09:00:00", freq="H", periods=3)
other = box([4, 3, 2])
msg = "Addition/subtraction of integers and integer-arrays"

with pytest.raises(TypeError, match=msg):
rng + other

with pytest.raises(TypeError, match=msg):
other + rng

with pytest.raises(TypeError, match=msg):
rng - other

with pytest.raises(TypeError, match=msg):
other - rng

@pytest.mark.parametrize("box", [np.array, pd.Index])
def test_tdi_addsub_integer_array_no_freq(self, box):
# GH#19959
tdi = TimedeltaIndex(["1 Day", "NaT", "3 Hours"])
other = box([14, -1, 16])
msg = "Addition/subtraction of integers"

with pytest.raises(TypeError, match=msg):
tdi + other
with pytest.raises(TypeError, match=msg):
other + tdi
with pytest.raises(TypeError, match=msg):
tdi - other
with pytest.raises(TypeError, match=msg):
other - tdi

# -------------------------------------------------------------
# Binary operations TimedeltaIndex and timedelta-like
# Note: add and sub are tested in tests.test_arithmetic, in-place
Expand Down