Skip to content

REF: catch more specific exceptions in Series.__setitem__ #45194

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 2 commits into from
Jan 8, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -1104,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) 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
Expand Down Expand Up @@ -1161,17 +1169,19 @@ 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)
Expand Down