Skip to content

TST: tighten PandasArray tests #39370

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 2 commits into from
Jan 24, 2021
Merged
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
108 changes: 45 additions & 63 deletions pandas/tests/extension/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import numpy as np
import pytest

from pandas.core.dtypes.dtypes import ExtensionDtype

import pandas as pd
import pandas._testing as tm
from pandas.core.arrays.numpy_ import PandasArray, PandasDtype
Expand Down Expand Up @@ -121,7 +123,7 @@ def data_for_grouping(allow_in_pandas, dtype):


@pytest.fixture
def skip_numpy_object(dtype):
def skip_numpy_object(dtype, request):
"""
Tests for PandasArray with nested data. Users typically won't create
these objects via `pd.array`, but they can show up through `.array`
Expand All @@ -132,14 +134,25 @@ def skip_numpy_object(dtype):
marker to either an individual test or a test class.
"""
if dtype == "object":
raise pytest.skip("Skipping for object dtype.")
mark = pytest.mark.xfail(reason="Fails for object dtype")
request.node.add_marker(mark)


skip_nested = pytest.mark.usefixtures("skip_numpy_object")


class BaseNumPyTests:
pass
@classmethod
def assert_series_equal(cls, left, right, *args, **kwargs):
# base class tests hard-code expected values with numpy dtypes,
# whereas we generally want the corresponding PandasDtype
if (
isinstance(right, pd.Series)
and not isinstance(right.dtype, ExtensionDtype)
and isinstance(left.dtype, PandasDtype)
):
right = right.astype(PandasDtype(right.dtype))
return tm.assert_series_equal(left, right, *args, **kwargs)


class TestCasting(BaseNumPyTests, base.BaseCastingTests):
Expand All @@ -148,24 +161,13 @@ def test_astype_str(self, data):
# ValueError: setting an array element with a sequence
super().test_astype_str(data)

@skip_nested
def test_astype_string(self, data):
# GH-33465
# ValueError: setting an array element with a sequence
super().test_astype_string(data)


class TestConstructors(BaseNumPyTests, base.BaseConstructorsTests):
@pytest.mark.skip(reason="We don't register our dtype")
# We don't want to register. This test should probably be split in two.
def test_from_dtype(self, data):
pass

@skip_nested
def test_array_from_scalars(self, data):
# ValueError: PandasArray must be 1-dimensional.
super().test_array_from_scalars(data)

@skip_nested
def test_series_constructor_scalar_with_index(self, data, dtype):
# ValueError: Length of passed values is 1, index implies 3.
Expand Down Expand Up @@ -202,10 +204,16 @@ def test_loc_iloc_frame_single_dtype(self, data, request):


class TestGroupby(BaseNumPyTests, base.BaseGroupbyTests):
@skip_nested
def test_groupby_extension_apply(
self, data_for_grouping, groupby_apply_op, request
):
dummy = groupby_apply_op([None])
if (
isinstance(dummy, pd.Series)
and data_for_grouping.dtype.numpy_dtype == object
):
mark = pytest.mark.xfail(reason="raises in MultiIndex construction")
request.node.add_marker(mark)
super().test_groupby_extension_apply(data_for_grouping, groupby_apply_op)


Expand All @@ -225,17 +233,6 @@ def test_value_counts(self, all_data, dropna):
def test_value_counts_with_normalize(self, data):
return super().test_value_counts_with_normalize(data)

@pytest.mark.skip(reason="Incorrect expected")
# We have a bool dtype, so the result is an ExtensionArray
# but expected is not
def test_combine_le(self, data_repeated):
super().test_combine_le(data_repeated)

@skip_nested
def test_combine_add(self, data_repeated):
# Not numeric
super().test_combine_add(data_repeated)

@skip_nested
def test_shift_fill_value(self, data):
# np.array shape inference. Shift implementation fails.
Expand All @@ -258,11 +255,6 @@ def test_fillna_copy_series(self, data_missing):
# The "scalar" for this array isn't a scalar.
super().test_fillna_copy_series(data_missing)

@skip_nested
def test_hash_pandas_object_works(self, data, as_frame):
# ndarray of tuples not hashable
super().test_hash_pandas_object_works(data, as_frame)

@skip_nested
def test_searchsorted(self, data_for_sorting, as_series):
# Test setup fails.
Expand All @@ -273,41 +265,51 @@ def test_where_series(self, data, na_value, as_frame):
# Test setup fails.
super().test_where_series(data, na_value, as_frame)

@skip_nested
@pytest.mark.parametrize("repeats", [0, 1, 2, [1, 2, 3]])
def test_repeat(self, data, repeats, as_series, use_numpy):
# Fails creating expected
def test_repeat(self, data, repeats, as_series, use_numpy, request):
if data.dtype.numpy_dtype == object and repeats != 0:
mark = pytest.mark.xfail(reason="mask shapes mismatch")
request.node.add_marker(mark)
super().test_repeat(data, repeats, as_series, use_numpy)

