diff --git a/src/pydase/data_service/state_manager.py b/src/pydase/data_service/state_manager.py index d43d5e5..60023e3 100644 --- a/src/pydase/data_service/state_manager.py +++ b/src/pydase/data_service/state_manager.py @@ -1,6 +1,7 @@ import json import logging import os +from collections.abc import Callable from pathlib import Path from typing import TYPE_CHECKING, Any, Optional, cast @@ -8,7 +9,6 @@ import pydase.units as u from pydase.data_service.data_service_cache import DataServiceCache from pydase.utils.helpers import ( get_object_attr_from_path_list, - is_property_attribute, parse_list_attr_and_index, ) from pydase.utils.serializer import ( @@ -23,6 +23,36 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +def load_state(func: Callable[..., Any]) -> Callable[..., Any]: + """This function should be used as a decorator on property setters to indicate that + the value should be loaded from the JSON file. + + Example: + >>> class Service(pydase.DataService): + ... _name = "Service" + ... + ... @property + ... def name(self) -> str: + ... return self._name + ... + ... @name.setter + ... @load_state + ... def name(self, value: str) -> None: + ... self._name = value + """ + + func._load_state = True + return func + + +def has_load_state_decorator(prop: property): + if prop and isinstance(prop, property): + # Check if the setter function has the attribute set by the @load_state + # decorator + return getattr(prop.fset, "_load_state", False) + return False + + class StateManager: """ Manages the state of a DataService instance, serving as both a cache and a @@ -211,6 +241,8 @@ class StateManager: def __attr_value_should_change(self, parent_object: Any, attr_name: str) -> bool: # If the attribute is a property, change it using the setter without getting # the property value (would otherwise be bad for expensive getter methods) - if is_property_attribute(parent_object, attr_name): - return True + prop = getattr(type(parent_object), attr_name, None) + + if isinstance(prop, property): + return has_load_state_decorator(prop) return True