From 01f9cbfd0d424adf19d5acb2cc535d4a4eefc074 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 19 Nov 2019 15:16:54 -0800 Subject: [PATCH 1/6] DEPR: remove Index.summary, fastpath kwarg --- doc/source/whatsnew/v1.0.0.rst | 2 ++ pandas/core/indexes/base.py | 32 +------------------------ pandas/core/indexes/category.py | 12 ---------- pandas/core/indexes/numeric.py | 13 +---------- pandas/core/indexes/range.py | 19 +-------------- pandas/tests/indexes/test_base.py | 39 +++++++------------------------ 6 files changed, 14 insertions(+), 103 deletions(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index 98d861d999ea9..67104c0618ce0 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -269,6 +269,8 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more. **Other removals** +- Removed the previously deprecated :meth:`Index.summary` (:issue:`18217`) +- Removed the previously deprecated "fastpath" keyword from the :class:`Index` constructor (:issue:`23110`) - Removed the previously deprecated :meth:`Series.get_value`, :meth:`Series.set_value`, :meth:`DataFrame.get_value`, :meth:`DataFrame.set_value` (:issue:`17739`) - Changed the the default value of `inplace` in :meth:`DataFrame.set_index` and :meth:`Series.set_axis`. It now defaults to False (:issue:`27600`) - :meth:`pandas.Series.str.cat` now defaults to aligning ``others``, using ``join='left'`` (:issue:`27611`) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 8978a09825ee9..9bd11c3079990 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -259,14 +259,7 @@ def _outer_indexer(self, left, right): # Constructors def __new__( - cls, - data=None, - dtype=None, - copy=False, - name=None, - fastpath=None, - tupleize_cols=True, - **kwargs, + cls, data=None, dtype=None, copy=False, name=None, tupleize_cols=True, **kwargs, ) -> "Index": from .range import RangeIndex @@ -278,16 +271,6 @@ def __new__( if name is None and hasattr(data, "name"): name = data.name - if fastpath is not None: - warnings.warn( - "The 'fastpath' keyword is deprecated, and will be " - "removed in a future version.", - FutureWarning, - stacklevel=2, - ) - if fastpath: - return cls._simple_new(data, name) - if isinstance(data, ABCPandasArray): # ensure users don't accidentally put a PandasArray in an index. data = data.to_numpy() @@ -1132,19 +1115,6 @@ def _summary(self, name=None): name = type(self).__name__ return f"{name}: {len(self)} entries{index_summary}" - def summary(self, name=None): - """ - Return a summarized representation. - - .. deprecated:: 0.23.0 - """ - warnings.warn( - "'summary' is deprecated and will be removed in a future version.", - FutureWarning, - stacklevel=2, - ) - return self._summary(name) - # -------------------------------------------------------------------- # Conversion Methods diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index e0ffc726bc3a1..d061f61effff3 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -1,6 +1,5 @@ import operator from typing import Any -import warnings import numpy as np @@ -172,19 +171,8 @@ def __new__( dtype=None, copy=False, name=None, - fastpath=None, ): - if fastpath is not None: - warnings.warn( - "The 'fastpath' keyword is deprecated, and will be " - "removed in a future version.", - FutureWarning, - stacklevel=2, - ) - if fastpath: - return cls._simple_new(data, name=name, dtype=dtype) - dtype = CategoricalDtype._from_values_or_dtype(data, categories, ordered, dtype) if name is None and hasattr(data, "name"): diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 29f56259dac79..b30d8c732fbef 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -1,5 +1,3 @@ -import warnings - import numpy as np from pandas._libs import index as libindex @@ -47,17 +45,8 @@ class NumericIndex(Index): _is_numeric_dtype = True - def __new__(cls, data=None, dtype=None, copy=False, name=None, fastpath=None): + def __new__(cls, data=None, dtype=None, copy=False, name=None): cls._validate_dtype(dtype) - if fastpath is not None: - warnings.warn( - "The 'fastpath' keyword is deprecated, and will be " - "removed in a future version.", - FutureWarning, - stacklevel=2, - ) - if fastpath: - return cls._simple_new(data, name=name) # Coerce to ndarray if not already ndarray or Index if not isinstance(data, (np.ndarray, Index)): diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 6f677848b1c79..79f6a5eea4643 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -81,26 +81,9 @@ class RangeIndex(Int64Index): # Constructors def __new__( - cls, - start=None, - stop=None, - step=None, - dtype=None, - copy=False, - name=None, - fastpath=None, + cls, start=None, stop=None, step=None, dtype=None, copy=False, name=None, ): - if fastpath is not None: - warnings.warn( - "The 'fastpath' keyword is deprecated, and will be " - "removed in a future version.", - FutureWarning, - stacklevel=2, - ) - if fastpath: - return cls._simple_new(range(start, stop, step), name=name) - cls._validate_dtype(dtype) # RangeIndex diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index 5bfa13c0865f1..9ef2c17bd88dd 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -1385,13 +1385,6 @@ def test_summary_bug(self): assert "~:{range}:0" in result assert "{other}%s" in result - # GH18217 - def test_summary_deprecated(self): - ind = Index(["{other}%s", "~:{range}:0"], name="A") - - with tm.assert_produces_warning(FutureWarning): - ind.summary() - def test_format(self, indices): self._check_method_works(Index.format, indices) @@ -2769,32 +2762,18 @@ def test_index_subclass_constructor_wrong_kwargs(index_maker): def test_deprecated_fastpath(): + msg = "[Uu]nexpected keyword argument" + with pytest.raises(TypeError, match=msg): + pd.Index(np.array(["a", "b"], dtype=object), name="test", fastpath=True) - with tm.assert_produces_warning(FutureWarning): - idx = pd.Index(np.array(["a", "b"], dtype=object), name="test", fastpath=True) - - expected = pd.Index(["a", "b"], name="test") - tm.assert_index_equal(idx, expected) - - with tm.assert_produces_warning(FutureWarning): - idx = pd.Int64Index( - np.array([1, 2, 3], dtype="int64"), name="test", fastpath=True - ) - - expected = pd.Index([1, 2, 3], name="test", dtype="int64") - tm.assert_index_equal(idx, expected) - - with tm.assert_produces_warning(FutureWarning): - idx = pd.RangeIndex(0, 5, 2, name="test", fastpath=True) - - expected = pd.RangeIndex(0, 5, 2, name="test") - tm.assert_index_equal(idx, expected) + with pytest.raises(TypeError, match=msg): + pd.Int64Index(np.array([1, 2, 3], dtype="int64"), name="test", fastpath=True) - with tm.assert_produces_warning(FutureWarning): - idx = pd.CategoricalIndex(["a", "b", "c"], name="test", fastpath=True) + with pytest.raises(TypeError, match=msg): + pd.RangeIndex(0, 5, 2, name="test", fastpath=True) - expected = pd.CategoricalIndex(["a", "b", "c"], name="test") - tm.assert_index_equal(idx, expected) + with pytest.raises(TypeError, match=msg): + pd.CategoricalIndex(["a", "b", "c"], name="test", fastpath=True) def test_shape_of_invalid_index(): From c258a770b90a8460f673ba509c2149f17151cbf6 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 24 Nov 2019 13:18:19 -0800 Subject: [PATCH 2/6] TST: index_or_series fixture --- pandas/conftest.py | 13 ++++++ pandas/tests/arrays/test_array.py | 5 ++- pandas/tests/dtypes/test_concat.py | 7 ++- pandas/tests/indexing/test_coercion.py | 28 ++++++------ .../tests/io/json/test_json_table_schema.py | 8 ++-- pandas/tests/test_base.py | 34 +++++++------- pandas/tests/test_strings.py | 44 +++++++++++-------- 7 files changed, 81 insertions(+), 58 deletions(-) diff --git a/pandas/conftest.py b/pandas/conftest.py index b032e14d8f7e1..cfd1ee6a301c7 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -854,3 +854,16 @@ def float_frame(): [30 rows x 4 columns] """ return DataFrame(tm.getSeriesData()) + + +@pytest.fixure(params=[pd.Index, pd.Series]) +def index_or_series(request): + """ + Fixture to parametrize over Index and Series, made necessary by a mypy + bug, giving an error: + + List item 0 has incompatible type "Type[Series]"; expected "Type[PandasObject]" + + See GH#????? + """ + return request.param diff --git a/pandas/tests/arrays/test_array.py b/pandas/tests/arrays/test_array.py index e8d9ecfac61e4..6f443f1841dcc 100644 --- a/pandas/tests/arrays/test_array.py +++ b/pandas/tests/arrays/test_array.py @@ -272,8 +272,9 @@ def _from_sequence(cls, scalars, dtype=None, copy=False): return super()._from_sequence(scalars, dtype=dtype, copy=copy) -@pytest.mark.parametrize("box", [pd.Series, pd.Index]) -def test_array_unboxes(box): +def test_array_unboxes(index_or_series): + box = index_or_series + data = box([decimal.Decimal("1"), decimal.Decimal("2")]) # make sure it works with pytest.raises(TypeError): diff --git a/pandas/tests/dtypes/test_concat.py b/pandas/tests/dtypes/test_concat.py index 0ca2f7c976535..02daa185b1cdb 100644 --- a/pandas/tests/dtypes/test_concat.py +++ b/pandas/tests/dtypes/test_concat.py @@ -2,7 +2,7 @@ import pandas.core.dtypes.concat as _concat -from pandas import DatetimeIndex, Index, Period, PeriodIndex, Series, TimedeltaIndex +from pandas import DatetimeIndex, Period, PeriodIndex, Series, TimedeltaIndex @pytest.mark.parametrize( @@ -40,9 +40,8 @@ ), ], ) -@pytest.mark.parametrize("klass", [Index, Series]) -def test_get_dtype_kinds(klass, to_concat, expected): - to_concat_klass = [klass(c) for c in to_concat] +def test_get_dtype_kinds(index_or_series, to_concat, expected): + to_concat_klass = [index_or_series(c) for c in to_concat] result = _concat.get_dtype_kinds(to_concat_klass) assert result == set(expected) diff --git a/pandas/tests/indexing/test_coercion.py b/pandas/tests/indexing/test_coercion.py index 8b29cf3813d13..e3ad3f733a302 100644 --- a/pandas/tests/indexing/test_coercion.py +++ b/pandas/tests/indexing/test_coercion.py @@ -513,12 +513,12 @@ def _assert_where_conversion( res = target.where(cond, values) self._assert(res, expected, expected_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val,exp_dtype", [(1, np.object), (1.1, np.object), (1 + 1j, np.object), (True, np.object)], ) - def test_where_object(self, klass, fill_val, exp_dtype): + def test_where_object(self, index_or_series, fill_val, exp_dtype): + klass = index_or_series obj = klass(list("abcd")) assert obj.dtype == np.object cond = klass([True, False, True, False]) @@ -539,12 +539,12 @@ def test_where_object(self, klass, fill_val, exp_dtype): exp = klass(["a", values[1], "c", values[3]]) self._assert_where_conversion(obj, cond, values, exp, exp_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val,exp_dtype", [(1, np.int64), (1.1, np.float64), (1 + 1j, np.complex128), (True, np.object)], ) - def test_where_int64(self, klass, fill_val, exp_dtype): + def test_where_int64(self, index_or_series, fill_val, exp_dtype): + klass = index_or_series if klass is pd.Index and exp_dtype is np.complex128: pytest.skip("Complex Index not supported") obj = klass([1, 2, 3, 4]) @@ -561,7 +561,6 @@ def test_where_int64(self, klass, fill_val, exp_dtype): exp = klass([1, values[1], 3, values[3]]) self._assert_where_conversion(obj, cond, values, exp, exp_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val, exp_dtype", [ @@ -571,7 +570,8 @@ def test_where_int64(self, klass, fill_val, exp_dtype): (True, np.object), ], ) - def test_where_float64(self, klass, fill_val, exp_dtype): + def test_where_float64(self, index_or_series, fill_val, exp_dtype): + klass = index_or_series if klass is pd.Index and exp_dtype is np.complex128: pytest.skip("Complex Index not supported") obj = klass([1.1, 2.2, 3.3, 4.4]) @@ -781,19 +781,18 @@ def _assert_fillna_conversion(self, original, value, expected, expected_dtype): res = target.fillna(value) self._assert(res, expected, expected_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val, fill_dtype", [(1, np.object), (1.1, np.object), (1 + 1j, np.object), (True, np.object)], ) - def test_fillna_object(self, klass, fill_val, fill_dtype): + def test_fillna_object(self, index_or_series, fill_val, fill_dtype): + klass = index_or_series obj = klass(["a", np.nan, "c", "d"]) assert obj.dtype == np.object exp = klass(["a", fill_val, "c", "d"]) self._assert_fillna_conversion(obj, fill_val, exp, fill_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val,fill_dtype", [ @@ -803,7 +802,8 @@ def test_fillna_object(self, klass, fill_val, fill_dtype): (True, np.object), ], ) - def test_fillna_float64(self, klass, fill_val, fill_dtype): + def test_fillna_float64(self, index_or_series, fill_val, fill_dtype): + klass = index_or_series obj = klass([1.1, np.nan, 3.3, 4.4]) assert obj.dtype == np.float64 @@ -831,7 +831,6 @@ def test_fillna_series_complex128(self, fill_val, fill_dtype): exp = pd.Series([1 + 1j, fill_val, 3 + 3j, 4 + 4j]) self._assert_fillna_conversion(obj, fill_val, exp, fill_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index], ids=["series", "index"]) @pytest.mark.parametrize( "fill_val,fill_dtype", [ @@ -842,7 +841,8 @@ def test_fillna_series_complex128(self, fill_val, fill_dtype): ], ids=["datetime64", "datetime64tz", "object", "object"], ) - def test_fillna_datetime(self, klass, fill_val, fill_dtype): + def test_fillna_datetime(self, index_or_series, fill_val, fill_dtype): + klass = index_or_series obj = klass( [ pd.Timestamp("2011-01-01"), @@ -863,7 +863,6 @@ def test_fillna_datetime(self, klass, fill_val, fill_dtype): ) self._assert_fillna_conversion(obj, fill_val, exp, fill_dtype) - @pytest.mark.parametrize("klass", [pd.Series, pd.Index]) @pytest.mark.parametrize( "fill_val,fill_dtype", [ @@ -874,7 +873,8 @@ def test_fillna_datetime(self, klass, fill_val, fill_dtype): ("x", np.object), ], ) - def test_fillna_datetime64tz(self, klass, fill_val, fill_dtype): + def test_fillna_datetime64tz(self, index_or_series, fill_val, fill_dtype): + klass = index_or_series tz = "US/Eastern" obj = klass( diff --git a/pandas/tests/io/json/test_json_table_schema.py b/pandas/tests/io/json/test_json_table_schema.py index ef9b0bdf053e9..49f666344dfa2 100644 --- a/pandas/tests/io/json/test_json_table_schema.py +++ b/pandas/tests/io/json/test_json_table_schema.py @@ -421,15 +421,15 @@ def test_date_format_raises(self): self.df.to_json(orient="table", date_format="iso") self.df.to_json(orient="table") - @pytest.mark.parametrize("kind", [pd.Series, pd.Index]) - def test_convert_pandas_type_to_json_field_int(self, kind): + def test_convert_pandas_type_to_json_field_int(self, index_or_series): + kind = index_or_series data = [1, 2, 3] result = convert_pandas_type_to_json_field(kind(data, name="name")) expected = {"name": "name", "type": "integer"} assert result == expected - @pytest.mark.parametrize("kind", [pd.Series, pd.Index]) - def test_convert_pandas_type_to_json_field_float(self, kind): + def test_convert_pandas_type_to_json_field_float(self, index_or_series): + kind = index_or_series data = [1.0, 2.0, 3.0] result = convert_pandas_type_to_json_field(kind(data, name="name")) expected = {"name": "name", "type": "number"} diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py index 58093ba4d90a5..f24bb9e72aef5 100644 --- a/pandas/tests/test_base.py +++ b/pandas/tests/test_base.py @@ -516,8 +516,8 @@ def test_value_counts_unique_nunique_null(self, null_obj): assert o.nunique() == 8 assert o.nunique(dropna=False) == 9 - @pytest.mark.parametrize("klass", [Index, Series]) - def test_value_counts_inferred(self, klass): + def test_value_counts_inferred(self, index_or_series): + klass = index_or_series s_values = ["a", "b", "b", "b", "b", "c", "d", "d", "a", "a"] s = klass(s_values) expected = Series([4, 3, 2, 1], index=["b", "a", "d", "c"]) @@ -547,8 +547,8 @@ def test_value_counts_inferred(self, klass): expected = Series([0.4, 0.3, 0.2, 0.1], index=["b", "a", "d", "c"]) tm.assert_series_equal(hist, expected) - @pytest.mark.parametrize("klass", [Index, Series]) - def test_value_counts_bins(self, klass): + def test_value_counts_bins(self, index_or_series): + klass = index_or_series s_values = ["a", "b", "b", "b", "b", "c", "d", "d", "a", "a"] s = klass(s_values) @@ -612,8 +612,8 @@ def test_value_counts_bins(self, klass): assert s.nunique() == 0 - @pytest.mark.parametrize("klass", [Index, Series]) - def test_value_counts_datetime64(self, klass): + def test_value_counts_datetime64(self, index_or_series): + klass = index_or_series # GH 3002, datetime64[ns] # don't test names though @@ -1090,13 +1090,13 @@ class TestToIterable: ], ids=["tolist", "to_list", "list", "iter"], ) - @pytest.mark.parametrize("typ", [Series, Index]) @pytest.mark.filterwarnings("ignore:\\n Passing:FutureWarning") # TODO(GH-24559): Remove the filterwarnings - def test_iterable(self, typ, method, dtype, rdtype): + def test_iterable(self, index_or_series, method, dtype, rdtype): # gh-10904 # gh-13258 # coerce iteration to underlying python / pandas types + typ = index_or_series s = typ([1], dtype=dtype) result = method(s)[0] assert isinstance(result, rdtype) @@ -1120,11 +1120,13 @@ def test_iterable(self, typ, method, dtype, rdtype): ], ids=["tolist", "to_list", "list", "iter"], ) - @pytest.mark.parametrize("typ", [Series, Index]) - def test_iterable_object_and_category(self, typ, method, dtype, rdtype, obj): + def test_iterable_object_and_category( + self, index_or_series, method, dtype, rdtype, obj + ): # gh-10904 # gh-13258 # coerce iteration to underlying python / pandas types + typ = index_or_series s = typ([obj], dtype=dtype) result = method(s)[0] assert isinstance(result, rdtype) @@ -1144,12 +1146,12 @@ def test_iterable_items(self, dtype, rdtype): @pytest.mark.parametrize( "dtype, rdtype", dtypes + [("object", int), ("category", int)] ) - @pytest.mark.parametrize("typ", [Series, Index]) @pytest.mark.filterwarnings("ignore:\\n Passing:FutureWarning") # TODO(GH-24559): Remove the filterwarnings - def test_iterable_map(self, typ, dtype, rdtype): + def test_iterable_map(self, index_or_series, dtype, rdtype): # gh-13236 # coerce iteration to underlying python / pandas types + typ = index_or_series s = typ([1], dtype=dtype) result = s.map(type)[0] if not isinstance(rdtype, tuple): @@ -1332,8 +1334,8 @@ def test_numpy_array_all_dtypes(any_numpy_dtype): ), ], ) -@pytest.mark.parametrize("box", [pd.Series, pd.Index]) -def test_array(array, attr, box): +def test_array(array, attr, index_or_series): + box = index_or_series if array.dtype.name in ("Int64", "Sparse[int64, 0]") and box is pd.Index: pytest.skip("No index type for {}".format(array.dtype)) result = box(array, copy=False).array @@ -1396,8 +1398,8 @@ def test_array_multiindex_raises(): ), ], ) -@pytest.mark.parametrize("box", [pd.Series, pd.Index]) -def test_to_numpy(array, expected, box): +def test_to_numpy(array, expected, index_or_series): + box = index_or_series thing = box(array) if array.dtype.name in ("Int64", "Sparse[int64, 0]") and box is pd.Index: diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 1261c3bbc86db..ac1c361ae4023 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -202,9 +202,9 @@ def test_api_mi_raises(self): assert not hasattr(mi, "str") @pytest.mark.parametrize("dtype", [object, "category"]) - @pytest.mark.parametrize("box", [Series, Index]) - def test_api_per_dtype(self, box, dtype, any_skipna_inferred_dtype): + def test_api_per_dtype(self, index_or_series, dtype, any_skipna_inferred_dtype): # one instance of parametrized fixture + box = index_or_series inferred_dtype, values = any_skipna_inferred_dtype t = box(values, dtype=dtype) # explicit dtype to avoid casting @@ -236,13 +236,17 @@ def test_api_per_dtype(self, box, dtype, any_skipna_inferred_dtype): assert not hasattr(t, "str") @pytest.mark.parametrize("dtype", [object, "category"]) - @pytest.mark.parametrize("box", [Series, Index]) def test_api_per_method( - self, box, dtype, any_allowed_skipna_inferred_dtype, any_string_method + self, + index_or_series, + dtype, + any_allowed_skipna_inferred_dtype, + any_string_method, ): # this test does not check correctness of the different methods, # just that the methods work on the specified (inferred) dtypes, # and raise on all others + box = index_or_series # one instance of each parametrized fixture inferred_dtype, values = any_allowed_skipna_inferred_dtype @@ -375,10 +379,10 @@ def test_iter_object_try_string(self): assert i == 100 assert s == "h" - @pytest.mark.parametrize("box", [Series, Index]) @pytest.mark.parametrize("other", [None, Series, Index]) - def test_str_cat_name(self, box, other): + def test_str_cat_name(self, index_or_series, other): # GH 21053 + box = index_or_series values = ["a", "b"] if other: other = other(values) @@ -387,8 +391,8 @@ def test_str_cat_name(self, box, other): result = box(values, name="name").str.cat(other, sep=",") assert result.name == "name" - @pytest.mark.parametrize("box", [Series, Index]) - def test_str_cat(self, box): + def test_str_cat(self, index_or_series): + box = index_or_series # test_cat above tests "str_cat" from ndarray; # here testing "str.cat" from Series/Indext to ndarray/list s = box(["a", "a", "b", "b", "c", np.nan]) @@ -427,9 +431,9 @@ def test_str_cat(self, box): with pytest.raises(ValueError, match=rgx): s.str.cat(list(z)) - @pytest.mark.parametrize("box", [Series, Index]) - def test_str_cat_raises_intuitive_error(self, box): + def test_str_cat_raises_intuitive_error(self, index_or_series): # GH 11334 + box = index_or_series s = box(["a", "b", "c", "d"]) message = "Did you mean to supply a `sep` keyword?" with pytest.raises(ValueError, match=message): @@ -440,8 +444,11 @@ def test_str_cat_raises_intuitive_error(self, box): @pytest.mark.parametrize("sep", ["", None]) @pytest.mark.parametrize("dtype_target", ["object", "category"]) @pytest.mark.parametrize("dtype_caller", ["object", "category"]) - @pytest.mark.parametrize("box", [Series, Index]) - def test_str_cat_categorical(self, box, dtype_caller, dtype_target, sep): + def test_str_cat_categorical( + self, index_or_series, dtype_caller, dtype_target, sep + ): + box = index_or_series + s = Index(["a", "a", "b", "a"], dtype=dtype_caller) s = s if box == Index else Series(s, index=s) t = Index(["b", "a", "b", "c"], dtype=dtype_target) @@ -494,8 +501,8 @@ def test_str_cat_wrong_dtype_raises(self, box, data): # need to use outer and na_rep, as otherwise Index would not raise s.str.cat(t, join="outer", na_rep="-") - @pytest.mark.parametrize("box", [Series, Index]) - def test_str_cat_mixed_inputs(self, box): + def test_str_cat_mixed_inputs(self, index_or_series): + box = index_or_series s = Index(["a", "b", "c", "d"]) s = s if box == Index else Series(s, index=s) @@ -596,9 +603,10 @@ def test_str_cat_mixed_inputs(self, box): s.str.cat(iter([t.values, list(s)])) @pytest.mark.parametrize("join", ["left", "outer", "inner", "right"]) - @pytest.mark.parametrize("box", [Series, Index]) - def test_str_cat_align_indexed(self, box, join): + def test_str_cat_align_indexed(self, index_or_series, join): # https://github.com/pandas-dev/pandas/issues/18657 + box = index_or_series + s = Series(["a", "b", "c", "d"], index=["a", "b", "c", "d"]) t = Series(["D", "A", "E", "B"], index=["d", "a", "e", "b"]) sa, ta = s.align(t, join=join) @@ -656,10 +664,10 @@ def test_str_cat_align_mixed_inputs(self, join): with pytest.raises(ValueError, match=rgx): s.str.cat([t, z], join=join) - @pytest.mark.parametrize("box", [Series, Index]) @pytest.mark.parametrize("other", [Series, Index]) - def test_str_cat_all_na(self, box, other): + def test_str_cat_all_na(self, index_or_series, other): # GH 24044 + box = index_or_series # check that all NaNs in caller / target work s = Index(["a", "b", "c", "d"]) From d6fa489b8aa0536583180278895dc9f324d56ba7 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 24 Nov 2019 14:25:31 -0800 Subject: [PATCH 3/6] typo fixup --- pandas/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/conftest.py b/pandas/conftest.py index cfd1ee6a301c7..a68d72d2fec53 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -856,7 +856,7 @@ def float_frame(): return DataFrame(tm.getSeriesData()) -@pytest.fixure(params=[pd.Index, pd.Series]) +@pytest.fixture(params=[pd.Index, pd.Series]) def index_or_series(request): """ Fixture to parametrize over Index and Series, made necessary by a mypy From c0ed56fa1061a7b295f0203c60ed24b72e22ccc3 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 24 Nov 2019 15:24:06 -0800 Subject: [PATCH 4/6] TST: fix test_comprehensiveness --- pandas/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/conftest.py b/pandas/conftest.py index a68d72d2fec53..122d6e94d9c1a 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -856,7 +856,7 @@ def float_frame(): return DataFrame(tm.getSeriesData()) -@pytest.fixture(params=[pd.Index, pd.Series]) +@pytest.fixture(params=[pd.Index, pd.Series], ids=["index", "series"]) def index_or_series(request): """ Fixture to parametrize over Index and Series, made necessary by a mypy From cd611360ebc9f2fea085c95c32661b10ac8fde52 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 24 Nov 2019 17:09:24 -0800 Subject: [PATCH 5/6] wrestle with mypy --- pandas/tests/arithmetic/test_numeric.py | 56 +++++++------------------ pandas/tests/test_strings.py | 6 ++- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index 584e22f8488f5..bbda0b6734b60 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -5,6 +5,7 @@ from decimal import Decimal from itertools import combinations import operator +from typing import List, Any import numpy as np import pytest @@ -30,6 +31,19 @@ def adjust_negative_zero(zero, expected): return expected +# TODO: remove this kludge once mypy stops giving false positives here +# List comprehension has incompatible type List[PandasObject]; expected List[RangeIndex] +# See GH#????? +ser_or_index: List[Any] = [pd.Series, pd.Index] +lefts: List[Any] = [pd.RangeIndex(10, 40, 10)] +lefts.extend( + [ + cls([10, 20, 30], dtype=dtype) + for dtype in ["i1", "i2", "i4", "i8", "u1", "u2", "u4", "u8", "f2", "f4", "f8"] + for cls in ser_or_index + ] +) + # ------------------------------------------------------------------ # Comparisons @@ -81,26 +95,7 @@ class TestNumericArraylikeArithmeticWithDatetimeLike: # TODO: also check name retentention @pytest.mark.parametrize("box_cls", [np.array, pd.Index, pd.Series]) @pytest.mark.parametrize( - "left", - [pd.RangeIndex(10, 40, 10)] - + [ - cls([10, 20, 30], dtype=dtype) - for dtype in [ - "i1", - "i2", - "i4", - "i8", - "u1", - "u2", - "u4", - "u8", - "f2", - "f4", - "f8", - ] - for cls in [pd.Series, pd.Index] - ], - ids=lambda x: type(x).__name__ + str(x.dtype), + "left", lefts, ids=lambda x: type(x).__name__ + str(x.dtype), ) def test_mul_td64arr(self, left, box_cls): # GH#22390 @@ -120,26 +115,7 @@ def test_mul_td64arr(self, left, box_cls): # TODO: also check name retentention @pytest.mark.parametrize("box_cls", [np.array, pd.Index, pd.Series]) @pytest.mark.parametrize( - "left", - [pd.RangeIndex(10, 40, 10)] - + [ - cls([10, 20, 30], dtype=dtype) - for dtype in [ - "i1", - "i2", - "i4", - "i8", - "u1", - "u2", - "u4", - "u8", - "f2", - "f4", - "f8", - ] - for cls in [pd.Series, pd.Index] - ], - ids=lambda x: type(x).__name__ + str(x.dtype), + "left", lefts, ids=lambda x: type(x).__name__ + str(x.dtype), ) def test_div_td64arr(self, left, box_cls): # GH#22390 diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index ac1c361ae4023..c00e792fb210f 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -664,7 +664,11 @@ def test_str_cat_align_mixed_inputs(self, join): with pytest.raises(ValueError, match=rgx): s.str.cat([t, z], join=join) - @pytest.mark.parametrize("other", [Series, Index]) + index_or_series2 = [Series, Index] # type: ignore + # List item 0 has incompatible type "Type[Series]"; expected "Type[PandasObject]" + # See GH#>???? + + @pytest.mark.parametrize("other", index_or_series2) def test_str_cat_all_na(self, index_or_series, other): # GH 24044 box = index_or_series From 89e69123c740edef3cd13bf9e3abb8377204d49c Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 24 Nov 2019 17:33:55 -0800 Subject: [PATCH 6/6] isort fixup --- pandas/tests/arithmetic/test_numeric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index bbda0b6734b60..77713deada44a 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -5,7 +5,7 @@ from decimal import Decimal from itertools import combinations import operator -from typing import List, Any +from typing import Any, List import numpy as np import pytest