-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
DEP: Deprecate NPY_CHAR #8948
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
DEP: Deprecate NPY_CHAR #8948
Conversation
f549803
to
34369b7
Compare
I used f2py quite a bit, so tried to review, but realized I don't understand things well enough to be of much use. Might it be an idea to warn on the mailing list and specifically ask people to add simple test cases for string behaviour that they know works right now? (my own code only passed through numbers, so is of little use, sadly). |
strings were apparently never really well supported and the few stackoverflow entries I have found are full of confused users. It has never been updated from the numarray times. |
thanks for picking this up Julian! |
Fortran character strings and arrays are very common in Fortran codes. So, please do not assume that there are not many users who need to wrap such Fortran codes for Python. I have helped out number of users in private regarding wrapping strings and string arrays. The fundamental trick is to not assume that Fortran strings (mutable) can be mapped directly to Python strings (immutable), and back. I have found that the mutability of strings in different languages is the main source of confusion. I agree that f2py can be improved regarding strings support and I have promised to do that years ago. However, this work takes some time but it is really hard for me to find couple of weeks to do the required work. |
we don't need full string supports now, we just need to remove the NPY_CHAR usage. |
I checked this PR with a test case containing
and the test script gives the same output as with NPY_CHAR enabled. |
numpy/f2py/src/fortranobject.c
Outdated
@@ -701,6 +706,15 @@ PyArrayObject* array_from_pyobj(const int type_num, | |||
} | |||
|
|||
descr = PyArray_DescrFromType(type_num); | |||
/* compatibility with NPY_CHAR */ | |||
if (type_num == NPY_STRING) { | |||
descr = PyArray_DescrNew(descr); |
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.
one could use PyArray_DESCR_REPLACE
but that decrefs and PyArray_DescrFromType does not incref basic types.
I assume that is actually a bug we just get away with it because we likely leak descriptors all over the place.
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.
oh it does incref I am just to dumb to read
fba23ca
to
245a52d
Compare
@@ -4435,6 +4436,13 @@ PyArray_DescrFromType(int type) | |||
return NULL; | |||
} | |||
else if ((type == NPY_CHAR) || (type == NPY_CHARLTR)) { |
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.
Puzzled by the distinction between CHAR
and CHARLTR
- and why this patch seems to translate CHAR
into CHARLTR
now
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.
It triggers some old numarray compatibility code. It probably doesn't work as f2py might very well be the only remaining user.
But this patch doesn't change anything in this regard.
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.
The CHAR_LTR
refers to the dtype(...).char
attribute, which is the only difference from the string type.
In [1]: dtype('c') == dtype('S1')
Out[1]: True
@juliantaylor Needs a release note. |
Also needs an entry in |
|
||
#if !defined _NPY_NO_DEPRECATIONS && \ |
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.
Would look better with the pseudo functional form defined(...)
.
@@ -4435,6 +4436,13 @@ PyArray_DescrFromType(int type) | |||
return NULL; | |||
} | |||
else if ((type == NPY_CHAR) || (type == NPY_CHARLTR)) { | |||
if (type == NPY_CHAR) { | |||
if (DEPRECATE("The NPY_CHAR type_num is deprecated. " | |||
"Please port your code to use " |
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.
Need comment with date and numpy version. Something like
/* 2017-04-25, 1.13 */
@@ -608,6 +609,13 @@ incref_elide_l(PyObject *dummy, PyObject *args) | |||
return res; | |||
} | |||
|
|||
static PyObject * | |||
npy_char_deprecation(PyObject *dummy) | |||
{ |
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.
Need a note as to why this is done this way. I assume to get a deprecation warning.
cppmacros[ | ||
m] = '#define %s(v,dims) (PyArray_SimpleNewFromData(1,dims,NPY_CHAR,(char *)v))' % (m) | ||
m] = '#define %s(v,dims) (PyArray_New(&PyArray_Type, 1, dims, NPY_STRING, NULL, v, 1, NPY_ARRAY_CARRAY, NULL))' % (m) |
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.
Be good to break this string into shorter lines. Breaking the index bracket to get a continuation line is just weird, but that is for another day.
numpy/f2py/src/fortranobject.c
Outdated
@@ -679,6 +679,11 @@ PyArrayObject* array_from_pyobj(const int type_num, | |||
|| ((intent & F2PY_OPTIONAL) && (obj==Py_None)) | |||
) { | |||
/* intent(cache), optional, intent(hide) */ | |||
int itemsize = 0; | |||
/* compatibility with NPY_CHAR */ |
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.
No zero sized strings the reason for 1?
EDIT: I am curious as to why it is set to 0 as 'c' is already 'S1'.
return NULL; | ||
} | ||
descr->elsize = 1; | ||
descr->type = NPY_CHARLTR; |
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.
Do we need to keep using NPY_CHARLTR
? The only difference from S1
I can see is that that dtype('c').char
is 'c'.
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.
probably not, but that define doesn't really bother use in a non-cosmetic way.
numpy/f2py/src/fortranobject.c
Outdated
@@ -691,7 +696,7 @@ PyArrayObject* array_from_pyobj(const int type_num, | |||
} | |||
arr = (PyArrayObject *) | |||
PyArray_New(&PyArray_Type, rank, dims, type_num, | |||
NULL,NULL,0, | |||
NULL,NULL,itemsize, |
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.
I think you can just set this to 1
. It is ignored for types of fixed size, which should be the case for NPY_CHAR and all the numeric types, so only used for string types
numpy/f2py/src/fortranobject.c
Outdated
PyArray_New(&PyArray_Type, PyArray_NDIM(arr), PyArray_DIMS(arr), type_num, | ||
NULL,NULL,0, | ||
NULL,NULL,itemsize, |
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.
See above.
numpy/core/tests/test_multiarray.py
Outdated
@@ -342,6 +342,10 @@ def test_array_cont(self): | |||
assert_(np.ascontiguousarray(d).flags.c_contiguous) | |||
assert_(np.asfortranarray(d).flags.f_contiguous) | |||
|
|||
def test_npy_char_deprecation(self): |
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.
Belongs in test_deprecations.py
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.
I can't get it to work the test_deprecation way.
class TestNPY_CHAR(_DeprecationTestCase):
def test_npy_char_deprecation(self):
from numpy.core.multiarray_tests import npy_char_deprecation
self.assert_deprecated(npy_char_deprecation)
does not work, it says AssertionError: No error raised during function call
. How is the test supposed to look like?
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.
Its not really important to use that infrastructure anymore I think. That said, this may be correct, since the test checks both that the warning is given, as well as tests that an error is raised when the warning is set to "raise".
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.
well, I guess this would work out with that test, if you just return the descriptor in the test function (since it should be NULL on error I guess).
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.
ah that was it thanks. Updated.
@juliantaylor Could you finish this up for 1.13? |
245a52d
to
9c39207
Compare
Thanks Julian. |
This avoids the following compilation message sherpa/include/sherpa/extension.hh:32:30: warning: ‘NPY_CHAR’ is deprecated: Use NPY_STRING [-Wdeprecated-declarations] and avoids a deprecation warning when running code in NumPy 1.13 and higher (see numpy/numpy#8948). The NPY_STRING symbol was added in NumPy 1.7, which I think is early enough that we don't need to try and support both the old and new versions (i.e. we do not guarantee support for Sherpa using versions as old as NumPy 1.7).
@juliantaylor We finally have a report of an issue, #10027. |
Do the deprecation that should have happened 7 releases ago.
Attempt to fix f2py but there are no tests for the NPY_CHAR code so it is most likely busted.
As f2pys usage of NPY_CHAR severely hinders further development by blocking addition of new dtypes without breaking ABI or baking more hacks into our existing ABI I say release it and fix as reports come in.