generic/tests/test_event_exception.py
Arjan Molenaar 557eb22e30
Event manager executes all handlers
It accumulates the exceptions and raises an ExceptionGroup
exception if there were any failures.

Rationale:

Event handlers should not be dependent on the order in which they
are executed.

If a handler fails the remaining handlers are not executed.
This can result in non-deterministic behavior.

This commit fixes that my allowing all handlers to be executed.

To make this work we use the (backported) ExceptionGroup from
Python 3.11.
2022-05-08 13:28:21 +02:00

53 lines
1.2 KiB
Python

from __future__ import annotations
from typing import Callable
import pytest
from exceptiongroup import ExceptionGroup
from generic.event import Event, Manager
@pytest.fixture
def events():
return Manager()
def make_handler(effect: object) -> Callable[[Event], None]:
def handler(e):
e.effects.append(effect)
raise ValueError(effect)
return handler
def test_handle_all_subscribers(events):
events.subscribe(make_handler("handler1"), MyEvent)
events.subscribe(make_handler("handler2"), MyEvent)
e = MyEvent()
with pytest.raises(ExceptionGroup):
events.handle(e)
assert len(e.effects) == 2
assert "handler1" in e.effects
assert "handler2" in e.effects
def test_collect_all_exceptions(events):
events.subscribe(make_handler("handler1"), MyEvent)
events.subscribe(make_handler("handler2"), MyEvent)
e = MyEvent()
with pytest.raises(ExceptionGroup) as excinfo:
events.handle(e)
exc = excinfo.value
nested_exc = [str(e) for e in exc.exceptions]
assert len(exc.exceptions) == 2
assert "handler1" in nested_exc
assert "handler2" in nested_exc
class MyEvent:
def __init__(self) -> None:
self.effects: list[object] = []