From ddb03215ab8ea39eb9f5aa30931e86f085ad257f Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 3 Jan 2022 12:55:36 -0800 Subject: [PATCH 1/2] REF: catch more specific exceptions in Series.__setitem__ --- pandas/core/series.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 7ca80601bbfd0..1cc5e79b78acc 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1084,7 +1084,9 @@ def __setitem__(self, key, value) -> None: try: self._set_with_engine(key, value) - except (KeyError, ValueError): + except KeyError: + # We have a scalar (or for MultiIndex or object-dtype, scalar-like) + # key that is not present in self.index. if is_integer(key) and self.index.inferred_type != "integer": # positional setter if not self.index._should_fallback_to_positional: @@ -1104,7 +1106,7 @@ def __setitem__(self, key, value) -> None: # GH#12862 adding a new key to the Series self.loc[key] = value - except (InvalidIndexError, TypeError) as err: + except (InvalidIndexError, TypeError, ValueError) as err: if isinstance(key, tuple) and not isinstance(self.index, MultiIndex): # cases with MultiIndex don't get here bc they raise KeyError raise KeyError( @@ -1175,7 +1177,13 @@ def _set_with(self, key, value): def _set_labels(self, key, value) -> None: key = com.asarray_tuplesafe(key) - indexer: np.ndarray = self.index.get_indexer(key) + try: + indexer: np.ndarray = self.index.get_indexer(key) + except InvalidIndexError: + # self.index is not unique, e.g. test_setitem_non_bool_into_bool + self.loc[key] = value + return + mask = indexer == -1 if mask.any(): raise KeyError(f"{key[mask]} not in index") From 8c53a23f9f5de44bf7b5b525eb3b2abae8665dc5 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 4 Jan 2022 20:28:02 -0800 Subject: [PATCH 2/2] REF: simplified exception catching in Series.__setitem__ --- pandas/core/series.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 1cc5e79b78acc..36e9119e14d5a 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1106,9 +1106,15 @@ def __setitem__(self, key, value) -> None: # GH#12862 adding a new key to the Series self.loc[key] = value - except (InvalidIndexError, TypeError, ValueError) as err: + except (TypeError, ValueError): + # The key was OK, but we cannot set the value losslessly + indexer = self.index.get_loc(key) + self._set_values(indexer, value) + + except InvalidIndexError as err: if isinstance(key, tuple) and not isinstance(self.index, MultiIndex): # cases with MultiIndex don't get here bc they raise KeyError + # e.g. test_basic_getitem_setitem_corner raise KeyError( "key of type tuple not found and not a MultiIndex" ) from err @@ -1163,27 +1169,23 @@ def _set_with(self, key, value): # Without this, the call to infer_dtype will consume the generator key = list(key) - key_type = lib.infer_dtype(key, skipna=False) + if not self.index._should_fallback_to_positional: + # Regardless of the key type, we're treating it as labels + self._set_labels(key, value) - # Note: key_type == "boolean" should not occur because that - # should be caught by the is_bool_indexer check in __setitem__ - if key_type == "integer": - if not self.index._should_fallback_to_positional: - self._set_labels(key, value) - else: - self._set_values(key, value) else: - self.loc[key] = value + # Note: key_type == "boolean" should not occur because that + # should be caught by the is_bool_indexer check in __setitem__ + key_type = lib.infer_dtype(key, skipna=False) + + if key_type == "integer": + self._set_values(key, value) + else: + self._set_labels(key, value) def _set_labels(self, key, value) -> None: key = com.asarray_tuplesafe(key) - try: - indexer: np.ndarray = self.index.get_indexer(key) - except InvalidIndexError: - # self.index is not unique, e.g. test_setitem_non_bool_into_bool - self.loc[key] = value - return - + indexer: np.ndarray = self.index.get_indexer(key) mask = indexer == -1 if mask.any(): raise KeyError(f"{key[mask]} not in index")