From 0c9ad0067b7c68a5a688bc6961bb2be75c03a224 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Mon, 4 Feb 2019 15:08:33 +0000 Subject: [PATCH 1/8] revert changes to tests in gh-24993 --- pandas/tests/extension/numpy_/__init__.py | 0 pandas/tests/extension/numpy_/conftest.py | 38 --- .../extension/numpy_/test_numpy_nested.py | 286 ------------------ .../extension/{numpy_ => }/test_numpy.py | 36 ++- 4 files changed, 35 insertions(+), 325 deletions(-) delete mode 100644 pandas/tests/extension/numpy_/__init__.py delete mode 100644 pandas/tests/extension/numpy_/conftest.py delete mode 100644 pandas/tests/extension/numpy_/test_numpy_nested.py rename pandas/tests/extension/{numpy_ => }/test_numpy.py (84%) diff --git a/pandas/tests/extension/numpy_/__init__.py b/pandas/tests/extension/numpy_/__init__.py deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/pandas/tests/extension/numpy_/conftest.py b/pandas/tests/extension/numpy_/conftest.py deleted file mode 100644 index daa93571c2957..0000000000000 --- a/pandas/tests/extension/numpy_/conftest.py +++ /dev/null @@ -1,38 +0,0 @@ -import numpy as np -import pytest - -from pandas.core.arrays.numpy_ import PandasArray - - -@pytest.fixture -def allow_in_pandas(monkeypatch): - """ - A monkeypatch to tell pandas to let us in. - - By default, passing a PandasArray to an index / series / frame - constructor will unbox that PandasArray to an ndarray, and treat - it as a non-EA column. We don't want people using EAs without - reason. - - The mechanism for this is a check against ABCPandasArray - in each constructor. - - But, for testing, we need to allow them in pandas. So we patch - the _typ of PandasArray, so that we evade the ABCPandasArray - check. - """ - with monkeypatch.context() as m: - m.setattr(PandasArray, '_typ', 'extension') - yield - - -@pytest.fixture -def na_value(): - return np.nan - - -@pytest.fixture -def na_cmp(): - def cmp(a, b): - return np.isnan(a) and np.isnan(b) - return cmp diff --git a/pandas/tests/extension/numpy_/test_numpy_nested.py b/pandas/tests/extension/numpy_/test_numpy_nested.py deleted file mode 100644 index cf9b34dd08798..0000000000000 --- a/pandas/tests/extension/numpy_/test_numpy_nested.py +++ /dev/null @@ -1,286 +0,0 @@ -""" -Tests for PandasArray with nested data. Users typically won't create -these objects via `pd.array`, but they can show up through `.array` -on a Series with nested data. - -We partition these tests into their own file, as many of the base -tests fail, as they aren't appropriate for nested data. It is easier -to have a seperate file with its own data generating fixtures, than -trying to skip based upon the value of a fixture. -""" -import pytest - -import pandas as pd -from pandas.core.arrays.numpy_ import PandasArray, PandasDtype - -from .. import base - -# For NumPy <1.16, np.array([np.nan, (1,)]) raises -# ValueError: setting an array element with a sequence. -np = pytest.importorskip('numpy', minversion='1.16.0') - - -@pytest.fixture -def dtype(): - return PandasDtype(np.dtype('object')) - - -@pytest.fixture -def data(allow_in_pandas, dtype): - return pd.Series([(i,) for i in range(100)]).array - - -@pytest.fixture -def data_missing(allow_in_pandas): - return PandasArray(np.array([np.nan, (1,)])) - - -@pytest.fixture -def data_for_sorting(allow_in_pandas): - """Length-3 array with a known sort order. - - This should be three items [B, C, A] with - A < B < C - """ - # Use an empty tuple for first element, then remove, - # to disable np.array's shape inference. - return PandasArray( - np.array([(), (2,), (3,), (1,)])[1:] - ) - - -@pytest.fixture -def data_missing_for_sorting(allow_in_pandas): - """Length-3 array with a known sort order. - - This should be three items [B, NA, A] with - A < B and NA missing. - """ - return PandasArray( - np.array([(1,), np.nan, (0,)]) - ) - - -@pytest.fixture -def data_for_grouping(allow_in_pandas): - """Data for factorization, grouping, and unique tests. - - Expected to be like [B, B, NA, NA, A, A, B, C] - - Where A < B < C and NA is missing - """ - a, b, c = (1,), (2,), (3,) - return PandasArray(np.array( - [b, b, np.nan, np.nan, a, a, b, c] - )) - - -skip_nested = pytest.mark.skip(reason="Skipping for nested PandasArray") - - -class BaseNumPyTests(object): - pass - - -class TestCasting(BaseNumPyTests, base.BaseCastingTests): - - @skip_nested - def test_astype_str(self, data): - pass - - -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): - pass - - -class TestDtype(BaseNumPyTests, base.BaseDtypeTests): - - @pytest.mark.skip(reason="Incorrect expected.") - # we unsurprisingly clash with a NumPy name. - def test_check_dtype(self, data): - pass - - -class TestGetitem(BaseNumPyTests, base.BaseGetitemTests): - - @skip_nested - def test_getitem_scalar(self, data): - pass - - @skip_nested - def test_take_series(self, data): - pass - - -class TestGroupby(BaseNumPyTests, base.BaseGroupbyTests): - @skip_nested - def test_groupby_extension_apply(self, data_for_grouping, op): - pass - - -class TestInterface(BaseNumPyTests, base.BaseInterfaceTests): - @skip_nested - def test_array_interface(self, data): - # NumPy array shape inference - pass - - -class TestMethods(BaseNumPyTests, base.BaseMethodsTests): - - @pytest.mark.skip(reason="TODO: remove?") - def test_value_counts(self, all_data, dropna): - pass - - @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(TestMethods, self).test_combine_le(data_repeated) - - @skip_nested - def test_combine_add(self, data_repeated): - # Not numeric - pass - - @skip_nested - def test_shift_fill_value(self, data): - # np.array shape inference. Shift implementation fails. - super().test_shift_fill_value(data) - - @skip_nested - def test_unique(self, data, box, method): - # Fails creating expected - pass - - @skip_nested - def test_fillna_copy_frame(self, data_missing): - # The "scalar" for this array isn't a scalar. - pass - - @skip_nested - def test_fillna_copy_series(self, data_missing): - # The "scalar" for this array isn't a scalar. - pass - - @skip_nested - def test_hash_pandas_object_works(self, data, as_frame): - # ndarray of tuples not hashable - pass - - @skip_nested - def test_searchsorted(self, data_for_sorting, as_series): - # Test setup fails. - pass - - @skip_nested - def test_where_series(self, data, na_value, as_frame): - # Test setup fails. - pass - - @skip_nested - def test_repeat(self, data, repeats, as_series, use_numpy): - # Fails creating expected - pass - - -class TestPrinting(BaseNumPyTests, base.BasePrintingTests): - pass - - -class TestMissing(BaseNumPyTests, base.BaseMissingTests): - - @skip_nested - def test_fillna_scalar(self, data_missing): - # Non-scalar "scalar" values. - pass - - @skip_nested - def test_fillna_series_method(self, data_missing, method): - # Non-scalar "scalar" values. - pass - - @skip_nested - def test_fillna_series(self, data_missing): - # Non-scalar "scalar" values. - pass - - @skip_nested - def test_fillna_frame(self, data_missing): - # Non-scalar "scalar" values. - pass - - -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(TestReshaping, self).test_concat_mixed_dtypes(data) - - @skip_nested - def test_merge(self, data, na_value): - # Fails creating expected - pass - - @skip_nested - def test_merge_on_extension_array(self, data): - # Fails creating expected - pass - - @skip_nested - def test_merge_on_extension_array_duplicates(self, data): - # Fails creating expected - pass - - -class TestSetitem(BaseNumPyTests, base.BaseSetitemTests): - - @skip_nested - def test_setitem_scalar_series(self, data, box_in_series): - pass - - @skip_nested - def test_setitem_sequence(self, data, box_in_series): - pass - - @skip_nested - def test_setitem_sequence_mismatched_length_raises(self, data, as_array): - pass - - @skip_nested - def test_setitem_sequence_broadcasts(self, data, box_in_series): - pass - - @skip_nested - def test_setitem_loc_scalar_mixed(self, data): - pass - - @skip_nested - def test_setitem_loc_scalar_multiple_homogoneous(self, data): - pass - - @skip_nested - def test_setitem_iloc_scalar_mixed(self, data): - pass - - @skip_nested - def test_setitem_iloc_scalar_multiple_homogoneous(self, data): - pass - - @skip_nested - def test_setitem_mask_broadcast(self, data, setter): - pass - - @skip_nested - def test_setitem_scalar_key_sequence_raise(self, data): - pass - - -# Skip Arithmetics, NumericReduce, BooleanReduce, Parsing diff --git a/pandas/tests/extension/numpy_/test_numpy.py b/pandas/tests/extension/test_numpy.py similarity index 84% rename from pandas/tests/extension/numpy_/test_numpy.py rename to pandas/tests/extension/test_numpy.py index 4c93d5ee0b9d7..7ca6882c7441b 100644 --- a/pandas/tests/extension/numpy_/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -6,7 +6,7 @@ from pandas.core.arrays.numpy_ import PandasArray, PandasDtype import pandas.util.testing as tm -from .. import base +from . import base @pytest.fixture @@ -14,6 +14,28 @@ def dtype(): return PandasDtype(np.dtype('float')) +@pytest.fixture +def allow_in_pandas(monkeypatch): + """ + A monkeypatch to tells pandas to let us in. + + By default, passing a PandasArray to an index / series / frame + constructor will unbox that PandasArray to an ndarray, and treat + it as a non-EA column. We don't want people using EAs without + reason. + + The mechanism for this is a check against ABCPandasArray + in each constructor. + + But, for testing, we need to allow them in pandas. So we patch + the _typ of PandasArray, so that we evade the ABCPandasArray + check. + """ + with monkeypatch.context() as m: + m.setattr(PandasArray, '_typ', 'extension') + yield + + @pytest.fixture def data(allow_in_pandas, dtype): return PandasArray(np.arange(1, 101, dtype=dtype._dtype)) @@ -24,6 +46,18 @@ def data_missing(allow_in_pandas): return PandasArray(np.array([np.nan, 1.0])) +@pytest.fixture +def na_value(): + return np.nan + + +@pytest.fixture +def na_cmp(): + def cmp(a, b): + return np.isnan(a) and np.isnan(b) + return cmp + + @pytest.fixture def data_for_sorting(allow_in_pandas): """Length-3 array with a known sort order. From fb165a386bb78961c7e0c0aeadce409e979563e0 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Tue, 5 Feb 2019 09:53:24 +0000 Subject: [PATCH 2/8] Test nested PandasArray --- pandas/tests/extension/base/groupby.py | 17 +- pandas/tests/extension/base/methods.py | 6 - pandas/tests/extension/base/missing.py | 8 +- pandas/tests/extension/base/setitem.py | 1 - pandas/tests/extension/conftest.py | 38 ++++ pandas/tests/extension/test_numpy.py | 249 +++++++++++++++++++++++-- pandas/tests/extension/test_sparse.py | 3 +- 7 files changed, 280 insertions(+), 42 deletions(-) diff --git a/pandas/tests/extension/base/groupby.py b/pandas/tests/extension/base/groupby.py index dd406ca0cd5ed..1929dad075695 100644 --- a/pandas/tests/extension/base/groupby.py +++ b/pandas/tests/extension/base/groupby.py @@ -55,19 +55,14 @@ def test_groupby_extension_transform(self, data_for_grouping): self.assert_series_equal(result, expected) - @pytest.mark.parametrize('op', [ - lambda x: 1, - lambda x: [1] * len(x), - lambda x: pd.Series([1] * len(x)), - lambda x: x, - ], ids=['scalar', 'list', 'series', 'object']) - def test_groupby_extension_apply(self, data_for_grouping, op): + def test_groupby_extension_apply( + self, data_for_grouping, groupby_apply_op): df = pd.DataFrame({"A": [1, 1, 2, 2, 3, 3, 1, 4], "B": data_for_grouping}) - df.groupby("B").apply(op) - df.groupby("B").A.apply(op) - df.groupby("A").apply(op) - df.groupby("A").B.apply(op) + df.groupby("B").apply(groupby_apply_op) + df.groupby("B").A.apply(groupby_apply_op) + df.groupby("A").apply(groupby_apply_op) + df.groupby("A").B.apply(groupby_apply_op) def test_in_numeric_groupby(self, data_for_grouping): df = pd.DataFrame({"A": [1, 1, 2, 2, 3, 3, 1, 4], diff --git a/pandas/tests/extension/base/methods.py b/pandas/tests/extension/base/methods.py index f64df7a84b7c0..1852edaa9e748 100644 --- a/pandas/tests/extension/base/methods.py +++ b/pandas/tests/extension/base/methods.py @@ -240,7 +240,6 @@ def test_shift_fill_value(self, data): expected = data.take([2, 3, 0, 0]) self.assert_extension_array_equal(result, expected) - @pytest.mark.parametrize("as_frame", [True, False]) def test_hash_pandas_object_works(self, data, as_frame): # https://github.com/pandas-dev/pandas/issues/23066 data = pd.Series(data) @@ -250,7 +249,6 @@ def test_hash_pandas_object_works(self, data, as_frame): b = pd.util.hash_pandas_object(data) self.assert_equal(a, b) - @pytest.mark.parametrize("as_series", [True, False]) def test_searchsorted(self, data_for_sorting, as_series): b, c, a = data_for_sorting arr = type(data_for_sorting)._from_sequence([a, b, c]) @@ -275,7 +273,6 @@ def test_searchsorted(self, data_for_sorting, as_series): sorter = np.array([1, 2, 0]) assert data_for_sorting.searchsorted(a, sorter=sorter) == 0 - @pytest.mark.parametrize("as_frame", [True, False]) def test_where_series(self, data, na_value, as_frame): assert data[0] != data[1] cls = type(data) @@ -309,8 +306,6 @@ def test_where_series(self, data, na_value, as_frame): expected = expected.to_frame(name='a') self.assert_equal(result, expected) - @pytest.mark.parametrize("use_numpy", [True, False]) - @pytest.mark.parametrize("as_series", [True, False]) @pytest.mark.parametrize("repeats", [0, 1, 2, [1, 2, 3]]) def test_repeat(self, data, repeats, as_series, use_numpy): arr = type(data)._from_sequence(data[:3], dtype=data.dtype) @@ -327,7 +322,6 @@ def test_repeat(self, data, repeats, as_series, use_numpy): self.assert_equal(result, expected) - @pytest.mark.parametrize("use_numpy", [True, False]) @pytest.mark.parametrize('repeats, kwargs, error, msg', [ (2, dict(axis=1), ValueError, "'axis"), (-1, dict(), ValueError, "negative"), diff --git a/pandas/tests/extension/base/missing.py b/pandas/tests/extension/base/missing.py index 2fe547e50a34b..834f49f0461f0 100644 --- a/pandas/tests/extension/base/missing.py +++ b/pandas/tests/extension/base/missing.py @@ -1,5 +1,4 @@ import numpy as np -import pytest import pandas as pd import pandas.util.testing as tm @@ -89,14 +88,13 @@ def test_fillna_series(self, data_missing): result = ser.fillna(ser) self.assert_series_equal(result, ser) - @pytest.mark.parametrize('method', ['ffill', 'bfill']) - def test_fillna_series_method(self, data_missing, method): + def test_fillna_series_method(self, data_missing, fillna_method): fill_value = data_missing[1] - if method == 'ffill': + if fillna_method == 'ffill': data_missing = data_missing[::-1] - result = pd.Series(data_missing).fillna(method=method) + result = pd.Series(data_missing).fillna(method=fillna_method) expected = pd.Series(data_missing._from_sequence( [fill_value, fill_value], dtype=data_missing.dtype)) diff --git a/pandas/tests/extension/base/setitem.py b/pandas/tests/extension/base/setitem.py index 42fda982f7339..db6328e39e6cc 100644 --- a/pandas/tests/extension/base/setitem.py +++ b/pandas/tests/extension/base/setitem.py @@ -24,7 +24,6 @@ def test_setitem_sequence(self, data, box_in_series): assert data[0] == original[1] assert data[1] == original[0] - @pytest.mark.parametrize('as_array', [True, False]) def test_setitem_sequence_mismatched_length_raises(self, data, as_array): ser = pd.Series(data) original = ser.copy() diff --git a/pandas/tests/extension/conftest.py b/pandas/tests/extension/conftest.py index 5349dd919f2a2..ea4952e589804 100644 --- a/pandas/tests/extension/conftest.py +++ b/pandas/tests/extension/conftest.py @@ -2,6 +2,8 @@ import pytest +from pandas import Series + @pytest.fixture def dtype(): @@ -108,3 +110,39 @@ def data_for_grouping(): def box_in_series(request): """Whether to box the data in a Series""" return request.param + + +@pytest.fixture(params=[ + lambda x: 1, + lambda x: [1] * len(x), + lambda x: Series([1] * len(x)), + lambda x: x, +], ids=['scalar', 'list', 'series', 'object']) +def groupby_apply_op(request): + """functions to test groupby.apply()""" + return request.param + + +@pytest.fixture(params=[True, False]) +def as_frame(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def as_series(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def use_numpy(request): + return request.param + + +@pytest.fixture(params=['ffill', 'bfill']) +def fillna_method(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def as_array(request): + return request.param diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index 7ca6882c7441b..b5d93c0612cb6 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -9,9 +9,12 @@ from . import base -@pytest.fixture -def dtype(): - return PandasDtype(np.dtype('float')) +NP_VERSION_INFO = tuple(int(x) for x in np.__version__.split('.')) + + +@pytest.fixture(params=['float', 'object']) +def dtype(request): + return PandasDtype(np.dtype(request.param)) @pytest.fixture @@ -38,11 +41,19 @@ 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)) @pytest.fixture -def data_missing(allow_in_pandas): +def data_missing(allow_in_pandas, dtype): + # For NumPy <1.16, np.array([np.nan, (1,)]) raises + # ValueError: setting an array element with a sequence. + if dtype.numpy_dtype == 'object': + if NP_VERSION_INFO < (1, 16): + raise pytest.skip("Skipping for NumPy <1.16") + return PandasArray(np.array([np.nan, (1,)])) return PandasArray(np.array([np.nan, 1.0])) @@ -59,49 +70,84 @@ def cmp(a, b): @pytest.fixture -def data_for_sorting(allow_in_pandas): +def data_for_sorting(allow_in_pandas, dtype): """Length-3 array with a known sort order. This should be three items [B, C, A] with A < B < C """ + if dtype.numpy_dtype == 'object': + # Use an empty tuple for first element, then remove, + # to disable np.array's shape inference. + return PandasArray( + np.array([(), (2,), (3,), (1,)])[1:] + ) return PandasArray( np.array([1, 2, 0]) ) @pytest.fixture -def data_missing_for_sorting(allow_in_pandas): +def data_missing_for_sorting(allow_in_pandas, dtype): """Length-3 array with a known sort order. This should be three items [B, NA, A] with A < B and NA missing. """ + if dtype.numpy_dtype == 'object': + return PandasArray( + np.array([(1,), np.nan, (0,)]) + ) return PandasArray( np.array([1, np.nan, 0]) ) @pytest.fixture -def data_for_grouping(allow_in_pandas): +def data_for_grouping(allow_in_pandas, dtype): """Data for factorization, grouping, and unique tests. Expected to be like [B, B, NA, NA, A, A, B, C] Where A < B < C and NA is missing """ - a, b, c = np.arange(3) + if dtype.numpy_dtype == 'object': + a, b, c = (1,), (2,), (3,) + else: + a, b, c = np.arange(3) return PandasArray(np.array( [b, b, np.nan, np.nan, a, a, b, c] )) +@pytest.fixture +def skip_numpy_object(dtype): + """ + Tests for PandasArray with nested data. Users typically won't create + these objects via `pd.array`, but they can show up through `.array` + on a Series with nested data. Many of the base tests fail, as they aren't + appropriate for nested data. + + This fixture allows these tests to be skipped when used as a usefixtures + marker to either an individual test or a test class. + """ + if dtype == 'object': + raise pytest.skip("Skipping for object dtype.") + + +skip_nested = pytest.mark.usefixtures('skip_numpy_object') + + class BaseNumPyTests(object): pass class TestCasting(BaseNumPyTests, base.BaseCastingTests): - pass + + @skip_nested + def test_astype_str(self, data): + # ValueError: setting an array element with a sequence + super(TestCasting, self).test_astype_str(data) class TestConstructors(BaseNumPyTests, base.BaseConstructorsTests): @@ -110,6 +156,11 @@ class TestConstructors(BaseNumPyTests, base.BaseConstructorsTests): def test_from_dtype(self, data): pass + @skip_nested + def test_array_from_scalars(self, data): + # ValueError: PandasArray must be 1-dimensional. + super(TestConstructors, self).test_array_from_scalars(data) + class TestDtype(BaseNumPyTests, base.BaseDtypeTests): @@ -120,15 +171,32 @@ def test_check_dtype(self, data): class TestGetitem(BaseNumPyTests, base.BaseGetitemTests): - pass + + @skip_nested + def test_getitem_scalar(self, data): + # AssertionError + super(TestGetitem, self).test_getitem_scalar(data) + + @skip_nested + def test_take_series(self, data): + # ValueError: PandasArray must be 1-dimensional. + super(TestGetitem, self).test_take_series(data) class TestGroupby(BaseNumPyTests, base.BaseGroupbyTests): - pass + @skip_nested + def test_groupby_extension_apply( + self, data_for_grouping, groupby_apply_op): + # ValueError: Names should be list-like for a MultiIndex + super(TestGroupby, self).test_groupby_extension_apply( + data_for_grouping, groupby_apply_op) class TestInterface(BaseNumPyTests, base.BaseInterfaceTests): - pass + @skip_nested + def test_array_interface(self, data): + # NumPy array shape inference + super(TestInterface, self).test_array_interface(data) class TestMethods(BaseNumPyTests, base.BaseMethodsTests): @@ -143,7 +211,57 @@ def test_value_counts(self, all_data, dropna): def test_combine_le(self, data_repeated): super(TestMethods, self).test_combine_le(data_repeated) - + @skip_nested + def test_combine_add(self, data_repeated): + # Not numeric + super(TestMethods, self).test_combine_add(data_repeated) + + @skip_nested + def test_shift_fill_value(self, data): + # np.array shape inference. Shift implementation fails. + super(TestMethods, self).test_shift_fill_value(data) + + @skip_nested + @pytest.mark.parametrize('box', [pd.Series, lambda x: x]) + @pytest.mark.parametrize('method', [lambda x: x.unique(), pd.unique]) + def test_unique(self, data, box, method): + # Fails creating expected + super(TestMethods, self).test_unique(data, box, method) + + @skip_nested + def test_fillna_copy_frame(self, data_missing): + # The "scalar" for this array isn't a scalar. + super(TestMethods, self).test_fillna_copy_frame(data_missing) + + @skip_nested + def test_fillna_copy_series(self, data_missing): + # The "scalar" for this array isn't a scalar. + super(TestMethods, self).test_fillna_copy_series(data_missing) + + @skip_nested + def test_hash_pandas_object_works(self, data, as_frame): + # ndarray of tuples not hashable + super(TestMethods, self).test_hash_pandas_object_works(data, as_frame) + + @skip_nested + def test_searchsorted(self, data_for_sorting, as_series): + # Test setup fails. + super(TestMethods, self).test_searchsorted(data_for_sorting, as_series) + + @skip_nested + def test_where_series(self, data, na_value, as_frame): + # Test setup fails. + super(TestMethods, self).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 + super(TestMethods, self).test_repeat( + data, repeats, as_series, use_numpy) + + +@skip_nested class TestArithmetics(BaseNumPyTests, base.BaseArithmeticOpsTests): divmod_exc = None series_scalar_exc = None @@ -183,6 +301,7 @@ class TestPrinting(BaseNumPyTests, base.BasePrintingTests): pass +@skip_nested class TestNumericReduce(BaseNumPyTests, base.BaseNumericReduceTests): def check_reduce(self, s, op_name, skipna): @@ -192,12 +311,33 @@ def check_reduce(self, s, op_name, skipna): tm.assert_almost_equal(result, expected) +@skip_nested class TestBooleanReduce(BaseNumPyTests, base.BaseBooleanReduceTests): pass -class TestMising(BaseNumPyTests, base.BaseMissingTests): - pass +class TestMissing(BaseNumPyTests, base.BaseMissingTests): + + @skip_nested + def test_fillna_scalar(self, data_missing): + # Non-scalar "scalar" values. + super(TestMissing, self).test_fillna_scalar(data_missing) + + @skip_nested + def test_fillna_series_method(self, data_missing, fillna_method): + # Non-scalar "scalar" values. + super(TestMissing, self).test_fillna_series_method( + data_missing, fillna_method) + + @skip_nested + def test_fillna_series(self, data_missing): + # Non-scalar "scalar" values. + super(TestMissing, self).test_fillna_series(data_missing) + + @skip_nested + def test_fillna_frame(self, data_missing): + # Non-scalar "scalar" values. + super(TestMissing, self).test_fillna_frame(data_missing) class TestReshaping(BaseNumPyTests, base.BaseReshapingTests): @@ -207,10 +347,85 @@ class TestReshaping(BaseNumPyTests, base.BaseReshapingTests): def test_concat_mixed_dtypes(self, data): super(TestReshaping, self).test_concat_mixed_dtypes(data) + @skip_nested + def test_merge(self, data, na_value): + # Fails creating expected + super(TestReshaping, self).test_merge(data, na_value) -class TestSetitem(BaseNumPyTests, base.BaseSetitemTests): - pass + @skip_nested + def test_merge_on_extension_array(self, data): + # Fails creating expected + super(TestReshaping, self).test_merge_on_extension_array(data) + + @skip_nested + def test_merge_on_extension_array_duplicates(self, data): + # Fails creating expected + super(TestReshaping, self).test_merge_on_extension_array_duplicates( + data) +class TestSetitem(BaseNumPyTests, base.BaseSetitemTests): + + @skip_nested + def test_setitem_scalar_series(self, data, box_in_series): + # AssertionError + super(TestSetitem, self).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(TestSetitem, self).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(TestSetitem, self). + 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 + # length than the value + super(TestSetitem, self).test_setitem_sequence_broadcasts( + data, box_in_series) + + @skip_nested + def test_setitem_loc_scalar_mixed(self, data): + # AssertionError + super(TestSetitem, self).test_setitem_loc_scalar_mixed(data) + + @skip_nested + def test_setitem_loc_scalar_multiple_homogoneous(self, data): + # AssertionError + super(TestSetitem, self).test_setitem_loc_scalar_multiple_homogoneous( + data) + + @skip_nested + def test_setitem_iloc_scalar_mixed(self, data): + # AssertionError + super(TestSetitem, self).test_setitem_iloc_scalar_mixed(data) + + @skip_nested + def test_setitem_iloc_scalar_multiple_homogoneous(self, data): + # AssertionError + super(TestSetitem, self).test_setitem_iloc_scalar_multiple_homogoneous( + data) + + @skip_nested + @pytest.mark.parametrize('setter', ['loc', None]) + def test_setitem_mask_broadcast(self, data, setter): + # ValueError: cannot set using a list-like indexer with a different + # length than the value + super(TestSetitem, self).test_setitem_mask_broadcast(data, setter) + + @skip_nested + def test_setitem_scalar_key_sequence_raise(self, data): + # Failed: DID NOT RAISE + super(TestSetitem, self).test_setitem_scalar_key_sequence_raise(data) + + +@skip_nested class TestParsing(BaseNumPyTests, base.BaseParsingTests): pass diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index 21dbf9524961c..146dea2b65d83 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -287,11 +287,10 @@ def test_combine_first(self, data): pytest.skip("TODO(SparseArray.__setitem__ will preserve dtype.") super(TestMethods, self).test_combine_first(data) - @pytest.mark.parametrize("as_series", [True, False]) def test_searchsorted(self, data_for_sorting, as_series): with tm.assert_produces_warning(PerformanceWarning): super(TestMethods, self).test_searchsorted(data_for_sorting, - as_series=as_series) + as_series) class TestCasting(BaseSparseTests, base.BaseCastingTests): From 2845b11d6463178206878496309cd55efd49bdaa Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Tue, 5 Feb 2019 10:26:42 +0000 Subject: [PATCH 3/8] isort test_numpy.py --- pandas/tests/extension/test_numpy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index b5d93c0612cb6..abc02326235a5 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -8,7 +8,6 @@ from . import base - NP_VERSION_INFO = tuple(int(x) for x in np.__version__.split('.')) From 7de12e73d2c458a6f647d104f3e193c994c533c4 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Tue, 5 Feb 2019 10:38:18 +0000 Subject: [PATCH 4/8] change NP_VERSION_INFO --- pandas/tests/extension/test_numpy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index abc02326235a5..ba83a86591105 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -8,7 +8,7 @@ from . import base -NP_VERSION_INFO = tuple(int(x) for x in np.__version__.split('.')) +NP_VERSION_INFO = tuple(int(x) for x in np.__version__.split('.')[:2]) @pytest.fixture(params=['float', 'object']) From 50c2cc3ca2fa793d91675eb51549e300eecac6e3 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Tue, 5 Feb 2019 11:09:58 +0000 Subject: [PATCH 5/8] use LooseVersion --- pandas/tests/extension/test_numpy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index ba83a86591105..2bbab85f9a1b4 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -1,3 +1,5 @@ +from distutils.version import LooseVersion + import numpy as np import pytest @@ -8,8 +10,6 @@ from . import base -NP_VERSION_INFO = tuple(int(x) for x in np.__version__.split('.')[:2]) - @pytest.fixture(params=['float', 'object']) def dtype(request): @@ -50,7 +50,7 @@ def data_missing(allow_in_pandas, dtype): # For NumPy <1.16, np.array([np.nan, (1,)]) raises # ValueError: setting an array element with a sequence. if dtype.numpy_dtype == 'object': - if NP_VERSION_INFO < (1, 16): + if LooseVersion(np.__version__) < LooseVersion("1.16"): raise pytest.skip("Skipping for NumPy <1.16") return PandasArray(np.array([np.nan, (1,)])) return PandasArray(np.array([np.nan, 1.0])) From 92f692437f03b7c2d9fd651d059b1d09870b7439 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Tue, 5 Feb 2019 11:54:39 +0000 Subject: [PATCH 6/8] add _np_version_under1p16 --- pandas/compat/numpy/__init__.py | 5 +++-- pandas/tests/extension/test_numpy.py | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pandas/compat/numpy/__init__.py b/pandas/compat/numpy/__init__.py index 5e67cf2ee2837..8ceb782daab5c 100644 --- a/pandas/compat/numpy/__init__.py +++ b/pandas/compat/numpy/__init__.py @@ -12,7 +12,7 @@ _np_version_under1p13 = _nlv < LooseVersion('1.13') _np_version_under1p14 = _nlv < LooseVersion('1.14') _np_version_under1p15 = _nlv < LooseVersion('1.15') - +_np_version_under1p16 = _nlv < LooseVersion('1.16') if _nlv < '1.12': raise ImportError('this version of pandas is incompatible with ' @@ -64,5 +64,6 @@ def np_array_datetime64_compat(arr, *args, **kwargs): __all__ = ['np', '_np_version_under1p13', '_np_version_under1p14', - '_np_version_under1p15' + '_np_version_under1p15', + '_np_version_under1p16' ] diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index 2bbab85f9a1b4..41f5beb8c885d 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -1,8 +1,8 @@ -from distutils.version import LooseVersion - import numpy as np import pytest +from pandas.compat.numpy import _np_version_under1p16 + import pandas as pd from pandas import compat from pandas.core.arrays.numpy_ import PandasArray, PandasDtype @@ -50,7 +50,7 @@ def data_missing(allow_in_pandas, dtype): # For NumPy <1.16, np.array([np.nan, (1,)]) raises # ValueError: setting an array element with a sequence. if dtype.numpy_dtype == 'object': - if LooseVersion(np.__version__) < LooseVersion("1.16"): + if _np_version_under1p16: raise pytest.skip("Skipping for NumPy <1.16") return PandasArray(np.array([np.nan, (1,)])) return PandasArray(np.array([np.nan, 1.0])) From 5f0c757b43fb4051abb0367b2fcaabaf9165874d Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Wed, 6 Feb 2019 11:12:53 +0000 Subject: [PATCH 7/8] remove blank line from merge master --- pandas/compat/numpy/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/compat/numpy/__init__.py b/pandas/compat/numpy/__init__.py index 8ceb782daab5c..bc9af01a97467 100644 --- a/pandas/compat/numpy/__init__.py +++ b/pandas/compat/numpy/__init__.py @@ -14,6 +14,7 @@ _np_version_under1p15 = _nlv < LooseVersion('1.15') _np_version_under1p16 = _nlv < LooseVersion('1.16') + if _nlv < '1.12': raise ImportError('this version of pandas is incompatible with ' 'numpy < 1.12.0\n' From a83bd4676ae82009baafc271f61ef5570bf6ef32 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Wed, 6 Feb 2019 11:41:17 +0000 Subject: [PATCH 8/8] add doctstrings to fixtures --- pandas/tests/extension/conftest.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/pandas/tests/extension/conftest.py b/pandas/tests/extension/conftest.py index ea4952e589804..3cc2d313b09f5 100644 --- a/pandas/tests/extension/conftest.py +++ b/pandas/tests/extension/conftest.py @@ -119,30 +119,49 @@ def box_in_series(request): lambda x: x, ], ids=['scalar', 'list', 'series', 'object']) def groupby_apply_op(request): - """functions to test groupby.apply()""" + """ + Functions to test groupby.apply(). + """ return request.param @pytest.fixture(params=[True, False]) def as_frame(request): + """ + Boolean fixture to support Series and Series.to_frame() comparison testing. + """ return request.param @pytest.fixture(params=[True, False]) def as_series(request): + """ + Boolean fixture to support arr and Series(arr) comparison testing. + """ return request.param @pytest.fixture(params=[True, False]) def use_numpy(request): + """ + Boolean fixture to support comparison testing of ExtensionDtype array + and numpy array. + """ return request.param @pytest.fixture(params=['ffill', 'bfill']) def fillna_method(request): + """ + Parametrized fixture giving method parameters 'ffill' and 'bfill' for + Series.fillna(method=) testing. + """ return request.param @pytest.fixture(params=[True, False]) def as_array(request): + """ + Boolean fixture to support ExtensionDtype _from_sequence method testing. + """ return request.param