Skip to content

Commit 42bd6db

Browse files
mattiperic-wieser
authored andcommitted
BUG: test, fix flexible dtype conversion on class with __array__ (numpy#15076)
Fixes issue numpygh-12256 where import numpy as np class MyArray: def __array__(self, result=None): return np.array(['0'*70], dtype=object) np.array(MyArray(), dtype=str) # has dtype U64, not U70 The problem was the result of obj.__array__ was not used when filling out a flexible dtype "by-value". I also renamed a test file, over time we should move the tests related to array protocol into it. * BUG: test, fix flexible dtype conversion on class with __array__ * Update numpy/core/_add_newdocs.py Thanks for the correction Co-Authored-By: Eric Wieser <[email protected]> Co-authored-by: Eric Wieser <[email protected]>
1 parent 4f97229 commit 42bd6db

File tree

4 files changed

+46
-32
lines changed

4 files changed

+46
-32
lines changed

numpy/core/_add_newdocs.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,7 +2507,7 @@
25072507

25082508

25092509
add_newdoc('numpy.core.multiarray', 'ndarray', ('__array__',
2510-
""" a.__array__(|dtype) -> reference if type unchanged, copy otherwise.
2510+
""" a.__array__([dtype], /) -> reference if type unchanged, copy otherwise.
25112511
25122512
Returns either a new reference to self if dtype is not given or a new array
25132513
of provided data type if dtype is different from the current dtype of the
@@ -6871,4 +6871,3 @@ def add_newdoc_for_scalar_type(obj, fixed_aliases, doc):
68716871
>>> np.{ftype}(-.25).as_integer_ratio()
68726872
(-1, 4)
68736873
""".format(ftype=float_name)))
6874-

numpy/core/src/multiarray/ctors.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1909,7 +1909,7 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
19091909

19101910
/* If the requested dtype is flexible, adapt it */
19111911
if (newtype != NULL) {
1912-
newtype = PyArray_AdaptFlexibleDType(op,
1912+
newtype = PyArray_AdaptFlexibleDType((arr == NULL) ? op : (PyObject *)arr,
19131913
(dtype == NULL) ? PyArray_DESCR(arr) : dtype,
19141914
newtype);
19151915
if (newtype == NULL) {

numpy/core/tests/test_issue14735.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

numpy/core/tests/test_protocols.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import pytest
2+
import warnings
3+
import numpy as np
4+
5+
6+
@pytest.mark.filterwarnings("error")
7+
def test_getattr_warning():
8+
# issue gh-14735: make sure we clear only getattr errors, and let warnings
9+
# through
10+
class Wrapper:
11+
def __init__(self, array):
12+
self.array = array
13+
14+
def __len__(self):
15+
return len(self.array)
16+
17+
def __getitem__(self, item):
18+
return type(self)(self.array[item])
19+
20+
def __getattr__(self, name):
21+
if name.startswith("__array_"):
22+
warnings.warn("object got converted", UserWarning, stacklevel=1)
23+
24+
return getattr(self.array, name)
25+
26+
def __repr__(self):
27+
return "<Wrapper({self.array})>".format(self=self)
28+
29+
array = Wrapper(np.arange(10))
30+
with pytest.raises(UserWarning, match="object got converted"):
31+
np.asarray(array)
32+
33+
34+
def test_array_called():
35+
class Wrapper:
36+
val = '0' * 100
37+
def __array__(self, result=None):
38+
return np.array([self.val], dtype=object)
39+
40+
41+
wrapped = Wrapper()
42+
arr = np.array(wrapped, dtype=str)
43+
assert arr.dtype == 'U100'
44+
assert arr[0] == Wrapper.val

0 commit comments

Comments
 (0)