Skip to content

Commit 22de58e

Browse files
authored
REF: de-duplicate MaskedArray tests (#44004)
* REF: share tests * REF: de-duplicate _compare_other
1 parent b159c75 commit 22de58e

File tree

10 files changed

+182
-283
lines changed

10 files changed

+182
-283
lines changed

pandas/tests/arrays/boolean/test_comparison.py

+7-41
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pandas as pd
55
import pandas._testing as tm
66
from pandas.arrays import BooleanArray
7-
from pandas.tests.extension.base import BaseOpsUtil
7+
from pandas.tests.arrays.masked_shared import ComparisonOps
88

99

1010
@pytest.fixture
@@ -15,30 +15,12 @@ def data():
1515
)
1616

1717

18-
class TestComparisonOps(BaseOpsUtil):
19-
def _compare_other(self, data, op_name, other):
20-
op = self.get_op_from_name(op_name)
21-
22-
# array
23-
result = pd.Series(op(data, other))
24-
expected = pd.Series(op(data._data, other), dtype="boolean")
25-
# propagate NAs
26-
expected[data._mask] = pd.NA
27-
28-
tm.assert_series_equal(result, expected)
29-
30-
# series
31-
s = pd.Series(data)
32-
result = op(s, other)
33-
34-
expected = pd.Series(data._data)
35-
expected = op(expected, other)
36-
expected = expected.astype("boolean")
37-
# propagate NAs
38-
expected[data._mask] = pd.NA
18+
@pytest.fixture
19+
def dtype():
20+
return pd.BooleanDtype()
3921

40-
tm.assert_series_equal(result, expected)
4122

23+
class TestComparisonOps(ComparisonOps):
4224
def test_compare_scalar(self, data, all_compare_operators):
4325
op_name = all_compare_operators
4426
self._compare_other(data, op_name, True)
@@ -53,24 +35,8 @@ def test_compare_array(self, data, all_compare_operators):
5335
self._compare_other(data, op_name, other)
5436

5537
@pytest.mark.parametrize("other", [True, False, pd.NA])
56-
def test_scalar(self, other, all_compare_operators):
57-
op = self.get_op_from_name(all_compare_operators)
58-
a = pd.array([True, False, None], dtype="boolean")
59-
60-
result = op(a, other)
61-
62-
if other is pd.NA:
63-
expected = pd.array([None, None, None], dtype="boolean")
64-
else:
65-
values = op(a._data, other)
66-
expected = BooleanArray(values, a._mask, copy=True)
67-
tm.assert_extension_array_equal(result, expected)
68-
69-
# ensure we haven't mutated anything inplace
70-
result[0] = None
71-
tm.assert_extension_array_equal(
72-
a, pd.array([True, False, None], dtype="boolean")
73-
)
38+
def test_scalar(self, other, all_compare_operators, dtype):
39+
ComparisonOps.test_scalar(self, other, all_compare_operators, dtype)
7440

7541
def test_array(self, all_compare_operators):
7642
op = self.get_op_from_name(all_compare_operators)

pandas/tests/arrays/floating/test_comparison.py

+7-88
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,17 @@
1-
import numpy as np
21
import pytest
32

43
import pandas as pd
54
import pandas._testing as tm
6-
from pandas.tests.extension.base import BaseOpsUtil
5+
from pandas.tests.arrays.masked_shared import (
6+
ComparisonOps,
7+
NumericOps,
8+
)
79

810

