Skip to content

ExceptionGroup should be generic #91549

Closed

Description

@JelleZijlstra

Thanks to PEP 654, 3.11 will have the new except* syntax. Let's take this sample:

try:
    do_failing_things()
except* ValueError as eg:
    reveal_type(eg)

In the except* block, eg is an ExceptionGroup instance that in its exceptions attribute contains either ValueError instances or more nested ExceptionGroups containing ValueErrors. I expect that many except* blocks will do operations specific to the exception type they operate on, but right now there's no way to represent that information in the type system.

To fix this, we can make ExceptionGroup (and BaseExceptionGroup) generic. In the example, eg would be of type ExceptionGroup[ValueError] (to static type checkers), indicating that all the contained exceptions are ValueErrors.

Recommendations:

  • In CPython, add the C equivalent of __class_getitem__ = GenericAlias to ExceptionGroup and BaseExceptionGroup.
  • In typeshed, make ExceptionGroup (and base) generic over a TypeVar("ExceptionT", bound=Exception), and type its exceptions attribute as tuple[ExceptionT | ExceptionGroup[ExceptionT], ...].
  • In type checkers, for code of the form except* T as eg:, infer eg to be of type ExceptionGroup[T]. (Or BaseExceptionGroup[T] if T does not inherit from Exception.)

If we're in agreement, I can implement the first two recommendations.

Links:

cc @iritkatriel @gvanrossum for PEP 654, @srittau @AlexWaygood for typeshed, @erictraut as a type checker maintainer.

Activity

  1. iritkatriel commented on Apr 14, 2022

    @iritkatriel
    Member

    Is this related?

    def test_exception_group_is_generic_type(self):

  2. JelleZijlstra commented on Apr 14, 2022

    @JelleZijlstra
    MemberAuthor

    Great, you're well ahead of me :). I should have checked. Then we just need to make the corresponding typeshed change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions