-
-
Notifications
You must be signed in to change notification settings - Fork 153
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
Catch Numpy "Could not locate executable" warnings #980
Conversation
Codecov Report
@@ Coverage Diff @@
## main #980 +/- ##
==========================================
- Coverage 79.25% 79.25% -0.01%
==========================================
Files 152 152
Lines 47882 47965 +83
Branches 10909 10923 +14
==========================================
+ Hits 37949 38014 +65
- Misses 7436 7445 +9
- Partials 2497 2506 +9
|
The CI looks good so far (except for that expected coverage error). I don't get the impression that any of the CI tests are using Windows runners, and I don't have Windows myself, so I would be grateful if someone with Windows could check to see if my changes successfully suppress the warnings. |
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 had a few questions about this that I did in the middle of the code. My suggestion for testing is that you mock numpy.distutils.system_info.get_info("blas_opt")
. Something like:
def mocked_blas_opt(*args, **kwargs):
print("This line won't be caught", sys.stdout)
print("This line will be caught and re-printed", sys.stderr)
print("Could not locate executable: this line will be caught and filtered", sys.stderr)
return {'libraries': [], 'library_dirs': [], 'define_macros': [], 'include_dirs': []}
@patch(
"numpy.distutils.system_info.get_info",
new_callable=mocked_blas_opt
)
def test_blas_opt_warnings(mocked_sys):
# Call the default_blas_ldflags and test that you get the expected warnings etc
aesara/link/c/cmodule.py
Outdated
@contextmanager | ||
def catch_numpy_warnings(): | ||
with warnings.catch_warnings(record=True): | ||
numpy.distutils.system_info.system_info.verbosity = 0 # side-effect |
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 the previous value be cached and then reset after exiting the context?
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 was wondering this myself. I think that resetting after exiting the context would be cleaner, but for the first step I wanted to preserve the current behavior of the code. (The code currently leaves this set to 0
, so resetting it could lead to other previously suppressed warnings resurfacing.)
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.
This is a really good point, but
- fixing this would require changing the existing behavior, which risks breaking lots of other stuff, and
- I don't need to touch this line in order to filter these "Could not locate executable" warnings.
Thus I propose we keep the code as-is for now, and address this in a subsequent PR. So that we don't forget, I opened #1005.
aesara/link/c/cmodule.py
Outdated
with warnings.catch_warnings(record=True): | ||
numpy.distutils.system_info.system_info.verbosity = 0 # side-effect | ||
sio = io.StringIO() | ||
with redirect_stderr(sio): |
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.
Are we sure that numpy is printing to stderr and not to stdout?
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'm pretty sure, but not 100%. That's why I need someone with Windows to test this! 😂
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.
Indeed, see #980 (comment).
Now fixed by filtering both stdout and stderr.
As mentioned in #974, we should probably use this as an opportunity to set up a Windows image run that performs these tests and limited subset of others. |
I just tested this patch using Conda-Forge infrastructure, and unfortunately it doesn't work. 😞 Maybe it will work with stdout instead of stderr... |
Oh, interesting... on Linux it goes to stderr, but on Windows it goes to stdout. It should work if I filter both... |
I managed to test this on the Conda-Forge infrastructure which includes Windows, and it appears to be working. Passing tests: conda-forge/aesara-feedstock#72 I'm ready for the next round of review. My thoughts:
Thanks so much @lucianopaz for writing the tricky part of the test for 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.
We can add a Windows VM run to our test config and use that to test this, as well. See my comment here.
aesara/link/c/cmodule.py
Outdated
@contextmanager | ||
def filter_numpy_missing_executable_warnings(): |
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.
A contextmanager
isn't necessary if it's only going to be used once/here (i.e. the yield
can be replaced with the numpy.distutils.system_info.get_info
call).
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 agree the contextmanager
is unnecessary. From a style perspective I find that it helps me to distinguish between the relevant action and scaffolding: I'm saying "here's the filter_numpy_missing_executable_warnings
context for the following command" and then I run that command with the context manager.
But if you prefer without the contextmanager
that's easy to fix.
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 eliminated the contextmanager
in d48f056. (It can be easily reverted in case you change your mind.)
aesara/link/c/cmodule.py
Outdated
# In case there are messages printed to both stdout and stderr, | ||
# they may be incorrectly interspersed. But in the normal case | ||
# there should be no output to either, so this should not pose | ||
# a problem. | ||
for sio, file in ((stdout_sio, sys.stdout), (stderr_sio, sys.stderr)): | ||
lines = sio.getvalue().splitlines() | ||
for line in lines: | ||
if all( | ||
f"Could not locate executable {exe}" not in line | ||
for exe in executables | ||
): | ||
print(line, file=file) |
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'm not entirely clear on what's happening here, but it reminds me that we should only suppress specific output messages and not all of them.
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.
Hmm, taking a look at this with fresh eyes I see that it's indeed confusing.
To make the comment more accurate, I think I should say
In case there are messages
printed tocaptured from both stdout and stderr, they may be print incorrectly interspersed. But in the normal case there should be no output to either, so this should not pose a problem.
I should probably also rename sio
→ captured_buffer
and file
→ print_dest
...
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.
tests/test_printing.py
Outdated
|
||
|
||
@patch("numpy.distutils.system_info.get_info", new=mocked_blas_opt) | ||
def test_blas_opt_warnings(): |
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.
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 for the tip! Implemented in 6c6f615. That's a nice improvement.
Sounds good, but I'm a bit confused about the conclusion... It seems that the Windows VM isn't ready yet. Did you want me to look into something particular? Or are you implying that we should wait on that before merging? Thanks for the review!!! I'll try to get to this in a few days. |
The CI was running my tests on Ubuntu instead of Windows because I forgot to set the |
I believe I have addressed all the issues from the previous review round. Any further thoughts? Also, could you please approve the CI run? |
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 looks like every matrix.include
needs an explicit os
entry now.
@brandonwillard let's see if e3d2feb fixes it |
This reverts commit e3d2feb.
The scope of this PR is only conda-forge/aesara-feedstock#54, not #1005. (This PR got erroneously linked as closing the follow-up issue #1005.) Setting a default for @brandonwillard could you please restart CI? |
This PR should necessarily address #1005. |
It looks like the shell scripting for the Windows cases needs to be adjusted. |
I thought this PR would be a quick UX win for the poor souls stuck on Windows. My current proposal accomplishes my goal while making minimal changes to the existing behavior.
It's very hard for me to add Windows to your CI testing framework given that I barely know Powershell (or whatever the CI runs with
Fixing this seems to me like a major change to existing behavior which would reenable currently disabled Numpy warnings not only for Aesara itself, but also for all downstream projects which import Aesara. Given how both of these points drastically expand the scope of this PR, I'm going to stop here on this one. I hope someone else can take it over, but if not, feel free to close it. Moving on, I'm actually quite interested in delving into the mathematical side. @brandonwillard, I see that you have some interesting blog posts regarding DLMs and such, and you had the hope that with PyMC4+Aesara that this stuff would become easier. I was wondering if you have any examples which are working on the current stack? Or is this still work-in-progress? |
In order to leave this PR in a clean state, I split out my CI attempt into #1029. Now all checks should be green. Status update:In order to make this easier for someone else to pick up, I want to summarize the current state. The goal of this PR is to solve conda-forge/aesara-feedstock#54. This PR solves that goal, and adds the tests to prove it. At the moment none of the CI tests for this repo run under Windows (#1028). However Conda-Forge does have a working Windows CI, and I have used that to confirm that these tests pass under Windows with my changes to @brandonwillard has made it clear that this PR won't be merged until #1005 and #1028 are solved. I'm stopping because in my view, those issues are independent of this PR, and I don't feel like I can effectively solve either of them. Please let me know if there's anything further I can do to help here, short of solving #1005 or #1028. |
Now that #1050 is merged, let's see if the issue is still present. |
Based on the tests at conda-forge/aesara-feedstock#92, it looks like that resolved this issue. Thanks @brandonwillard for the superior solution! Closing this one. |
Closes conda-forge/aesara-feedstock#54 by capturing stderr while reading
blas_info
from Numpy.Specifically, the suppressed errors appear on Windows and look like
I am having trouble running the pytest suite locally. Additionally, I have no means of testing this locally since I don't have Windows.
I have not yet written any tests, but I'm open to advice.
I did this a bit rushed, so apologies in advance in case I missed some guideline.
Thank you for opening a PR!
Here are a few important guidelines and requirements to check before your PR can be merged:
pre-commit
is installed and set up.Don't worry, your PR doesn't need to be in perfect order to submit it. As development progresses and/or reviewers request changes, you can always rewrite the history of your feature/PR branches.
If your PR is an ongoing effort and you would like to involve us in the process, simply make it a draft PR.