From 162236a56a29535b103bd10e875f50c744977b93 Mon Sep 17 00:00:00 2001 From: Floze <88098863+floze-the-genius@users.noreply.github.com> Date: Sun, 19 Jul 2026 06:33:17 +0400 Subject: [PATCH 1/2] Fix RawArray init kwargs retaining stale data --- mne/io/array/_array.py | 23 +++++++++++++++++++++ mne/io/array/tests/test_array.py | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/mne/io/array/_array.py b/mne/io/array/_array.py index f1c987cb006..6e0379db602 100644 --- a/mne/io/array/_array.py +++ b/mne/io/array/_array.py @@ -50,6 +50,29 @@ class RawArray(BaseRaw): * AU: misc """ + _extra_attributes = ("_init_kwargs_without_data",) + + @property + def _init_kwargs(self): + """Return constructor arguments without retaining stale data.""" + try: + kwargs = self._init_kwargs_without_data + except AttributeError: + # Support instances serialized before ``data`` was stored dynamically. + kwargs = self.__dict__.pop("_init_kwargs") + self._init_kwargs = kwargs + kwargs = self._init_kwargs_without_data + if kwargs is None: + return None + return dict(data=self._data, **kwargs) + + @_init_kwargs.setter + def _init_kwargs(self, kwargs): + if kwargs is not None: + kwargs = kwargs.copy() + kwargs.pop("data", None) + self._init_kwargs_without_data = kwargs + @verbose def __init__(self, data, info, first_samp=0, copy="auto", verbose=None): _validate_type(info, "info", "info") diff --git a/mne/io/array/tests/test_array.py b/mne/io/array/tests/test_array.py index edac2923c2d..1f414c9fcd7 100644 --- a/mne/io/array/tests/test_array.py +++ b/mne/io/array/tests/test_array.py @@ -2,6 +2,9 @@ # License: BSD-3-Clause # Copyright the MNE-Python contributors. +import gc +import pickle +import weakref from pathlib import Path import matplotlib.pyplot as plt @@ -74,6 +77,37 @@ def test_array_copy(): RawArray(data.astype(np.float32), info, copy=None) +def test_array_init_kwargs(): + """Test that constructor arguments do not retain stale array data.""" + data = np.zeros((1, 1000)) + data_ref = weakref.ref(data) + raw = RawArray(data, create_info(1, 1000.0, "eeg")) + + init_kwargs = raw._init_kwargs + assert isinstance(init_kwargs, dict) + assert tuple(init_kwargs) == ("data", "info", "first_samp", "copy", "verbose") + assert init_kwargs["data"] is raw._data + del init_kwargs, data + + raw.resample(500) + gc.collect() + assert data_ref() is None + assert raw._init_kwargs["data"] is raw._data + + raw_copy = raw.copy() + assert raw_copy._init_kwargs["data"] is raw_copy._data + assert raw_copy._data is not raw._data + + raw_reconstructed = RawArray(**raw._init_kwargs) + assert_allclose(raw_reconstructed.get_data(), raw.get_data()) + assert repr(raw_reconstructed) == repr(raw) + + raw_unpickled = pickle.loads(pickle.dumps(raw)) + assert raw_unpickled._init_kwargs["data"] is raw_unpickled._data + assert_allclose(raw_unpickled.get_data(), raw.get_data()) + assert repr(raw_unpickled) == repr(raw) + + @pytest.mark.slowtest def test_array_raw(): """Test creating raw from array.""" From 7e0b9771c649f8096d03fef9ff56d6d67961fca6 Mon Sep 17 00:00:00 2001 From: Floze <88098863+floze-the-genius@users.noreply.github.com> Date: Sun, 19 Jul 2026 06:33:58 +0400 Subject: [PATCH 2/2] Add changelog for RawArray retention fix --- doc/changes/dev/14075.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changes/dev/14075.bugfix.rst diff --git a/doc/changes/dev/14075.bugfix.rst b/doc/changes/dev/14075.bugfix.rst new file mode 100644 index 00000000000..7ab80de7a08 --- /dev/null +++ b/doc/changes/dev/14075.bugfix.rst @@ -0,0 +1 @@ +Fix :class:`mne.io.RawArray` constructor metadata retaining stale array data after operations replace the active data, by :newcontrib:`Floze`.