Skip to content
This repository has been archived by the owner on Jul 17, 2024. It is now read-only.

feat: Add file and line numbers to exception traceback #28

Merged
merged 6 commits into from
Apr 5, 2024
Merged

feat: Add file and line numbers to exception traceback #28

merged 6 commits into from
Apr 5, 2024

Conversation

Christopher-Chianelli
Copy link
Collaborator

  • CPython does not expose any sane way to set the traceback
    of an exception that does not orginate from a CPython
    exception. In particular, traceback must be an
    internal Traceback type, and that Traceback type
    cannot be constructed without using internal frame
    and code types, which also cannot be constructed.

  • To get around this, we exploit the traceback module,
    which does not care about types and only care about
    interfaces. This allow us to use our own fake frame
    and code classes that match their interface.

  • We exploit object.new to create an instance of
    TracebackException without calling its constructor,
    and set all its fields manually

  • To set the stack field, we use StackSummary.from_list.
    with the Java traceback.

  • Python 3.10 has a quirk: it calls RERAISE in
    the finally block corresponding to an except
    block. That finally immediately calls RERAISE,
    but TOS is a type, so that exception loses both
    it cause and message. So work around this,
    we deviate a bit from how the code apparently
    works

    • After finally branch is taken, stack is
      <block (3 items)> traceback, exeception, exception
      instead of
      <block (3 items)> traceback, exeception, type
    • JUMP_IF_NOT_EXEC_MATCH is now an instanceof
      instead of issubclass

    This works since Python pops off all these values when
    actually entering the code for an except block, and
    JUMP_IF_NOT_EXEC_MATCH is the only opcode that can
    be encountered.

- CPython does not expose any sane way to set the traceback
  of an exception that does not orginate from a CPython
  exception. In particular, __traceback__ must be an
  internal Traceback type, and that Traceback type
  cannot be constructed without using internal frame
  and code types, which also cannot be constructed.

- To get around this, we exploit the traceback module,
  which does not care about types and only care about
  interfaces. This allow us to use our own fake frame
  and code classes that match their interface.

- We exploit object.__new__ to create an instance of
  TracebackException without calling its constructor,
  and set all its fields manually

- To set the stack field, we use StackSummary.extract.
  We might be able to use StackSummary.from_list and
  avoid the fake frames and use FrameSummary directly
- Python 3.10 has a quirk: it calls RERAISE in
  the finally block corresponding to an except
  block. That finally immediately calls RERAISE,
  but TOS is a type, so that exception loses both
  it cause and message. So work around this,
  we deviate a bit from how the code apparenty
  works

  - After finally branch is taken, stack is
    <old stack> <block (3 items)> traceback, exeception, exception
    instead of
    <old stack> <block (3 items)> traceback, exeception, type
  - JUMP_IF_NOT_EXEC_MATCH is now an instanceof
    instead of issubclass

  This works since Python pops off all these values when
  actually entering the code for an except block, and
  JUMP_IF_NOT_EXEC_MATCH is the only opcode that can
  be encountered.

- Fix a bug in generating traceback
Copy link
Contributor

@triceo triceo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo, otherwise LGTM.

jpyinterpreter/tests/test_builtins.py Outdated Show resolved Hide resolved
@triceo triceo self-requested a review April 5, 2024 17:29
@Christopher-Chianelli Christopher-Chianelli merged commit 850ff44 into TimefoldAI:main Apr 5, 2024
3 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants