diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 718cd0957cdc6..fe6f8d55baa87 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -398,15 +398,17 @@ def _convert_scalar_indexer(self, key, kind=None): assert kind in ["loc", "getitem", "iloc", None] + if not is_scalar(key): + raise TypeError(key) + # we don't allow integer/float indexing for loc - # we don't allow float indexing for ix/getitem - if is_scalar(key): - is_int = is_integer(key) - is_flt = is_float(key) - if kind in ["loc"] and (is_int or is_flt): - self._invalid_indexer("index", key) - elif kind in ["getitem"] and is_flt: - self._invalid_indexer("index", key) + # we don't allow float indexing for getitem + is_int = is_integer(key) + is_flt = is_float(key) + if kind == "loc" and (is_int or is_flt): + self._invalid_indexer("index", key) + elif kind == "getitem" and is_flt: + self._invalid_indexer("index", key) return super()._convert_scalar_indexer(key, kind=kind) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 91e86112f5efd..c818112e3e7d0 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -599,7 +599,7 @@ def _slice(self, obj, axis: int, kind=None): def _get_setitem_indexer(self, key): if self.axis is not None: - return self._convert_tuple(key) + return self._convert_tuple(key, setting=True) ax = self.obj._get_axis(0) @@ -612,7 +612,7 @@ def _get_setitem_indexer(self, key): if isinstance(key, tuple): try: - return self._convert_tuple(key) + return self._convert_tuple(key, setting=True) except IndexingError: pass @@ -620,7 +620,7 @@ def _get_setitem_indexer(self, key): return list(key) try: - return self._convert_to_indexer(key, axis=0) + return self._convert_to_indexer(key, axis=0, setting=True) except TypeError as e: # invalid indexer type vs 'other' indexing errors @@ -683,20 +683,22 @@ def _is_nested_tuple_indexer(self, tup: Tuple) -> bool: return any(is_nested_tuple(tup, ax) for ax in self.obj.axes) return False - def _convert_tuple(self, key): + def _convert_tuple(self, key, setting: bool = False): keyidx = [] if self.axis is not None: axis = self.obj._get_axis_number(self.axis) for i in range(self.ndim): if i == axis: - keyidx.append(self._convert_to_indexer(key, axis=axis)) + keyidx.append( + self._convert_to_indexer(key, axis=axis, setting=setting) + ) else: keyidx.append(slice(None)) else: for i, k in enumerate(key): if i >= self.ndim: raise IndexingError("Too many indexers") - idx = self._convert_to_indexer(k, axis=i) + idx = self._convert_to_indexer(k, axis=i, setting=setting) keyidx.append(idx) return tuple(keyidx) @@ -1566,7 +1568,7 @@ def _validate_read_indexer( "https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike" # noqa:E501 ) - def _convert_to_indexer(self, key, axis: int): + def _convert_to_indexer(self, key, axis: int, setting: bool = False): raise AbstractMethodError(self) def __getitem__(self, key): @@ -1775,7 +1777,7 @@ def _get_slice_axis(self, slice_obj: slice, axis: int): # return a DatetimeIndex instead of a slice object. return self.obj.take(indexer, axis=axis) - def _convert_to_indexer(self, key, axis: int): + def _convert_to_indexer(self, key, axis: int, setting: bool = False): """ Convert indexing key into something we can use to do actual fancy indexing on a ndarray. @@ -1795,12 +1797,14 @@ def _convert_to_indexer(self, key, axis: int): if isinstance(key, slice): return self._convert_slice_indexer(key, axis) - # try to find out correct indexer, if not type correct raise - try: - key = self._convert_scalar_indexer(key, axis) - except TypeError: - # but we will allow setting - pass + if is_scalar(key): + # try to find out correct indexer, if not type correct raise + try: + key = self._convert_scalar_indexer(key, axis) + except TypeError: + # but we will allow setting + if not setting: + raise # see if we are positional in nature is_int_index = labels.is_integer() @@ -2032,7 +2036,7 @@ def _get_slice_axis(self, slice_obj: slice, axis: int): indexer = self._convert_slice_indexer(slice_obj, axis) return self._slice(indexer, axis=axis, kind="iloc") - def _convert_to_indexer(self, key, axis: int): + def _convert_to_indexer(self, key, axis: int, setting: bool = False): """ Much simpler as we only have to deal with our valid types. """