-
Notifications
You must be signed in to change notification settings - Fork 17
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
refactor: change EmitLoopError message, and mechanism of info gathering #302
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #302 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 22 22
Lines 2033 2071 +38
=========================================
+ Hits 2033 2071 +38 ☔ View full report in Codecov by Sentry. |
CodSpeed Performance ReportMerging #302 will not alter performanceComparing Summary
|
side-note: I played a bit with using raise Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1045, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1059, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 8, in some_func
print(1 / x)
~~^~~
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/x.py", line 11, in <module>
sig.emit(0)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1025, in emit
self._run_emit_loop(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1052, in _run_emit_loop
raise EmitLoopError(exc=e, signal=self) from e
psygnal.EmitLoopError:
While emitting signal "<SignalInstance 'sig'>", an error occurred in a callback:
File /Users/talley/dev/self/psygnal/x.py:8, in some_func
With local variables:
x = 0
See ZeroDivisionError above for details. but a slight modification of: try:
with Signal._emitting(self):
# allow receiver to query sender with Signal.current_emitter()
self._run_emit_loop_inner()
except Exception as e:
raise EmitLoopError(exc=e, signal=self).with_traceback(
e.__traceback__
) from None would make it look like this: Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/x.py", line 11, in <module>
sig.emit(0)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1025, in emit
self._run_emit_loop(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1052, in _run_emit_loop
raise EmitLoopError(exc=e, signal=self).with_traceback(
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1045, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1061, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 8, in some_func
print(1 / x)
~~^~~
psygnal.EmitLoopError:
While emitting signal "<SignalInstance 'sig'>", an error occurred in a callback:
File /Users/talley/dev/self/psygnal/x.py:8, in some_func
With local variables:
x = 0
See ZeroDivisionError above for details. i think that reads a bit easier since it starts with @jni, I know that's a lot of text to look at, but if you have a thought/opinion here I'd welcome it (again, the goal is making event callbacks easier to debug) |
I like your modification @tlambert03! It is indeed much clearer — I always thought the "this is not a bug in psygnal" message sounded kinda cocky. 😂 Side note: why is it called EmitLoopError? I might call it EmitCallbackError? Am I misunderstanding something about the source of the error? |
Cocky?! There are plenty of other places that could raise exceptions that would be a bug in psygnal. But anyway, it's going away now :) So, which traceback did you prefer? The one using with_traceback or not? |
i guess it came from "an error that occurs while looping through callbacks during an emit" ... which i term the emit loop. But |
😂 haha it's just the certainty of the thing, like, no callback-calling + traceback-catching system I ever devised would make me confident enough to think that it could never be me. 😂 ie I would have chucked a "probably" or "almost certainly" in there 😂 Of course I understand the source of the message. But the new message is better. 😊
Yes, the one using with_traceback. It seems much easier to find the relevant information.
that is where my thoughts went but I think the existence of a for-loop should not really determine the error name...
I think this is important here. 😊 |
ok, cleaned up the stack inspection a bit to deal with differences between compiled and uncompiled stacks. This is the final rendering now of the traceback Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/x.py", line 9, in <module>
sig.emit(0)
File "src/psygnal/_signal.py", line 1176, in emit
self._run_emit_loop(args)
File "src/psygnal/_signal.py", line 1207, in _run_emit_loop
raise loop_err from cb_err # emit() call ABOVE || callback error BELOW
File "src/psygnal/_signal.py", line 1196, in _run_emit_loop
self._run_emit_loop_inner()
File "src/psygnal/_signal.py", line 1219, in _run_emit_loop_immediate
caller.cb(args)
File "src/psygnal/_weak_callback.py", line 354, in cb
def cb(self, args: tuple[Any, ...] = ()) -> None:
File "/Users/talley/dev/self/psygnal/x.py", line 7, in some_func
print(1 / x)
~~^~~
psygnal._exceptions.EmitLoopError:
While emitting signal <SignalInstance 'sig'>, a ZeroDivisionError occurred in a callback:
Signal emitted at: /Users/talley/dev/self/psygnal/x.py:9, in <module>
> sig.emit(0)
Callback error at: /Users/talley/dev/self/psygnal/x.py:7, in some_func
> print(1 / x)
Local variables:
x = 0
See ZeroDivisionError above for original traceback. |
also made sure it works for deeply nested signals, which will look like this: full traceback Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1196, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1221, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 23, in cb3
1.0 / value
~~~~^~~~~~~
ZeroDivisionError: float division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/talley/dev/self/psygnal/x.py", line 29, in <module>
sig.emit(1)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1176, in emit
self._run_emit_loop(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1204, in _run_emit_loop
raise cb_err
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1196, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1221, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 11, in cb1
sig.emit(2)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1176, in emit
self._run_emit_loop(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1204, in _run_emit_loop
raise cb_err
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1196, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1221, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 18, in cb2
sig.emit(0)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1176, in emit
self._run_emit_loop(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1209, in _run_emit_loop
raise loop_err from cb_err # emit() call ABOVE || callback error BELOW
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1196, in _run_emit_loop
self._run_emit_loop_inner()
File "/Users/talley/dev/self/psygnal/src/psygnal/_signal.py", line 1221, in _run_emit_loop_immediate
caller.cb(args)
File "/Users/talley/dev/self/psygnal/src/psygnal/_weak_callback.py", line 357, in cb
self._f(*self._args, *args, **self._kwargs)
File "/Users/talley/dev/self/psygnal/x.py", line 23, in cb3
1.0 / value
~~~~^~~~~~~
psygnal.EmitLoopError:
|
i think the codecov thing is wrong. closing and reopening |
This PR avoids the need to hang on to any information about the current callback & args by inspecting the stack after an exception happens. I think it also makes the error a bit easier to read.
With the following error as an example:
before this PR:
# ... stack trace psygnal._exceptions.EmitLoopError: While emitting signal 'builtins.NoneType.sig', an error occurred in callback '__main__.some_func'. The args passed to the callback were: (0,) This is not a bug in psygnal. See 'ZeroDivisionError' above for details.
after this PR:
@Czaki, since it does some mildly deep inspection, your eyes on this would be appreciated.