-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
MNT: replace _PyDict_GetItemStringWithError with PyDict_GetItemStringRef #26282
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
MNT: replace _PyDict_GetItemStringWithError with PyDict_GetItemStringRef #26282
Conversation
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.
cc @serhiy-storchaka who made similar changes and might also want to review this numpy change :-)
06417b0
to
26f7421
Compare
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.
LGTM (but I'm not a numpy developer).
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.
Thanks, some of that code looks like it could use more love, but it isn't directly related to the change. The change looks fine to me and I am sure Victor has a great eye for spotting refcounting errors as well.
So putting this in, thanks Nathan.
goto fail; | ||
} | ||
if (!is_default) { | ||
if (PyArray_DescrConverter2(descr, &new_dtype) != NPY_SUCCEED) { | ||
Py_DECREF(descr); | ||
goto fail; |
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.
Weird how we use goto fail
here, but not below it. But OK.
@@ -142,8 +142,10 @@ PyUFunc_clearfperr() | |||
NPY_NO_EXPORT int | |||
set_matmul_flags(PyObject *d) | |||
{ | |||
PyObject *matmul = _PyDict_GetItemStringWithError(d, "matmul"); | |||
if (matmul == NULL) { | |||
PyObject *matmul = NULL; |
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.
Does this need an init? If it does, might make sense to mention that in the Python docs, @vstinner, even if not a big deal. (I.e. that it effectively uses Py_SETREF(res, ...)
internally.
But this would be a silly nitpick here to actually remove it.
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.
You can check the doc: https://docs.python.org/dev/c-api/dict.html#c.PyDict_GetItemRef
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.
Right, the docs are fine. It isn't like result
can be reasonably set to a e.g. a default
value before the call: The code here unnecessarily initializes it, which made me wonder.
EDIT: Sorry, right... it lists that result
is set on all paths, so it is very obvious.
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 tend to initialize variables in C code even if I don't strictly need to. Probably a knee-jerk response from experiences of reading from an uninitialized variable causing heisenbugs.
} | ||
|
||
Py_DECREF(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.
@ngoldbaum this is at the wrong indentation level. It's too late here, and I am not sure where to put a test though. cunumeric
notices this, it seems they use void (I suspect unstructured but dunno), without a 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.
Oops, thanks for catching. I unfortunately can't help with a test, I was doing a mechanical refactor here.
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.
We must have some __array_interface__
tests. It shouldn't be hard to create a dict that runs into this, tbh. Although I could overlook it, it would be nice to just have.
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.
My initial reading of your message was that it was a head's up and an ask for help. I'm happy to fix this but if, in the future, you want me to look at something, it would help me if you could say that explicitly in your initial message to me.
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 don't think the indentation level is wrong, doesn't it just need to be an xdecref?
I also don't immediately see how to write a test for this, the existing __array_interface__
tests mostly use the ndarray __array_interface__
implementation. It would be a good idea to improve the tests there but I don't want to do that just to fix this bug.
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.
Should have just created an issue. I wanted to look at it quickly, but realized that adding a test was not quite as quick as I had hoped, and hoped you might have a look.
Replaces all usages of the private
_PyDict_GetItemStringWithError
Python C API function withPyDict_GetItemStringRef
. The latter is available in the python 3.13 C API and viapython-capicompat
in older python versions.The new function has the same semantics as
PyDict_GetItemRef
but takes a UTF-8 C string instead of a python object. Like_PyDict_GetItemStringWithError
, it does not suppress errors. It also has the nice improvement that the return type is now int and it signals success or failure. This lets me re-structure control flow a bit and avoidPyErr_Occurred()
calls.I used the new
PyDict_ContainsString
function if all we care about is whether a key is in the dict. I also usedPy_SETREF
in a few places that were using the unsafe decref then set pattern.See #26159 for the relevant tracking issue.