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

Unexpected location of naked exception wrapped in except* block #128799

Open
jobh opened this issue Jan 13, 2025 · 2 comments
Open

Unexpected location of naked exception wrapped in except* block #128799

jobh opened this issue Jan 13, 2025 · 2 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@jobh
Copy link

jobh commented Jan 13, 2025

Bug report

Bug description:

When an ExceptionGroup is implicitly constructed by catching a naked exception in an except* block, the traceback of the ExceptionGroup seems to point to the stackframe above where it is logically created:

def f():
    try:
        raise Exception  # Exception (inner) traceback terminates here
    except* Exception as e:
        raise

f()  # ExceptionGroup (wrapper) traceback terminates here

  + Exception Group Traceback (most recent call last):
  |   File "/home/jobh/src/hypothesis/test_naked_exception.py", line 7, in <module>
  |     f()  # ExceptionGroup (wrapper) traceback terminates here
  |     ^^^
  | ExceptionGroup:  (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/home/jobh/src/hypothesis/test_naked_exception.py", line 3, in f
    |     raise Exception  # Exception (inner) traceback terminates here
    |     ^^^^^^^^^^^^^^^
    | Exception
    +------------------------------------

I'm not sure if this should be called a bug, as it's not specifically documented how the wrapping ExceptionGroup traceback is constructed. But it is surprising, and did cause a bug in hypothesis where the Exception traceback is used to detect whether an exception originates in hypothesis itself or in user code 12. The issue being that for wrapped naked exceptions we have to inspect the inner exception since the outer exception appears to be raised by the calling function.

As an alternative to the current behaviour, would it be possible to create the wrapper ExceptionGroup with a traceback pointing to where it is logically triggered - i.e., the except* block - rather than initially empty? IMO, that would be less suprising and would allow us to use the traceback without special-casing ExceptionGroup.

([edit] Or, if the desire is to avoid branching the traceback between the wrapper and the inner exception, use the outermost frame of the naked exception as the initial ExceptionGroup traceback. This would still avoid the appearance of happening in the caller.)

CPython versions tested on:

3.11, 3.12, 3.13

Operating systems tested on:

Linux

Footnotes

  1. https://github.com/HypothesisWorks/hypothesis/issues/4183

  2. https://github.com/HypothesisWorks/hypothesis/pull/4239

@jobh jobh added the type-bug An unexpected behavior, bug, or error label Jan 13, 2025
@picnixz picnixz added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Jan 13, 2025
@picnixz
Copy link
Member

picnixz commented Jan 14, 2025

cc @iritkatriel @1st1 @gvanrossum as the authors of PEP-654.

@iritkatriel
Copy link
Member

I think it's fine to add a frame in the traceback for the except Exception* line. It would be clearer than making it look like the raise Exception line created an ExceptionGroup..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants