Skip to content

Commit

Permalink
[POC] implement test_arithmetic.py (#22033)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Jul 29, 2018
1 parent ff1fa4e commit d30c4a0
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 56 deletions.
38 changes: 1 addition & 37 deletions pandas/tests/indexes/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import pandas.util.testing as tm

import pandas as pd
from pandas._libs.tslibs import Timestamp, Timedelta
from pandas._libs.tslibs import Timestamp

from pandas.tests.indexes.common import Base

Expand All @@ -26,42 +26,6 @@ def full_like(array, value):
return ret


class TestIndexArithmeticWithTimedeltaScalar(object):

@pytest.mark.parametrize('index', [
Int64Index(range(1, 11)),
UInt64Index(range(1, 11)),
Float64Index(range(1, 11)),
RangeIndex(1, 11)])
@pytest.mark.parametrize('scalar_td', [Timedelta(days=1),
Timedelta(days=1).to_timedelta64(),
Timedelta(days=1).to_pytimedelta()])
def test_index_mul_timedelta(self, scalar_td, index):
# GH#19333
expected = pd.timedelta_range('1 days', '10 days')

result = index * scalar_td
tm.assert_index_equal(result, expected)
commute = scalar_td * index
tm.assert_index_equal(commute, expected)

@pytest.mark.parametrize('index', [Int64Index(range(1, 3)),
UInt64Index(range(1, 3)),
Float64Index(range(1, 3)),
RangeIndex(1, 3)])
@pytest.mark.parametrize('scalar_td', [Timedelta(days=1),
Timedelta(days=1).to_timedelta64(),
Timedelta(days=1).to_pytimedelta()])
def test_index_rdiv_timedelta(self, scalar_td, index):
expected = pd.TimedeltaIndex(['1 Day', '12 Hours'])

result = scalar_td / index
tm.assert_index_equal(result, expected)

with pytest.raises(TypeError):
index / scalar_td


class Numeric(Base):

def test_can_hold_identifiers(self):
Expand Down
19 changes: 0 additions & 19 deletions pandas/tests/series/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,22 +891,3 @@ def test_td64series_mul_timedeltalike_invalid(self, scalar_td):
td1 * scalar_td
with tm.assert_raises_regex(TypeError, pattern):
scalar_td * td1


class TestTimedeltaSeriesInvalidArithmeticOps(object):
@pytest.mark.parametrize('scalar_td', [
timedelta(minutes=5, seconds=4),
Timedelta('5m4s'),
Timedelta('5m4s').to_timedelta64()])
def test_td64series_pow_invalid(self, scalar_td):
td1 = Series([timedelta(minutes=5, seconds=3)] * 3)
td1.iloc[2] = np.nan

# check that we are getting a TypeError
# with 'operate' (from core/ops.py) for the ops that are not
# defined
pattern = 'operate|unsupported|cannot|not supported'
with tm.assert_raises_regex(TypeError, pattern):
scalar_td ** td1
with tm.assert_raises_regex(TypeError, pattern):
td1 ** scalar_td
119 changes: 119 additions & 0 deletions pandas/tests/test_arithmetic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# Arithmetc tests for DataFrame/Series/Index/Array classes that should
# behave identically.
from datetime import timedelta

import pytest
import numpy as np

import pandas as pd
import pandas.util.testing as tm

from pandas import Timedelta


# ------------------------------------------------------------------
# Numeric dtypes Arithmetic with Timedelta Scalar

class TestNumericArraylikeArithmeticWithTimedeltaScalar(object):

@pytest.mark.parametrize('box', [
pd.Index,
pd.Series,
pytest.param(pd.DataFrame,
marks=pytest.mark.xfail(reason="block.eval incorrect",
strict=True))
])
@pytest.mark.parametrize('index', [
pd.Int64Index(range(1, 11)),
pd.UInt64Index(range(1, 11)),
pd.Float64Index(range(1, 11)),
pd.RangeIndex(1, 11)],
ids=lambda x: type(x).__name__)
@pytest.mark.parametrize('scalar_td', [
Timedelta(days=1),
Timedelta(days=1).to_timedelta64(),
Timedelta(days=1).to_pytimedelta()],
ids=lambda x: type(x).__name__)
def test_index_mul_timedelta(self, scalar_td, index, box):
# GH#19333

if (box is pd.Series and
type(scalar_td) is timedelta and index.dtype == 'f8'):
raise pytest.xfail(reason="Cannot multiply timedelta by float")

expected = pd.timedelta_range('1 days', '10 days')

index = tm.box_expected(index, box)
expected = tm.box_expected(expected, box)

result = index * scalar_td
tm.assert_equal(result, expected)

commute = scalar_td * index
tm.assert_equal(commute, expected)

@pytest.mark.parametrize('box', [pd.Index, pd.Series, pd.DataFrame])
@pytest.mark.parametrize('index', [
pd.Int64Index(range(1, 3)),
pd.UInt64Index(range(1, 3)),
pd.Float64Index(range(1, 3)),
pd.RangeIndex(1, 3)],
ids=lambda x: type(x).__name__)
@pytest.mark.parametrize('scalar_td', [
Timedelta(days=1),
Timedelta(days=1).to_timedelta64(),
Timedelta(days=1).to_pytimedelta()],
ids=lambda x: type(x).__name__)
def test_index_rdiv_timedelta(self, scalar_td, index, box):

if box is pd.Series and type(scalar_td) is timedelta:
raise pytest.xfail(reason="TODO: Figure out why this case fails")
if box is pd.DataFrame and isinstance(scalar_td, timedelta):
raise pytest.xfail(reason="TODO: Figure out why this case fails")

expected = pd.TimedeltaIndex(['1 Day', '12 Hours'])

index = tm.box_expected(index, box)
expected = tm.box_expected(expected, box)

result = scalar_td / index
tm.assert_equal(result, expected)

with pytest.raises(TypeError):
index / scalar_td


# ------------------------------------------------------------------
# Timedelta64[ns] dtype Arithmetic Operations


class TestTimedeltaArraylikeInvalidArithmeticOps(object):

@pytest.mark.parametrize('box', [
pd.Index,
pd.Series,
pytest.param(pd.DataFrame,
marks=pytest.mark.xfail(reason="raises ValueError "
"instead of TypeError",
strict=True))
])
@pytest.mark.parametrize('scalar_td', [
timedelta(minutes=5, seconds=4),
Timedelta('5m4s'),
Timedelta('5m4s').to_timedelta64()])
def test_td64series_pow_invalid(self, scalar_td, box):
td1 = pd.Series([timedelta(minutes=5, seconds=3)] * 3)
td1.iloc[2] = np.nan

td1 = tm.box_expected(td1, box)

# check that we are getting a TypeError
# with 'operate' (from core/ops.py) for the ops that are not
# defined
pattern = 'operate|unsupported|cannot|not supported'
with tm.assert_raises_regex(TypeError, pattern):
scalar_td ** td1

with tm.assert_raises_regex(TypeError, pattern):
td1 ** scalar_td
44 changes: 44 additions & 0 deletions pandas/util/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,50 @@ def assert_panel_equal(left, right,
assert item in left, msg


def assert_equal(left, right, **kwargs):
"""
Wrapper for tm.assert_*_equal to dispatch to the appropriate test function.
Parameters
----------
left : Index, Series, or DataFrame
right : Index, Series, or DataFrame
**kwargs
"""
if isinstance(left, pd.Index):
assert_index_equal(left, right, **kwargs)
elif isinstance(left, pd.Series):
assert_series_equal(left, right, **kwargs)
elif isinstance(left, pd.DataFrame):
assert_frame_equal(left, right, **kwargs)
else:
raise NotImplementedError(type(left))


def box_expected(expected, box_cls):
"""
Helper function to wrap the expected output of a test in a given box_class.
Parameters
----------
expected : np.ndarray, Index, Series
box_cls : {Index, Series, DataFrame}
Returns
-------
subclass of box_cls
"""
if box_cls is pd.Index:
expected = pd.Index(expected)
elif box_cls is pd.Series:
expected = pd.Series(expected)
elif box_cls is pd.DataFrame:
expected = pd.Series(expected).to_frame()
else:
raise NotImplementedError(box_cls)
return expected


# -----------------------------------------------------------------------------
# Sparse

Expand Down

0 comments on commit d30c4a0

Please sign in to comment.