8000 Merge pull request #6588 from jjhelmus/fix_copy_mutable · numpy/numpy@7389b51 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7389b51

Browse files
committed
Merge pull request #6588 from jjhelmus/fix_copy_mutable
BUG: immutable _arraymethod function in ma.core
2 parents 78d9628 + db85ede commit 7389b51

File tree

2 files changed

+30
-45
lines changed

2 files changed

+30
-45
lines changed

numpy/ma/core.py

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,25 +2467,18 @@ def flatten_sequence(iterable):
24672467
return out
24682468

24692469

2470-
class _arraymethod(object):
2470+
def _arraymethod(funcname, onmask=True):
24712471
"""
2472-
Define a wrapper for basic array methods.
2472+
Return a class method wrapper around a basic array method.
24732473
2474-
Upon call, returns a masked array, where the new ``_data`` array is
2475-
the output of the corresponding method called on the original
2476-
``_data``.
2474+
Creates a class method which returns a masked array, where the new
2475+
``_data`` array is the output of the corresponding basic method called
2476+
on the original ``_data``.
24772477
24782478
If `onmask` is True, the new mask is the output of the method called
24792479
on the initial mask. Otherwise, the new mask is just a reference
24802480
to the initial mask.
24812481
2482-
Attributes
2483-
----------
2484-
_onmask : bool
2485-
Holds the `onmask` parameter.
2486-
obj : object
2487-
The object calling `_arraymethod`.
2488-
24892482
Parameters
24902483
----------
24912484
funcname : str
@@ -2495,47 +2488,31 @@ class _arraymethod(object):
24952488
alone (False). Default is True. Make available as `_onmask`
24962489
attribute.
24972490
2498-
"""
2499-
2500-
def __init__(self, funcname, onmask=True):
2501-
self.__name__ = funcname
2502-
self._onmask = onmask
2503-
self.obj = None
2504-
self.__doc__ = self.getdoc()
2505-
2506-
def getdoc(self):
2507-
"Return the doc of the function (from the doc of the method)."
2508-
methdoc = getattr(ndarray, self.__name__, None) or \
2509-
getattr(np, self.__name__, None)
2510-
if methdoc is not None:
2511-
return methdoc.__doc__
2512-
2513-
def __get__(self, obj, objtype=None):
2514-
self.obj = obj
2515-
return self
2491+
Returns
2492+
-------
2493+
method : instancemethod
2494+
Class method wrapper of the specified basic array method.
25162495
2517-
def __call__(self, *args, **params):
2518-
methodname = self.__name__
2519-
instance = self.obj
2520-
# Fallback : if the instance has not been initialized, use the first
2521-
# arg
2522-
if instance is None:
2523-
args = list(args)
2524-
instance = args.pop(0)
2525-
data = instance._data
2526-
mask = instance._mask
2527-
cls = type(instance)
2528-
result = getattr(data, methodname)(*args, **params).view(cls)
2529-
result._update_from(instance)
2496+
"""
2497+
def wrapped_method(self, *args, **params):
2498+
result = getattr(self._data, funcname)(*args, **params)
2499+
result = result.view(type(self))
2500+
result._update_from(self)
2501+
mask = self._mask
25302502
if result.ndim:
2531-
if not self._onmask:
2503+
if not onmask:
25322504
result.__setmask__(mask)
25332505
elif mask is not nomask:
2534-
result.__setmask__(getattr(mask, methodname)(*args, **params))
2506+
result.__setmask__(getattr(mask, funcname)(*args, **params))
25352507
else:
25362508
if mask.ndim and (not mask.dtype.names and mask.all()):
25372509
return masked
25382510
return result
2511+
methdoc = getattr(ndarray, funcname, None) or getattr(np, funcname, None)
2512+
if methdoc is not None:
2513+
wrapped_method.__doc__ = methdoc.__doc__
2514+
wrapped_method.__name__ = funcname
2515+
return wrapped_method
25392516

25402517

25412518
class MaskedIterator(object):

numpy/ma/tests/test_core.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,14 @@ def test_copy(self):
401401
assert_not_equal(y._data.ctypes.data, x._data.ctypes.data)
402402
assert_not_equal(y._mask.ctypes.data, x._mask.ctypes.data)
403403

404+
def test_copy_immutable(self):
405+
# Tests that the copy method is immutable, GitHub issue #5247
406+
a = np.ma.array([1, 2, 3])
407+
b = np.ma.array([4, 5, 6])
408+
a_copy_method = a.copy
409+
b.copy
410+
assert_equal(a_copy_method(), [1, 2, 3])
411+
404412
def test_deepcopy(self):
405413
from copy import deepcopy
406414
a = array([0, 1, 2], mask=[False, True, False])

0 commit comments

Comments
 (0)
0