9-
class TestComparisonOps(BaseOpsUtil):
10-
def _compare_other(self, data, op_name, other):
11-
op = self.get_op_from_name(op_name)
12-
13-
# array
14-
result = pd.Series(op(data, other))
15-
expected = pd.Series(op(data._data, other), dtype="boolean")
16-
17-
# fill the nan locations
18-
expected[data._mask] = pd.NA
19-
20-
tm.assert_series_equal(result, expected)
21-
22-
# series
23-
s = pd.Series(data)
24-
result = op(s, other)
25-
26-
expected = op(pd.Series(data._data), other)
27-
28-
# fill the nan locations
29-
expected[data._mask] = pd.NA
30-
expected = expected.astype("boolean")
31-
32-
tm.assert_series_equal(result, expected)
33-
11+
class TestComparisonOps(NumericOps, ComparisonOps):
3412
@pytest.mark.parametrize("other", [True, False, pd.NA, -1.0, 0.0, 1])
35-
def test_scalar(self, other, all_compare_operators):
36-
op = self.get_op_from_name(all_compare_operators)
37-
a = pd.array([1.0, 0.0, None], dtype="Float64")
38-
39-
result = op(a, other)
40-
41-
if other is pd.NA:
42-
expected = pd.array([None, None, None], dtype="boolean")
43-
else:
44-
values = op(a._data, other)
45-
expected = pd.arrays.BooleanArray(values, a._mask, copy=True)
46-
tm.assert_extension_array_equal(result, expected)
47-
48-
# ensure we haven't mutated anything inplace
49-
result[0] = pd.NA
50-
tm.assert_extension_array_equal(a, pd.array([1.0, 0.0, None], dtype="Float64"))
51-
52-
def test_array(self, all_compare_operators):
53-
op = self.get_op_from_name(all_compare_operators)
54-
a = pd.array([0, 1, 2, None, None, None], dtype="Float64")
55-
b = pd.array([0, 1, None, 0, 1, None], dtype="Float64")
56-
57-
result = op(a, b)
58-
values = op(a._data, b._data)
59-
mask = a._mask | b._mask
60-
61-
expected = pd.arrays.BooleanArray(values, mask)
62-
tm.assert_extension_array_equal(result, expected)
63-
64-
# ensure we haven't mutated anything inplace
65-
result[0] = pd.NA
66-
tm.assert_extension_array_equal(
67-
a, pd.array([0, 1, 2, None, None, None], dtype="Float64")
68-
)
69-
tm.assert_extension_array_equal(
70-
b, pd.array([0, 1, None, 0, 1, None], dtype="Float64")
71-
)
72-
73-
def test_compare_with_booleanarray(self, all_compare_operators):
74-
op = self.get_op_from_name(all_compare_operators)
75-
a = pd.array([True, False, None] * 3, dtype="boolean")
76-
b = pd.array([0] * 3 + [1] * 3 + [None] * 3, dtype="Float64")
77-
other = pd.array([False] * 3 + [True] * 3 + [None] * 3, dtype="boolean")
78-
expected = op(a, other)
79-
result = op(a, b)
80-
tm.assert_extension_array_equal(result, expected)
81-
expected = op(other, a)
82-
result = op(b, a)
83-
tm.assert_extension_array_equal(result, expected)
13+
def test_scalar(self, other, all_compare_operators, dtype):
14+
ComparisonOps.test_scalar(self, other, all_compare_operators, dtype)
8415

8516
def test_compare_with_integerarray(self, all_compare_operators):
8617
op = self.get_op_from_name(all_compare_operators)
@@ -94,18 +25,6 @@ def test_compare_with_integerarray(self, all_compare_operators):
9425
result = op(b, a)
9526
tm.assert_extension_array_equal(result, expected)
9627

97-
def test_no_shared_mask(self, data):
98-
result = data + 1
99-
assert np.shares_memory(result._mask, data._mask) is False
100-
101-
def test_compare_to_string(self, dtype):
102-
# GH 28930
103-
s = pd.Series([1, None], dtype=dtype)
104-
result = s == "a"
105-
expected = pd.Series([False, pd.NA], dtype="boolean")
106-
107-
self.assert_series_equal(result, expected)
108-
10928

11029
def test_equals():
11130
# GH-30652

pandas/tests/arrays/integer/test_comparison.py

+9-88
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,20 @@
1-
import numpy as np
21
import pytest
32

43
import pandas as pd
5-
import pandas._testing as tm
6-
from pandas.tests.extension.base import BaseOpsUtil
4+
from pandas.tests.arrays.masked_shared import (
5+
ComparisonOps,
6+
NumericOps,
7+
)
78

89

