From 3209be2264a176de1bb1e1f6b29f3a8592f65ebd Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 23 Jan 2021 09:09:45 -0800 Subject: [PATCH 1/4] TST: fix xfailed tests for IntegerArray, FloatingArray --- pandas/_testing/__init__.py | 1 + pandas/_testing/compat.py | 13 +++++++++++++ pandas/tests/extension/base/ops.py | 21 ++++++++++++--------- pandas/tests/extension/json/test_json.py | 6 ++++++ pandas/tests/extension/test_floating.py | 9 +++++---- pandas/tests/extension/test_integer.py | 15 ++++++++------- pandas/tests/extension/test_sparse.py | 14 ++++++++++++++ 7 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 pandas/_testing/compat.py diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index a28b119854bb7..0b2be53131af6 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -88,6 +88,7 @@ assert_timedelta_array_equal, raise_assert_detail, ) +from pandas._testing.compat import get_dtype # noqa:F401 from pandas._testing.contexts import ( # noqa:F401 RNGContext, decompress_file, diff --git a/pandas/_testing/compat.py b/pandas/_testing/compat.py new file mode 100644 index 0000000000000..1b7d038214949 --- /dev/null +++ b/pandas/_testing/compat.py @@ -0,0 +1,13 @@ +""" +Helpers for sharing tests between DataFrame/Series +""" + +from pandas import DataFrame + + +def get_dtype(obj): + if isinstance(obj, DataFrame): + # Note: we are assuming only one column + return obj.dtypes.iat[0] + else: + return obj.dtype diff --git a/pandas/tests/extension/base/ops.py b/pandas/tests/extension/base/ops.py index c93603398977e..3ba998477fb38 100644 --- a/pandas/tests/extension/base/ops.py +++ b/pandas/tests/extension/base/ops.py @@ -18,17 +18,21 @@ def check_opname(self, s, op_name, other, exc=Exception): self._check_op(s, op, other, op_name, exc) + def _combine(self, obj, other, op): + if isinstance(obj, pd.DataFrame): + if len(obj.columns) != 1: + raise NotImplementedError + expected = obj.iloc[:, 0].combine(other, op).to_frame() + else: + expected = obj.combine(other, op) + return expected + def _check_op(self, s, op, other, op_name, exc=NotImplementedError): if exc is None: result = op(s, other) - if isinstance(s, pd.DataFrame): - if len(s.columns) != 1: - raise NotImplementedError - expected = s.iloc[:, 0].combine(other, op).to_frame() - self.assert_frame_equal(result, expected) - else: - expected = s.combine(other, op) - self.assert_series_equal(result, expected) + expected = self._combine(s, other, op) + assert isinstance(result, type(s)) + self.assert_equal(result, expected) else: with pytest.raises(exc): op(s, other) @@ -72,7 +76,6 @@ def test_arith_series_with_scalar(self, data, all_arithmetic_operators): s = pd.Series(data) self.check_opname(s, op_name, s.iloc[0], exc=self.series_scalar_exc) - @pytest.mark.xfail(run=False, reason="_reduce needs implementation") def test_arith_frame_with_scalar(self, data, all_arithmetic_operators): # frame & scalar op_name = all_arithmetic_operators diff --git a/pandas/tests/extension/json/test_json.py b/pandas/tests/extension/json/test_json.py index 164a39498ec73..a63aaef52ccef 100644 --- a/pandas/tests/extension/json/test_json.py +++ b/pandas/tests/extension/json/test_json.py @@ -322,6 +322,12 @@ class TestArithmeticOps(BaseJSON, base.BaseArithmeticOpsTests): def test_error(self, data, all_arithmetic_operators): pass + def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): + if len(data[0]) != 1: + mark = pytest.mark.xfail(reason="raises in coercing to Series") + request.node.add_marker(mark) + super().test_arith_frame_with_scalar(data, all_arithmetic_operators) + def test_add_series_with_extension_array(self, data): ser = pd.Series(data) with pytest.raises(TypeError, match="unsupported"): diff --git a/pandas/tests/extension/test_floating.py b/pandas/tests/extension/test_floating.py index 440d7391c558f..53a31ead73515 100644 --- a/pandas/tests/extension/test_floating.py +++ b/pandas/tests/extension/test_floating.py @@ -99,6 +99,7 @@ def check_opname(self, s, op_name, other, exc=None): def _check_op(self, s, op, other, op_name, exc=NotImplementedError): if exc is None: + sdtype = tm.get_dtype(s) if ( hasattr(other, "dtype") and not is_extension_array_dtype(other.dtype) @@ -106,15 +107,15 @@ def _check_op(self, s, op, other, op_name, exc=NotImplementedError): ): # other is np.float64 and would therefore always result in # upcasting, so keeping other as same numpy_dtype - other = other.astype(s.dtype.numpy_dtype) + other = other.astype(sdtype.numpy_dtype) result = op(s, other) - expected = s.combine(other, op) + expected = self._combine(s, other, op) # combine method result in 'biggest' (float64) dtype - expected = expected.astype(s.dtype) + expected = expected.astype(sdtype) - self.assert_series_equal(result, expected) + self.assert_equal(result, expected) else: with pytest.raises(exc): op(s, other) diff --git a/pandas/tests/extension/test_integer.py b/pandas/tests/extension/test_integer.py index 2a469bb388fbe..1f9a24d4242d1 100644 --- a/pandas/tests/extension/test_integer.py +++ b/pandas/tests/extension/test_integer.py @@ -111,7 +111,8 @@ def check_opname(self, s, op_name, other, exc=None): def _check_op(self, s, op, other, op_name, exc=NotImplementedError): if exc is None: - if s.dtype.is_unsigned_integer and (op_name == "__rsub__"): + sdtype = tm.get_dtype(s) + if sdtype.is_unsigned_integer and (op_name == "__rsub__"): # TODO see https://github.com/pandas-dev/pandas/issues/22023 pytest.skip("unsigned subtraction gives negative values") @@ -122,21 +123,21 @@ def _check_op(self, s, op, other, op_name, exc=NotImplementedError): ): # other is np.int64 and would therefore always result in # upcasting, so keeping other as same numpy_dtype - other = other.astype(s.dtype.numpy_dtype) + other = other.astype(sdtype.numpy_dtype) result = op(s, other) - expected = s.combine(other, op) + expected = self._combine(s, other, op) if op_name in ("__rtruediv__", "__truediv__", "__div__"): expected = expected.fillna(np.nan).astype("Float64") elif op_name.startswith("__r"): # TODO reverse operators result in object dtype # see https://github.com/pandas-dev/pandas/issues/22024 - expected = expected.astype(s.dtype) - result = result.astype(s.dtype) + expected = expected.astype(sdtype) + result = result.astype(sdtype) else: # combine method result in 'biggest' (int64) dtype - expected = expected.astype(s.dtype) + expected = expected.astype(sdtype) pass if (op_name == "__rpow__") and isinstance(other, pd.Series): @@ -144,7 +145,7 @@ def _check_op(self, s, op, other, op_name, exc=NotImplementedError): # see https://github.com/pandas-dev/pandas/issues/22022 result = result.fillna(1) - self.assert_series_equal(result, expected) + self.assert_equal(result, expected) else: with pytest.raises(exc): op(s, other) diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index 86f9080571459..b2b622718bb04 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -403,6 +403,20 @@ def test_arith_series_with_array(self, data, all_arithmetic_operators): self._skip_if_different_combine(data) super().test_arith_series_with_array(data, all_arithmetic_operators) + def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): + if data.dtype.fill_value == 0 and all_arithmetic_operators.strip("_") not in [ + "mul", + "rmul", + "floordiv", + "rfloordiv", + "pow", + "mod", + "rmod", + ]: + mark = pytest.mark.xfail(reason="result dtype.fill_value mismatch") + request.node.add_marker(mark) + super().test_arith_frame_with_scalar(data, all_arithmetic_operators) + class TestComparisonOps(BaseSparseTests, base.BaseComparisonOpsTests): def _compare_other(self, s, data, op_name, other): From caff3898296b7ca6282dcf4fe2c42c896519c3be Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 23 Jan 2021 10:48:52 -0800 Subject: [PATCH 2/4] 32bit xfail --- pandas/tests/extension/test_sparse.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index b2b622718bb04..bb8fe9a762230 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -16,6 +16,7 @@ import numpy as np import pytest +from pandas.compat import IS64 from pandas.errors import PerformanceWarning from pandas.core.dtypes.common import is_object_dtype @@ -415,6 +416,9 @@ def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): ]: mark = pytest.mark.xfail(reason="result dtype.fill_value mismatch") request.node.add_marker(mark) + elif not IS64: + mark = pytest.mark.xfail(reason="results are int32, expected int64") + request.node.add_marker(mark) super().test_arith_frame_with_scalar(data, all_arithmetic_operators) From aa54b9011854f27ca117c0200bd6ce821ba00fa8 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 23 Jan 2021 13:07:35 -0800 Subject: [PATCH 3/4] troubleshoot 32bit/windows builds --- pandas/tests/extension/test_sparse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index bb8fe9a762230..81cb5c2cdddbd 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -16,7 +16,7 @@ import numpy as np import pytest -from pandas.compat import IS64 +from pandas.compat import is_platform_windows from pandas.errors import PerformanceWarning from pandas.core.dtypes.common import is_object_dtype @@ -416,7 +416,7 @@ def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): ]: mark = pytest.mark.xfail(reason="result dtype.fill_value mismatch") request.node.add_marker(mark) - elif not IS64: + elif is_platform_windows(): mark = pytest.mark.xfail(reason="results are int32, expected int64") request.node.add_marker(mark) super().test_arith_frame_with_scalar(data, all_arithmetic_operators) From ae5e9ba584cacf4b3284f3eb0e9f71fd701e2ab7 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 23 Jan 2021 16:08:16 -0800 Subject: [PATCH 4/4] troubleshoot windows and 32bit --- pandas/tests/extension/test_sparse.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index 81cb5c2cdddbd..b1027ea3f6881 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -16,7 +16,7 @@ import numpy as np import pytest -from pandas.compat import is_platform_windows +from pandas.compat import IS64, is_platform_windows from pandas.errors import PerformanceWarning from pandas.core.dtypes.common import is_object_dtype @@ -405,7 +405,9 @@ def test_arith_series_with_array(self, data, all_arithmetic_operators): super().test_arith_series_with_array(data, all_arithmetic_operators) def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): - if data.dtype.fill_value == 0 and all_arithmetic_operators.strip("_") not in [ + if data.dtype.fill_value != 0: + pass + elif all_arithmetic_operators.strip("_") not in [ "mul", "rmul", "floordiv", @@ -416,7 +418,7 @@ def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): ]: mark = pytest.mark.xfail(reason="result dtype.fill_value mismatch") request.node.add_marker(mark) - elif is_platform_windows(): + elif is_platform_windows() or not IS64: mark = pytest.mark.xfail(reason="results are int32, expected int64") request.node.add_marker(mark) super().test_arith_frame_with_scalar(data, all_arithmetic_operators)