mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
Chore: Queued event system (#5514)
* implemented queued event system * implemented basic tests
This commit is contained in:
parent
c157f74b49
commit
e56d3530cb
2 changed files with 171 additions and 2 deletions
|
|
@ -3,6 +3,7 @@ import os
|
|||
import re
|
||||
import copy
|
||||
import inspect
|
||||
import collections
|
||||
import logging
|
||||
import weakref
|
||||
from uuid import uuid4
|
||||
|
|
@ -340,8 +341,8 @@ class EventSystem(object):
|
|||
event.emit()
|
||||
return event
|
||||
|
||||
def emit_event(self, event):
|
||||
"""Emit event object.
|
||||
def _process_event(self, event):
|
||||
"""Process event topic and trigger callbacks.
|
||||
|
||||
Args:
|
||||
event (Event): Prepared event with topic and data.
|
||||
|
|
@ -356,6 +357,91 @@ class EventSystem(object):
|
|||
for callback in invalid_callbacks:
|
||||
self._registered_callbacks.remove(callback)
|
||||
|
||||
def emit_event(self, event):
|
||||
"""Emit event object.
|
||||
|
||||
Args:
|
||||
event (Event): Prepared event with topic and data.
|
||||
"""
|
||||
|
||||
self._process_event(event)
|
||||
|
||||
|
||||
class QueuedEventSystem(EventSystem):
|
||||
"""Events are automatically processed in queue.
|
||||
|
||||
If callback triggers another event, the event is not processed until
|
||||
all callbacks of previous event are processed.
|
||||
|
||||
Allows to implement custom event process loop by changing 'auto_execute'.
|
||||
|
||||
Note:
|
||||
This probably should be default behavior of 'EventSystem'. Changing it
|
||||
now could cause problems in existing code.
|
||||
|
||||
Args:
|
||||
auto_execute (Optional[bool]): If 'True', events are processed
|
||||
automatically. Custom loop calling 'process_next_event'
|
||||
must be implemented when set to 'False'.
|
||||
"""
|
||||
|
||||
def __init__(self, auto_execute=True):
|
||||
super(QueuedEventSystem, self).__init__()
|
||||
self._event_queue = collections.deque()
|
||||
self._current_event = None
|
||||
self._auto_execute = auto_execute
|
||||
|
||||
def __len__(self):
|
||||
return self.count()
|
||||
|
||||
def count(self):
|
||||
"""Get number of events in queue.
|
||||
|
||||
Returns:
|
||||
int: Number of events in queue.
|
||||
"""
|
||||
|
||||
return len(self._event_queue)
|
||||
|
||||
def process_next_event(self):
|
||||
"""Process next event in queue.
|
||||
|
||||
Should be used only if 'auto_execute' is set to 'False'. Only single
|
||||
event is processed.
|
||||
|
||||
Returns:
|
||||
Union[Event, None]: Processed event.
|
||||
"""
|
||||
|
||||
if self._current_event is not None:
|
||||
raise ValueError("An event is already in progress.")
|
||||
|
||||
if not self._event_queue:
|
||||
return None
|
||||
event = self._event_queue.popleft()
|
||||
self._current_event = event
|
||||
self._process_event(event)
|
||||
self._current_event = None
|
||||
return event
|
||||
|
||||
def emit_event(self, event):
|
||||
"""Emit event object.
|
||||
|
||||
Args:
|
||||
event (Event): Prepared event with topic and data.
|
||||
"""
|
||||
|
||||
if not self._auto_execute or self._current_event is not None:
|
||||
self._event_queue.append(event)
|
||||
return
|
||||
|
||||
self._event_queue.append(event)
|
||||
while self._event_queue:
|
||||
event = self._event_queue.popleft()
|
||||
self._current_event = event
|
||||
self._process_event(event)
|
||||
self._current_event = None
|
||||
|
||||
|
||||
class GlobalEventSystem:
|
||||
"""Event system living in global scope of process.
|
||||
|
|
|
|||
83
tests/unit/openpype/lib/test_event_system.py
Normal file
83
tests/unit/openpype/lib/test_event_system.py
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
from openpype.lib.events import EventSystem, QueuedEventSystem
|
||||
|
||||
|
||||
def test_default_event_system():
|
||||
output = []
|
||||
expected_output = [3, 2, 1]
|
||||
event_system = EventSystem()
|
||||
|
||||
def callback_1():
|
||||
event_system.emit("topic.2", {}, None)
|
||||
output.append(1)
|
||||
|
||||
def callback_2():
|
||||
event_system.emit("topic.3", {}, None)
|
||||
output.append(2)
|
||||
|
||||
def callback_3():
|
||||
output.append(3)
|
||||
|
||||
event_system.add_callback("topic.1", callback_1)
|
||||
event_system.add_callback("topic.2", callback_2)
|
||||
event_system.add_callback("topic.3", callback_3)
|
||||
|
||||
event_system.emit("topic.1", {}, None)
|
||||
|
||||
assert output == expected_output, (
|
||||
"Callbacks were not called in correct order")
|
||||
|
||||
|
||||
def test_base_event_system_queue():
|
||||
output = []
|
||||
expected_output = [1, 2, 3]
|
||||
event_system = QueuedEventSystem()
|
||||
|
||||
def callback_1():
|
||||
event_system.emit("topic.2", {}, None)
|
||||
output.append(1)
|
||||
|
||||
def callback_2():
|
||||
event_system.emit("topic.3", {}, None)
|
||||
output.append(2)
|
||||
|
||||
def callback_3():
|
||||
output.append(3)
|
||||
|
||||
event_system.add_callback("topic.1", callback_1)
|
||||
event_system.add_callback("topic.2", callback_2)
|
||||
event_system.add_callback("topic.3", callback_3)
|
||||
|
||||
event_system.emit("topic.1", {}, None)
|
||||
|
||||
assert output == expected_output, (
|
||||
"Callbacks were not called in correct order")
|
||||
|
||||
|
||||
def test_manual_event_system_queue():
|
||||
output = []
|
||||
expected_output = [1, 2, 3]
|
||||
event_system = QueuedEventSystem(auto_execute=False)
|
||||
|
||||
def callback_1():
|
||||
event_system.emit("topic.2", {}, None)
|
||||
output.append(1)
|
||||
|
||||
def callback_2():
|
||||
event_system.emit("topic.3", {}, None)
|
||||
output.append(2)
|
||||
|
||||
def callback_3():
|
||||
output.append(3)
|
||||
|
||||
event_system.add_callback("topic.1", callback_1)
|
||||
event_system.add_callback("topic.2", callback_2)
|
||||
event_system.add_callback("topic.3", callback_3)
|
||||
|
||||
event_system.emit("topic.1", {}, None)
|
||||
|
||||
while True:
|
||||
if event_system.process_next_event() is None:
|
||||
break
|
||||
|
||||
assert output == expected_output, (
|
||||
"Callbacks were not called in correct order")
|
||||
Loading…
Add table
Add a link
Reference in a new issue