Skip to content

Commit 4d1750c

Browse files
added new fixtures that can replace the Ops mixin
1 parent 989a415 commit 4d1750c

File tree

3 files changed

+153
-21
lines changed

3 files changed

+153
-21
lines changed

pandas/conftest.py

+72
Original file line numberDiff line numberDiff line change
@@ -881,3 +881,75 @@ def index_or_series(request):
881881
See GH#29725
882882
"""
883883
return request.param
884+
885+
886+
_int_index = tm.makeIntIndex(10, name="a")
887+
_indexes = [
888+
tm.makeBoolIndex(10, name="a"),
889+
_int_index,
890+
tm.makeFloatIndex(10, name="a"),
891+
tm.makeDateIndex(10, name="a"),
892+
tm.makeDateIndex(10, name="a", tz="US/Eastern"),
893+
tm.makePeriodIndex(10, name="a"),
894+
tm.makeStringIndex(10, name="a"),
895+
tm.makeUnicodeIndex(10, name="a"),
896+
]
897+
_index_ids = [
898+
"bool-index",
899+
"int-index",
900+
"float-index",
901+
"date-index",
902+
"localized-date-index",
903+
"period-index",
904+
"string-index",
905+
"unicode-index",
906+
]
907+
908+
909+
@pytest.fixture(params=_indexes, ids=_index_ids)
910+
def index(request):
911+
""" Fixture for tests on indexes """
912+
return request.param.copy(deep=True)
913+
914+
915+
_arr = arr = np.random.randn(10)
916+
917+
918+
@pytest.fixture
919+
def int_series():
920+
""" Fixture for Series with random numbers and integer index """
921+
index = _int_index.copy(deep=True)
922+
return pd.Series(_arr, index=index, name=index.name)
923+
924+
925+
_series = [pd.Series(_arr, index=index, name=index.name) for index in _indexes]
926+
_series_ids = [f"series-with-{index_id}" for index_id in _index_ids]
927+
928+
_arr_int = np.random.choice(10, size=10, replace=False)
929+
_narrow_series = [
930+
pd.Series(_arr.astype(np.float32), index=_int_index, name="a"),
931+
pd.Series(_arr_int.astype(np.int8), index=_int_index, name="a"),
932+
pd.Series(_arr_int.astype(np.int16), index=_int_index, name="a"),
933+
pd.Series(_arr_int.astype(np.int32), index=_int_index, name="a"),
934+
pd.Series(_arr_int.astype(np.uint8), index=_int_index, name="a"),
935+
pd.Series(_arr_int.astype(np.uint16), index=_int_index, name="a"),
936+
pd.Series(_arr_int.astype(np.uint32), index=_int_index, name="a"),
937+
]
938+
_narrow_series_ids = [
939+
"float32-series",
940+
"int8-series",
941+
"int16-series",
942+
"int32-series",
943+
"uint8-series",
944+
"uint16-series",
945+
"uint32-series",
946+
]
947+
948+
_all_objs = _indexes + _series + _narrow_series
949+
_all_obj_ids = _index_ids + _series_ids + _narrow_series_ids
950+
951+
952+
@pytest.fixture(params=_all_objs, ids=_all_obj_ids)
953+
def index_or_series_obj(request):
954+
""" Fixture for tests on indexes, series and series with a narrow dtype """
955+
return request.param.copy(deep=True)

pandas/tests/base/test_ops.py

+22-21
Original file line numberDiff line numberDiff line change
@@ -130,27 +130,28 @@ def check_ops_properties(self, props, filter=None, ignore_failures=False):
130130
with pytest.raises(err):
131131
getattr(o, op)
132132

133-
@pytest.mark.parametrize("klass", [Series, DataFrame])
134-
def test_binary_ops_docs(self, klass):
135-
op_map = {
136-
"add": "+",
137-
"sub": "-",
138-
"mul": "*",
139-
"mod": "%",
140-
"pow": "**",
141-
"truediv": "/",
142-
"floordiv": "//",
143-
}
144-
for op_name in op_map:
145-
operand1 = klass.__name__.lower()
146-
operand2 = "other"
147-
op = op_map[op_name]
148-
expected_str = " ".join([operand1, op, operand2])
149-
assert expected_str in getattr(klass, op_name).__doc__
150-
151-
# reverse version of the binary ops
152-
expected_str = " ".join([operand2, op, operand1])
153-
assert expected_str in getattr(klass, "r" + op_name).__doc__
133+
134+
@pytest.mark.parametrize("klass", [Series, DataFrame])
135+
def test_binary_ops_docs(klass):
136+
op_map = {
137+
"add": "+",
138+
"sub": "-",
139+
"mul": "*",
140+
"mod": "%",
141+
"pow": "**",
142+
"truediv": "/",
143+
"floordiv": "//",
144+
}
145+
for op_name in op_map:
146+
operand1 = klass.__name__.lower()
147+
operand2 = "other"
148+
op = op_map[op_name]
149+
expected_str = " ".join([operand1, op, operand2])
150+
assert expected_str in getattr(klass, op_name).__doc__
151+
152+
# reverse version of the binary ops
153+
expected_str = " ".join([operand2, op, operand1])
154+
assert expected_str in getattr(klass, "r" + op_name).__doc__
154155

155156

156157
class TestTranspose(Ops):

pandas/tests/base/utils.py

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from typing import Any, Callable, List
2+
3+
import numpy as np
4+
import pytest
5+
6+
from pandas import Index, Series
7+
from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
8+
import pandas.util.testing as tm
9+
10+
11+
def allow_na_ops(obj: Any) -> bool:
12+
"""Whether to skip test cases including NaN"""
13+
is_bool_index = isinstance(obj, Index) and obj.is_boolean()
14+
return not is_bool_index and obj._can_hold_na
15+
16+
17+
def check_ops_properties_valid(obj: Any, props: List[str], filter: Callable) -> None:
18+
""" Validates that certain properties are available """
19+
for op in props:
20+
# if a filter, skip if it doesn't match
21+
index = obj.index if isinstance(obj, Series) else obj
22+
if not filter(index):
23+
continue
24+
25+
try:
26+
if isinstance(obj, Series):
27+
expected = Series(getattr(obj.index, op), index=obj.index, name="a")
28+
else:
29+
expected = getattr(obj, op)
30+
except AttributeError:
31+
continue
32+
33+
result = getattr(obj, op)
34+
35+
# these could be series, arrays or scalars
36+
if isinstance(result, Series) and isinstance(expected, Series):
37+
tm.assert_series_equal(result, expected)
38+
elif isinstance(result, Index) and isinstance(expected, Index):
39+
tm.assert_index_equal(result, expected)
40+
elif isinstance(result, np.ndarray) and isinstance(expected, np.ndarray):
41+
tm.assert_numpy_array_equal(result, expected)
42+
else:
43+
assert result == expected
44+
45+
46+
def check_ops_properties_invalid(obj: Any, props: List[str]) -> None:
47+
""" Validates that certain properties are not available """
48+
for op in props:
49+
# freq raises AttributeError on an Int64Index because its not
50+
# defined we mostly care about Series here anyhow
51+
52+
# an object that is datetimelike will raise a TypeError,
53+
# otherwise an AttributeError
54+
err = AttributeError
55+
if issubclass(type(obj), DatetimeIndexOpsMixin):
56+
err = TypeError
57+
58+
with pytest.raises(err):
59+
getattr(obj, op)

0 commit comments

Comments
 (0)