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

Implement+Test Tick.__rtruediv__ #24832

Merged
merged 14 commits into from
Feb 1, 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
16 changes: 16 additions & 0 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ from numpy cimport int64_t
cnp.import_array()


from pandas._libs.tslibs cimport util
from pandas._libs.tslibs.util cimport is_string_object, is_integer_object

from pandas._libs.tslibs.ccalendar import MONTHS, DAYS
Expand Down Expand Up @@ -408,6 +409,10 @@ class _BaseOffset(object):
return self.apply(other)

def __mul__(self, other):
if hasattr(other, "_typ"):
return NotImplemented
if util.is_array(other):
return np.array([self * x for x in other])
return type(self)(n=other * self.n, normalize=self.normalize,
**self.kwds)

Expand Down Expand Up @@ -458,6 +463,9 @@ class _BaseOffset(object):
TypeError if `int(n)` raises
ValueError if n != int(n)
"""
if util.is_timedelta64_object(n):
raise TypeError('`n` argument must be an integer, '
'got {ntype}'.format(ntype=type(n)))
try:
nint = int(n)
except (ValueError, TypeError):
Expand Down Expand Up @@ -533,12 +541,20 @@ class _Tick(object):
can do isinstance checks on _Tick and avoid importing tseries.offsets
"""

# ensure that reversed-ops with numpy scalars return NotImplemented
__array_priority__ = 1000

def __truediv__(self, other):
result = self.delta.__truediv__(other)
return _wrap_timedelta_result(result)

def __rtruediv__(self, other):
result = self.delta.__rtruediv__(other)
return _wrap_timedelta_result(result)

if PY2:
__div__ = __truediv__
__rdiv__ = __rtruediv__


# ----------------------------------------------------------------------
Expand Down
20 changes: 20 additions & 0 deletions pandas/tests/tseries/offsets/test_offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,26 @@ def test_offset_n(self, offset_types):
mul_offset = offset * 3
assert mul_offset.n == 3

def test_offset_timedelta64_arg(self, offset_types):
# check that offset._validate_n raises TypeError on a timedelt64
# object
off = self._get_offset(offset_types)

td64 = np.timedelta64(4567, 's')
with pytest.raises(TypeError, match="argument must be an integer"):
type(off)(n=td64, **off.kwds)

def test_offset_mul_ndarray(self, offset_types):
off = self._get_offset(offset_types)

expected = np.array([[off, off * 2], [off * 3, off * 4]])

result = np.array([[1, 2], [3, 4]]) * off
tm.assert_numpy_array_equal(result, expected)

result = off * np.array([[1, 2], [3, 4]])
tm.assert_numpy_array_equal(result, expected)

def test_offset_freqstr(self, offset_types):
offset = self._get_offset(offset_types)

Expand Down
23 changes: 23 additions & 0 deletions pandas/tests/tseries/offsets/test_ticks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import pytest

from pandas import Timedelta, Timestamp
import pandas.util.testing as tm

from pandas.tseries import offsets
from pandas.tseries.offsets import Hour, Micro, Milli, Minute, Nano, Second
Expand Down Expand Up @@ -262,6 +263,28 @@ def test_tick_division(cls):
assert result.delta == off.delta / .001


@pytest.mark.parametrize('cls', tick_classes)
def test_tick_rdiv(cls):
off = cls(10)
delta = off.delta
td64 = delta.to_timedelta64()

with pytest.raises(TypeError):
2 / off
with pytest.raises(TypeError):
2.0 / off

assert (td64 * 2.5) / off == 2.5

if cls is not Nano:
# skip pytimedelta for Nano since it gets dropped
assert (delta.to_pytimedelta() * 2) / off == 2

result = np.array([2 * td64, td64]) / off
expected = np.array([2., 1.])
tm.assert_numpy_array_equal(result, expected)


@pytest.mark.parametrize('cls1', tick_classes)
@pytest.mark.parametrize('cls2', tick_classes)
def test_tick_zero(cls1, cls2):
Expand Down