diff options
author | Sebastian Berg <sebastianb@nvidia.com> | 2023-02-26 00:26:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-26 00:26:34 +0100 |
commit | e141d9074e95bbdaa33ce727e9c9baa33d00875a (patch) | |
tree | 792edac50335909a914f2a17c21828a7515ac18e /numpy | |
parent | 78221d0dc4cd1c4f44114d85c73d665d6846c090 (diff) | |
parent | 284523848164454f8d3f780824c1a827477c9957 (diff) | |
download | numpy-e141d9074e95bbdaa33ce727e9c9baa33d00875a.tar.gz |
Merge pull request #23269 from tylerjereddy/treddy_ma_deepcopy_fix
BUG: masked array proper deepcopies
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/ma/core.py | 14 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 45 |
2 files changed, 58 insertions, 1 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index b76ff8ea9..9584e56d2 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -2870,7 +2870,13 @@ class MaskedArray(ndarray): _data._mask = _data._mask.copy() # Reset the shape of the original mask if getmask(data) is not nomask: - data._mask.shape = data.shape + # gh-21022 encounters an issue here + # because data._mask.shape is not writeable, but + # the op was also pointless in that case, because + # the shapes were the same, so we can at least + # avoid that path + if data._mask.shape != data.shape: + data._mask.shape = data.shape else: # Case 2. : With a mask in input. # If mask is boolean, create an array of True or False @@ -6300,6 +6306,12 @@ class MaskedArray(ndarray): memo[id(self)] = copied for (k, v) in self.__dict__.items(): copied.__dict__[k] = deepcopy(v, memo) + # as clearly documented for np.copy(), you need to use + # deepcopy() directly for arrays of object type that may + # contain compound types--you cannot depend on normal + # copy semantics to do the right thing here + if self.dtype.hasobject: + copied._data[...] = deepcopy(copied._data) return copied diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 7d23e32ec..172a1ee8d 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -8,6 +8,7 @@ __author__ = "Pierre GF Gerard-Marchant" import sys import warnings +import copy import operator import itertools import textwrap @@ -5570,3 +5571,47 @@ note original note""" assert_equal(np.ma.core.doc_note(method.__doc__, "note"), expected_doc) + + +def test_gh_22556(): + source = np.ma.array([0, [0, 1, 2]], dtype=object) + deepcopy = copy.deepcopy(source) + deepcopy[1].append('this should not appear in source') + assert len(source[1]) == 3 + + +def test_gh_21022(): + # testing for absence of reported error + source = np.ma.masked_array(data=[-1, -1], mask=True, dtype=np.float64) + axis = np.array(0) + result = np.prod(source, axis=axis, keepdims=False) + result = np.ma.masked_array(result, + mask=np.ones(result.shape, dtype=np.bool_)) + array = np.ma.masked_array(data=-1, mask=True, dtype=np.float64) + copy.deepcopy(array) + copy.deepcopy(result) + + +def test_deepcopy_2d_obj(): + source = np.ma.array([[0, "dog"], + [1, 1], + [[1, 2], "cat"]], + mask=[[0, 1], + [0, 0], + [0, 0]], + dtype=object) + deepcopy = copy.deepcopy(source) + deepcopy[2, 0].extend(['this should not appear in source', 3]) + assert len(source[2, 0]) == 2 + assert len(deepcopy[2, 0]) == 4 + assert_equal(deepcopy._mask, source._mask) + deepcopy._mask[0, 0] = 1 + assert source._mask[0, 0] == 0 + + +def test_deepcopy_0d_obj(): + source = np.ma.array(0, mask=[0], dtype=object) + deepcopy = copy.deepcopy(source) + deepcopy[...] = 17 + assert_equal(source, 0) + assert_equal(deepcopy, 17) |