From 1b71ab996cf1637ac3fd605002623c8d7e632bf4 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 18:46:27 -0800 Subject: [PATCH 1/5] CLN: prune unreachable --- pandas/core/frame.py | 12 ++---------- pandas/core/series.py | 15 +-------------- pandas/tests/series/indexing/test_datetime.py | 12 ++++-------- pandas/tests/series/indexing/test_indexing.py | 10 ++++------ 4 files changed, 11 insertions(+), 38 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index e0efa93379bca..c67679b5ecc41 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -3011,17 +3011,12 @@ def _set_value(self, index, col, value, takeable: bool = False): col : column label value : scalar takeable : interpret the index/col as indexers, default False - - Returns - ------- - DataFrame - If label pair is contained, will be reference to calling DataFrame, - otherwise a new object. """ try: if takeable is True: series = self._iget_item_cache(col) - return series._set_value(index, value, takeable=True) + series._set_value(index, value, takeable=True) + return series = self._get_item_cache(col) engine = self.index._engine @@ -3031,7 +3026,6 @@ def _set_value(self, index, col, value, takeable: bool = False): series._values[loc] = value # Note: trying to use series._set_value breaks tests in # tests.frame.indexing.test_indexing and tests.indexing.test_partial - return self except (KeyError, TypeError): # set using a non-recursive method & reset the cache if takeable: @@ -3040,8 +3034,6 @@ def _set_value(self, index, col, value, takeable: bool = False): self.loc[index, col] = value self._item_cache.pop(col, None) - return self - def _ensure_valid_index(self, value): """ Ensure that if we don't have an index, that we can create one from the diff --git a/pandas/core/series.py b/pandas/core/series.py index 0786674daf874..155093f8af840 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -987,8 +987,6 @@ def __setitem__(self, key, value): try: self._set_with_engine(key, value) - except com.SettingWithCopyError: - raise except (KeyError, ValueError): values = self._values if is_integer(key) and not self.index.inferred_type == "integer": @@ -997,9 +995,6 @@ def __setitem__(self, key, value): self[:] = value else: self.loc[key] = value - except InvalidIndexError: - # e.g. slice - self._set_with(key, value) except TypeError as e: if isinstance(key, tuple) and not isinstance(self.index, MultiIndex): @@ -1070,7 +1065,7 @@ def _set_with(self, key, value): def _set_labels(self, key, value): key = com.asarray_tuplesafe(key) - indexer = self.index.get_indexer(key) + indexer: np.ndarray = self.index.get_indexer(key) mask = indexer == -1 if mask.any(): raise ValueError(f"{key[mask]} not contained in the index") @@ -1096,12 +1091,6 @@ def _set_value(self, label, value, takeable: bool = False): value : object Scalar value. takeable : interpret the index as indexers, default False - - Returns - ------- - Series - If label is contained, will be reference to calling Series, - otherwise a new object. """ try: if takeable: @@ -1115,8 +1104,6 @@ def _set_value(self, label, value, takeable: bool = False): # set using a non-recursive method self.loc[label] = value - return self - # ---------------------------------------------------------------------- # Unsorted diff --git a/pandas/tests/series/indexing/test_datetime.py b/pandas/tests/series/indexing/test_datetime.py index acaa9de88a836..4b846a1ab4f28 100644 --- a/pandas/tests/series/indexing/test_datetime.py +++ b/pandas/tests/series/indexing/test_datetime.py @@ -73,17 +73,13 @@ def test_series_set_value(): dates = [datetime(2001, 1, 1), datetime(2001, 1, 2)] index = DatetimeIndex(dates) - s = Series(dtype=object)._set_value(dates[0], 1.0) - s2 = s._set_value(dates[1], np.nan) + s = Series(dtype=object) + s._set_value(dates[0], 1.0) + s._set_value(dates[1], np.nan) expected = Series([1.0, np.nan], index=index) - tm.assert_series_equal(s2, expected) - - # FIXME: dont leave commented-out - # s = Series(index[:1], index[:1]) - # s2 = s._set_value(dates[1], index[1]) - # assert s2.values.dtype == 'M8[ns]' + tm.assert_series_equal(s, expected) @pytest.mark.slow diff --git a/pandas/tests/series/indexing/test_indexing.py b/pandas/tests/series/indexing/test_indexing.py index fa5c75d5e4ad9..5a22f64b628c5 100644 --- a/pandas/tests/series/indexing/test_indexing.py +++ b/pandas/tests/series/indexing/test_indexing.py @@ -364,16 +364,14 @@ def test_setitem_dtypes(): def test_set_value(datetime_series, string_series): idx = datetime_series.index[10] - res = datetime_series._set_value(idx, 0) - assert res is datetime_series + datetime_series._set_value(idx, 0) assert datetime_series[idx] == 0 # equiv s = string_series.copy() - res = s._set_value("foobar", 0) - assert res is s - assert res.index[-1] == "foobar" - assert res["foobar"] == 0 + s._set_value("foobar", 0) + assert s.index[-1] == "foobar" + assert s["foobar"] == 0 s = string_series.copy() s.loc["foobar"] = 0 From 102ce46b9be9ded38f0b500dfef4da93ab809ec8 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 18:59:45 -0800 Subject: [PATCH 2/5] parametrize test --- pandas/tests/indexing/test_floats.py | 164 ++++++++++++++------------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index 199d9e1013e23..02dbf6db37176 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -59,115 +59,117 @@ def test_scalar_error(self, index_func): with pytest.raises(TypeError, match=msg): s.iloc[3.0] = 0 - def test_scalar_non_numeric(self): - - # GH 4892 - # float_indexers should raise exceptions - # on appropriate Index types & accessors - - for index in [ + @pytest.mark.parametrize( + "index_func", + [ tm.makeStringIndex, tm.makeUnicodeIndex, tm.makeCategoricalIndex, tm.makeDateIndex, tm.makeTimedeltaIndex, tm.makePeriodIndex, - ]: + ], + ) + def test_scalar_non_numeric(self, index_func): - i = index(5) + # GH 4892 + # float_indexers should raise exceptions + # on appropriate Index types & accessors - for s in [ - Series(np.arange(len(i)), index=i), - DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), - ]: + i = index_func(5) - # getting - for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: + for s in [ + Series(np.arange(len(i)), index=i), + DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), + ]: - # gettitem on a DataFrame is a KeyError as it is indexing - # via labels on the columns - if getitem and isinstance(s, DataFrame): - error = KeyError - msg = r"^3(\.0)?$" - else: - error = TypeError - msg = ( - r"cannot do (label|index|positional) indexing " - r"on {klass} with these indexers \[3\.0\] of " - r"{kind}|" - "Cannot index by location index with a " - "non-integer key".format(klass=type(i), kind=str(float)) - ) - with pytest.raises(error, match=msg): - idxr(s)[3.0] - - # label based can be a TypeError or KeyError - if s.index.inferred_type in { - "categorical", - "string", - "unicode", - "mixed", - }: + # getting + for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: + + # gettitem on a DataFrame is a KeyError as it is indexing + # via labels on the columns + if getitem and isinstance(s, DataFrame): error = KeyError - msg = r"^3\.0$" + msg = r"^3(\.0)?$" else: error = TypeError msg = ( - r"cannot do (label|index) indexing " + r"cannot do (label|index|positional) indexing " r"on {klass} with these indexers \[3\.0\] of " - r"{kind}".format(klass=type(i), kind=str(float)) + r"{kind}|" + "Cannot index by location index with a " + "non-integer key".format(klass=type(i), kind=str(float)) ) with pytest.raises(error, match=msg): - s.loc[3.0] - - # contains - assert 3.0 not in s - - # setting with a float fails with iloc + idxr(s)[3.0] + + # label based can be a TypeError or KeyError + if s.index.inferred_type in { + "categorical", + "string", + "unicode", + "mixed", + }: + error = KeyError + msg = r"^3\.0$" + else: + error = TypeError msg = ( - r"cannot do (label|index|positional) indexing " + r"cannot do (label|index) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) - with pytest.raises(TypeError, match=msg): - s.iloc[3.0] = 0 - - # setting with an indexer - if s.index.inferred_type in ["categorical"]: - # Value or Type Error - pass - elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: - - # these should prob work - # and are inconsistent between series/dataframe ATM - # for idxr in [lambda x: x]: - # s2 = s.copy() - # - # with pytest.raises(TypeError): - # idxr(s2)[3.0] = 0 - pass + with pytest.raises(error, match=msg): + s.loc[3.0] - else: - - s2 = s.copy() - s2.loc[3.0] = 10 - assert s2.index.is_object() - - for idxr in [lambda x: x]: - s2 = s.copy() - idxr(s2)[3.0] = 0 - assert s2.index.is_object() + # contains + assert 3.0 not in s - # fallsback to position selection, series only - s = Series(np.arange(len(i)), index=i) - s[3] + # setting with a float fails with iloc msg = ( - r"cannot do (label|index) indexing " + r"cannot do (label|index|positional) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) with pytest.raises(TypeError, match=msg): - s[3.0] + s.iloc[3.0] = 0 + + # setting with an indexer + if s.index.inferred_type in ["categorical"]: + # Value or Type Error + pass + elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: + + # these should prob work + # and are inconsistent between series/dataframe ATM + # for idxr in [lambda x: x]: + # s2 = s.copy() + # + # with pytest.raises(TypeError): + # idxr(s2)[3.0] = 0 + pass + + else: + + s2 = s.copy() + s2.loc[3.0] = 10 + assert s2.index.is_object() + + for idxr in [lambda x: x]: + s2 = s.copy() + idxr(s2)[3.0] = 0 + assert s2.index.is_object() + + # fallsback to position selection, series only + s = Series(np.arange(len(i)), index=i) + s[3] + msg = ( + r"cannot do (label|index) indexing " + r"on {klass} with these indexers \[3\.0\] of " + r"{kind}".format(klass=type(i), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s[3.0] def test_scalar_with_mixed(self): From 66669fd2a9c21668fe604b2a07efeb65becfc1ab Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 19:30:04 -0800 Subject: [PATCH 3/5] allow EA through --- pandas/core/series.py | 2 +- pandas/tests/indexing/test_floats.py | 164 +++++++++++++-------------- 2 files changed, 82 insertions(+), 84 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 155093f8af840..ffc669e473cd7 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -902,7 +902,7 @@ def _get_with(self, key): return self._get_values(key) raise - if not isinstance(key, (list, np.ndarray, Series, Index)): + if not isinstance(key, (list, np.ndarray, ExtensionArray, Series, Index)): key = list(key) if isinstance(key, Index): diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index 02dbf6db37176..199d9e1013e23 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -59,117 +59,115 @@ def test_scalar_error(self, index_func): with pytest.raises(TypeError, match=msg): s.iloc[3.0] = 0 - @pytest.mark.parametrize( - "index_func", - [ + def test_scalar_non_numeric(self): + + # GH 4892 + # float_indexers should raise exceptions + # on appropriate Index types & accessors + + for index in [ tm.makeStringIndex, tm.makeUnicodeIndex, tm.makeCategoricalIndex, tm.makeDateIndex, tm.makeTimedeltaIndex, tm.makePeriodIndex, - ], - ) - def test_scalar_non_numeric(self, index_func): - - # GH 4892 - # float_indexers should raise exceptions - # on appropriate Index types & accessors + ]: - i = index_func(5) + i = index(5) - for s in [ - Series(np.arange(len(i)), index=i), - DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), - ]: + for s in [ + Series(np.arange(len(i)), index=i), + DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), + ]: - # getting - for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: + # getting + for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: - # gettitem on a DataFrame is a KeyError as it is indexing - # via labels on the columns - if getitem and isinstance(s, DataFrame): + # gettitem on a DataFrame is a KeyError as it is indexing + # via labels on the columns + if getitem and isinstance(s, DataFrame): + error = KeyError + msg = r"^3(\.0)?$" + else: + error = TypeError + msg = ( + r"cannot do (label|index|positional) indexing " + r"on {klass} with these indexers \[3\.0\] of " + r"{kind}|" + "Cannot index by location index with a " + "non-integer key".format(klass=type(i), kind=str(float)) + ) + with pytest.raises(error, match=msg): + idxr(s)[3.0] + + # label based can be a TypeError or KeyError + if s.index.inferred_type in { + "categorical", + "string", + "unicode", + "mixed", + }: error = KeyError - msg = r"^3(\.0)?$" + msg = r"^3\.0$" else: error = TypeError msg = ( - r"cannot do (label|index|positional) indexing " + r"cannot do (label|index) indexing " r"on {klass} with these indexers \[3\.0\] of " - r"{kind}|" - "Cannot index by location index with a " - "non-integer key".format(klass=type(i), kind=str(float)) + r"{kind}".format(klass=type(i), kind=str(float)) ) with pytest.raises(error, match=msg): - idxr(s)[3.0] - - # label based can be a TypeError or KeyError - if s.index.inferred_type in { - "categorical", - "string", - "unicode", - "mixed", - }: - error = KeyError - msg = r"^3\.0$" - else: - error = TypeError + s.loc[3.0] + + # contains + assert 3.0 not in s + + # setting with a float fails with iloc msg = ( - r"cannot do (label|index) indexing " + r"cannot do (label|index|positional) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) - with pytest.raises(error, match=msg): - s.loc[3.0] + with pytest.raises(TypeError, match=msg): + s.iloc[3.0] = 0 + + # setting with an indexer + if s.index.inferred_type in ["categorical"]: + # Value or Type Error + pass + elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: + + # these should prob work + # and are inconsistent between series/dataframe ATM + # for idxr in [lambda x: x]: + # s2 = s.copy() + # + # with pytest.raises(TypeError): + # idxr(s2)[3.0] = 0 + pass - # contains - assert 3.0 not in s + else: + + s2 = s.copy() + s2.loc[3.0] = 10 + assert s2.index.is_object() + + for idxr in [lambda x: x]: + s2 = s.copy() + idxr(s2)[3.0] = 0 + assert s2.index.is_object() - # setting with a float fails with iloc + # fallsback to position selection, series only + s = Series(np.arange(len(i)), index=i) + s[3] msg = ( - r"cannot do (label|index|positional) indexing " + r"cannot do (label|index) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) with pytest.raises(TypeError, match=msg): - s.iloc[3.0] = 0 - - # setting with an indexer - if s.index.inferred_type in ["categorical"]: - # Value or Type Error - pass - elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: - - # these should prob work - # and are inconsistent between series/dataframe ATM - # for idxr in [lambda x: x]: - # s2 = s.copy() - # - # with pytest.raises(TypeError): - # idxr(s2)[3.0] = 0 - pass - - else: - - s2 = s.copy() - s2.loc[3.0] = 10 - assert s2.index.is_object() - - for idxr in [lambda x: x]: - s2 = s.copy() - idxr(s2)[3.0] = 0 - assert s2.index.is_object() - - # fallsback to position selection, series only - s = Series(np.arange(len(i)), index=i) - s[3] - msg = ( - r"cannot do (label|index) indexing " - r"on {klass} with these indexers \[3\.0\] of " - r"{kind}".format(klass=type(i), kind=str(float)) - ) - with pytest.raises(TypeError, match=msg): - s[3.0] + s[3.0] def test_scalar_with_mixed(self): From 57000edbaf6eb3218ff9018c7114bb843ebd2a70 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 7 Feb 2020 08:11:02 -0800 Subject: [PATCH 4/5] fix missed test --- pandas/tests/frame/indexing/test_indexing.py | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index ca4d1ff067f3d..b415576f15a1d 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -1369,29 +1369,28 @@ def test_set_value(self, float_frame): def test_set_value_resize(self, float_frame): - res = float_frame._set_value("foobar", "B", 0) - assert res is float_frame - assert res.index[-1] == "foobar" - assert res._get_value("foobar", "B") == 0 + float_frame._set_value("foobar", "B", 0) + assert float_frame.index[-1] == "foobar" + assert float_frame._get_value("foobar", "B") == 0 float_frame.loc["foobar", "qux"] = 0 assert float_frame._get_value("foobar", "qux") == 0 res = float_frame.copy() - res3 = res._set_value("foobar", "baz", "sam") - assert res3["baz"].dtype == np.object_ + res._set_value("foobar", "baz", "sam") + assert res["baz"].dtype == np.object_ res = float_frame.copy() - res3 = res._set_value("foobar", "baz", True) - assert res3["baz"].dtype == np.object_ + res._set_value("foobar", "baz", True) + assert res["baz"].dtype == np.object_ res = float_frame.copy() - res3 = res._set_value("foobar", "baz", 5) - assert is_float_dtype(res3["baz"]) - assert isna(res3["baz"].drop(["foobar"])).all() + res._set_value("foobar", "baz", 5) + assert is_float_dtype(res["baz"]) + assert isna(res["baz"].drop(["foobar"])).all() msg = "could not convert string to float: 'sam'" with pytest.raises(ValueError, match=msg): - res3._set_value("foobar", "baz", "sam") + res._set_value("foobar", "baz", "sam") def test_set_value_with_index_dtype_change(self): df_orig = DataFrame(np.random.randn(3, 3), index=range(3), columns=list("ABC")) From 0765ffb0a5f36f05ba13061a30178b69db794206 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 9 Feb 2020 09:34:58 -0800 Subject: [PATCH 5/5] none assertions --- pandas/tests/frame/indexing/test_indexing.py | 3 ++- pandas/tests/series/indexing/test_indexing.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index cd73a6a61ae40..d892e3d637772 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -1376,7 +1376,8 @@ def test_set_value(self, float_frame): def test_set_value_resize(self, float_frame): - float_frame._set_value("foobar", "B", 0) + res = float_frame._set_value("foobar", "B", 0) + assert res is None assert float_frame.index[-1] == "foobar" assert float_frame._get_value("foobar", "B") == 0 diff --git a/pandas/tests/series/indexing/test_indexing.py b/pandas/tests/series/indexing/test_indexing.py index bf10bc26cf556..18fcbea683dd3 100644 --- a/pandas/tests/series/indexing/test_indexing.py +++ b/pandas/tests/series/indexing/test_indexing.py @@ -374,12 +374,14 @@ def test_setitem_dtypes(): def test_set_value(datetime_series, string_series): idx = datetime_series.index[10] - datetime_series._set_value(idx, 0) + res = datetime_series._set_value(idx, 0) + assert res is None assert datetime_series[idx] == 0 # equiv s = string_series.copy() - s._set_value("foobar", 0) + res = s._set_value("foobar", 0) + assert res is None assert s.index[-1] == "foobar" assert s["foobar"] == 0