8000 BUG: fix for #4753 (out keyword with __numpy_ufunc__) by cowlicks · Pull Request #5566 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: fix for #4753 (out keyword with __numpy_ufunc__) #5566

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

Closed
wants to merge 2 commits into from

Conversation

cowlicks
Copy link
Contributor

This address bug #4753

It should be noted that while we now check the out keyword arg for an overriding object, the third party __numpy_ufunc__ method needs to implement its own breaking of function scoping to actually assign the result to whatever is in kwds['out'] outside the function.

So when we do

c = OverrideObject()
some_ufunc(a, b, out=c)

if we actually want c to contain the result like:

c = some_ufunc(a, b)

Then in OverrideObject.__numpy_ufunc__ you would have to access c (which is out of scope) and set it as the result.

To fix this I would probably have to integrate the override stuff more into ufunc argument processing. I'm not sure how to do this yet.

@njsmith
8000 Copy link
Member
njsmith commented Feb 13, 2015

I haven't looked at the code yet, but your summary note has me scared and
confused! What is this about breaking scoping? Can you elaborate?
On 12 Feb 2015 23:23, "Blake Griffith" notifications@github.com wrote:

This address bug #4753 #4753

It should be noted that while we now check the out keyword arg for an
overriding object, the third party numpy_ufunc method needs to
implement its own breaking of function scoping to actually assign the
result to whatever is in kwds['out'] outside the function.

So when we do

c = OverrideObject()
some_ufunc(a, b, out=c)

if we actually want c to contain the result like:

c = some_ufunc(a, b)

Then in OverrideObject.numpy_ufunc you would have to access c (which
is out of scope) and set it as the result.

To fix this I would probably have to integrate the override stuff more

into ufunc argument processing. I'm not sure how to do this yet.

You can view, comment on, or merge this pull request online at:

#5566
Commit Summary

  • Check out kwarg for nump_ufunc override
  • Tests for bug 4753

File Changes

Patch Links:


Reply to this email directly or view it on GitHub
#5566.

@pv
Copy link
Member
pv commented Feb 13, 2015

I don't understand the meaning of this comment either. ufuncs do not break scoping, whether they are overridden or not?

@pv
Copy link
Member
pv commented Feb 13, 2015

If I understand the meaning correctly, in the statement "... if we actually want c to contain the result like ..." the answer is that we certainly don't want this --- the non-overridden ufuncs do not do this sort of magic either.

@cowlicks
Copy link
Contributor Author

@pv @njsmith I think I was confusing myself with how numpy handles the out kwarg... This actually is fine.

@cowlicks
Copy link
Contributor Author

Basically I as confused about how this would work if kwarg['out'] was immutable, in which case it can't really be passed by reference. So mutating the value of kwarg['out'] would be impossible (without accessing the namespace outside of the function "breaking function scoping") but the kwarg['out'] thing should always be mutable. So it doesn't matter.

@njsmith
Copy link
Member
njsmith commented Feb 16, 2015

Yeah, if kwarg["out"] were immutable then the correct thing to do would be
to try to mutate it anyway and then propagate the resulting error. Even
breaking scoping wouldn't let us mutate the kwarg["out"] object if it were
immutable -- all it would let us do is mutate a binding in the outer
function's scope, so that it pointed to a different object entirely.
On Feb 16, 2015 2:22 AM, "Blake Griffith" notifications@github.com wrote:

Basically I as confused about how this would work if kwarg['out'] was
immutable, in which case it can't really be passed by reference. So
mutating the value of kwarg['out'] would be impossible (without accessing
the namespace outside of the function "breaking function scoping") but the
kwarg['out'] thing should always be mutable. So it doesn't matter.


Reply to this email directly or view it on GitHub
#5566 (comment).

@cowlicks cowlicks force-pushed the bug-4753 branch 2 times, most recently from 397845d to 7ec0347 Compare February 16, 2015 21:09
@cowlicks
Copy link
Contributor Author

I updated the tests when I realized what was going on. This is ready for review.

@charris
Copy link
Member
charris commented Feb 22, 2015

Where is this at now?

@cowlicks
Copy link
Contributor Author

Still waiting for review. ping @pv @njsmith

@charris
Copy link
Member
charris commented Feb 27, 2015

ping @pv @njsmith

@mhvk
Copy link
Contributor
mhvk commented Feb 27, 2015

@cowlicks - just to add that I think from the perspective of a developer using this, having to deal with out in the __numpy_ufunc__ is definitely what I would expect to have to do. Indeed, quite a bit of Quantity.__numpy_ufunc__ does exactly that: https://github.com/mhvk/astropy/blob/quantity-numpy-ufunc-additions/astropy/units/quantity.py#L414

if ((kwds)&& (PyDict_CheckExact(kwds))) {
obj = PyDict_GetItemString(kwds, "out");
if (obj != NULL) {
if (PyObject_HasAttrString(obj, "__numpy_ufunc__")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a microoptimization, but similarly to what you do in check_tuple_for_numpy_ufunc, you could skip searching the object's dictionary for the string if it is None or a strict ndarray or scalar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay thanks @jaimefrio

@rgommers rgommers changed the title Bug 4753 BUG: fix for #4753 (out keyword with __numpy_ufunc__) Mar 8, 2015
int nargs = PyTuple_GET_SIZE(args);
PyObject *obj;

for (; *i < (og_i + nargs); ++*i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ewww. Instead of *i, use a local variable and assign its value on exit. Best rename the argument to something other than i also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted.

@cowlicks
Copy link
Contributor Author

I will rebase and take a look at #5674 tomorrow and see what needs to change here. I think my original incorrect comments on this PR are just confusing everyone. So I'll make a new PR when I'm done and close this.

@cowlicks cowlicks closed this Mar 14, 2015
@cowlicks
Copy link
Contributor Author

Thanks @mhvk since that seems to be the general expectation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0