A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://peps.python.org/pep-0565/ below:

PEP 565 – Show DeprecationWarning in __main__

PEP 565 – Show DeprecationWarning in __main__
Author:
Alyssa Coghlan <ncoghlan at gmail.com>
Status:
Final
Type:
Standards Track
Created:
12-Nov-2017
Python-Version:
3.7
Post-History:
12-Nov-2017, 25-Nov-2017
Resolution:
Python-Dev message
Table of Contents Abstract

In Python 2.7 and Python 3.2, the default warning filters were updated to hide DeprecationWarning by default, such that deprecation warnings in development tools that were themselves written in Python (e.g. linters, static analysers, test runners, code generators), as well as any other applications that merely happened to be written in Python, wouldn’t be visible to their users unless those users explicitly opted in to seeing them.

However, this change has had the unfortunate side effect of making DeprecationWarning markedly less effective at its primary intended purpose: providing advance notice of breaking changes in APIs (whether in CPython, the standard library, or in third party libraries) to users of those APIs.

To improve this situation, this PEP proposes a single adjustment to the default warnings filter: displaying deprecation warnings attributed to the main module by default.

This change will mean that code entered at the interactive prompt and code in single file scripts will revert to reporting these warnings by default, while they will continue to be silenced by default for packaged code distributed as part of an importable module.

The PEP also proposes a number of small adjustments to the reference interpreter and standard library documentation to help make the warnings subsystem more approachable for new Python developers.

As part of the documentation updates, it will be made clearer that the unittest test runner displays all warnings by default when executing test cases, and that other test runners are advised to follow that example.

Specification New default warnings filter entry

The current set of default warnings filters consists of:

ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning

The default unittest test runner then uses warnings.catch_warnings() warnings.simplefilter('default') to override the default filters while running test cases.

The change proposed in this PEP is to update the default warning filter list to be:

default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning

This means that in cases where the nominal location of the warning (as determined by the stacklevel parameter to warnings.warn) is in the __main__ module, the first occurrence of each DeprecationWarning will once again be reported.

This change will lead to DeprecationWarning being displayed by default for:

While continuing to be hidden by default for:

This means that tool developers that create an installable or executable artifact (such as a zipapp archive) for distribution to their users shouldn’t see any change from the status quo, while users of more ad hoc personal or locally distributed scripts are likely to start seeing relevant deprecation warnings again (as they did in Python 2.6 and earlier).

Additional use case for FutureWarning

The standard library documentation will be updated to explicitly recommend the use of FutureWarning (rather than DeprecationWarning) for backwards compatibility warnings that are intended to be seen by users of an application. (This will be in addition to the existing use of FutureWarning to warn about constructs that will remain valid code in the future, but will have different semantics).

This will give the following three distinct categories of backwards compatibility warning, with three different intended audiences:

For library and framework authors that want to ensure their API compatibility warnings are more reliably seen by their users, the recommendation is to use a custom warning class that derives from DeprecationWarning in Python 3.7+, and from FutureWarning in earlier versions.

Recommended filter settings for test runners

Developers of test runners are advised to implement logic equivalent to the following when determining their default warnings filters:

if not sys.warnoptions:
    warnings.simplefilter("default")

This effectively enables all warnings by default, as if the -Wd command line option had been passed.

Note that actually enabling BytesWarning in a test suite still requires passing the -b option to the interpreter at the command line. For implicit bytes conversion and bytes comparison warnings, the warnings filter machinery is only used to determine whether they should be printed as warnings or raised as exceptions - when the command line flag isn’t set, the interpreter doesn’t even emit the warning in the first place.

Recommended filter settings for interactive shells

Developers of interactive shells are advised to add a filter that enables DeprecationWarning in the namespace where user code is entered and executed.

If that namespace is __main__ (as it is for the default CPython REPL), then no changes are needed beyond those in this PEP.

Interactive shell implementations which use a namespace other than __main__ will need to add their own filter. For example, IPython uses the following command ([6]) to set up a suitable filter:

warnings.filterwarnings("default", category=DeprecationWarning,
                                   module=self.user_ns.get("__name__"))
Other documentation updates

The current reference documentation for the warnings system is relatively short on specific examples of possible settings for the -W command line option or the PYTHONWARNINGS environment variably that achieve particular end results.

The following improvements are proposed as part of the implementation of this PEP:

None of these are new (they already work in all still supported Python versions), but they’re not especially obvious given the current structure of the related documentation.

Reference Implementation

A reference implementation is available in the PR [4] linked from the related tracker issue for this PEP [5].

As a side-effect of implementing this PEP, the internal warnings filter list will start allowing the use of plain strings as part of filter definitions (in addition to the existing use of compiled regular expressions). When present, the plain strings will be compared for exact matches only. This approach allows the new default filter to be added during interpreter startup without requiring early access to the re module.

Motivation

As discussed in [1] and mentioned in [2], Python 2.7 and Python 3.2 changed the default handling of DeprecationWarning such that:

The intent was to avoid cases of tooling output like the following:

$ devtool mycode/
/usr/lib/python3.6/site-packages/devtool/cli.py:1: DeprecationWarning: 'async' and 'await' will become reserved keywords in Python 3.7
  async = True
... actual tool output ...

Even when devtool is a tool specifically for Python programmers, this is not a particularly useful warning, as it will be shown on every invocation, even though the main helpful step an end user can take is to report a bug to the developers of devtool.

The warning is even less helpful for general purpose developer tools that are used across more languages than just Python, and almost entirely *un*helpful for applications that simply happen to be written in Python, and aren’t necessarily intended for a developer audience at all.

However, this change proved to have unintended consequences for the following audiences:

In these cases, DeprecationWarning ended up become almost entirely equivalent to PendingDeprecationWarning: it was simply never seen at all.

Limitations on PEP Scope

This PEP exists specifically to explain both the proposed addition to the default warnings filter for 3.7, and to more clearly articulate the rationale for the original change to the handling of DeprecationWarning back in Python 2.7 and 3.2.

This PEP does not solve all known problems with the current approach to handling deprecation warnings. Most notably:

While these are real problems with the status quo, they’re excluded from consideration in this PEP because they’re going to require more complex solutions than a single additional entry in the default warnings filter, and resolving them at least potentially won’t require going through the PEP process.

For anyone interested in pursuing them further, the first two would be unittest module enhancement requests, the third would be a warnings module enhancement request, while the last would only require a PEP if inferring API deprecations from their contents was deemed to be an intractable code analysis problem, and an explicit function and parameter marker syntax in annotations was proposed instead.

The CPython reference implementation will also include the following related changes in 3.7:

Independently of the proposed changes to the default filters in this PEP, issue 32229 [7] is a proposal to add a warnings.hide_warnings API to make it simpler for application developers to hide warnings during normal operation, while easily making them visible when testing.

References Copyright

This document has been placed in the public domain.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4