feat: adding notification callback functionality to DataService

This commit is contained in:
Mose Müller 2023-08-02 12:06:19 +02:00
parent 8fdfe577a0
commit 3858c7efc2

View File

@ -24,6 +24,7 @@ class DataService(rpyc.Service):
be tracked consistently. The keys of the dictionary are the ids of the original be tracked consistently. The keys of the dictionary are the ids of the original
lists, and the values are the DataServiceList instances that wrap these lists. lists, and the values are the DataServiceList instances that wrap these lists.
""" """
_notification_callbacks: list[Callable[[str, str, Any], Any]] = []
def __init__(self) -> None: def __init__(self) -> None:
# Keep track of the root object. This helps to filter the emission of # Keep track of the root object. This helps to filter the emission of
@ -40,11 +41,7 @@ class DataService(rpyc.Service):
self._callbacks: set[Callable[[str, Any], None]] = set() self._callbacks: set[Callable[[str, Any], None]] = set()
self._set_start_and_stop_for_async_methods() self._set_start_and_stop_for_async_methods()
self._register_list_change_callbacks(self, f"{self.__class__.__name__}") self._register_callbacks()
self._register_DataService_instance_callbacks(
self, f"{self.__class__.__name__}"
)
self._register_property_callbacks(self, f"{self.__class__.__name__}")
self.__check_instance_classes() self.__check_instance_classes()
self._initialised = True self._initialised = True
@ -119,6 +116,13 @@ class DataService(rpyc.Service):
setattr(self, f"start_{name}", start_task) setattr(self, f"start_{name}", start_task)
setattr(self, f"stop_{name}", stop_task) setattr(self, f"stop_{name}", stop_task)
def _register_callbacks(self) -> None:
self._register_list_change_callbacks(self, f"{self.__class__.__name__}")
self._register_DataService_instance_callbacks(
self, f"{self.__class__.__name__}"
)
self._register_property_callbacks(self, f"{self.__class__.__name__}")
def _register_list_change_callbacks( def _register_list_change_callbacks(
self, obj: "DataService", parent_path: str self, obj: "DataService", parent_path: str
) -> None: ) -> None:
@ -407,6 +411,12 @@ class DataService(rpyc.Service):
def _emit_notification(self, parent_path: str, name: str, value: Any) -> None: def _emit_notification(self, parent_path: str, name: str, value: Any) -> None:
logger.debug(f"{parent_path}.{name} changed to {value}!") logger.debug(f"{parent_path}.{name} changed to {value}!")
for callback in self._notification_callbacks:
try:
callback(parent_path, name, value)
except Exception as e:
logger.error(e)
def serialize(self, prefix: str = "") -> dict[str, dict[str, Any]]: def serialize(self, prefix: str = "") -> dict[str, dict[str, Any]]:
""" """
Serializes the instance into a dictionary, preserving the structure of the Serializes the instance into a dictionary, preserving the structure of the
@ -465,7 +475,6 @@ class DataService(rpyc.Service):
"type": type(value).__name__, "type": type(value).__name__,
"value": value.serialize(prefix=key), "value": value.serialize(prefix=key),
"readonly": False, "readonly": False,
"id": id(value),
"doc": inspect.getdoc(value), "doc": inspect.getdoc(value),
} }
elif isinstance(value, list): elif isinstance(value, list):
@ -515,3 +524,22 @@ class DataService(rpyc.Service):
} }
return result return result
def add_notification_callback(
self, callback: Callable[[str, str, Any], None]
) -> None:
"""
Adds a new notification callback function to the list of callbacks.
This function is intended to be used for registering a function that will be
called whenever a the value of an attribute changes.
Args:
callback (Callable[[str, str, Any], None]): The callback function to
register.
It should accept three parameters:
- parent_path (str): The parent path of the parameter.
- name (str): The name of the changed parameter.
- value (Any): The value of the parameter.
"""
self._notification_callbacks.append(callback)