Skip to content

TST: fix xfailed tests for IntegerArray, FloatingArray #39350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pandas/_testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions pandas/_testing/compat.py
Original file line number Diff line number Diff line change
@@ -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
21 changes: 12 additions & 9 deletions pandas/tests/extension/base/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions pandas/tests/extension/json/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"):
Expand Down
9 changes: 5 additions & 4 deletions pandas/tests/extension/test_floating.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,23 @@ 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)
and is_float_dtype(other.dtype)
):
# 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)
Expand Down
15 changes: 8 additions & 7 deletions pandas/tests/extension/test_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand All @@ -122,29 +123,29 @@ 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):
# TODO pow on Int arrays gives different result with NA
# 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)
Expand Down
20 changes: 20 additions & 0 deletions pandas/tests/extension/test_sparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import numpy as np
import pytest

from pandas.compat import IS64, is_platform_windows
from pandas.errors import PerformanceWarning

from pandas.core.dtypes.common import is_object_dtype
Expand Down Expand Up @@ -403,6 +404,25 @@ 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:
pass
elif 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)
elif is_platform_windows() or not IS64:
mark = pytest.mark.xfail(reason="results are int32, expected int64")
request.node.add_marker(mark)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is interesting why is this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

havent been able to track it down

super().test_arith_frame_with_scalar(data, all_arithmetic_operators)


class TestComparisonOps(BaseSparseTests, base.BaseComparisonOpsTests):
def _compare_other(self, s, data, op_name, other):
Expand Down