GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Support Exception-like Objects (TracebackException) For exc.__cause__ and exc.__context__ · Issue #111921 · python/cpython

Support Exception-like Objects (TracebackException) For exc.__cause__ and exc.__context__ #111921

New issue
Copy link
New issue
Copy link
Closed
Closed
Support Exception-like Objects (TracebackException) For exc.__cause__ and exc.__context__#111921
Copy link
Labels
3.13only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

Description

@ericsnowcurrently
ericsnowcurrently
opened on Nov 9, 2023
Issue body actions

Feature or enhancement

Currently __cause__ and __context__ are expected to be exception objects (i.e. instances of BaseException). 1 We don't always enforce this expectation, but we definitely do in some places.

Proposal

I'd like to allow them to be non-exception objects, as long as the objects look like exceptions. My own interest is that I be able to set either attribute to traceback.TracebackException objects specifically. However, I expect that supporting them would in practice mean supporting any object that matches the appropriate drop-in-replacement interface. [^2]

[^2] See gh-111917.

Note that I am not suggesting that we be able to use such drop-in-replacements anywhere the runtime expects exception objects. You couldn't start raising TracebackException objects nor catch them I don't have any motivating case for any of that. I'm only suggesting support in __cause__ and __context__.

drop-in-replacement for exception objects

The idea of drop-in-replacement (proxy or not) for an exception object isn't mine alone. The implication of the traceback.TracebackException docs is that it may be used as a representative proxy of an exception object. Furthermore, there has already been some consideration for treating TracebackException as a drop-in-replacement in actual technical situations, e.g. when pickling: #73652 (comment).

What would need to happen?

How are __cause__ and __context__ used (or might be used)?

  • sys.excepthook()
  • introspection
  • (hypothetical?) raised directly after handling an exception
  • ???

What would have to change?

  • update TracebackException appropriately (it is used for the default sys.excepthook()2); the diff is actually relatively small
  • ???

Other Notes

Prior discussion about supporting traceback.StackSummary where we currently support __traceback__: #74764 (comment)

Footnotes

  1. This is just like how __traceback__ is currently expected to be a TracebackType instance. ↩

  2. Since gh-110721: Use the traceback module for PyErr_Display() and fallback to the C implementation #110702 landed, we can accommodate TracebackException like this much more easily. ↩

Activity

  1. ericsnowcurrently
    added
    type-featureA feature request or enhancementA feature request or enhancement
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    3.13only security fixesonly security fixes
    on Nov 9, 2023
  2. ericsnowcurrently commented on Nov 9, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 9, 2023
    MemberAuthor
    More actions

    CC @iritkatriel, @pablogsal

  3. iritkatriel commented on Nov 9, 2023

    @iritkatriel
    iritkatriel
    on Nov 9, 2023
    Member
    More actions

    Can we just make traceback.TracebackException be an Exception?

  4. ericsnowcurrently commented on Nov 9, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 9, 2023
    MemberAuthor
    More actions

    I suppose we could. That would certainly be simpler.

  5. ericsnowcurrently commented on Nov 18, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 18, 2023
    MemberAuthor
    More actions

    Having thought about it, the thing I don't like about subclassing Exception is that then people could start raising TracebackException, which seems like a strange thing. Things get weird when __cause__, __traceback__, etc. might end up getting overwritten. It would be less of an issue if TracebackException were a read-only snapshot. Regardless, maybe mutability and raising isn't such a big deal.

    Another option: support a new attr (something like __remote_cause__) for the traceback module to use in cases like subinterpreters where the exception we want to display simply does not exist. The value would be an object that matches TracebackException's API:

    • .format()
    • .format_exception_only()
    • .print()
  6. iritkatriel commented on Nov 18, 2023

    @iritkatriel
    iritkatriel
    on Nov 18, 2023
    Member
    More actions

    There might be a third option:

    Instead of making TracebackException extend Exception, define an exception type that wraps a TracebackException. Then if the wrapper gets raised, it doesn't trample on the data in the wrapped TracebackException.

  7. ericsnowcurrently commented on Nov 20, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 20, 2023
    MemberAuthor
    More actions

    I'm glad you brought this up because I had the same idea. Last week I actually spent some time trying out a dedicated exception that wraps TracebackException, which I named _DummyException. My conclusion is that it would work but there's something that feels slightly off about it. Mainly, this would require a new TracebackException.__new__() to return the wrapped object, which would mostly mean throwing away the dummy exception's info (e.g. traceback, cause). For my use case that isn't a big deal, but if folks started using the dummy directly then it could easily get confusing. I'm apprehensive about opening that door...

    ...which is why I thought of __remove_cause__. That feels like a very natural, clean, and clear solution. However, it has its own problem: adding a new "dunder" attribute to exceptions, even if only optional, feels like serious overkill.

  8. ericsnowcurrently commented on Nov 20, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 20, 2023
    MemberAuthor
    More actions

    Just to summarize, here are the options we've discussed so far:

    1. support TracebackException-like non-exception objects in __cause__
    2. make TracebackException an actual exception type
    3. wrap the TracebackException object with a separate exception type (e.g. _DummyException)
    4. like (1), but in a new __remote_cause__

    Each of (1)-(3) has awkward potential corner cases and some awkward conceptual weirdness. I'd strongly favor (4) if it didn't feel so heavy-handed.

  9. ericsnowcurrently commented on Nov 20, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 20, 2023
    MemberAuthor
    More actions

    Another idea:

    Ditch the generalized solution and deal with it via the specific exception (like we do with ExceptionGroup). That could involve using __notes__ or the exception's __repr__().

  10. iritkatriel commented on Nov 20, 2023

    @iritkatriel
    iritkatriel
    on Nov 20, 2023
    Member
    More actions

    I think __repr__ is better than __notes__, because notes are supposed to be for where the exception needs to be enriched with more information after it was created, and that's not what's happening here.

    Reacted by Eric Snow
  11. ericsnowcurrently commented on Nov 28, 2023

    @ericsnowcurrently
    ericsnowcurrently
    on Nov 28, 2023
    MemberAuthor
    More actions

    I'm closing this since I don't need it or any of its variants any more.

  12. ericsnowcurrently
    closed this as completedon Nov 28, 2023
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

    3.13only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.