From aaa64f53d0434724384b056a3c195d63a5cc3761 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Tue, 28 Nov 2017 20:26:52 +1000 Subject: [PATCH] PEP 565: Address Guido & Serhiy's comments - note advice for test runners in abstract - add explicit sections for test runner and interactive shell guidance - simplify the warning category descriptions by moving the test runner details to their new section - make it clear FutureWarning is gaining a second use case, while also keeping its old one - note that IPython already follows the new guidance for interactive shells (and use their approach as an example) - reword the advice for library and framework authors wanting seeking noisier compatibility warnings on earlier Python versions --- pep-0565.rst | 123 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/pep-0565.rst b/pep-0565.rst index c8cfd7203..856533687 100644 --- a/pep-0565.rst +++ b/pep-0565.rst @@ -37,10 +37,18 @@ 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 @@ -82,42 +90,87 @@ While continuing to be hidden by default for: * code imported from an executable script wrapper generated at installation time based on a ``console_scripts`` or ``gui_scripts`` entry point definition -As a result, API deprecation warnings encountered by development tools written -in Python should continue to be hidden by default for users of those tools +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). -While not its originally intended purpose, the standard library documentation -will also 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. + +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: -* ``PendingDeprecationWarning``: reported by default only in test runners that - override the default set of warning filters. The intended audience is Python - developers that take an active interest in ensuring the future compatibility - of their software (e.g. professional Python application developers with - specific support obligations). +* ``PendingDeprecationWarning``: hidden by default for all code. + The intended audience is Python developers that take an active interest in + ensuring the future compatibility of their software (e.g. professional + Python application developers with specific support obligations). * ``DeprecationWarning``: reported by default for code that runs directly in the ``__main__`` module (as such code is considered relatively unlikely to - have a dedicated test suite), but relies on test suite based reporting for - code in other modules. The intended audience is Python developers that are at - risk of upgrades to their dependencies (including upgrades to Python itself) - breaking their software (e.g. developers using Python to script environments - where someone else is in control of the timing of dependency upgrades). -* ``FutureWarning``: always reported by default. The intended audience is users - of applications written in Python, rather than other Python developers - (e.g. warning about use of a deprecated setting in a configuration file - format). + have a dedicated test suite), but hidden by default for code in other modules. + The intended audience is Python developers that are at risk of upgrades to + their dependencies (including upgrades to Python itself) breaking their + software (e.g. developers using Python to script environments where someone + else is in control of the timing of dependency upgrades). +* ``FutureWarning``: reported by default for all code. + The intended audience is users of applications written in Python, rather than + other Python developers (e.g. warning about use of a deprecated setting in a + configuration file format). -Given its presence in the standard library since Python 2.3, ``FutureWarning`` -would then also have a secondary use case for libraries and frameworks that -support multiple Python versions: as a more reliably visible alternative to -``DeprecationWarning`` in Python 2.7 and versions of Python 3.x prior to 3.7. +For libraries 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. -Documentation Updates -===================== +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 ([8_]) 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 @@ -226,18 +279,18 @@ and 3.2. This PEP does not solve all known problems with the current approach to handling deprecation warnings. Most notably: -* the default ``unittest`` test runner does not currently report deprecation +* The default ``unittest`` test runner does not currently report deprecation warnings emitted at module import time, as the warnings filter override is only put in place during test execution, not during test discovery and loading. -* the default ``unittest`` test runner does not currently report deprecation +* The default ``unittest`` test runner does not currently report deprecation warnings in subprocesses, as the warnings filter override is applied directly to the loaded ``warnings`` module, not to the ``PYTHONWARNINGS`` environment variable. -* the standard library doesn't provide a straightforward way to opt-in to seeing +* The standard library doesn't provide a straightforward way to opt-in to seeing all warnings emitted *by* a particular dependency prior to upgrading it (the third-party ``warn`` module [3_] does provide this, but enabling it involves monkeypatching the standard library's ``warnings`` module). -* re-enabling deprecation warnings by default in __main__ doesn't help in +* Re-enabling deprecation warnings by default in ``__main__`` doesn't help in handling cases where software has been factored out into support modules, but those modules still have little or no automated test coverage. Near term, the best currently available answer is to run such applications with @@ -247,7 +300,7 @@ deprecation warnings. Most notably: working on static analysis of Python code: how to reliably find usage of deprecated APIs, and how to infer that an API or parameter is deprecated based on ``warnings.warn`` calls, without actually running either the code - providing the API or the code accessing it + providing the API or the code accessing it. 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 @@ -290,9 +343,15 @@ References .. [5] Tracker issue for PEP 565 implementation (https://bugs.python.org/issue31975) -.. [6] python-dev discussion thread for this PEP +.. [6] First python-dev discussion thread (https://mail.python.org/pipermail/python-dev/2017-November/150477.html) +.. [7] Second python-dev discussion thread + (https://mail.python.org/pipermail/python-dev/2017-November/150819.html) + +.. [8] IPython's DeprecationWarning auto-configuration + (https://github.com/ipython/ipython/blob/6.2.x/IPython/core/interactiveshell.py#L619) + Copyright =========