Skip to content

Commit

Permalink
Merge pull request #65 from OFFIS-DAI/feature-role-internal-events
Browse files Browse the repository at this point in the history
Feature role internal events
  • Loading branch information
jsagerOffis authored Feb 8, 2024
2 parents 54b71f8 + cd45bb8 commit aaef2ab
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 3 deletions.
37 changes: 35 additions & 2 deletions mango/agent/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"""
import asyncio
from abc import ABC
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Tuple, Union, Callable

from mango.agent.core import Agent, AgentContext, AgentDelegates
from mango.util.scheduling import Scheduler
Expand Down Expand Up @@ -113,6 +113,7 @@ def __init__(self, agent_context, scheduler):
self._role_model_type_to_subs = {}
self._message_subs = []
self._send_msg_subs = {}
self._role_event_type_to_handler = {}
self._agent_context = agent_context
self._scheduler = scheduler
self._data = DataContainer()
Expand Down Expand Up @@ -284,12 +285,23 @@ def subscribe_message(self, role, method, message_condition, priority=0):
elif i == len(self._message_subs) - 1:
self._message_subs.append((role, message_condition, method, priority))

def subscribe_send(self, role, method):
def subscribe_send(self, role: Role, method: Callable):
if role in self._send_msg_subs:
self._send_msg_subs[role].append(method)
else:
self._send_msg_subs[role] = [method]

def emit_event(self, event: Any, event_source: Any = None):
subs = self._role_event_type_to_handler[type(event)]
for _, method in subs:
method(event, event_source)

def subscribe_event(self, role: Role, event_type: type, method: Callable):
if not event_type in self._role_event_type_to_handler:
self._role_event_type_to_handler[event_type] = []

self._role_event_type_to_handler[event_type] += [(role, method)]


class RoleContext(AgentDelegates):
"""Implementation of the RoleContext."""
Expand Down Expand Up @@ -407,6 +419,27 @@ async def send_acl_message(
**kwargs
)

def emit_event(self, event: Any, event_source: Any = None):
"""Emit an custom event to other roles.
:param event: the event
:type event: Any
:param event_source: emitter of the event (mostly the emitting role), defaults to None
:type event_source: Any, optional
"""
self._role_handler.emit_event(event, event_source)

def subscribe_event(self, role: Role, event_type: Any, handler_method: Callable):
"""Subscribe to specific event types. The listener will be evaluated based
on their order of subscription
:param role: the role in which you want to handle the event
:type role: Role
:param event_type: the event type you want to handle
:type event_type: Any
"""
self._role_handler.subscribe_event(role, event_type, handler_method)

@property
def addr(self):
return self._agent_context.addr
Expand Down
46 changes: 45 additions & 1 deletion tests/unit_tests/role/role_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from mango.agent.role import Role, RoleHandler, DataContainer
from mango.agent.role import Role, RoleHandler, DataContainer, RoleContext
from mango.util.scheduling import Scheduler
from dataclasses import dataclass


class RoleModel:
Expand Down Expand Up @@ -100,3 +101,46 @@ def test_data_container():
assert "abc" in data_container
assert "cba" in data_container
assert not "bca" in data_container


@dataclass
class Event:
name: str


class RoleHandlingEvents(Role):
def __init__(self):
self.source = None
self.event = None

def handle_event(self, event, source):
self.event = event
self.source = source

def setup(self) -> None:
self.context.subscribe_event(self, Event, self.handle_event)


def test_emit_event():
# GIVEN
role_handler = RoleHandler(None, None)
context = RoleContext(None, None, role_handler, None, None)
ex_role = SubRole()
ex_role2 = RoleHandlingEvents()
context.add_role(ex_role)
context.add_role(ex_role2)
event = Event("Here I am!")

# WHEN
context.emit_event(event=event)

# THEN
assert ex_role2.event == event
assert ex_role2.source is None

# WHEN
context.emit_event(event=event, event_source=ex_role)

# THEN
assert ex_role2.event == event
assert ex_role2.source == ex_role

0 comments on commit aaef2ab

Please sign in to comment.