This is inspired by the [discussion on iterable 
strings](https://mail.python.org/archives/list/python-ideas@python.org/thread/WKEFHT4JYCL2PMZ5LB6HJRLVP3OGZI56/),
 although I think it has applications elsewhere.

Sometimes programs emit warnings that need to be filtered out. Maybe they're 
coming from dependencies that we don't control, or maybe it's our own code but 
it's a problem that can't be fixed or isn't worth the trouble.

But filtering warnings correctly isn't very easy. You generally shouldn't 
ignore all warnings, as this would hide important ones. Similarly, you probably 
shouldn't even filter an entire category, which is what many end up doing. A 
good compromise is to specify both the category and the module. In particular 
this lets you ignore warnings from libraries while still being able to see 
warnings from your own code. But there are obstacles on the way:

1. Remembering the syntax is hard. I've never been able to.
2. Looking it up is hard. If I Google "python ignore warnings" the top result 
is a Stack Overflow question where neither the accepted answer nor the most 
upvoted answer mention specifying a module. The second Google result is the 
Python docs which are not easy to read through.
3. There's lots of similarly named methods and it's hard to find the right one. 
Is it catch_warnings, simplefilter, or filterwarnings?
4. When warnings are displayed, they show the filename, but filters require a 
module name, and converting between the two is tedious.
5. The more warnings there are, and thus the more serious the need to filter 
them properly, the more work it is to write all the filters.

I propose we add a built in mechanism that is easy to use and remember which 
displays Python code that can be copy pasted. For example, this could be a 
configuration option which causes the line of code to be shown in stderr 
immediately after the actual warning. Alternatively, here's a context manager / 
decorator which prints the code after it exits:

    import inspect
    import warnings
    from contextlib import contextmanager
    import __main__
    
    
    @contextmanager
    def showfilters():
        with warnings.catch_warnings(record=True) as warnings_list:
            yield
    
        for warning in warnings_list:
            if warning.filename == getattr(__main__, "__file__", object()):
                module = "__main__"
            else:
                module = inspect.getmodulename(warning.filename)
            module = bool(module) * f", module={module!r}"
            print(
                f"warnings.filterwarnings('ignore', "
                f"category={warning.category.__name__}"
                f"{module})"
            )
    
    
    # Sample usage
    # Prints the below, uncomment to confirm that output disappears
    # warnings.filterwarnings('ignore', category=UserWarning, module='__main__')
    # warnings.filterwarnings('ignore', category=SyntaxWarning)
    
    @showfilters()  # comment out to see original warnings
    def main():
        warnings.warn("DOOM")
        exec("assert (1, 2)")
    
    
    main()

This is of course a rough implementation, there are probably things it does 
wrong and there's all sorts of details about the desired behaviour we could 
debate about. The aim is that the code it prints is good enough for most cases 
and can easily be edited, particularly by deleting lines. Does this seem like a 
good general idea?
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YGI6EJ6Q7HQ37YBIOMJEQ7SGW4WU4F22/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to