diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 9084395871675..c67250ed3164b 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -794,11 +794,7 @@ def swapaxes(self, axis1: Axis, axis2: Axis, copy: bool_t | None = None) -> Self new_axes = [self._get_axis(mapping.get(k, k)) for k in range(self._AXIS_LEN)] new_values = self._values.swapaxes(i, j) # type: ignore[union-attr] - if ( - using_copy_on_write() - and self._mgr.is_single_block - and isinstance(self._mgr, BlockManager) - ): + if self._mgr.is_single_block and isinstance(self._mgr, BlockManager): # This should only get hit in case of having a single block, otherwise a # copy is made, we don't have to set up references. new_mgr = ndarray_to_mgr( @@ -815,10 +811,10 @@ def swapaxes(self, axis1: Axis, axis2: Axis, copy: bool_t | None = None) -> Self new_mgr.blocks[0].refs.add_reference( new_mgr.blocks[0] # type: ignore[arg-type] ) - return self._constructor(new_mgr).__finalize__(self, method="swapaxes") + if not using_copy_on_write() and copy is not False: + new_mgr = new_mgr.copy(deep=True) - elif (copy or copy is None) and self._mgr.is_single_block: - new_values = new_values.copy() + return self._constructor(new_mgr).__finalize__(self, method="swapaxes") return self._constructor( new_values, diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index ae77bd09f8995..aca50ffba077e 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -486,7 +486,7 @@ def _downcast_2d(self, dtype, using_cow: bool = False) -> list[Block]: """ new_values = maybe_downcast_to_dtype(self.values, dtype=dtype) new_values = maybe_coerce_values(new_values) - refs = self.refs if using_cow and new_values is self.values else None + refs = self.refs if new_values is self.values else None return [self.make_block(new_values, refs=refs)] @final @@ -529,7 +529,7 @@ def convert( refs = None if copy and res_values is values: res_values = values.copy() - elif res_values is values and using_cow: + elif res_values is values: refs = self.refs res_values = ensure_block_shape(res_values, self.ndim) @@ -577,7 +577,7 @@ def astype( new_values = maybe_coerce_values(new_values) refs = None - if using_cow and astype_is_view(values.dtype, new_values.dtype): + if (using_cow or not copy) and astype_is_view(values.dtype, new_values.dtype): refs = self.refs newb = self.make_block(new_values, refs=refs) @@ -914,7 +914,7 @@ def _replace_coerce( nb = self.astype(np.dtype(object), copy=False, using_cow=using_cow) if (nb is self or using_cow) and not inplace: nb = nb.copy() - elif inplace and has_ref and nb.refs.has_reference(): + elif inplace and has_ref and nb.refs.has_reference() and using_cow: # no copy in astype and we had refs before nb = nb.copy() putmask_inplace(nb.values, mask, value) diff --git a/pandas/core/series.py b/pandas/core/series.py index f17a633259816..079366a942f8e 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -893,7 +893,7 @@ def view(self, dtype: Dtype | None = None) -> Series: # implementation res_values = self.array.view(dtype) res_ser = self._constructor(res_values, index=self.index, copy=False) - if isinstance(res_ser._mgr, SingleBlockManager) and using_copy_on_write(): + if isinstance(res_ser._mgr, SingleBlockManager): blk = res_ser._mgr._block blk.refs = cast("BlockValuesRefs", self._references) blk.refs.add_reference(blk) # type: ignore[arg-type]