9-
class TestComparisonOps(BaseOpsUtil):
10-
def _compare_other(self, data, op_name, other):
11-
op = self.get_op_from_name(op_name)
12-
13-
# array
14-
result = pd.Series(op(data, other))
15-
expected = pd.Series(op(data._data, other), dtype="boolean")
16-
17-
# fill the nan locations
18-
expected[data._mask] = pd.NA
19-
20-
tm.assert_series_equal(result, expected)
21-
22-
# series
23-
s = pd.Series(data)
24-
result = op(s, other)
25-
26-
expected = op(pd.Series(data._data), other)
27-
28-
# fill the nan locations
29-
expected[data._mask] = pd.NA
30-
expected = expected.astype("boolean")
31-
32-
tm.assert_series_equal(result, expected)
33-
10+
class TestComparisonOps(NumericOps, ComparisonOps):
3411
@pytest.mark.parametrize("other", [True, False, pd.NA, -1, 0, 1])
35-
def test_scalar(self, other, all_compare_operators):
36-
op = self.get_op_from_name(all_compare_operators)
37-
a = pd.array([1, 0, None], dtype="Int64")
38-
39-
result = op(a, other)
40-
41-
if other is pd.NA:
42-
expected = pd.array([None, None, None], dtype="boolean")
43-
else:
44-
values = op(a._data, other)
45-
expected = pd.arrays.BooleanArray(values, a._mask, copy=True)
46-
tm.assert_extension_array_equal(result, expected)
47-
48-
# ensure we haven't mutated anything inplace
49-
result[0] = pd.NA
50-
tm.assert_extension_array_equal(a, pd.array([1, 0, None], dtype="Int64"))
51-
52-
def test_array(self, all_compare_operators):
53-
op = self.get_op_from_name(all_compare_operators)
54-
a = pd.array([0, 1, 2, None, None, None], dtype="Int64")
55-
b = pd.array([0, 1, None, 0, 1, None], dtype="Int64")
56-
57-
result = op(a, b)
58-
values = op(a._data, b._data)
59-
mask = a._mask | b._mask
60-
61-
expected = pd.arrays.BooleanArray(values, mask)
62-
tm.assert_extension_array_equal(result, expected)
63-
64-
# ensure we haven't mutated anything inplace
65-
result[0] = pd.NA
66-
tm.assert_extension_array_equal(
67-
a, pd.array([0, 1, 2, None, None, None], dtype="Int64")
68-
)
69-
tm.assert_extension_array_equal(
70-
b, pd.array([0, 1, None, 0, 1, None], dtype="Int64")
71-
)
72-
73-
def test_compare_with_booleanarray(self, all_compare_operators):
74-
op = self.get_op_from_name(all_compare_operators)
75-
a = pd.array([True, False, None] * 3, dtype="boolean")
76-
b = pd.array([0] * 3 + [1] * 3 + [None] * 3, dtype="Int64")
77-
other = pd.array([False] * 3 + [True] * 3 + [None] * 3, dtype="boolean")
78-
expected = op(a, other)
79-
result = op(a, b)
80-
tm.assert_extension_array_equal(result, expected)
81-
82-
def test_no_shared_mask(self, data):
83-
result = data + 1
84-
assert np.shares_memory(result._mask, data._mask) is False
85-
86-
def test_compare_to_string(self, any_int_ea_dtype):
87-
# GH 28930
88-
s = pd.Series([1, None], dtype=any_int_ea_dtype)
89-
result = s == "a"
90-
expected = pd.Series([False, pd.NA], dtype="boolean")
91-
92-
self.assert_series_equal(result, expected)
12+
def test_scalar(self, other, all_compare_operators, dtype):
13+
ComparisonOps.test_scalar(self, other, all_compare_operators, dtype)
9314

94-
def test_compare_to_int(self, any_int_ea_dtype, all_compare_operators):
15+
def test_compare_to_int(self, dtype, all_compare_operators):
9516
# GH 28930
96-
s1 = pd.Series([1, None, 3], dtype=any_int_ea_dtype)
17+
s1 = pd.Series([1, None, 3], dtype=dtype)
9718
s2 = pd.Series([1, None, 3], dtype="float")
9819

