diff --git a/pandas/core/series.py b/pandas/core/series.py index e5f2370b395ef..8b6cdbd844aa7 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -385,6 +385,8 @@ def __init__( and dtype is None and copy is False ): + if using_copy_on_write(): + data = data.copy(deep=False) # GH#33357 called with just the SingleBlockManager NDFrame.__init__(self, data) if fastpath: @@ -403,6 +405,8 @@ def __init__( data = SingleBlockManager.from_array(data, index) elif manager == "array": data = SingleArrayManager.from_array(data, index) + elif using_copy_on_write() and not copy: + data = data.copy(deep=False) if copy: data = data.copy() # skips validation of the name @@ -410,6 +414,9 @@ def __init__( NDFrame.__init__(self, data) return + if isinstance(data, SingleBlockManager) and using_copy_on_write() and not copy: + data = data.copy(deep=False) + name = ibase.maybe_extract_name(name, data, type(self)) if index is not None: diff --git a/pandas/tests/copy_view/test_constructors.py b/pandas/tests/copy_view/test_constructors.py index 8ceb3cd7d2d2b..5a232acf6e987 100644 --- a/pandas/tests/copy_view/test_constructors.py +++ b/pandas/tests/copy_view/test_constructors.py @@ -1,6 +1,7 @@ import numpy as np import pytest +import pandas as pd from pandas import ( DataFrame, DatetimeIndex, @@ -118,6 +119,33 @@ def test_series_from_index_different_dtypes(using_copy_on_write): assert ser._mgr._has_no_reference(0) +@pytest.mark.parametrize("fastpath", [False, True]) +@pytest.mark.parametrize("dtype", [None, "int64"]) +@pytest.mark.parametrize("idx", [None, pd.RangeIndex(start=0, stop=3, step=1)]) +def test_series_from_block_manager(using_copy_on_write, idx, dtype, fastpath): + ser = Series([1, 2, 3], dtype="int64") + ser_orig = ser.copy() + ser2 = Series(ser._mgr, dtype=dtype, fastpath=fastpath, index=idx) + assert np.shares_memory(get_array(ser), get_array(ser2)) + if using_copy_on_write: + assert not ser2._mgr._has_no_reference(0) + + ser2.iloc[0] = 100 + if using_copy_on_write: + tm.assert_series_equal(ser, ser_orig) + else: + expected = Series([100, 2, 3]) + tm.assert_series_equal(ser, expected) + + +def test_series_from_block_manager_different_dtype(using_copy_on_write): + ser = Series([1, 2, 3], dtype="int64") + ser2 = Series(ser._mgr, dtype="int32") + assert not np.shares_memory(get_array(ser), get_array(ser2)) + if using_copy_on_write: + assert ser2._mgr._has_no_reference(0) + + @pytest.mark.parametrize("func", [lambda x: x, lambda x: x._mgr]) @pytest.mark.parametrize("columns", [None, ["a"]]) def test_dataframe_constructor_mgr_or_df(using_copy_on_write, columns, func):