Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Added
-----

- Python 3.14 to the CI and release test matrices.
- ``Event.reset()`` to clear propagation state and allow re-dispatching the
same event instance.

Changed
-------
Expand Down
45 changes: 45 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,48 @@ def test_first_event_will_get_reference_to_dispatcher_and_name(event_id):
assert not e.propagation_stopped
assert e.dispatcher == dispatcher
assert e.name == event_id


def test_event_reset():
event = Event()
event.stop_propagation()
assert event.propagation_stopped

event.reset()
assert not event.propagation_stopped


def test_event_is_reusable_after_reset():
dispatcher = EventDispatcher()

listener1 = mock.MagicMock()
state = {"stop": True}

def stopper(event):
if state["stop"]:
event.stop_propagation()

listener3 = mock.MagicMock()

dispatcher.add_listener("evt", listener1)
dispatcher.add_listener("evt", stopper)
dispatcher.add_listener("evt", listener3)

event = Event()
dispatcher.dispatch("evt", event)
assert listener1.call_count == 1
assert listener3.call_count == 0
assert event.propagation_stopped

# reused as-is the instance stays stopped, so later listeners are still skipped
dispatcher.dispatch("evt", event)
assert listener3.call_count == 0

# after reset the instance is reusable and propagation runs through again
state["stop"] = False
event.reset()
assert not event.propagation_stopped
dispatcher.dispatch("evt", event)
assert listener1.call_count == 3
assert listener3.call_count == 1
assert not event.propagation_stopped
9 changes: 9 additions & 0 deletions whistle/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@ class Event(object):
def stop_propagation(self):
"""Stop event propagation, meaning that the remaining handlers won't be called after this one."""
self.propagation_stopped = True

def reset(self):
"""
Reset the propagation state so the same event instance can be dispatched again.

Useful when a single event instance is reused across several dispatches and an intermediate
listener stopped propagation in a previous run.
"""
self.propagation_stopped = False
Loading