mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-21 16:50:02 +02:00
Merge pull request #77 from tiqi-group/69-add-support-for-adding-objects-to-a-list
69 add support for adding objects to a list
This commit is contained in:
commit
9778541ee4
2
.github/workflows/python-package.yml
vendored
2
.github/workflows/python-package.yml
vendored
@ -21,6 +21,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: chartboost/ruff-action@v1
|
- uses: chartboost/ruff-action@v1
|
||||||
|
with:
|
||||||
|
src: "./src"
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
|
@ -82,7 +82,7 @@ ignore = [
|
|||||||
"PERF203", # try-except-in-loop
|
"PERF203", # try-except-in-loop
|
||||||
]
|
]
|
||||||
extend-exclude = [
|
extend-exclude = [
|
||||||
"docs", "frontend", "tests"
|
"docs", "frontend"
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.mccabe]
|
[tool.ruff.lint.mccabe]
|
||||||
|
@ -4,6 +4,7 @@ from copy import deepcopy
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pydase.data_service.state_manager import StateManager
|
from pydase.data_service.state_manager import StateManager
|
||||||
|
from pydase.observer_pattern.observable.observable_object import ObservableObject
|
||||||
from pydase.observer_pattern.observer.property_observer import (
|
from pydase.observer_pattern.observer.property_observer import (
|
||||||
PropertyObserver,
|
PropertyObserver,
|
||||||
)
|
)
|
||||||
@ -37,6 +38,9 @@ class DataServiceObserver(PropertyObserver):
|
|||||||
for callback in self._notification_callbacks:
|
for callback in self._notification_callbacks:
|
||||||
callback(full_access_path, value, cached_value_dict)
|
callback(full_access_path, value, cached_value_dict)
|
||||||
|
|
||||||
|
if isinstance(value, ObservableObject):
|
||||||
|
self._update_property_deps_dict()
|
||||||
|
|
||||||
self._notify_dependent_property_changes(full_access_path)
|
self._notify_dependent_property_changes(full_access_path)
|
||||||
|
|
||||||
def _update_cache_value(
|
def _update_cache_value(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import TYPE_CHECKING, Any, ClassVar
|
from collections.abc import Iterable
|
||||||
|
from typing import TYPE_CHECKING, Any, ClassVar, SupportsIndex
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pydase.observer_pattern.observer.observer import Observer
|
from pydase.observer_pattern.observer.observer import Observer
|
||||||
@ -146,6 +147,67 @@ class _ObservableList(ObservableObject, list[Any]):
|
|||||||
|
|
||||||
self._notify_changed(f"[{key}]", value)
|
self._notify_changed(f"[{key}]", value)
|
||||||
|
|
||||||
|
def append(self, __object: Any) -> None:
|
||||||
|
self._initialise_new_objects(f"[{len(self)}]", __object)
|
||||||
|
super().append(__object)
|
||||||
|
self._notify_changed("", self)
|
||||||
|
|
||||||
|
def clear(self) -> None:
|
||||||
|
self._remove_self_from_observables()
|
||||||
|
|
||||||
|
super().clear()
|
||||||
|
|
||||||
|
self._notify_changed("", self)
|
||||||
|
|
||||||
|
def extend(self, __iterable: Iterable[Any]) -> None:
|
||||||
|
self._remove_self_from_observables()
|
||||||
|
|
||||||
|
try:
|
||||||
|
super().extend(__iterable)
|
||||||
|
finally:
|
||||||
|
for i, item in enumerate(self):
|
||||||
|
super().__setitem__(i, self._initialise_new_objects(f"[{i}]", item))
|
||||||
|
|
||||||
|
self._notify_changed("", self)
|
||||||
|
|
||||||
|
def insert(self, __index: SupportsIndex, __object: Any) -> None:
|
||||||
|
self._remove_self_from_observables()
|
||||||
|
|
||||||
|
try:
|
||||||
|
super().insert(__index, __object)
|
||||||
|
finally:
|
||||||
|
for i, item in enumerate(self):
|
||||||
|
super().__setitem__(i, self._initialise_new_objects(f"[{i}]", item))
|
||||||
|
|
||||||
|
self._notify_changed("", self)
|
||||||
|
|
||||||
|
def pop(self, __index: SupportsIndex = -1) -> Any:
|
||||||
|
self._remove_self_from_observables()
|
||||||
|
|
||||||
|
try:
|
||||||
|
popped_item = super().pop(__index)
|
||||||
|
finally:
|
||||||
|
for i, item in enumerate(self):
|
||||||
|
super().__setitem__(i, self._initialise_new_objects(f"[{i}]", item))
|
||||||
|
|
||||||
|
self._notify_changed("", self)
|
||||||
|
return popped_item
|
||||||
|
|
||||||
|
def remove(self, __value: Any) -> None:
|
||||||
|
self._remove_self_from_observables()
|
||||||
|
|
||||||
|
try:
|
||||||
|
super().remove(__value)
|
||||||
|
finally:
|
||||||
|
for i, item in enumerate(self):
|
||||||
|
super().__setitem__(i, self._initialise_new_objects(f"[{i}]", item))
|
||||||
|
|
||||||
|
self._notify_changed("", self)
|
||||||
|
|
||||||
|
def _remove_self_from_observables(self) -> None:
|
||||||
|
for i in range(len(self)):
|
||||||
|
self._remove_observer_if_observable(f"[{i}]")
|
||||||
|
|
||||||
def _remove_observer_if_observable(self, name: str) -> None:
|
def _remove_observer_if_observable(self, name: str) -> None:
|
||||||
key = int(name[1:-1])
|
key = int(name[1:-1])
|
||||||
current_value = self.__getitem__(key)
|
current_value = self.__getitem__(key)
|
||||||
|
@ -29,6 +29,9 @@ def get_property_dependencies(prop: property, prefix: str = "") -> list[str]:
|
|||||||
class PropertyObserver(Observer):
|
class PropertyObserver(Observer):
|
||||||
def __init__(self, observable: Observable) -> None:
|
def __init__(self, observable: Observable) -> None:
|
||||||
super().__init__(observable)
|
super().__init__(observable)
|
||||||
|
self._update_property_deps_dict()
|
||||||
|
|
||||||
|
def _update_property_deps_dict(self) -> None:
|
||||||
self.property_deps_dict = reverse_dict(
|
self.property_deps_dict = reverse_dict(
|
||||||
self._get_properties_and_their_dependencies(self.observable)
|
self._get_properties_and_their_dependencies(self.observable)
|
||||||
)
|
)
|
||||||
|
76
tests/data_service/test_data_service_observer.py
Normal file
76
tests/data_service/test_data_service_observer.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
import pydase
|
||||||
|
from pydase.data_service.data_service_observer import DataServiceObserver
|
||||||
|
from pydase.data_service.state_manager import StateManager
|
||||||
|
|
||||||
|
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"],
|
||||||
|
}
|
@ -20,7 +20,7 @@ def test_simple_instance_list_attribute(caplog: pytest.LogCaptureFixture) -> Non
|
|||||||
self.list_attr = [1, 2]
|
self.list_attr = [1, 2]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.list_attr[0] = 12
|
instance.list_attr[0] = 12
|
||||||
|
|
||||||
assert "'list_attr[0]' changed to '12'" in caplog.text
|
assert "'list_attr[0]' changed to '12'" in caplog.text
|
||||||
@ -38,7 +38,7 @@ def test_instance_object_list_attribute(caplog: pytest.LogCaptureFixture) -> Non
|
|||||||
self.list_attr = [NestedObservable()]
|
self.list_attr = [NestedObservable()]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.list_attr[0].name = "Ciao"
|
instance.list_attr[0].name = "Ciao"
|
||||||
|
|
||||||
assert "'list_attr[0].name' changed to 'Ciao'" in caplog.text
|
assert "'list_attr[0].name' changed to 'Ciao'" in caplog.text
|
||||||
@ -49,7 +49,7 @@ def test_simple_class_list_attribute(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
list_attr = [1, 2]
|
list_attr = [1, 2]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.list_attr[0] = 12
|
instance.list_attr[0] = 12
|
||||||
|
|
||||||
assert "'list_attr[0]' changed to '12'" in caplog.text
|
assert "'list_attr[0]' changed to '12'" in caplog.text
|
||||||
@ -63,7 +63,7 @@ def test_class_object_list_attribute(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
list_attr = [NestedObservable()]
|
list_attr = [NestedObservable()]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.list_attr[0].name = "Ciao"
|
instance.list_attr[0].name = "Ciao"
|
||||||
|
|
||||||
assert "'list_attr[0].name' changed to 'Ciao'" in caplog.text
|
assert "'list_attr[0].name' changed to 'Ciao'" in caplog.text
|
||||||
@ -76,7 +76,7 @@ def test_simple_instance_dict_attribute(caplog: pytest.LogCaptureFixture) -> Non
|
|||||||
self.dict_attr = {"first": "Hello"}
|
self.dict_attr = {"first": "Hello"}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.dict_attr["first"] = "Ciao"
|
instance.dict_attr["first"] = "Ciao"
|
||||||
instance.dict_attr["second"] = "World"
|
instance.dict_attr["second"] = "World"
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ def test_simple_class_dict_attribute(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
dict_attr = {"first": "Hello"}
|
dict_attr = {"first": "Hello"}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.dict_attr["first"] = "Ciao"
|
instance.dict_attr["first"] = "Ciao"
|
||||||
instance.dict_attr["second"] = "World"
|
instance.dict_attr["second"] = "World"
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ def test_instance_dict_attribute(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
self.dict_attr = {"first": NestedObservable()}
|
self.dict_attr = {"first": NestedObservable()}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.dict_attr["first"].name = "Ciao"
|
instance.dict_attr["first"].name = "Ciao"
|
||||||
|
|
||||||
assert "'dict_attr['first'].name' changed to 'Ciao'" in caplog.text
|
assert "'dict_attr['first'].name' changed to 'Ciao'" in caplog.text
|
||||||
@ -123,7 +123,7 @@ def test_class_dict_attribute(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
dict_attr = {"first": NestedObservable()}
|
dict_attr = {"first": NestedObservable()}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.dict_attr["first"].name = "Ciao"
|
instance.dict_attr["first"].name = "Ciao"
|
||||||
|
|
||||||
assert "'dict_attr['first'].name' changed to 'Ciao'" in caplog.text
|
assert "'dict_attr['first'].name' changed to 'Ciao'" in caplog.text
|
||||||
@ -140,7 +140,7 @@ def test_removed_observer_on_class_list_attr(caplog: pytest.LogCaptureFixture) -
|
|||||||
changed_list_attr = [nested_instance]
|
changed_list_attr = [nested_instance]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.changed_list_attr[0] = "Ciao"
|
instance.changed_list_attr[0] = "Ciao"
|
||||||
|
|
||||||
assert "'changed_list_attr[0]' changed to 'Ciao'" in caplog.text
|
assert "'changed_list_attr[0]' changed to 'Ciao'" in caplog.text
|
||||||
@ -169,7 +169,7 @@ def test_removed_observer_on_instance_dict_attr(
|
|||||||
self.changed_dict_attr = {"nested": nested_instance}
|
self.changed_dict_attr = {"nested": nested_instance}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.changed_dict_attr["nested"] = "Ciao"
|
instance.changed_dict_attr["nested"] = "Ciao"
|
||||||
|
|
||||||
assert "'changed_dict_attr['nested']' changed to 'Ciao'" in caplog.text
|
assert "'changed_dict_attr['nested']' changed to 'Ciao'" in caplog.text
|
||||||
@ -198,7 +198,7 @@ def test_removed_observer_on_instance_list_attr(
|
|||||||
self.changed_list_attr = [nested_instance]
|
self.changed_list_attr = [nested_instance]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.changed_list_attr[0] = "Ciao"
|
instance.changed_list_attr[0] = "Ciao"
|
||||||
|
|
||||||
assert "'changed_list_attr[0]' changed to 'Ciao'" in caplog.text
|
assert "'changed_list_attr[0]' changed to 'Ciao'" in caplog.text
|
||||||
@ -225,7 +225,7 @@ def test_removed_observer_on_class_dict_attr(caplog: pytest.LogCaptureFixture) -
|
|||||||
self.changed_dict_attr = {"nested": nested_instance}
|
self.changed_dict_attr = {"nested": nested_instance}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.changed_dict_attr["nested"] = "Ciao"
|
instance.changed_dict_attr["nested"] = "Ciao"
|
||||||
|
|
||||||
assert "'changed_dict_attr['nested']' changed to 'Ciao'" in caplog.text
|
assert "'changed_dict_attr['nested']' changed to 'Ciao'" in caplog.text
|
||||||
@ -246,7 +246,7 @@ def test_nested_dict_instances(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
self.nested_dict_attr = {"nested": dict_instance}
|
self.nested_dict_attr = {"nested": dict_instance}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.nested_dict_attr["nested"]["first"] = "Ciao"
|
instance.nested_dict_attr["nested"]["first"] = "Ciao"
|
||||||
|
|
||||||
assert "'nested_dict_attr['nested']['first']' changed to 'Ciao'" in caplog.text
|
assert "'nested_dict_attr['nested']['first']' changed to 'Ciao'" in caplog.text
|
||||||
@ -261,14 +261,14 @@ def test_dict_in_list_instance(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
self.dict_in_list = [dict_instance]
|
self.dict_in_list = [dict_instance]
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.dict_in_list[0]["first"] = "Ciao"
|
instance.dict_in_list[0]["first"] = "Ciao"
|
||||||
|
|
||||||
assert "'dict_in_list[0]['first']' changed to 'Ciao'" in caplog.text
|
assert "'dict_in_list[0]['first']' changed to 'Ciao'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
def test_list_in_dict_instance(caplog: pytest.LogCaptureFixture) -> None:
|
def test_list_in_dict_instance(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
list_instance = [1, 2, 3]
|
list_instance: list[Any] = [1, 2, 3]
|
||||||
|
|
||||||
class MyObservable(Observable):
|
class MyObservable(Observable):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@ -276,7 +276,199 @@ def test_list_in_dict_instance(caplog: pytest.LogCaptureFixture) -> None:
|
|||||||
self.list_in_dict = {"some_list": list_instance}
|
self.list_in_dict = {"some_list": list_instance}
|
||||||
|
|
||||||
instance = MyObservable()
|
instance = MyObservable()
|
||||||
observer = MyObserver(instance)
|
MyObserver(instance)
|
||||||
instance.list_in_dict["some_list"][0] = "Ciao"
|
instance.list_in_dict["some_list"][0] = "Ciao"
|
||||||
|
|
||||||
assert "'list_in_dict['some_list'][0]' changed to 'Ciao'" in caplog.text
|
assert "'list_in_dict['some_list'][0]' changed to 'Ciao'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_append(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Other Observable"
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = []
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
observable_instance.my_list.append(OtherObservable())
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
observable_instance.my_list.append(OtherObservable())
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
observable_instance.my_list[0].greeting = "Hi"
|
||||||
|
observable_instance.my_list[1].greeting = "Hello"
|
||||||
|
|
||||||
|
assert observable_instance.my_list[0].greeting == "Hi"
|
||||||
|
assert observable_instance.my_list[1].greeting == "Hello"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hi'" in caplog.text
|
||||||
|
assert "'my_list[1].greeting' changed to 'Hello'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_pop(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Hello there!"
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = [OtherObservable() for _ in range(2)]
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
popped_instance = observable_instance.my_list.pop(0)
|
||||||
|
|
||||||
|
assert len(observable_instance.my_list) == 1
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
|
||||||
|
# checks if observer is removed
|
||||||
|
popped_instance.greeting = "Ciao"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Ciao'" not in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
# checks if observer keys have been updated (index 1 moved to 0)
|
||||||
|
observable_instance.my_list[0].greeting = "Hi"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hi'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_clear(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Hello there!"
|
||||||
|
|
||||||
|
other_observable_instance = OtherObservable()
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = [other_observable_instance]
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
other_observable_instance.greeting = "Hello"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hello'" in caplog.text
|
||||||
|
|
||||||
|
observable_instance.my_list.clear()
|
||||||
|
|
||||||
|
assert len(observable_instance.my_list) == 0
|
||||||
|
assert "'my_list' changed to '[]'" in caplog.text
|
||||||
|
|
||||||
|
# checks if observer has been removed
|
||||||
|
other_observable_instance.greeting = "Hi"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hi'" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_extend(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Hello there!"
|
||||||
|
|
||||||
|
other_observable_instance = OtherObservable()
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = []
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
other_observable_instance.greeting = "Hello"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hello'" not in caplog.text
|
||||||
|
|
||||||
|
observable_instance.my_list.extend([other_observable_instance, OtherObservable()])
|
||||||
|
|
||||||
|
assert len(observable_instance.my_list) == 2
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
|
||||||
|
# checks if observer has been removed
|
||||||
|
other_observable_instance.greeting = "Hi"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hi'" in caplog.text
|
||||||
|
observable_instance.my_list[1].greeting = "Ciao"
|
||||||
|
assert "'my_list[1].greeting' changed to 'Ciao'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_insert(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Hello there!"
|
||||||
|
|
||||||
|
other_observable_instance_1 = OtherObservable()
|
||||||
|
other_observable_instance_2 = OtherObservable()
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = [other_observable_instance_1, OtherObservable()]
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
other_observable_instance_1.greeting = "Hello"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hello'" in caplog.text
|
||||||
|
|
||||||
|
observable_instance.my_list.insert(0, other_observable_instance_2)
|
||||||
|
|
||||||
|
assert len(observable_instance.my_list) == 3
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
|
||||||
|
# checks if observer keys have been updated
|
||||||
|
other_observable_instance_2.greeting = "Hey"
|
||||||
|
other_observable_instance_1.greeting = "Hi"
|
||||||
|
observable_instance.my_list[2].greeting = "Ciao"
|
||||||
|
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hey'" in caplog.text
|
||||||
|
assert "'my_list[1].greeting' changed to 'Hi'" in caplog.text
|
||||||
|
assert "'my_list[2].greeting' changed to 'Ciao'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_remove(caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
class OtherObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.greeting = "Hello there!"
|
||||||
|
|
||||||
|
other_observable_instance_1 = OtherObservable()
|
||||||
|
other_observable_instance_2 = OtherObservable()
|
||||||
|
|
||||||
|
class MyObservable(Observable):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.my_list = [other_observable_instance_1, other_observable_instance_2]
|
||||||
|
|
||||||
|
observable_instance = MyObservable()
|
||||||
|
MyObserver(observable_instance)
|
||||||
|
|
||||||
|
other_observable_instance_1.greeting = "Hello"
|
||||||
|
other_observable_instance_2.greeting = "Hi"
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
observable_instance.my_list.remove(other_observable_instance_1)
|
||||||
|
|
||||||
|
assert len(observable_instance.my_list) == 1
|
||||||
|
assert f"'my_list' changed to '{observable_instance.my_list}'" in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
# checks if observer has been removed
|
||||||
|
other_observable_instance_1.greeting = "Hi"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Hi'" not in caplog.text
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
# checks if observer key was updated correctly (was index 1)
|
||||||
|
other_observable_instance_2.greeting = "Ciao"
|
||||||
|
assert "'my_list[0].greeting' changed to 'Ciao'" in caplog.text
|
||||||
|
Loading…
x
Reference in New Issue
Block a user