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
This commit is contained in:
Nick Coghlan 2017-11-28 20:26:52 +10:00
parent 749a7a060c
commit aaa64f53d0
1 changed files with 91 additions and 32 deletions

View File

@ -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
=========