-
-
Notifications
You must be signed in to change notification settings - Fork 9.5k
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
MAINT: Warn if out argument has refcnt 1 and owns its data. #9632
Conversation
numpy/core/tests/test_ufunc.py
Outdated
with warnings.catch_warnings(record=True) as w: | ||
warnings.simplefilter('always') | ||
np.add(arr, arr, out=np.empty(3)) | ||
assert len(w) == 1 |
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 needs to be skipped on non-refcounting Pythons (PyPy).
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 also just use assert_warns
(or also suppress_warnings
since you also match the text). I just like it a bit more:
with suppress_warnings() as sup:
r = sup.record(RutimeWarning, ".*the result may be lost")
...
assert_(len(r) == 1)
but I do not care much about 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.
And yes, you have to check for refcounting of the interpreter (I am not sure if the C-Code needs something 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.
Do we allow assert
statements nowadays? I something think we might, but we used to not use them (since they are more commonly used with pytest?)
and no idea why this fails on Python 3.6. Did they change something in Also if that change would be too disruptive I won't mind if it's declined. |
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.
Not sure why it fails in 3.6, there were some minor changes, but I do not really see them affecting the tests/catch_warnings in any case.
I think I like the change as such, there is practically no use case for this case, so it probably almost always will be a programming oversight, in that sense, I should think a bit about what the warning should say.
The PyPy stuff needs to be fixed (I am not sure what Py_REFNT does on PyPy, but it might be best to just put the whole thing into an #ifndef block.
numpy/core/tests/test_mem_overlap.py
Outdated
@@ -887,7 +892,9 @@ def test_unary_ufunc_where_same(self): | |||
ufunc = np.invert | |||
|
|||
def check(a, out, mask): | |||
c1 = ufunc(a, out=out.copy(), where=mask.copy()) | |||
with warnings.catch_warnings(record=True) as w: | |||
warnings.simplefilter("always") |
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.
Please use:
with suppress_warnings() as sup:
sup.filter(WarningType, [warning_message_regexp])
its not a big thing, but its nicer since it is more specific (especially if you put the message text).
numpy/core/tests/test_ufunc.py
Outdated
with warnings.catch_warnings(record=True) as w: | ||
warnings.simplefilter('always') | ||
np.add(arr, arr, out=np.empty(3)) | ||
assert len(w) == 1 |
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 also just use assert_warns
(or also suppress_warnings
since you also match the text). I just like it a bit more:
with suppress_warnings() as sup:
r = sup.record(RutimeWarning, ".*the result may be lost")
...
assert_(len(r) == 1)
but I do not care much about it.
numpy/core/tests/test_ufunc.py
Outdated
with warnings.catch_warnings(record=True) as w: | ||
warnings.simplefilter('always') | ||
np.add(arr, arr, out=np.empty(3)) | ||
assert len(w) == 1 |
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.
And yes, you have to check for refcounting of the interpreter (I am not sure if the C-Code needs something here).
numpy/core/tests/test_ufunc.py
Outdated
with warnings.catch_warnings(record=True) as w: | ||
warnings.simplefilter('always') | ||
np.add(arr, arr, out=np.empty(3)) | ||
assert len(w) == 1 |
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 allow assert
statements nowadays? I something think we might, but we used to not use them (since they are more commonly used with pytest?)
Interesting. It really doesn't warn on Python3.6. I'm not sure what the reason for this is though. Probably the |
@seberg Thanks for all the suggestions. I should've investigated how NumPy does these warning tests before submitting the PR. |
okay, some investigation later ... it's really that a simple example like this:
doesn't warn on Python 3.6 because the reference count for
The |
@MSeifart04: Probably there's one reference for the value on the stack, and one for the value passed into numpy, or something like that. I wonder if this means that @juliantaylor's temporary elision is broken on 3.6... |
I think elision require big arrays. I don't see that here
EDIT: Python 3.6.2 |
I tested it with this change:
with these results:
Based on this PR. On Python 3.5 the same test gave different results:
|
@njsmith Yes, I was wondering. Not sure if it's maybe related to the |
Probably not a "good solution" but I skipped the assert on 3.6. At least it's passing the tests. It would be possible to change it so that it asserts "no warning" on 3.6+ in case the reference counting is updated again and the |
I suspect I dunno, if this is fragile enough that our choices are to either encode quirky interpreter details, or else give up on supporting it on the most recent versions of Python, then is it worth doing? Presumably in a few years then all the Python versions we support will be like 3.6... |
Probably not. |
@MSeifert04 It was a nice idea; sorry it didn't work out. |
Based on the feedback in #7244 but it doesn't actually solve it (see below) emit a RuntimeWarning in case the
out
argument seems dubious. Note that this test can lead to false positives in case someone actually catches the result:And it won't trigger if someone actually makes a new array and creates a view on that: