diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index be105f0035447..54ac1a3fd52c2 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -1758,6 +1758,14 @@ def setitem(self, indexer, value): `indexer` is a direct slice/positional indexer. `value` must be a compatible shape. """ + if not self._can_hold_element(value): + # This is only relevant for DatetimeTZBlock, which has a + # non-trivial `_can_hold_element`. + # https://github.com/pandas-dev/pandas/issues/24020 + # Need a dedicated setitem until GH#24020 (type promotion in setitem + # for extension arrays) is designed and implemented. + return self.astype(object).setitem(indexer, value) + if isinstance(indexer, tuple): # TODO(EA2D): not needed with 2D EAs # we are always 1-D @@ -2175,7 +2183,13 @@ def astype(self, dtype, copy: bool = False, errors: str = "raise"): def _can_hold_element(self, element: Any) -> bool: tipo = maybe_infer_dtype_type(element) if tipo is not None: - if self.is_datetimetz: + if isinstance(element, list) and len(element) == 0: + # Following DatetimeArray._validate_setitem_value + # convention, we treat this as object-dtype + # (even though tipo is float64) + return True + + elif self.is_datetimetz: # require exact match, since non-nano does not exist return is_dtype_equal(tipo, self.dtype) or is_valid_nat_for_dtype( element, self.dtype @@ -2339,21 +2353,6 @@ def fillna(self, value, limit=None, inplace=False, downcast=None): value, limit=limit, inplace=inplace, downcast=downcast ) - def setitem(self, indexer, value): - # https://github.com/pandas-dev/pandas/issues/24020 - # Need a dedicated setitem until #24020 (type promotion in setitem - # for extension arrays) is designed and implemented. - if self._can_hold_element(value) or ( - isinstance(indexer, np.ndarray) and indexer.size == 0 - ): - return super().setitem(indexer, value) - - obj_vals = self.values.astype(object) - newb = make_block( - obj_vals, placement=self.mgr_locs, klass=ObjectBlock, ndim=self.ndim - ) - return newb.setitem(indexer, value) - def quantile(self, qs, interpolation="linear", axis=0): naive = self.values.view("M8[ns]")