From cc142497707bf085e2b24f7da74b7ae0ee15d09a Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Thu, 16 Mar 2023 20:29:25 +0100 Subject: [PATCH 1/2] BUG-CoW: from_records not tracking references when called with df --- pandas/core/frame.py | 2 +- pandas/tests/copy_view/test_constructors.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c2ee684751b5f..ce4f65ff91f39 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -2205,7 +2205,7 @@ def from_records( data = data.set_index(index) if exclude is not None: data = data.drop(columns=exclude) - return data + return data.copy(deep=False) result_index = None diff --git a/pandas/tests/copy_view/test_constructors.py b/pandas/tests/copy_view/test_constructors.py index 6cf45c194707e..ca457e4724765 100644 --- a/pandas/tests/copy_view/test_constructors.py +++ b/pandas/tests/copy_view/test_constructors.py @@ -179,3 +179,18 @@ def test_dataframe_from_dict_of_series_with_dtype(index): df.iloc[0, 0] = 100 arr_after = get_array(df, "a") assert np.shares_memory(arr_before, arr_after) + + +def test_dataframe_from_records_with_dataframe(using_copy_on_write): + df = DataFrame({"a": [1, 2, 3]}) + df_orig = df.copy() + with tm.assert_produces_warning(FutureWarning): + df2 = DataFrame.from_records(df) + if using_copy_on_write: + assert not df._mgr._has_no_reference(0) + assert np.shares_memory(get_array(df, "a"), get_array(df2, "a")) + df2.iloc[0, 0] = 100 + if using_copy_on_write: + tm.assert_frame_equal(df, df_orig) + else: + tm.assert_frame_equal(df, df2) From ad686f7ec002e6cbe1bb69df43a104ef83c111ce Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Thu, 16 Mar 2023 20:31:04 +0100 Subject: [PATCH 2/2] Add whatsnew --- doc/source/whatsnew/v2.0.0.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 55185afc0a098..2b3b6287d0e9b 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -190,6 +190,9 @@ Copy-on-Write improvements of Series objects and specifying ``copy=False``, will now use a lazy copy of those Series objects for the columns of the DataFrame (:issue:`50777`) +- The :meth:`DataFrame.from_records` will now respect Copy-on-Write when called + with a :class:`DataFrame`. + - Trying to set values using chained assignment (for example, ``df["a"][1:3] = 0``) will now always raise an warning when Copy-on-Write is enabled. In this mode, chained assignment can never work because we are always setting into a temporary