diff --git a/src/pydase/data_service/data_service.py b/src/pydase/data_service/data_service.py index aaff141..7a7c2bd 100644 --- a/src/pydase/data_service/data_service.py +++ b/src/pydase/data_service/data_service.py @@ -64,24 +64,47 @@ class DataService(rpyc.Service, AbstractDataService): self._initialised = True def __setattr__(self, __name: str, __value: Any) -> None: - # converting attributes that are not properties - if not is_property_attribute(self, __name): - current_value = getattr(self, __name, None) - # parse ints into floats if current value is a float - if isinstance(current_value, float) and isinstance(__value, int): - __value = float(__value) + # Check and warn for unexpected type changes in attributes + self._warn_on_type_change(__name, __value) - if isinstance(current_value, u.Quantity): - __value = u.convert_to_quantity(__value, str(current_value.u)) + # Warn if setting private attributes + self._warn_on_private_attr_set(__name) + # Set the attribute super().__setattr__(__name, __value) - if __name.startswith(f"_{self.__class__.__name__}__"): + def _warn_on_type_change(self, attr_name: str, new_value: Any) -> None: + if is_property_attribute(self, attr_name): + return + + current_value = getattr(self, attr_name, None) + if self._is_unexpected_type_change(current_value, new_value): + logger.warning( + "Type of '%s' changed from '%s' to '%s'. This may have unwanted " + "side effects! Consider setting it to '%s' directly.", + attr_name, + type(current_value).__name__, + type(new_value).__name__, + type(current_value).__name__, + ) + + def _is_unexpected_type_change(self, current_value: Any, new_value: Any) -> bool: + return ( + isinstance(current_value, float) + and not isinstance(new_value, float) + or ( + isinstance(current_value, u.Quantity) + and not isinstance(new_value, u.Quantity) + ) + ) + + def _warn_on_private_attr_set(self, attr_name: str) -> None: + if attr_name.startswith(f"_{self.__class__.__name__}__"): logger.warning( "Warning: You should not set private but rather protected attributes! " "Use %s instead of %s.", - __name.replace(f"_{self.__class__.__name__}__", "_"), - __name.replace(f"_{self.__class__.__name__}__", "__"), + attr_name.replace(f"_{self.__class__.__name__}__", "_"), + attr_name.replace(f"_{self.__class__.__name__}__", "__"), ) def __check_instance_classes(self) -> None: