-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
BUG: Allow int
to be called on nested object arrays, fix np.str_.__int__
#10042
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
Conversation
int
to be called on nested object arraysint
to be called on nested object arrays, fix np.str_.__int__
numpy/core/src/multiarray/number.c
Outdated
"object array may be self-referencing"); | ||
Py_DECREF(pv); | ||
res = PyObject_CallMethodObjArgs(mod, "oct", o, NULL); | ||
Py_DECREF(module); |
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.
"module" is not defined, you probably meant "mod"
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.
Good catch, only tested on python 3 locally
numpy/core/src/multiarray/number.c
Outdated
Py_DECREF(pv); | ||
return pv2; | ||
res = PyObject_CallMethodObjArgs(mod, "hex", o, NULL); | ||
Py_DECREF(module); |
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.
"module" -> "mod" ?
numpy/core/tests/test_regression.py
Outdated
|
||
# Test the same for a circular reference. | ||
b = np.array(a, dtype=object) | ||
a[()] = b | ||
assert_raises(TypeError, int, a) | ||
assert_raises(RecursionError, int, a) |
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.
RecursionError is a python3-ism, is there a trick for python 2?
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.
test_multiarray does:
try:
Error = RecursionError
except NameError:
Error = RuntimeError # python < 3.5
assert_raises(Error, bool, self_containing) # previously stack overflow
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.
Turns out it was me that wrote the code in multiarray... Again, good catch!
93a0254
to
413c38a
Compare
b353de3
to
a4c30ee
Compare
Something fishy going on here on py 2... EDIT: PyCallMethodObjArgs didn't have the signature I thought it did. Solved. |
a4c30ee
to
a4c44aa
Compare
document in release notes? |
Not sure it's note-worthy, since this is a bugfix for a bunch of contrived corner-cases. I don't think it has any compatibility ramifications either. |
array_int(PyArrayObject *v) | ||
array_scalar_forward(PyArrayObject *v, | ||
PyObject *(*builtin_func)(PyObject *), | ||
const char *where) |
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.
In principle we could use templating instead of function pointers, but we don't really care about speed here.
f6b7eda
to
6c6da73
Compare
Travis fails with:
However, this is a python bug, not a numpy bug - it's fixed in python/cpython@5fa22fc (3.4.4) and python/cpython@1670af6 (2.7.11), which are greater than or equal to the versions the python docs are generated from. |
could you either skip the test or do a cast (for specifically that version)? |
@eric-wieser This pull request is required for PyPy to pass the test suite. There is a regression somewhere from 1.13 wrt handling of string scalars, I am not sure exactly where. Could we mark the pull request for inclusion in 1.14? |
If this truly is a regression, it should make 1.13.4 - but I'm surprised, as I don't remember changes that would cause this - indeed, the tests of |
6c6da73
to
1578dda
Compare
Milestone added, along with workaround to squash the warning for old python |
Rather than assuming that any object array is self-referencing, we can just use PyEnter_RecursiveCall in: * `__int__` * `__float__` * `__long__` * `__hex__` * `__oct__` This works towards (but does _not_ fix) numpy#9972, by not directly touching the `nb_*` slots ourselves. Substantial code deduplication here. Error message is different, but perhaps also better: ```python >>> int(np.array([None])) TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType' # now TypeError: cannot convert to an int; scalar object is not a number #before ```
1578dda
to
bcec12b
Compare
Seems like a good cleanup, code LGTM. So it now it allows object arrays (that don't recurse), and uses the python-builtin conversion funcs instead of (badly) trying to do the conversion ourselves. I don't totally see why this supersedes #10040 - that PR did adjustments of the |
#10040 was needed specifically because we did a bad job of doing the conversion ourselves - our approach didn't special-case string types like the builtin It does seem a little weird that |
@eric-wieser wrt regression comment above, for PyPy tests started failing after commit 931758e (#9856), "BUG: Make bool(void_scalar) and void_scalar.astype(bool) consistent", which added extra calls to And yes, it is strange that |
Thanks for the info - looks like I'm to blame for the accidental breakage, so it's fitting that I should accidentally fix it too. |
That commit AFAICT is not part of a 1.13 release, as far as These tests newly fail after that commit (since in PyPy the logic in
After this pull request those tests now pass |
Got it - the problem is that before in conversions we were doing You're right, it's not in 1.13, so this only needs to make it into 1.14 for there to be no regression. |
I think this is ready to go. I'll merge in a little while if there are no further comments. |
Merging. Thanks Eric! |
Rather than assuming that any object array is self-referencing, we can just use PyEnter_RecursiveCall, in:
__int__
__float__
__long__
__hex__
__oct__
This works towards (but does not fix) #9972, by not trying to touch the
nb_*
slots ourselves (the same way as #10040).Substantial code deduplication here. Error message is different, but perhaps also better: