@@ -1081,7 +1081,9 @@ def __setitem__(self, key, value) -> None:
1081
1081
1082
1082
try :
1083
1083
self ._set_with_engine (key , value )
1084
- except (KeyError , ValueError ):
1084
+ except KeyError :
1085
+ # We have a scalar (or for MultiIndex or object-dtype, scalar-like)
1086
+ # key that is not present in self.index.
1085
1087
if is_integer (key ) and self .index .inferred_type != "integer" :
1086
1088
# positional setter
1087
1089
if not self .index ._should_fallback_to_positional :
@@ -1102,9 +1104,15 @@ def __setitem__(self, key, value) -> None:
1102
1104
# GH#12862 adding a new key to the Series
1103
1105
self .loc [key ] = value
1104
1106
1105
- except (InvalidIndexError , TypeError ) as err :
1107
+ except (TypeError , ValueError ):
1108
+ # The key was OK, but we cannot set the value losslessly
1109
+ indexer = self .index .get_loc (key )
1110
+ self ._set_values (indexer , value )
1111
+
1112
+ except InvalidIndexError as err :
1106
1113
if isinstance (key , tuple ) and not isinstance (self .index , MultiIndex ):
1107
1114
# cases with MultiIndex don't get here bc they raise KeyError
1115
+ # e.g. test_basic_getitem_setitem_corner
1108
1116
raise KeyError (
1109
1117
"key of type tuple not found and not a MultiIndex"
1110
1118
) from err
@@ -1163,17 +1171,19 @@ def _set_with(self, key, value):
1163
1171
# Without this, the call to infer_dtype will consume the generator
1164
1172
key = list (key )
1165
1173
1166
- key_type = lib .infer_dtype (key , skipna = False )
1174
+ if not self .index ._should_fallback_to_positional :
1175
+ # Regardless of the key type, we're treating it as labels
1176
+ self ._set_labels (key , value )
1167
1177
1168
- # Note: key_type == "boolean" should not occur because that
1169
- # should be caught by the is_bool_indexer check in __setitem__
1170
- if key_type == "integer" :
1171
- if not self .index ._should_fallback_to_positional :
1172
- self ._set_labels (key , value )
1173
- else :
1174
- self ._set_values (key , value )
1175
1178
else :
1176
- self .loc [key ] = value
1179
+ # Note: key_type == "boolean" should not occur because that
1180
+ # should be caught by the is_bool_indexer check in __setitem__
1181
+ key_type = lib .infer_dtype (key , skipna = False )
1182
+
1183
+ if key_type == "integer" :
1184
+ self ._set_values (key , value )
1185
+ else :
1186
+ self ._set_labels (key , value )
1177
1187
1178
1188
def _set_labels (self , key , value ) -> None :
1179
1189
key = com .asarray_tuplesafe (key )
0 commit comments