pydase/tests/data_service/test_data_service_observer.py

187 lines
5.5 KiB
Python

import logging
from typing import Any
import pydase
import pytest
from pydase.data_service.data_service_observer import DataServiceObserver
from pydase.data_service.state_manager import StateManager
from pydase.utils.serialization.serializer import SerializationError, dump
logger = logging.getLogger()
def test_static_property_dependencies() -> None:
class SubClass(pydase.DataService):
_name = "SubClass"
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, value: str) -> None:
self._name = value
class ServiceClass(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.list_attr = [SubClass()]
self._name = "ServiceClass"
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, value: str) -> None:
self._name = value
service_instance = ServiceClass()
state_manager = StateManager(service_instance)
observer = DataServiceObserver(state_manager)
logger.debug(observer.property_deps_dict)
assert observer.property_deps_dict == {
"list_attr[0]._name": ["list_attr[0].name"],
"_name": ["name"],
}
def test_dynamic_list_property_dependencies() -> None:
class SubClass(pydase.DataService):
_name = "SubClass"
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, value: str) -> None:
self._name = value
class ServiceClass(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.list_attr = [SubClass()]
service_instance = ServiceClass()
state_manager = StateManager(service_instance)
observer = DataServiceObserver(state_manager)
assert observer.property_deps_dict == {
"list_attr[0]._name": ["list_attr[0].name"],
}
service_instance.list_attr.append(SubClass())
assert observer.property_deps_dict == {
"list_attr[0]._name": ["list_attr[0].name"],
"list_attr[1]._name": ["list_attr[1].name"],
}
def test_protected_or_private_change_logs(caplog: pytest.LogCaptureFixture) -> None:
class OtherService(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self._name = "Hi"
class MyService(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.subclass = OtherService()
service = MyService()
state_manager = StateManager(service)
DataServiceObserver(state_manager)
service.subclass._name = "Hello"
assert "'subclass._name' changed to 'Hello'" not in caplog.text
def test_dynamic_list_entry_with_property(caplog: pytest.LogCaptureFixture) -> None:
class PropertyClass(pydase.DataService):
_name = "Hello"
@property
def name(self) -> str:
"""The name property."""
return self._name
class MyService(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.list_attr = []
def toggle_high_voltage(self) -> None:
self.list_attr = []
self.list_attr.append(PropertyClass())
self.list_attr[0]._name = "Hoooo"
service = MyService()
state_manager = StateManager(service)
DataServiceObserver(state_manager)
service.toggle_high_voltage()
assert "'list_attr[0].name' changed to 'Hello'" not in caplog.text
assert "'list_attr[0].name' changed to 'Hoooo'" in caplog.text
def test_private_attribute_does_not_have_to_be_serializable() -> None:
class MyService(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.publ_attr: Any = 1
self.__priv_attr = (1,)
def change_publ_attr(self) -> None:
self.publ_attr = (2,) # cannot be serialized
def change_priv_attr(self) -> None:
self.__priv_attr = (2,)
service_instance = MyService()
pydase.Server(service_instance)
with pytest.raises(SerializationError):
service_instance.change_publ_attr()
service_instance.change_priv_attr()
def test_normalized_attr_path_in_dependent_property_changes(
caplog: pytest.LogCaptureFixture,
) -> None:
class SubService(pydase.DataService):
_prop = 10.0
@property
def prop(self) -> float:
return self._prop
class MyService(pydase.DataService):
def __init__(self) -> None:
super().__init__()
self.service_dict = {"one": SubService()}
service_instance = MyService()
state_manager = StateManager(service=service_instance)
observer = DataServiceObserver(state_manager=state_manager)
assert observer.property_deps_dict["service_dict['one']._prop"] == [
"service_dict['one'].prop"
]
# We can use dict key path encoded with double quotes
state_manager.set_service_attribute_value_by_path(
'service_dict["one"]._prop', dump(11.0)
)
assert service_instance.service_dict["one"].prop == 11.0
assert "'service_dict[\"one\"].prop' changed to '11.0'" in caplog.text
# We can use dict key path encoded with single quotes
state_manager.set_service_attribute_value_by_path(
"service_dict['one']._prop", dump(12.0)
)
assert service_instance.service_dict["one"].prop == 12.0
assert "'service_dict[\"one\"].prop' changed to '12.0'" in caplog.text