9920
method = getattr(s1, all_compare_operators)

pandas/tests/arrays/masked_shared.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
Tests shared by MaskedArray subclasses.
3+
"""
4+
import numpy as np
5+
6+
import pandas as pd
7+
import pandas._testing as tm
8+
from pandas.tests.extension.base import BaseOpsUtil
9+
10+
11+
class ComparisonOps(BaseOpsUtil):
12+
def _compare_other(self, data, op_name, other):
13+
op = self.get_op_from_name(op_name)
14+
15+
# array
16+
result = pd.Series(op(data, other))
17+
expected = pd.Series(op(data._data, other), dtype="boolean")
18+
19+
# fill the nan locations
20+
expected[data._mask] = pd.NA
21+
22+
tm.assert_series_equal(result, expected)
23+
24+
# series
25+
ser = pd.Series(data)
26+
result = op(ser, other)
27+
28+
expected = op(pd.Series(data._data), other)
29+
30+
# fill the nan locations
31+
expected[data._mask] = pd.NA
32+
expected = expected.astype("boolean")
33+
34+
tm.assert_series_equal(result, expected)
35+
36+
# subclass will override to parametrize 'other'
37+
def test_scalar(self, other, all_compare_operators, dtype):
38+
op = self.get_op_from_name(all_compare_operators)
39+
left = pd.array([1, 0, None], dtype=dtype)
40+
41+
result = op(left, other)
42+
43+
if other is pd.NA:
44+
expected = pd.array([None, None, None], dtype="boolean")
45+
else:
46+
values = op(left._data, other)
47+
expected = pd.arrays.BooleanArray(values, left._mask, copy=True)
48+
tm.assert_extension_array_equal(result, expected)
49+
50+
# ensure we haven't mutated anything inplace
51+
result[0] = pd.NA
52+
tm.assert_extension_array_equal(left, pd.array([1, 0, None], dtype=dtype))
53+
54+
55+
class NumericOps:
56+
# Shared by IntegerArray and FloatingArray, not BooleanArray
57+
58+
def test_no_shared_mask(self, data):
59+
result = data + 1
60+
assert np.shares_memory(result._mask, data._mask) is False
61+
62+
def test_array(self, all_compare_operators, dtype):
63+
op = self.get_op_from_name(all_compare_operators)
64+
65+
left = pd.array([0, 1, 2, None, None, None], dtype=dtype)
66+
right = pd.array([0, 1, None, 0, 1, None], dtype=dtype)
67+
68+
result = op(left, right)
69+
values = op(left._data, right._data)
70+
mask = left._mask | right._mask
71+
72+
expected = pd.arrays.BooleanArray(values, mask)
73+
tm.assert_extension_array_equal(result, expected)
74+
75+
# ensure we haven't mutated anything inplace
76+
result[0] = pd.NA
77+
tm.assert_extension_array_equal(
78+
left, pd.array([0, 1, 2, None, None, None], dtype=dtype)
79+
)
80+
tm.assert_extension_array_equal(
81+
right, pd.array([0, 1, None, 0, 1, None], dtype=dtype)
82+
)
83+
84+
def test_compare_with_booleanarray(self, all_compare_operators, dtype):
85+
op = self.get_op_from_name(all_compare_operators)
86+
87+
left = pd.array([True, False, None] * 3, dtype="boolean")
88+
right = pd.array([0] * 3 + [1] * 3 + [None] * 3, dtype=dtype)
89+
other = pd.array([False] * 3 + [True] * 3 + [None] * 3, dtype="boolean")
90+
91+
expected = op(left, other)
92+
result = op(left, right)
93+
tm.assert_extension_array_equal(result, expected)
94+
95+
# reversed op
96+
expected = op(other, left)
97+
result = op(right, left)
98+
tm.assert_extension_array_equal(result, expected)
99+
100+
def test_compare_to_string(self, dtype):
101+
# GH#28930
102+
ser = pd.Series([1, None], dtype=dtype)
103+
result = ser == "a"
104+
expected = pd.Series([False, pd.NA], dtype="boolean")
105+
106+
self.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)