Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PEP-654: except *T --> except* T #2091

Merged
merged 1 commit into from
Oct 6, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions pep-0654.rst
Original file line number Diff line number Diff line change
Expand Up @@ -532,11 +532,11 @@ exceptions can be handled by each ``except*`` clause:

try:
...
except *SpamError:
except* SpamError:
...
except *FooError as e:
except* FooError as e:
...
except *(BarError, BazError) as e:
except* (BarError, BazError) as e:
...

In a traditional ``try-except`` statement there is only one exception to handle,
Expand Down Expand Up @@ -572,7 +572,7 @@ Exceptions are matched using a subclass check. For example:

try:
low_level_os_operation()
except *OSError as eg:
except* OSError as eg:
for e in eg.exceptions:
print(type(e).__name__)

Expand All @@ -593,9 +593,9 @@ The order of ``except*`` clauses is significant just like with the regular

>>> try:
... raise ExceptionGroup("problem", [BlockingIOError()])
... except *OSError as e: # Would catch the error
... except* OSError as e: # Would catch the error
... print(repr(e))
... except *BlockingIOError: # Would never run
... except* BlockingIOError: # Would never run
... print('never')
...
ExceptionGroup('problem', [BlockingIOError()])
Expand All @@ -619,9 +619,9 @@ recursively, using the ``split()`` method:
... [TypeError('c'), KeyError('d')])
... ]
... )
... except *TypeError as e1:
... except* TypeError as e1:
... print(f'e1 = {e1!r}')
... except *Exception as e2:
... except* Exception as e2:
... print(f'e2 = {e2!r}')
...
e1 = ExceptionGroup('eg', [TypeError('b'), ExceptionGroup('nested', [TypeError('c')])])
Expand All @@ -644,9 +644,9 @@ clauses, the remaining part of the group is propagated on:
... TypeError('c'), KeyError('e')
... ]
... )
... except *ValueError as e:
... except* ValueError as e:
... print(f'got some ValueErrors: {e!r}')
... except *TypeError as e:
... except* TypeError as e:
... print(f'got some TypeErrors: {e!r}')
... except ExceptionGroup as e:
... print(f'propagated: {e!r}')
Expand All @@ -670,7 +670,7 @@ message string. This is to make the type of ``e`` consistent and statically know

>>> try:
... raise BlockingIOError
... except *OSError as e:
... except* OSError as e:
... print(repr(e))
...
ExceptionGroup('', [BlockingIOError()])
Expand All @@ -683,7 +683,7 @@ naked form:
>>> try:
... try:
... raise ValueError(12)
... except *TypeError as e:
... except* TypeError as e:
... print('never')
... except ValueError as e:
... print(f'caught ValueError: {e!r}')
Expand Down Expand Up @@ -755,10 +755,10 @@ the original ``ExceptionGroup``:
... [OSError(4), TypeError(5), ValueError(6)])
... ]
... )
... except *ValueError as e:
... except* ValueError as e:
... print(f'*ValueError: {e!r}')
... raise
... except *OSError as e:
... except* OSError as e:
... print(f'*OSError: {e!r}')
... except ExceptionGroup as e:
... print(repr(e))
Expand Down Expand Up @@ -793,10 +793,10 @@ merged with the unhandled ``TypeErrors``.
... [OSError(4), TypeError(5), ValueError(6)])
... ]
... )
... except *ValueError as e:
... except* ValueError as e:
... print(f'*ValueError: {e!r}')
... raise e
... except *OSError as e:
... except* OSError as e:
... print(f'*OSError: {e!r}')
... raise
...
Expand Down Expand Up @@ -850,7 +850,7 @@ it into the new ``ExceptionGroup``.

>>> try:
... raise ExceptionGroup("one", [ValueError('a'), TypeError('b')])
... except *ValueError:
... except* ValueError:
... raise ExceptionGroup("two", [KeyError('x'), KeyError('y')])
...
| ExceptionGroup
Expand Down Expand Up @@ -897,7 +897,7 @@ chaining:

>>> try:
... raise TypeError('bad type')
... except *TypeError as e:
... except* TypeError as e:
... raise ValueError('bad value') from e
...
| ExceptionGroup
Expand Down Expand Up @@ -927,9 +927,9 @@ other clauses from the same ``try`` statement:

