@@ -1477,16 +1477,7 @@ _array_from_array_like(PyObject *op,
1477
1477
}
1478
1478
}
1479
1479
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 ) {
1490
1481
tmp = PyArray_FromArrayAttr_int (op , requested_dtype , never_copy );
1491
1482
if (tmp == NULL ) {
1492
1483
return NULL ;
@@ -2418,9 +2409,8 @@ PyArray_FromInterface(PyObject *origin)
2418
2409
* @param descr The desired `arr.dtype`, passed into the `__array__` call,
2419
2410
* as information but is not checked/enforced!
2420
2411
* @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)`.
2424
2414
* @returns NotImplemented if `__array__` is not defined or a NumPy array
2425
2415
* (or subclass). On error, return NULL.
2426
2416
*/
@@ -2438,15 +2428,6 @@ PyArray_FromArrayAttr_int(
2438
2428
}
2439
2429
return Py_NotImplemented ;
2440
2430
}
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
- return NULL ;
2449
- }
2450
2431
2451
2432
if (PyType_Check (op ) && PyObject_HasAttrString (array_meth , "__get__" )) {
2452
2433
/*
@@ -2458,12 +2439,33 @@ PyArray_FromArrayAttr_int(
2458
2439
Py_DECREF (array_meth );
2459
2440
return Py_NotImplemented ;
2460
2441
}
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
+ Py_DECREF (type );
2456
+ Py_XDECREF (value );
2457
+ Py_XDECREF (traceback );
2458
+ if (PyErr_WarnEx (PyExc_UserWarning ,
2459
+ "__array__ should implement 'dtype' and 'copy' keywords" , 1 ) < 0 ) {
2460
+ return NULL ;
2461
+ }
2462
+ new = PyObject_Call (array_meth , args , NULL );
2463
+ } else {
2464
+ PyErr_Restore (type , value , traceback );
2465
+ return NULL ;
2466
+ }
2466
2467
}
2468
+
2467
2469
Py_DECREF (array_meth );
2468
2470
if (new == NULL ) {
2469
2471
return NULL ;
0 commit comments