diff --git a/src/psygnal/_signal.py b/src/psygnal/_signal.py index f746db9c..8e04090a 100644 --- a/src/psygnal/_signal.py +++ b/src/psygnal/_signal.py @@ -1212,9 +1212,9 @@ def emit_fast(self, *args: Any) -> None: f"RecursionError when " f"emitting signal {self.name!r} with args {args}" ) from e + except EmitLoopError as e: # pragma: no cover + raise e except Exception as cb_err: - if isinstance(cb_err, EmitLoopError): - raise cb_err loop_err = EmitLoopError(exc=cb_err, signal=self).with_traceback( cb_err.__traceback__ ) @@ -1245,9 +1245,9 @@ def _run_emit_loop(self, args: tuple[Any, ...]) -> None: f"RecursionError when " f"emitting signal {self.name!r} with args {args}" ) from e + except EmitLoopError as e: + raise e except Exception as cb_err: - if isinstance(cb_err, EmitLoopError): - raise cb_err loop_err = EmitLoopError( exc=cb_err, signal=self, diff --git a/tests/test_psygnal.py b/tests/test_psygnal.py index 04155e1f..7696d594 100644 --- a/tests/test_psygnal.py +++ b/tests/test_psygnal.py @@ -132,6 +132,57 @@ def test_emit_fast(): # calling directly also works emitter.one_int(1) mock.assert_called_once_with(1) + mock.reset_mock() + + with emitter.one_int.blocked(): + emitter.one_int.emit_fast(2) + mock.assert_not_called() + + with emitter.one_int.paused(): + emitter.one_int.emit_fast(3) + mock.assert_not_called() + emitter.one_int.emit_fast(4) + mock.assert_has_calls([call(3), call(4)]) + + +def test_emit_fast_errors(): + emitter = Emitter() + err = ValueError() + + @emitter.one_int.connect + def boom(v: int) -> None: + raise err + + import re + + error_re = re.compile( + "signal 'tests.test_psygnal.Emitter.one_int'" f".*{re.escape(__file__)}", + re.DOTALL, + ) + with pytest.raises(EmitLoopError, match=error_re): + emitter.one_int.emit_fast(42) + + +def test_emit_fast_recursion_errors(): + """Test emit_fast method.""" + emitter = Emitter() + emitter.one_int.emit_fast(1) + + @emitter.one_int.connect + def callback() -> None: + emitter.one_int.emit(2) + + with pytest.raises(RecursionError): + emitter.one_int.emit_fast(3) + + emitter.one_int.disconnect(callback) + + @emitter.one_int.connect + def callback() -> None: + emitter.one_int.emit_fast(2) + + with pytest.raises(RecursionError): + emitter.one_int.emit_fast(3) def test_decorator():