-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
ENH, DEP refactor updateifcopy #9451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,7 +112,7 @@ PyArray_SetUpdateIfCopyBase(PyArrayObject *arr, PyArrayObject *base) | |
* references. | ||
*/ | ||
((PyArrayObject_fields *)arr)->base = (PyObject *)base; | ||
PyArray_ENABLEFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY); | ||
PyArray_ENABLEFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ugh, this is dubious. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, will add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I don't understand the naming scheme here. IIRC (from my phone), There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct, so maybe |
||
PyArray_CLEARFLAGS(base, NPY_ARRAY_WRITEABLE); | ||
|
||
return 0; | ||
|
@@ -372,10 +372,63 @@ PyArray_TypeNumFromName(char *str) | |
return NPY_NOTYPE; | ||
} | ||
|
||
/*NUMPY_API | ||
* | ||
* If UPDATEIFCOPY and self has data, reset the base WRITEABLE flag, | ||
* copy the local data to base, release the local data, and set flags | ||
* appropriately. Return 0 if not relevant, 1 if success, < 0 on failure | ||
*/ | ||
NPY_NO_EXPORT int | ||
PyArray_ResolveUpdateIfCopy(PyArrayObject * self) | ||
{ | ||
PyArrayObject_fields *fa = (PyArrayObject_fields *)self; | ||
if (fa && fa->base) { | ||
if (fa->flags & NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT) { | ||
/* | ||
* UPDATEIFCOPY means that fa->base's data | ||
* should be updated with the contents | ||
* of self. | ||
* fa->base->flags is not WRITEABLE to protect the relationship | ||
* unlock it. | ||
*/ | ||
int retval = 0; | ||
PyArray_ENABLEFLAGS(((PyArrayObject *)fa->base), | ||
NPY_ARRAY_WRITEABLE); | ||
PyArray_CLEARFLAGS(self, NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT); | ||
retval = PyArray_CopyAnyInto((PyArrayObject *)fa->base, self); | ||
if (retval < 0) { | ||
/* this should never happen, how did the two copies of data | ||
* get out of sync? | ||
*/ | ||
return retval; | ||
} | ||
if ((fa->flags & NPY_ARRAY_OWNDATA) && fa->data) { | ||
/* Free internal references if an Object array */ | ||
if (PyDataType_FLAGCHK(fa->descr, NPY_ITEM_REFCOUNT)) { | ||
Py_INCREF(self); /*hold on to self */ | ||
PyArray_XDECREF(self); | ||
Py_DECREF(self); | ||
} | ||
npy_free_cache(fa->data, PyArray_NBYTES(self)); | ||
fa->data = NULL; | ||
PyArray_CLEARFLAGS(self, NPY_ARRAY_OWNDATA); | ||
} | ||
return 1; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
/*********************** end C-API functions **********************/ | ||
|
||
/* array object functions */ | ||
|
||
#ifdef PYPY_VERSION | ||
#ifndef DEPRECATE_UPDATEIFCOPY | ||
#define DEPRECATE_UPDATEIFCOPY | ||
#endif | ||
#endif | ||
|
||
static void | ||
array_dealloc(PyArrayObject *self) | ||
{ | ||
|
@@ -387,27 +440,24 @@ array_dealloc(PyArrayObject *self) | |
PyObject_ClearWeakRefs((PyObject *)self); | ||
} | ||
if (fa->base) { | ||
/* | ||
* UPDATEIFCOPY means that base points to an | ||
* array that should be updated with the contents | ||
* of this array upon destruction. | ||
* fa->base->flags must have been WRITEABLE | ||
* (checked previously) and it was locked here | ||
* thus, unlock it. | ||
*/ | ||
if (fa->flags & NPY_ARRAY_UPDATEIFCOPY) { | ||
PyArray_ENABLEFLAGS(((PyArrayObject *)fa->base), | ||
NPY_ARRAY_WRITEABLE); | ||
Py_INCREF(self); /* hold on to self in next call */ | ||
if (PyArray_CopyAnyInto((PyArrayObject *)fa->base, self) < 0) { | ||
PyErr_Print(); | ||
PyErr_Clear(); | ||
} | ||
/* | ||
* Don't need to DECREF -- because we are deleting | ||
*self already... | ||
int retval; | ||
Py_INCREF(self); /* hold on to self in next call */ | ||
retval = PyArray_ResolveUpdateIfCopy(self); | ||
if (retval < 0) | ||
{ | ||
PyErr_Print(); | ||
PyErr_Clear(); | ||
} | ||
#ifdef DEPRECATE_UPDATEIFCOPY | ||
if (retval > 0) { | ||
DEPRECATE("UPDATEIFCOPY resolution in array_dealloc is " | ||
"incompatible with PyPy and will be removed in " | ||
"the future"); | ||
/* dealloc must not raise an error, even if warning filters are set | ||
*/ | ||
PyErr_Clear(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch, will add a test as well |
||
} | ||
#endif | ||
/* | ||
* In any case base is pointing to something that we need | ||
* to DECREF -- either a view or a buffer object | ||
|
@@ -482,7 +532,7 @@ PyArray_DebugPrint(PyArrayObject *obj) | |
printf(" NPY_ALIGNED"); | ||
if (fobj->flags & NPY_ARRAY_WRITEABLE) | ||
printf(" NPY_WRITEABLE"); | ||
if (fobj->flags & NPY_ARRAY_UPDATEIFCOPY) | ||
if (fobj->flags & NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT) | ||
printf(" NPY_UPDATEIFCOPY"); | ||
printf("\n"); | ||
|
||
|
@@ -507,8 +557,6 @@ PyArray_SetDatetimeParseFunction(PyObject *op) | |
{ | ||
} | ||
|
||
|
||
|
||
/*NUMPY_API | ||
*/ | ||
NPY_NO_EXPORT int | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1009,7 +1009,7 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd, | |
} | ||
} | ||
else { | ||
fa->flags = (flags & ~NPY_ARRAY_UPDATEIFCOPY); | ||
fa->flags = (flags & ~NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should clear both versions of the flag, I think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
} | ||
fa->descr = descr; | ||
fa->base = (PyObject *)NULL; | ||
|
@@ -1703,7 +1703,8 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth, | |
|
||
/* If we got dimensions and dtype instead of an array */ | ||
if (arr == NULL) { | ||
if (flags & NPY_ARRAY_UPDATEIFCOPY) { | ||
if ((flags & NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT) || | ||
(flags & NPY_ARRAY_UPDATEIFCOPY)) { | ||
Py_XDECREF(newtype); | ||
PyErr_SetString(PyExc_TypeError, | ||
"UPDATEIFCOPY used for non-array input."); | ||
|
@@ -1811,6 +1812,7 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth, | |
* NPY_ARRAY_NOTSWAPPED, | ||
* NPY_ARRAY_ENSURECOPY, | ||
* NPY_ARRAY_UPDATEIFCOPY, | ||
* NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT, | ||
* NPY_ARRAY_FORCECAST, | ||
* NPY_ARRAY_ENSUREARRAY, | ||
* NPY_ARRAY_ELEMENTSTRIDES | ||
|
@@ -1835,10 +1837,13 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth, | |
* Fortran arrays are always behaved (aligned, | ||
* notswapped, and writeable) and not (C) CONTIGUOUS (if > 1d). | ||
* | ||
* NPY_ARRAY_UPDATEIFCOPY flag sets this flag in the returned array if a copy | ||
* is made and the base argument points to the (possibly) misbehaved array. | ||
* When the new array is deallocated, the original array held in base | ||
* is updated with the contents of the new array. | ||
* NPY_ARRAY_UPDATEIFCOPY is deprecated in favor of | ||
* NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT in 1.14 | ||
|
||
* NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT flag sets this flag in the returned | ||
* array if a copy is made and the base argument points to the (possibly) | ||
* misbehaved array. Before returning to python, PyArray_ResolveUpdateIfCopy | ||
* must be called to update the contents of the orignal array from the copy. | ||
* | ||
* NPY_ARRAY_FORCECAST will cause a cast to occur regardless of whether or not | ||
* it is safe. | ||
|
@@ -2005,7 +2010,16 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) | |
return NULL; | ||
} | ||
|
||
if (flags & NPY_ARRAY_UPDATEIFCOPY) { | ||
if ((flags & NPY_ARRAY_UPDATEIFCOPY) || | ||
(flags & NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT)) { | ||
if (flags & NPY_ARRAY_UPDATEIFCOPY) { | ||
if (DEPRECATE("Use NPY_ARRAY_UPDATEIFCOPY_CLEAR_B4_EXIT and" | ||
" be sure to call PyArray_ResolveUpdateIfCopy") < 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this have an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What kind of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ultimately yeah it should be deprecated, but I thought your plan was to initially introduce this with all the warnings hidden behind a |
||
/* 2017-07-24, 1.14 */ | ||
Py_DECREF(ret); | ||
return NULL; | ||
} | ||
} | ||
Py_INCREF(arr); | ||
if (PyArray_SetUpdateIfCopyBase(ret, arr) < 0) { | ||
Py_DECREF(ret); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be reverted -- if someone's using the deprecated
NPY_UPDATEIFCOPY
alias, then they should getNPY_ARRAY_UPDATEIFCOPY
semantics.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok