pydase/tests/test_properties.py

309 lines
9.2 KiB
Python

from pytest import LogCaptureFixture
from pydase import DataService
def test_properties(caplog: LogCaptureFixture) -> None:
class ServiceClass(DataService):
_voltage = 10.0
_current = 1.0
@property
def power(self) -> float:
return self._voltage * self.current
@property
def voltage(self) -> float:
return self._voltage
@voltage.setter
def voltage(self, value: float) -> None:
self._voltage = value
@property
def current(self) -> float:
return self._current
@current.setter
def current(self, value: float) -> None:
self._current = value
test_service = ServiceClass()
test_service.voltage = 1
assert "ServiceClass.power changed to 1.0" in caplog.text
assert "ServiceClass.voltage changed to 1.0" in caplog.text
caplog.clear()
test_service.current = 12.0
assert "ServiceClass.power changed to 12.0" in caplog.text
assert "ServiceClass.current changed to 12.0" in caplog.text
def test_nested_properties(caplog: LogCaptureFixture) -> None:
class SubSubClass(DataService):
name = "Hello"
class SubClass(DataService):
name = "Hello"
class_attr = SubSubClass()
class ServiceClass(DataService):
class_attr = SubClass()
name = "World"
@property
def subsub_name(self) -> str:
return f"{self.class_attr.class_attr.name} {self.name}"
@property
def sub_name(self) -> str:
return f"{self.class_attr.name} {self.name}"
test_service = ServiceClass()
test_service.name = "Peepz"
assert "ServiceClass.name changed to Peepz" in caplog.text
assert "ServiceClass.sub_name changed to Hello Peepz" in caplog.text
assert "ServiceClass.subsub_name changed to Hello Peepz" in caplog.text
caplog.clear()
test_service.class_attr.name = "Hi"
assert "ServiceClass.sub_name changed to Hi Peepz" in caplog.text
assert (
"ServiceClass.subsub_name changed to Hello Peepz" in caplog.text
) # registers subclass changes
assert "ServiceClass.class_attr.name changed to Hi" in caplog.text
caplog.clear()
test_service.class_attr.class_attr.name = "Ciao"
assert (
"ServiceClass.sub_name changed to Hi Peepz" in caplog.text
) # registers subclass changes
assert "ServiceClass.subsub_name changed to Ciao Peepz" in caplog.text
assert "ServiceClass.class_attr.class_attr.name changed to Ciao" in caplog.text
caplog.clear()
def test_simple_list_properties(caplog: LogCaptureFixture) -> None:
class ServiceClass(DataService):
list = ["Hello", "Ciao"]
name = "World"
@property
def total_name(self) -> str:
return f"{self.list[0]} {self.name}"
test_service = ServiceClass()
test_service.name = "Peepz"
assert "ServiceClass.name changed to Peepz" in caplog.text
assert "ServiceClass.total_name changed to Hello Peepz" in caplog.text
caplog.clear()
test_service.list[0] = "Hi"
assert "ServiceClass.total_name changed to Hi Peepz" in caplog.text
assert "ServiceClass.list[0] changed to Hi" in caplog.text
def test_class_list_properties(caplog: LogCaptureFixture) -> None:
class SubClass(DataService):
name = "Hello"
class ServiceClass(DataService):
list = [SubClass()]
name = "World"
@property
def total_name(self) -> str:
return f"{self.list[0].name} {self.name}"
test_service = ServiceClass()
test_service.name = "Peepz"
assert "ServiceClass.name changed to Peepz" in caplog.text
assert "ServiceClass.total_name changed to Hello Peepz" in caplog.text
caplog.clear()
test_service.list[0].name = "Hi"
assert "ServiceClass.total_name changed to Hi Peepz" in caplog.text
assert "ServiceClass.list[0].name changed to Hi" in caplog.text
def test_subclass_properties(caplog: LogCaptureFixture) -> None:
class SubClass(DataService):
name = "Hello"
_voltage = 10.0
_current = 1.0
@property
def power(self) -> float:
return self._voltage * self.current
@property
def voltage(self) -> float:
return self._voltage
@voltage.setter
def voltage(self, value: float) -> None:
self._voltage = value
@property
def current(self) -> float:
return self._current
@current.setter
def current(self, value: float) -> None:
self._current = value
class ServiceClass(DataService):
class_attr = SubClass()
@property
def voltage(self) -> float:
return self.class_attr.voltage
test_service = ServiceClass()
test_service.class_attr.voltage = 10.0
# using a set here as "ServiceClass.voltage = 10.0" is emitted twice. Once for
# changing voltage, and once for changing power.
assert "ServiceClass.class_attr.voltage changed to 10.0" in caplog.text
assert "ServiceClass.class_attr.power changed to 10.0" in caplog.text
assert "ServiceClass.voltage changed to 10.0" in caplog.text
caplog.clear()
def test_subclass_properties_2(caplog: LogCaptureFixture) -> None:
class SubClass(DataService):
name = "Hello"
_voltage = 10.0
_current = 1.0
@property
def power(self) -> float:
return self._voltage * self.current
@property
def voltage(self) -> float:
return self._voltage
@voltage.setter
def voltage(self, value: float) -> None:
self._voltage = value
@property
def current(self) -> float:
return self._current
@current.setter
def current(self, value: float) -> None:
self._current = value
class ServiceClass(DataService):
class_attr = [SubClass() for i in range(2)]
@property
def voltage(self) -> float:
return self.class_attr[0].voltage
test_service = ServiceClass()
test_service.class_attr[1].current = 10.0
# using a set here as "ServiceClass.voltage = 10.0" is emitted twice. Once for
# changing current, and once for changing power. Note that the voltage property is
# only dependent on class_attr[0] but still emits an update notification. This is
# because every time any item in the list `test_service.class_attr` is changed,
# a notification will be emitted.
assert "ServiceClass.class_attr[1].current changed to 10.0" in caplog.text
assert "ServiceClass.class_attr[1].power changed to 100.0" in caplog.text
assert "ServiceClass.voltage changed to 10.0" in caplog.text
def test_subsubclass_properties(caplog: LogCaptureFixture) -> None:
class SubSubClass(DataService):
_voltage = 10.0
@property
def voltage(self) -> float:
return self._voltage
@voltage.setter
def voltage(self, value: float) -> None:
self._voltage = value
class SubClass(DataService):
class_attr = SubSubClass()
current = 0.5
@property
def power(self) -> float:
return self.class_attr.voltage * self.current
class ServiceClass(DataService):
class_attr = [SubClass() for i in range(2)]
@property
def power(self) -> float:
return self.class_attr[0].power
test_service = ServiceClass()
test_service.class_attr[1].class_attr.voltage = 100.0
assert (
"ServiceClass.class_attr[0].class_attr.voltage changed to 100.0" in caplog.text
)
assert (
"ServiceClass.class_attr[1].class_attr.voltage changed to 100.0" in caplog.text
)
assert "ServiceClass.class_attr[0].power changed to 50.0" in caplog.text
assert "ServiceClass.class_attr[1].power changed to 50.0" in caplog.text
assert "ServiceClass.power changed to 50.0" in caplog.text
def test_subsubclass_instance_properties(caplog: LogCaptureFixture) -> None:
class SubSubClass(DataService):
def __init__(self) -> None:
self._voltage = 10.0
super().__init__()
@property
def voltage(self) -> float:
return self._voltage
@voltage.setter
def voltage(self, value: float) -> None:
self._voltage = value
class SubClass(DataService):
def __init__(self) -> None:
self.attr = [SubSubClass()]
self.current = 0.5
super().__init__()
@property
def power(self) -> float:
return self.attr[0].voltage * self.current
class ServiceClass(DataService):
class_attr = [SubClass() for i in range(2)]
@property
def power(self) -> float:
return self.class_attr[0].power
test_service = ServiceClass()
test_service.class_attr[1].attr[0].voltage = 100.0
# again, changing an item in a list will trigger the callbacks. This is why a
# notification for `ServiceClass.power` is emitted although it did not change its
# value
assert "ServiceClass.class_attr[1].attr[0].voltage changed to 100.0" in caplog.text
assert "ServiceClass.class_attr[1].power changed to 50.0" in caplog.text
assert "ServiceClass.power changed to 5.0" in caplog.text