Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitee8993b

Browse files
committed
np.array: call __array__ with copy keyword
1 parente0c24ae commitee8993b

24 files changed

+72
-72
lines changed

‎numpy/_core/src/multiarray/ctors.c‎

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,16 +1477,7 @@ _array_from_array_like(PyObject *op,
14771477
}
14781478
}
14791479

1480-
/*
1481-
* If op supplies the __array__ function.
1482-
* The documentation says this should produce a copy, so
1483-
* we skip this method if writeable is true, because the intent
1484-
* of writeable is to modify the operand.
1485-
* XXX: If the implementation is wrong, and/or if actual
1486-
* usage requires this behave differently,
1487-
* this should be changed!
1488-
*/
1489-
if (!writeable&&tmp==Py_NotImplemented) {
1480+
if (tmp==Py_NotImplemented) {
14901481
tmp=PyArray_FromArrayAttr_int(op,requested_dtype,never_copy);
14911482
if (tmp==NULL) {
14921483
returnNULL;
@@ -2418,9 +2409,8 @@ PyArray_FromInterface(PyObject *origin)
24182409
* @param descr The desired `arr.dtype`, passed into the `__array__` call,
24192410
* as information but is not checked/enforced!
24202411
* @param never_copy Specifies that a copy is not allowed.
2421-
* NOTE: Currently, this means an error is raised instead of calling
2422-
* `op.__array__()`. In the future we could call for example call
2423-
* `op.__array__(never_copy=True)` instead.
2412+
* NOTE: For false it passes `op.__array__(copy=None)`,
2413+
* for true: `op.__array__(copy=False)`.
24242414
* @returns NotImplemented if `__array__` is not defined or a NumPy array
24252415
* (or subclass). On error, return NULL.
24262416
*/
@@ -2438,15 +2428,6 @@ PyArray_FromArrayAttr_int(
24382428
}
24392429
returnPy_NotImplemented;
24402430
}
2441-
if (never_copy) {
2442-
/* Currently, we must always assume that `__array__` returns a copy */
2443-
PyErr_SetString(PyExc_ValueError,
2444-
"Unable to avoid copy while converting from an object "
2445-
"implementing the `__array__` protocol. NumPy cannot ensure "
2446-
"that no copy will be made.");
2447-
Py_DECREF(array_meth);
2448-
returnNULL;
2449-
}
24502431

24512432
if (PyType_Check(op)&&PyObject_HasAttrString(array_meth,"__get__")) {
24522433
/*
@@ -2458,12 +2439,30 @@ PyArray_FromArrayAttr_int(
24582439
Py_DECREF(array_meth);
24592440
returnPy_NotImplemented;
24602441
}
2461-
if (descr==NULL) {
2462-
new=PyObject_CallFunction(array_meth,NULL);
2463-
}
2464-
else {
2465-
new=PyObject_CallFunction(array_meth,"O",descr);
2442+
2443+
PyObject*copy=never_copy ?Py_False :Py_None;
2444+
PyObject*kwargs=PyDict_New();
2445+
PyDict_SetItemString(kwargs,"copy",copy);
2446+
PyObject*args=descr!=NULL ?PyTuple_Pack(1,descr) :PyTuple_New(0);
2447+
2448+
new=PyObject_Call(array_meth,args,kwargs);
2449+
2450+
if (PyErr_Occurred()) {
2451+
PyObject*type,*value,*traceback;
2452+
PyErr_Fetch(&type,&value,&traceback);
2453+
if (PyUnicode_Check(value)&&PyUnicode_CompareWithASCIIString(value,
2454+
"__array__() got an unexpected keyword argument 'copy'")==0) {
2455+
if (PyErr_WarnEx(PyExc_UserWarning,
2456+
"__array__ should implement 'copy' keyword",1)<0) {
2457+
returnNULL;
2458+
}
2459+
new=PyObject_Call(array_meth,args,NULL);
2460+
}else {
2461+
PyErr_Restore(type,value,traceback);
2462+
returnNULL;
2463+
}
24662464
}
2465+
24672466
Py_DECREF(array_meth);
24682467
if (new==NULL) {
24692468
returnNULL;

‎numpy/_core/src/multiarray/iterators.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ static PyMappingMethods iter_as_mapping = {
10721072
* ignored.
10731073
*/
10741074
staticPyArrayObject*
1075-
iter_array(PyArrayIterObject*it,PyObject*NPY_UNUSED(op))
1075+
iter_array(PyArrayIterObject*it,PyObject*NPY_UNUSED(args),PyObject*NPY_UNUSED(kwds))
10761076
{
10771077

10781078
PyArrayObject*ret;
@@ -1121,7 +1121,7 @@ static PyMethodDef iter_methods[] = {
11211121
/* to get array */
11221122
{"__array__",
11231123
(PyCFunction)iter_array,
1124-
METH_VARARGS,NULL},
1124+
METH_VARARGS |METH_KEYWORDS,NULL},
11251125
{"copy",
11261126
(PyCFunction)iter_copy,
11271127
METH_VARARGS,NULL},
@@ -1133,7 +1133,7 @@ iter_richcompare(PyArrayIterObject *self, PyObject *other, int cmp_op)
11331133
{
11341134
PyArrayObject*new;
11351135
PyObject*ret;
1136-
new= (PyArrayObject*)iter_array(self,NULL);
1136+
new= (PyArrayObject*)iter_array(self,NULL,NULL);
11371137
if (new==NULL) {
11381138
returnNULL;
11391139
}

‎numpy/_core/src/multiarray/multiarraymodule.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ _array_fromobject_generic(
16551655
if (copy==NPY_COPY_ALWAYS) {
16561656
flags=NPY_ARRAY_ENSURECOPY;
16571657
}
1658-
elseif (copy==NPY_COPY_NEVER) {
1658+
elseif (copy==NPY_COPY_NEVER) {
16591659
flags=NPY_ARRAY_ENSURENOCOPY;
16601660
}
16611661
if (order==NPY_CORDER) {

‎numpy/_core/tests/test_api.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ def test_array_array():
8787
assert_equal(bytes(np.array(o).data),bytes(a.data))
8888

8989
# test array
90-
o=type("o", (object,),
91-
dict(__array__=lambda*x:np.array(100.0,dtype=np.float64)))()
90+
defcustom__array__(self,dtype=None,copy=None):
91+
returnnp.array(100.0,dtype=dtype,copy=copy)
92+
93+
o=type("o", (object,),dict(__array__=custom__array__))()
9294
assert_equal(np.array(o,dtype=np.float64),np.array(100.0,np.float64))
9395

9496
# test recursion

‎numpy/_core/tests/test_array_coercion.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class ArrayDunder(_SequenceLike):
5353
def__init__(self,a):
5454
self.a=a
5555

56-
def__array__(self,dtype=None):
56+
def__array__(self,dtype=None,copy=None):
5757
returnself.a
5858

5959
yieldparam(ArrayDunder,id="__array__")
@@ -706,7 +706,7 @@ def __array_interface__(self):
706706
def__array_struct__(self):
707707
pass
708708

709-
def__array__(self):
709+
def__array__(self,dtype=None,copy=None):
710710
pass
711711

712712
arr=np.array(ArrayLike)
@@ -832,7 +832,7 @@ class TestSpecialAttributeLookupFailure:
832832

833833
classWeirdArrayLike:
834834
@property
835-
def__array__(self):
835+
def__array__(self,dtype=None,copy=None):
836836
raiseRuntimeError("oops!")
837837

838838
classWeirdArrayInterface:

‎numpy/_core/tests/test_deprecations.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ class TestDeprecatedArrayWrap(_DeprecationTestCase):
696696

697697
deftest_deprecated(self):
698698
classTest1:
699-
def__array__(self,):
699+
def__array__(self,dtype=None,copy=None):
700700
returnnp.arange(4)
701701

702702
def__array_wrap__(self,arr,context=None):

‎numpy/_core/tests/test_indexing.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def __index__(self):
420420

421421
classArrayLike:
422422
# Simple array, should behave like the array
423-
def__array__(self):
423+
def__array__(self,dtype=None,copy=None):
424424
returnnp.array(0)
425425

426426
a=np.zeros(())

‎numpy/_core/tests/test_mem_overlap.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ class MyArray2:
553553
def__init__(self,data):
554554
self.data=data
555555

556-
def__array__(self):
556+
def__array__(self,dtype=None,copy=None):
557557
returnself.data
558558

559559
forclsin [MyArray,MyArray2]:

‎numpy/_core/tests/test_multiarray.py‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ class TestCreation:
890890
"""
891891
deftest_from_attribute(self):
892892
classx:
893-
def__array__(self,dtype=None):
893+
def__array__(self,dtype=None,copy=None):
894894
pass
895895

896896
assert_raises(ValueError,np.array,x())
@@ -6855,7 +6855,7 @@ def test_huge_vectordot(self, dtype):
68556855
deftest_dtype_discovery_fails(self):
68566856
# See gh-14247, error checking was missing for failed dtype discovery
68576857
classBadObject(object):
6858-
def__array__(self):
6858+
def__array__(self,dtype=None,copy=None):
68596859
raiseTypeError("just this tiny mint leaf")
68606860

68616861
withpytest.raises(TypeError):
@@ -8432,7 +8432,7 @@ def test___array__(self):
84328432
base_arr=np.arange(10)
84338433

84348434
classArrayLike:
8435-
def__array__(self):
8435+
def__array__(self,dtype=None,copy=None):
84368436
# __array__ should return a copy, numpy cannot know this
84378437
# however.
84388438
returnbase_arr
@@ -8447,15 +8447,11 @@ def __array__(self):
84478447
# may be open for change:
84488448
assertresisnotbase_arr
84498449

8450-
forcopyinself.if_needed_vals:
8450+
forcopyinself.if_needed_vals+self.false_vals:
84518451
res=np.array(arr,copy=copy)
84528452
assert_array_equal(res,base_arr)
84538453
assertresisbase_arr# numpy trusts the ArrayLike
84548454

8455-
forcopyinself.false_vals:
8456-
withpytest.raises(ValueError):
8457-
np.array(arr,copy=copy)
8458-
84598455
deftest___array__copy_arg(self):
84608456
a=np.ones((10,10),dtype=int)
84618457

@@ -9709,7 +9705,7 @@ def test_no_loop_gives_all_true_or_false(dt1, dt2):
97099705
operator.gt])
97109706
deftest_comparisons_forwards_error(op):
97119707
classNotArray:
9712-
def__array__(self):
9708+
def__array__(self,dtype=None,copy=None):
97139709
raiseTypeError("run you fools")
97149710

97159711
withpytest.raises(TypeError,match="run you fools"):

‎numpy/_core/tests/test_overrides.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ def test_function_like():
712712
asserttype(np.mean)isnp._core._multiarray_umath._ArrayFunctionDispatcher
713713

714714
classMyClass:
715-
def__array__(self):
715+
def__array__(self,dtype=None,copy=None):
716716
# valid argument to mean:
717717
returnnp.arange(3)
718718

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp