Setting many types of values to `category` argument of `warnings.simplefilter()` doesn't get any error
Bug report
Bug description:
Setting Warning to category argument of warnings.filterwarnings() works, then setting the str type value "Hello World" to category argument of warnings.filterwarnings() gets the error message as shown below. *This is an understandable behavior:
import warnings
warnings.resetwarnings()
warnings.filterwarnings(action="ignore", category=Warning)
print(warnings.filters)
# [('ignore', None, <class 'Warning'>, None, 0)]
warnings.filterwarnings(action="ignore", category="Hello World") # Error
print(warnings.filters)
AssertionError: category must be a class
But, setting many types of values to category argument of warnings.simplefilter() doesn't get any error as shown below. *This isn't an understandable behavior:
import warnings
warnings.simplefilter(action="default", category=Warning) # Understandable
warnings.simplefilter(action="default", category="Hello World") # Not understandable
warnings.simplefilter(action="default", category=100) # Not understandable
warnings.simplefilter(action="default", category=3.14) # Not understandable
warnings.simplefilter(action="default", category=3.14+0.j) # Not understandable
warnings.simplefilter(action="default", category=True) # Not understandable
print(warnings.filters)
# [('default', None, True, None, 0),
# ('default', None, (3.14+0j), None, 0),
# ('default', None, 100, None, 0),
# ('default', None, 'Hello World', None, 0),
# ('default', None, <class 'Warning'>, None, 0)]
So, category argument of warnings.simplefilter() should also return the error message as shown below:
AssertionError: category must be a class
CPython versions tested on:
3.12
Operating systems tested on:
Windows
Running with python -O on the first example also results in the same behavior:
>>> import warnings
>>> warnings.resetwarnings()
>>> warnings.filterwarnings(action="ignore", category=Warning)
>>> print(warnings.filters)
[('ignore', None, <class 'Warning'>, None, 0)]
>>> warnings.filterwarnings(action="ignore", category="Hello World")
>>> print(warnings.filters)
[('ignore', None, 'Hello World', None, 0), ('ignore', None, <class 'Warning'>, None, 0)]
I think it makes sense to add a simple type check for both cases.
We should just extract the type check that we have in warnings.warn. See: https://github.com/python/cpython/issues/125854. We can address those issues at the same time IMO.
Hi, I’m interested in contributing to this issue. It currently appears to be open. May I take it up and start working on it?
Go for it! You can refer to the devguide if any part of the process is unclear :)
Hi @ZeroIntensity I raised the PR a few days ago. Please feel free to review it at your convenience. Thank you!
#136305 not just adds type checks. It adds a new feature (filterwarnings() accepting a tuple of Warning subclasses) and breaks an undocumented (and unintentional) feature (simplefilter() accepting a union of Warning subclasses).
Before moving forward, we need to decide which features should be supported. Accepting a tuple or a union of Warning subclasses in simplefilter() is not documented. simplefilter() is just a limited variant of filterwarnings() that does not use regular expressions, it should not have more features. Not adding a type check for category in simplefilter() looks like error. It was not fixed because we suspected that users could use an undocumented feature.
So now we should decide what to do.
- Make the code matching the documentation. This can break user code, although I do not think that it will break too much (if any).
- Officially document support of tuples and unions in
simplefilter()and such feature infilterwarnings(). There were no requests for such feature, and implementing fast type check for this is not easy.
Anyway, if you need to add a filters that matches several Warning subclasses, you can just call simplefilter() or filterwarnings() for each subclass. -W and PYTHONWARNINGS do not support multiple categories for a filter, but they support multiple filters.