mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-23 01:20:03 +02:00
Merge pull request #30 from tiqi-group/29-protected-lists-crash-pydase
fix: removes notification for updating protected lists
This commit is contained in:
commit
4abea8785c
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pydase"
|
name = "pydase"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
description = "A flexible and robust Python library for creating, managing, and interacting with data services, with built-in support for web and RPC servers, and customizable features for diverse use cases."
|
description = "A flexible and robust Python library for creating, managing, and interacting with data services, with built-in support for web and RPC servers, and customizable features for diverse use cases."
|
||||||
authors = ["Mose Mueller <mosmuell@ethz.ch>"]
|
authors = ["Mose Mueller <mosmuell@ethz.ch>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
@ -55,9 +55,10 @@ class CallbackManager:
|
|||||||
self, obj: "AbstractDataService", parent_path: str
|
self, obj: "AbstractDataService", parent_path: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
This method ensures that notifications are emitted whenever a list attribute of
|
This method ensures that notifications are emitted whenever a public list
|
||||||
a DataService instance changes. These notifications pertain solely to the list
|
attribute of a DataService instance changes. These notifications pertain solely
|
||||||
item changes, not to changes in attributes of objects within the list.
|
to the list item changes, not to changes in attributes of objects within the
|
||||||
|
list.
|
||||||
|
|
||||||
The method works by converting all list attributes (both at the class and
|
The method works by converting all list attributes (both at the class and
|
||||||
instance levels) into DataServiceList objects. Each DataServiceList is then
|
instance levels) into DataServiceList objects. Each DataServiceList is then
|
||||||
@ -101,6 +102,8 @@ class CallbackManager:
|
|||||||
value=value,
|
value=value,
|
||||||
)
|
)
|
||||||
if self.service == self.service.__root__
|
if self.service == self.service.__root__
|
||||||
|
# Skip private and protected lists
|
||||||
|
and not cast(str, attr_name).startswith("_")
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,9 +112,12 @@ class CallbackManager:
|
|||||||
attr_value.add_callback(callback)
|
attr_value.add_callback(callback)
|
||||||
continue
|
continue
|
||||||
if id(attr_value) in self._list_mapping:
|
if id(attr_value) in self._list_mapping:
|
||||||
|
# If the list `attr_value` was already referenced somewhere else
|
||||||
notifying_list = self._list_mapping[id(attr_value)]
|
notifying_list = self._list_mapping[id(attr_value)]
|
||||||
notifying_list.add_callback(callback)
|
notifying_list.add_callback(callback)
|
||||||
else:
|
else:
|
||||||
|
# convert the builtin list into a DataServiceList and add the
|
||||||
|
# callback
|
||||||
notifying_list = DataServiceList(attr_value, callback=[callback])
|
notifying_list = DataServiceList(attr_value, callback=[callback])
|
||||||
self._list_mapping[id(attr_value)] = notifying_list
|
self._list_mapping[id(attr_value)] = notifying_list
|
||||||
|
|
||||||
|
@ -99,3 +99,29 @@ def test_nested_reused_instance_list_attribute(capsys: CaptureFixture) -> None:
|
|||||||
)
|
)
|
||||||
actual_output = sorted(captured.out.strip().split("\n"))
|
actual_output = sorted(captured.out.strip().split("\n"))
|
||||||
assert actual_output == expected_output
|
assert actual_output == expected_output
|
||||||
|
|
||||||
|
|
||||||
|
def test_protected_list_attribute(capsys: CaptureFixture) -> None:
|
||||||
|
"""Changing protected lists should not emit notifications for the lists themselves, but
|
||||||
|
still for all properties depending on them.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ServiceClass(DataService):
|
||||||
|
_attr = [0, 1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def list_dependend_property(self) -> int:
|
||||||
|
return self._attr[0]
|
||||||
|
|
||||||
|
service_instance = ServiceClass()
|
||||||
|
|
||||||
|
service_instance._attr[0] = 1337
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
|
expected_output = sorted(
|
||||||
|
[
|
||||||
|
"ServiceClass.list_dependend_property = 1337",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
actual_output = sorted(captured.out.strip().split("\n")) # type: ignore
|
||||||
|
assert actual_output == expected_output
|
||||||
|
Loading…
x
Reference in New Issue
Block a user