>>> try:
... raise TypeError(1)
... except *TypeError:
... except* TypeError:
... raise ValueError(2) from None # <- not caught in the next clause
... except *ValueError:
... except* ValueError:
... print('never')
...
| ExceptionGroup
Expand All @@ -952,7 +952,7 @@ direct child of the new exception group created for that:

>>> try:
... raise ExceptionGroup("eg", [ValueError('a')])
... except *ValueError:
... except* ValueError:
... raise KeyError('x')
...
| ExceptionGroup
Expand All @@ -975,7 +975,7 @@ direct child of the new exception group created for that:
>>>
>>> try:
... raise ExceptionGroup("eg", [ValueError('a'), TypeError('b')])
... except *ValueError:
... except* ValueError:
... raise KeyError('x')
...
| ExceptionGroup
Expand Down Expand Up @@ -1013,7 +1013,7 @@ OS errors, while letting all other exceptions propagate.

try:
low_level_os_operation()
except *OSError as errors:
except* OSError as errors:
raise errors.subgroup(lambda e: e.errno != errno.EPIPE) from None


Expand All @@ -1031,7 +1031,7 @@ exception group. Any modifications to ``e`` will likely be lost:
>>> eg.foo = 'foo'
>>> try:
... raise eg
... except *TypeError as e:
... except* TypeError as e:
... e.foo = 'bar'
... # ^----------- ``e`` is an ephemeral object that might get
>>> # destroyed after the ``except*`` clause.
Expand All @@ -1052,7 +1052,7 @@ It is not possible to use both traditional ``except`` blocks and the new
...
except ValueError:
pass
except *CancelledError: # <- SyntaxError:
except* CancelledError: # <- SyntaxError:
pass # combining ``except`` and ``except*``
# is prohibited

Expand All @@ -1069,12 +1069,12 @@ ambiguous:

try:
...
except *ExceptionGroup: # <- Runtime error
except* ExceptionGroup: # <- Runtime error
pass

try:
...
except *(TypeError, ExceptionGroup): # <- Runtime error
except* (TypeError, ExceptionGroup): # <- Runtime error
pass


Expand Down Expand Up @@ -1121,7 +1121,7 @@ Once programs begin to use these features, there will be migration issues to
consider:

* An ``except T:`` clause that wraps code which is now potentially raising
an exception group may need to become ``except *T:``, and its body may
an exception group may need to become ``except* T:``, and its body may
need to be updated. This means that raising an exception group is an
API-breaking change and will likely be done in new APIs rather than
added to existing ones.
Expand Down Expand Up @@ -1308,7 +1308,7 @@ It is unlikely that asyncio users would want to do something like this:
try:
async with asyncio.TaskGroup() as g:
g.create_task(task1); g.create_task(task2)
except *KeyError:
except* KeyError:
# handling KeyError here is meaningless, there's
# no context to do anything with it but to log it.

Expand All @@ -1326,7 +1326,7 @@ exceptions in it.
Not Matching Naked Exceptions in ``except*``
--------------------------------------------

We considered the option of making ``except *T`` match only exception groups
We considered the option of making ``except* T`` match only exception groups
that contain ``Ts``, but not naked ``Ts``. To see why we thought this would
not be a desirable feature, return to the distinction in the previous paragraph
between operation errors and control flow exceptions. If we don't know whether
Expand All @@ -1352,7 +1352,7 @@ write a separate code block to handle each case:
...
except SomeError:
# handle the naked exception
except *SomeError:
except* SomeError:
# handle the exception group


Expand All @@ -1361,7 +1361,7 @@ Allow mixing ``except:`` and ``except*:`` in the same ``try``

This option was rejected because it adds complexity without adding useful
semantics. Presumably the intention would be that an ``except T:`` block handles
only naked exceptions of type ``T``, while ``except *T:`` handles ``T`` in
only naked exceptions of type ``T``, while ``except* T:`` handles ``T`` in
exception groups. We already discussed above why this is unlikely
to be useful in practice, and if it is needed then the nested ``try-except``
block can be used instead to achieve the same result.
Expand All @@ -1379,7 +1379,7 @@ specified in the same place where we state ``T``.
Programming Without 'except \*'
===============================

Consider the following simple example of the ``except *`` syntax (pretending
Consider the following simple example of the ``except*`` syntax (pretending
Trio natively supported this proposal):

.. code-block::
Expand All @@ -1389,7 +1389,7 @@ Trio natively supported this proposal):
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except *ValueError:
except* ValueError:
pass

Here is how this code would look in Python 3.9:
Expand Down