Skip to content

Commit

Permalink
added new fixtures that can replace the Ops mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
SaturnFromTitan committed Dec 8, 2019
1 parent 989a415 commit 4d1750c
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 21 deletions.
72 changes: 72 additions & 0 deletions pandas/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,3 +881,75 @@ def index_or_series(request):
See GH#29725
"""
return request.param


_int_index = tm.makeIntIndex(10, name="a")
_indexes = [
tm.makeBoolIndex(10, name="a"),
_int_index,
tm.makeFloatIndex(10, name="a"),
tm.makeDateIndex(10, name="a"),
tm.makeDateIndex(10, name="a", tz="US/Eastern"),
tm.makePeriodIndex(10, name="a"),
tm.makeStringIndex(10, name="a"),
tm.makeUnicodeIndex(10, name="a"),
]
_index_ids = [
"bool-index",
"int-index",
"float-index",
"date-index",
"localized-date-index",
"period-index",
"string-index",
"unicode-index",
]


@pytest.fixture(params=_indexes, ids=_index_ids)
def index(request):
""" Fixture for tests on indexes """
return request.param.copy(deep=True)


_arr = arr = np.random.randn(10)


@pytest.fixture
def int_series():
""" Fixture for Series with random numbers and integer index """
index = _int_index.copy(deep=True)
return pd.Series(_arr, index=index, name=index.name)


_series = [pd.Series(_arr, index=index, name=index.name) for index in _indexes]
_series_ids = [f"series-with-{index_id}" for index_id in _index_ids]

_arr_int = np.random.choice(10, size=10, replace=False)
_narrow_series = [
pd.Series(_arr.astype(np.float32), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.int8), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.int16), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.int32), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.uint8), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.uint16), index=_int_index, name="a"),
pd.Series(_arr_int.astype(np.uint32), index=_int_index, name="a"),
]
_narrow_series_ids = [
"float32-series",
"int8-series",
"int16-series",
"int32-series",
"uint8-series",
"uint16-series",
"uint32-series",
]

_all_objs = _indexes + _series + _narrow_series
_all_obj_ids = _index_ids + _series_ids + _narrow_series_ids


@pytest.fixture(params=_all_objs, ids=_all_obj_ids)
def index_or_series_obj(request):
""" Fixture for tests on indexes, series and series with a narrow dtype """
return request.param.copy(deep=True)
43 changes: 22 additions & 21 deletions pandas/tests/base/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,27 +130,28 @@ def check_ops_properties(self, props, filter=None, ignore_failures=False):
with pytest.raises(err):
getattr(o, op)

@pytest.mark.parametrize("klass", [Series, DataFrame])
def test_binary_ops_docs(self, klass):
op_map = {
"add": "+",
"sub": "-",
"mul": "*",
"mod": "%",
"pow": "**",
"truediv": "/",
"floordiv": "//",
}
for op_name in op_map:
operand1 = klass.__name__.lower()
operand2 = "other"
op = op_map[op_name]
expected_str = " ".join([operand1, op, operand2])
assert expected_str in getattr(klass, op_name).__doc__

# reverse version of the binary ops
expected_str = " ".join([operand2, op, operand1])
assert expected_str in getattr(klass, "r" + op_name).__doc__

@pytest.mark.parametrize("klass", [Series, DataFrame])
def test_binary_ops_docs(klass):
op_map = {
"add": "+",
"sub": "-",
"mul": "*",
"mod": "%",
"pow": "**",
"truediv": "/",
"floordiv": "//",
}
for op_name in op_map:
operand1 = klass.__name__.lower()
operand2 = "other"
op = op_map[op_name]
expected_str = " ".join([operand1, op, operand2])
assert expected_str in getattr(klass, op_name).__doc__

# reverse version of the binary ops
expected_str = " ".join([operand2, op, operand1])
assert expected_str in getattr(klass, "r" + op_name).__doc__


class TestTranspose(Ops):
Expand Down
59 changes: 59 additions & 0 deletions pandas/tests/base/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Any, Callable, List

import numpy as np
import pytest

from pandas import Index, Series
from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
import pandas.util.testing as tm


def allow_na_ops(obj: Any) -> bool:
"""Whether to skip test cases including NaN"""
is_bool_index = isinstance(obj, Index) and obj.is_boolean()
return not is_bool_index and obj._can_hold_na


def check_ops_properties_valid(obj: Any, props: List[str], filter: Callable) -> None:
""" Validates that certain properties are available """
for op in props:
# if a filter, skip if it doesn't match
index = obj.index if isinstance(obj, Series) else obj
if not filter(index):
continue

try:
if isinstance(obj, Series):
expected = Series(getattr(obj.index, op), index=obj.index, name="a")
else:
expected = getattr(obj, op)
except AttributeError:
continue

result = getattr(obj, op)

# these could be series, arrays or scalars
if isinstance(result, Series) and isinstance(expected, Series):
tm.assert_series_equal(result, expected)
elif isinstance(result, Index) and isinstance(expected, Index):
tm.assert_index_equal(result, expected)
elif isinstance(result, np.ndarray) and isinstance(expected, np.ndarray):
tm.assert_numpy_array_equal(result, expected)
else:
assert result == expected


def check_ops_properties_invalid(obj: Any, props: List[str]) -> None:
""" Validates that certain properties are not available """
for op in props:
# freq raises AttributeError on an Int64Index because its not
# defined we mostly care about Series here anyhow

# an object that is datetimelike will raise a TypeError,
# otherwise an AttributeError
err = AttributeError
if issubclass(type(obj), DatetimeIndexOpsMixin):
err = TypeError

with pytest.raises(err):
getattr(obj, op)

0 comments on commit 4d1750c

Please sign in to comment.