From 44cd8d121ae26c2727b0dfaf774527783792382e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Wed, 27 Jul 2022 13:42:05 +0300 Subject: [PATCH 1/5] PEP 601: Fix footnotes --- pep-0601.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pep-0601.txt b/pep-0601.txt index d0046a6c0be..e3ecf51a353 100644 --- a/pep-0601.txt +++ b/pep-0601.txt @@ -87,7 +87,7 @@ Independent to the semantics, implementing return/break/continue within a finally suite is non-trivial as it requires to correctly track any active exceptions at runtime (an executing finally suite may or may not have an active exception) and cancel them as appropriate. CPython did have a bug in -this for the case of continue and so originally disallowed it [1]. Requiring +this for the case of continue and so originally disallowed it [1]_. Requiring correct behaviour for return/break/continue within a finally puts an unnecessary burden on alternative implementations of Python. @@ -95,18 +95,18 @@ Other languages =============== Java allows to return from within a finally block, but its use is discouraged -according to [2], [3], [4]. The Java compiler later on included a linting +according to [2]_, [3]_, [4]_. The Java compiler later on included a linting option -Xlint:finally to warn against the use of return within a finally block. The Eclipse editor also warns about this use. Ruby allows return from inside ensure (Python's finally), but it should be an -explicit return. It is discouraged and handled by linters [5], [6]. +explicit return. It is discouraged and handled by linters [5]_, [6]_. Like Ruby, JavaScript also allows use of return/break/continue within a finally -but it is seen as unsafe and it is handled by eslint [7]. +but it is seen as unsafe and it is handled by eslint [7]_. C# forbids the use of ending statements like return/goto/break within a finally -[8], [9]. +[8]_, [9]_. Rationale ========= From 3c75e1b4784163176e4e3cc369b8c89efc178989 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Wed, 27 Jul 2022 13:42:26 +0300 Subject: [PATCH 2/5] PEP 601: Remove redundant emacs metadata --- pep-0601.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pep-0601.txt b/pep-0601.txt index e3ecf51a353..cb40f0e2bc1 100644 --- a/pep-0601.txt +++ b/pep-0601.txt @@ -243,14 +243,3 @@ Copyright This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive. - - - -.. - Local Variables: - mode: indented-text - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 70 - coding: utf-8 - End: From a05c10d65d3c2ab7ebef1f2076f971bba6f53f2c Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Wed, 27 Jul 2022 13:54:57 +0300 Subject: [PATCH 3/5] PEP 601: Fix links --- pep-0601.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0601.txt b/pep-0601.txt index cb40f0e2bc1..6c1bd2d7a5f 100644 --- a/pep-0601.txt +++ b/pep-0601.txt @@ -220,7 +220,7 @@ to return and break. References ========== -.. [1] https://bugs.python.org/issue37830 +.. [1] https://github.com/python/cpython/issues/82011 .. [2] https://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java @@ -228,9 +228,9 @@ References .. [4] https://wiki.sei.cmu.edu/confluence/display/java/ERR04-J.+Do+not+complete+abruptly+from+a+finally+block -.. [5] https://github.com/rubocop-hq/rubocop/issues/5949 +.. [5] https://github.com/rubocop/rubocop/issues/5949 -.. [6] https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/EnsureReturn +.. [6] https://web.archive.org/web/20210622135940/https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/EnsureReturn .. [7] https://eslint.org/docs/rules/no-unsafe-finally From 8ff4b1c85cfbd6016183d24fa7a830a8c3c7175f Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Wed, 27 Jul 2022 14:02:38 +0300 Subject: [PATCH 4/5] PEP 601: Add inline code formatting --- pep-0601.txt | 82 ++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/pep-0601.txt b/pep-0601.txt index 6c1bd2d7a5f..c2a00d23395 100644 --- a/pep-0601.txt +++ b/pep-0601.txt @@ -25,21 +25,21 @@ is a conditional return (or break etc.) inside a finally block.". Abstract ======== -This PEP proposes to forbid return, break and continue statements within -a finally suite where they would break out of the finally. Their use in +This PEP proposes to forbid ``return``, ``break`` and ``continue`` statements within +a ``finally`` suite where they would break out of the ``finally``. Their use in such a location silently cancels any active exception being raised through -the finally, leading to unclear code and possible bugs. +the ``finally``, leading to unclear code and possible bugs. -Continue is currently not supported in a finally in Python 3.7 (due to +``continue`` is currently not supported in a ``finally`` in Python 3.7 (due to implementation issues) and the proposal is to not add support for it in -Python 3.8. For return and break the proposal is to deprecate their use +Python 3.8. For ``return`` and ``break`` the proposal is to deprecate their use in Python 3.9, emit a compilation warning in Python 3.10 and then forbid their use after that. Motivation ========== -The use of return, break and continue within a finally suite leads to behaviour +The use of ``return``, ``break`` and ``continue`` within a ``finally`` suite leads to behaviour which is not at all obvious. Consider the following function:: def foo(): @@ -49,9 +49,9 @@ which is not at all obvious. Consider the following function:: return This will return cleanly (without an exception) even though it has infinite -recursion and raises an exception within the try. The reason is that the return -within the finally will silently cancel any exception that propagates through -the finally suite. Such behaviour is unexpected and not at all obvious. +recursion and raises an exception within the ``try``. The reason is that the ``return`` +within the ``finally`` will silently cancel any exception that propagates through +the ``finally`` suite. Such behaviour is unexpected and not at all obvious. This function is equivalent to:: def foo(): @@ -61,8 +61,8 @@ This function is equivalent to:: pass return -Break and continue have similar behaviour (they silence exceptions) if they -jump to code outside the finally suite. For example:: +``break`` and ``continue`` have similar behaviour (they silence exceptions) if they +jump to code outside the ``finally`` suite. For example:: def bar(): while True: @@ -83,35 +83,35 @@ This behaviour goes against the following parts of The Zen of Python: If this behaviour of silencing exceptions is really needed then the explicit form of a try-except can be used instead, and this makes the code clearer. -Independent to the semantics, implementing return/break/continue within a -finally suite is non-trivial as it requires to correctly track any active -exceptions at runtime (an executing finally suite may or may not have an +Independent to the semantics, implementing ``return``/``break``/``continue`` within a +``finally`` suite is non-trivial as it requires to correctly track any active +exceptions at runtime (an executing ``finally`` suite may or may not have an active exception) and cancel them as appropriate. CPython did have a bug in -this for the case of continue and so originally disallowed it [1]_. Requiring -correct behaviour for return/break/continue within a finally puts an +this for the case of ``continue`` and so originally disallowed it [1]_. Requiring +correct behaviour for ``return``/``break``/``continue`` within a ``finally`` puts an unnecessary burden on alternative implementations of Python. Other languages =============== -Java allows to return from within a finally block, but its use is discouraged +Java allows to return from within a ``finally`` block, but its use is discouraged according to [2]_, [3]_, [4]_. The Java compiler later on included a linting -option -Xlint:finally to warn against the use of return within a finally block. +option ``-Xlint:finally`` to warn against the use of return within a ``finally`` block. The Eclipse editor also warns about this use. Ruby allows return from inside ensure (Python's finally), but it should be an explicit return. It is discouraged and handled by linters [5]_, [6]_. -Like Ruby, JavaScript also allows use of return/break/continue within a finally +Like Ruby, JavaScript also allows use of ``return``/``break``/``continue`` within a ``finally`` but it is seen as unsafe and it is handled by eslint [7]_. -C# forbids the use of ending statements like return/goto/break within a finally +C# forbids the use of ending statements like ``return``/``goto``/``break`` within a ``finally`` [8]_, [9]_. Rationale ========= -Since the behaviour of return/break/continue within a finally is unclear, the +Since the behaviour of ``return``/``break``/``continue`` within a ``finally`` is unclear, the pattern is rarely used, and there is a simple alternative to writing equivalent code (which is more explicit), forbidding the syntax is the most straightforward approach. @@ -119,19 +119,19 @@ approach. Specification ============= -This is a change to the compiler, not the grammar. The compiler should -check for the following in a finally suite: +This is a change to the compiler, not the grammar. The compiler should +check for the following in a ``finally`` suite: -* A return in any statement, at any level of nesting. +* A ``return`` in any statement, at any level of nesting. -* A break/continue in any statement, at any level of nesting, that would - transfer control flow outside the finally suite. +* A ``break``/``continue`` in any statement, at any level of nesting, that would + transfer control flow outside the ``finally`` suite. Upon finding such a case it should emit the appropriate exception: -* For continue, a SyntaxError (this is the current behaviour of 3.7). +* For ``continue``, a ``SyntaxError`` (this is the current behaviour of 3.7). -* For return/break, a SyntaxWarning in 3.10, and a SyntaxError after that. +* For ``return``/``break``, a ``SyntaxWarning`` in 3.10, and a ``SyntaxError`` after that. For example, the following are all forbidden by this proposal:: @@ -160,8 +160,8 @@ For example, the following are all forbidden by this proposal:: for x in range(10): return -The following is still allowed because the continue doesn't escape the -finally:: +The following is still allowed because the ``continue`` doesn't escape the +``finally``:: try: pass @@ -169,17 +169,17 @@ finally:: for x in range(10): continue -Note that yielding from within a finally remains acceptable by this PEP -because resuming the generator will resume the finally and eventually +Note that yielding from within a ``finally`` remains acceptable by this PEP +because resuming the generator will resume the ``finally`` and eventually raise any active exceptions (so they are never silenced by yielding). Backwards Compatibility ======================= -This is a backwards incompatible change, for return and break. +This is a backwards incompatible change, for ``return`` and ``break``. The following locations in the CPython standard library (at -v3.8.0b1-651-g7fcc2088a5) use return within finally: +v3.8.0b1-651-g7fcc2088a5) use ``return`` within ``finally``: * Lib/subprocess.py:921 - the use here looks like a bug @@ -189,11 +189,11 @@ v3.8.0b1-651-g7fcc2088a5) use return within finally: * Lib/multiprocessing/connection.py:318 - the use here looks legitimate but the intention is not clear -* Lib/test/test_sys_settrace.py:837 - a test for return within finally +* Lib/test/test_sys_settrace.py:837 - a test for ``return`` within ``finally`` -* Lib/test/test_sys_settrace.py:1346 - a test for return within finally +* Lib/test/test_sys_settrace.py:1346 - a test for ``return`` within ``finally`` -There are no uses of break within a finally (that break out of the finally) +There are no uses of ``break`` within a ``finally`` (that break out of the ``finally``) in the standard library. Security Implications @@ -207,15 +207,15 @@ How to Teach This This feature is very rarely used so forbidding it will likely only impact advanced users, not beginners and probably not any existing teaching -material. Since this is the removal of a feature teaching users will be -one by the raising of a SyntaxError if/when the forbidden feature is used. +material. Since this is the removal of a feature teaching users will be +one by the raising of a ``SyntaxError`` if/when the forbidden feature is used. Reference Implementation ======================== There is currently no reference implementation, although the way continue -is currently handled in a finally (raising a SyntaxError) can be extended -to return and break. +is currently handled in a ``finally`` (raising a ``SyntaxError``) can be extended +to ``return`` and ``break``. References ========== From 1489d12433e992c08055dad6d2218e3f3b01a1a4 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Thu, 28 Jul 2022 12:18:03 +0300 Subject: [PATCH 5/5] PEP 601: Fix link to version active at time of writing Co-authored-by: CAM Gerlach --- pep-0601.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pep-0601.txt b/pep-0601.txt index c2a00d23395..046c898b2b8 100644 --- a/pep-0601.txt +++ b/pep-0601.txt @@ -230,7 +230,7 @@ References .. [5] https://github.com/rubocop/rubocop/issues/5949 -.. [6] https://web.archive.org/web/20210622135940/https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/EnsureReturn +.. [6] https://www.rubydoc.info/gems/rubocop/0.74.0/RuboCop/Cop/Lint/EnsureReturn .. [7] https://eslint.org/docs/rules/no-unsafe-finally