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
Add ability to wholesale silence DeprecationWarnings while running the test suite #89015
Comments
Sometimes we have the following problem:
In particular, there is such a case right now with asyncio in 3.9 vs. later branches. 3.8 deprecated the loop= argument in a bunch of functions but due to poor warning placement, most of them were silent. This is being fixed in BPO-44815 which would go out to users in 3.9.7 but that created 220 new warnings when running test_asyncion in regression tests. Fixing them one by one would be both tedious, and would make the 3.9 branch forever conflicting with newer branches in many asyncio test files. In 3.11 there's a new round of deprecations raised in test_asyncio, making the branches different. Moreover, those warnings are typically silenced by So, what the PR does is it introduces:
The former adds a new filter to warnings, the message regex is mandatory. The latter removes only the filters that were added by the former, leaving all other filters alone. Example usage is in |
For example, all that's needed to silence the 220 new warnings in all asyncio tests, is adding this in Lib/test/test_asyncio/init.py:
Since the
With that, all of asyncio tests silence unnecessary deprecation warnings. Additionally, testing for warnings with |
There are problems with clearing all ignored deprecation filters. We can want to ignore warnings in narrower or wider scope: per-method, per-class, per-module. We should use the warnings.catch_warnings() context manager for restoring filters in the correct scope. For example, use setUp/tearDown, setUpClass/tearDownClass, setUpModule/tearDownModule and save the context manager as an instance/class attribute or module global. def setUp(self):
self.w = warnings.catch_warnings()
self.w.__enter__()
warnings.filterwarnings(...)
def tearDown():
self.w.__exit__(None, None, None) It is hard to use any helper here because the code should be added in multiple places. Or use setUp/addCleanup, setUpClass/addClassCleanup, setUpModule/addModuleCleanup if you want to keep all code in one place: def setUp(self):
w = warnings.catch_warnings()
w.__enter__()
self.addCleanup(w.__exit__, None, None, None)
warnings.filterwarnings(...) The helper can call catch_warnings(), __enter__(), set filters and return a caller which calls __exit__(None, None, None): def setUp(self):
self.addCleanup(some_helper(...)) For class and method scopes it would be convenient to use class and method decorators correspondingly. @ignore_some_warnings(...)
def test_foo(self):
...
@ignore_some_warnings(...)
class BarTests(unittest.TestCase):
... |
Serhiy, if you take a look at the code, def setUp(self):
self.w = warnings.catch_warnings()
self.w.__enter__()
warnings.filterwarnings(...)
def tearDown():
self.w.__exit__(None, None, None) Making the API symmetrical is a good idea though, I'll look into that tomorrow. |
clear_ignored_deprecations() does not know whether filters were added in setUp(), setUpClass(), setUpModule() or just in a particular method. We should use teadDown*() or add*Cleanup() to clean up at appropriate level. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: