Skip to content

Test nested PandasArray #24993

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 13 commits into from
Jan 30, 2019
2 changes: 1 addition & 1 deletion pandas/core/arrays/numpy_.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def __getitem__(self, item):
item = item._ndarray

result = self._ndarray[item]
if not lib.is_scalar(result):
if not lib.is_scalar(item):
result = type(self)(result)
return result

Expand Down
Empty file.
53 changes: 53 additions & 0 deletions pandas/tests/extension/numpy_/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import pytest

# A set of Base EA tests that are know to not work for
# the object-dtype PandasArray holding nested data.
skips = {
'BaseCastingTests.test_astype_str',
'BaseConstructorsTests.test_array_from_scalars',
# tuple isn't instance of np.object
'BaseGetitemTests.test_getitem_scalar',
# Can't pass tuples to _from_sequence
'BaseGetitemTests.test_take_series',
# np.array shape inference
'BaseInterfaceTests.test_array_interface',
# Can't construct expected.
'BaseMethodsTests.test_unique',
'BaseMethodsTests.test_combine_add',
'BaseMethodsTests.test_shift_fill_value',
'BaseMethodsTests.test_where_series',
'BaseMethodsTests.test_repeat',
# Can't hash ndarray[tuple]
'BaseMethodsTests.test_hash_pandas_object_works',
# Can't construct expected.
'BaseReshapingTests.test_merge',
'BaseReshapingTests.test_merge_on_extension_array',
'BaseReshapingTests.test_merge_on_extension_array_duplicates',

# ndarray setting
'BaseSetitemTests.test_setitem_scalar_series',
'BaseSetitemTests.test_setitem_sequence',
'BaseSetitemTests.test_setitem_sequence_mismatched_length_raises',
'BaseSetitemTests.test_setitem_sequence_broadcasts',
'BaseSetitemTests.test_setitem_sequence_broadcasts',
'BaseSetitemTests.test_setitem_loc_scalar_mixed',
'BaseSetitemTests.test_setitem_iloc_scalar_mixed',
'BaseSetitemTests.test_setitem_loc_scalar_multiple_homogoneous',
'BaseSetitemTests.test_setitem_iloc_scalar_multiple_homogoneous',
'BaseSetitemTests.test_setitem_mask_broadcast',
'BaseSetitemTests.test_setitem_scalar_key_sequence_raise',

'BaseParsingTests.test_EA_types',
}


def pytest_collection_modifyitems(config, items):
skip = pytest.mark.skip(reason="Skipping this because ...")
for item in items:
# TODO: See if pytest has a better way to resolve the *value*
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd be eager to hear of a better way to do this. Right now, we rely on the name being like TestMethods::test_where_series[object-True] do determine if we should skip. Not the cleanest. Ideally we would be able to resolve that to the actual value, but pytest may not have that yet.

Copy link
Contributor

Choose a reason for hiding this comment

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

@simonjayhawkins any thoughts here

Copy link
Contributor

Choose a reason for hiding this comment

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

@TomAugspurger why don't you just add a marker to specific tests? (and skip on that)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not aware of a way for a test marker to get access to the value of another fixture.

Copy link
Member

Choose a reason for hiding this comment

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

Ideally we would be able to resolve that to the actual value, but pytest may not have that yet.

IIUC, from a test or fixture you get the value supplied to the fixture by including that (used by) fixture in the function signature. seems to work...

https://github.com/simonjayhawkins/pandas/blob/6ebf2c52d8925663a9242d3c58a069000b2c3f06/pandas/tests/io/formats/conftest.py#L141-L146

that would mean changing all the tests individually though. so this may not be what your after.

# supplied to a fixture. Right now .keywords gets things
# like 'object' or 'data-object'.
parts = item.name.split("[")
if (len(parts) > 1 and 'object' in item.name.split('[')[1]
and item.obj.__qualname__ in skips):
item.add_marker(skip)
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from pandas.core.arrays.numpy_ import PandasArray, PandasDtype
import pandas.util.testing as tm

from . import base
from .. import base


@pytest.fixture
def dtype():
return PandasDtype(np.dtype('float'))
@pytest.fixture(params=['float', 'object'])
def dtype(request):
return PandasDtype(np.dtype(request.param))


@pytest.fixture
Expand All @@ -38,6 +38,8 @@ def allow_in_pandas(monkeypatch):

@pytest.fixture
def data(allow_in_pandas, dtype):
if dtype.numpy_dtype == 'object':
return pd.Series([(i,) for i in range(100)]).array
return PandasArray(np.arange(1, 101, dtype=dtype._dtype))


Expand Down Expand Up @@ -150,6 +152,19 @@ class TestArithmetics(BaseNumPyTests, base.BaseArithmeticOpsTests):
frame_scalar_exc = None
series_array_exc = None

def _check_op(self, s, op, other, op_name, exc=NotImplementedError):
if s.dtype == 'object':
raise pytest.skip("Skipping for object dtype.")
super(TestArithmetics, self)._check_op(s, op, other, op_name, exc)

def _check_divmod_op(self, s, op, other, exc=Exception):
if isinstance(s, pd.Series) and s.dtype == 'object':
raise pytest.skip("Skipping for object dtype.")
elif isinstance(other, pd.Series) and other.dtype == 'object':
raise pytest.skip("Skipping for object dtype.")

super(TestArithmetics, self)._check_divmod_op(s, op, other, exc)

def test_divmod_series_array(self, data):
s = pd.Series(data)
self._check_divmod_op(s, divmod, data, exc=None)
Expand Down Expand Up @@ -186,17 +201,24 @@ class TestPrinting(BaseNumPyTests, base.BasePrintingTests):
class TestNumericReduce(BaseNumPyTests, base.BaseNumericReduceTests):

def check_reduce(self, s, op_name, skipna):
if s.dtype == 'object':
raise pytest.skip("Skipping for object dtype.")
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)


class TestBooleanReduce(BaseNumPyTests, base.BaseBooleanReduceTests):
pass

def check_reduce(self, s, op_name, skipna):
if s.dtype == 'object':
raise pytest.skip("Skipping for object dtype.")

super(TestBooleanReduce, self).check_reduce(s, op_name, skipna)


class TestMising(BaseNumPyTests, base.BaseMissingTests):
class TestMissing(BaseNumPyTests, base.BaseMissingTests):
pass


Expand Down