@pytest.mark.xfail(reason="PandasArray.diff may fail on dtype")
def test_diff(self, data, periods):
return super().test_diff(data, periods)

@skip_nested
@pytest.mark.parametrize("box", [pd.array, pd.Series, pd.DataFrame])
def test_equals(self, data, na_value, as_series, box):
def test_equals(self, data, na_value, as_series, box, request):
# Fails creating with _from_sequence
if box is pd.DataFrame and data.dtype.numpy_dtype == object:
mark = pytest.mark.xfail(reason="AssertionError in _get_same_shape_values")
request.node.add_marker(mark)

super().test_equals(data, na_value, as_series, box)


@skip_nested
class TestArithmetics(BaseNumPyTests, base.BaseArithmeticOpsTests):
divmod_exc = None
series_scalar_exc = None
frame_scalar_exc = None
series_array_exc = None

@skip_nested
def test_divmod(self, data):
super().test_divmod(data)

@skip_nested
def test_divmod_series_array(self, data):
s = pd.Series(data)
self._check_divmod_op(s, divmod, data, exc=None)
ser = pd.Series(data)
self._check_divmod_op(ser, divmod, data, exc=None)

@pytest.mark.skip("We implement ops")
def test_error(self, data, all_arithmetic_operators):
pass

@skip_nested
def test_arith_series_with_scalar(self, data, all_arithmetic_operators):
super().test_arith_series_with_scalar(data, all_arithmetic_operators)

@skip_nested
def test_arith_series_with_array(self, data, all_arithmetic_operators):
super().test_arith_series_with_array(data, all_arithmetic_operators)

Expand All @@ -316,14 +318,17 @@ class TestPrinting(BaseNumPyTests, base.BasePrintingTests):
pass


@skip_nested
class TestNumericReduce(BaseNumPyTests, base.BaseNumericReduceTests):
def check_reduce(self, s, op_name, skipna):
result = getattr(s, op_name)(skipna=skipna)
# avoid coercing int -> float. Just cast to the actual numpy type.
expected = getattr(s.astype(s.dtype._dtype), op_name)(skipna=skipna)
tm.assert_almost_equal(result, expected)

@pytest.mark.parametrize("skipna", [True, False])
def test_reduce_series(self, data, all_boolean_reductions, skipna):
super().test_reduce_series(data, all_boolean_reductions, skipna)


@skip_nested
class TestBooleanReduce(BaseNumPyTests, base.BaseBooleanReduceTests):
Expand Down Expand Up @@ -364,11 +369,6 @@ def test_fillna_fill_other(self, data_missing):


class TestReshaping(BaseNumPyTests, base.BaseReshapingTests):
@pytest.mark.skip("Incorrect parent test")
# not actually a mixed concat, since we concat int and int.
def test_concat_mixed_dtypes(self, data):
super().test_concat_mixed_dtypes(data)

@skip_nested
def test_merge(self, data, na_value):
# Fails creating expected
Expand All @@ -390,22 +390,6 @@ def test_transpose_frame(self, data):


class TestSetitem(BaseNumPyTests, base.BaseSetitemTests):
@skip_nested
def test_setitem_scalar_series(self, data, box_in_series):
# AssertionError
super().test_setitem_scalar_series(data, box_in_series)

@skip_nested
def test_setitem_sequence(self, data, box_in_series):
# ValueError: shape mismatch: value array of shape (2,1) could not
# be broadcast to indexing result of shape (2,)
super().test_setitem_sequence(data, box_in_series)

@skip_nested
def test_setitem_sequence_mismatched_length_raises(self, data, as_array):
# ValueError: PandasArray must be 1-dimensional.
super().test_setitem_sequence_mismatched_length_raises(data, as_array)

@skip_nested
def test_setitem_sequence_broadcasts(self, data, box_in_series):
# ValueError: cannot set using a list-like indexer with a different
Expand Down Expand Up @@ -459,7 +443,6 @@ def test_setitem_scalar_key_sequence_raise(self, data):
def test_setitem_mask(self, data, mask, box_in_series):
super().test_setitem_mask(data, mask, box_in_series)

@skip_nested
def test_setitem_mask_raises(self, data, box_in_series):
super().test_setitem_mask_raises(data, box_in_series)

Expand All @@ -472,7 +455,6 @@ def test_setitem_mask_raises(self, data, box_in_series):
def test_setitem_integer_array(self, data, idx, box_in_series):
super().test_setitem_integer_array(data, idx, box_in_series)

@skip_nested
@pytest.mark.parametrize(
"idx, box_in_series",
[
Expand Down