From 0faf347376d3805fb4cc027b75a25e820b837496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mose=20M=C3=BCller?= Date: Mon, 11 Dec 2023 09:15:08 +0100 Subject: [PATCH] moves inheritance warning into DataService, improves logic --- src/pydase/data_service/data_service.py | 29 +++++++++++--- src/pydase/utils/warnings.py | 28 -------------- tests/utils/test_warnings.py | 50 ------------------------- 3 files changed, 23 insertions(+), 84 deletions(-) delete mode 100644 src/pydase/utils/warnings.py delete mode 100644 tests/utils/test_warnings.py diff --git a/src/pydase/data_service/data_service.py b/src/pydase/data_service/data_service.py index 42519eb..d5902cb 100644 --- a/src/pydase/data_service/data_service.py +++ b/src/pydase/data_service/data_service.py @@ -1,3 +1,4 @@ +import inspect import logging import warnings from enum import Enum @@ -8,6 +9,9 @@ import rpyc # type: ignore[import-untyped] import pydase.units as u from pydase.data_service.abstract_data_service import AbstractDataService from pydase.data_service.task_manager import TaskManager +from pydase.observer_pattern.observable.observable import ( + Observable, +) from pydase.utils.helpers import ( convert_arguments_to_hinted_types, get_class_and_instance_attributes, @@ -21,9 +25,6 @@ from pydase.utils.serializer import ( generate_serialized_data_paths, get_nested_dict_by_path, ) -from pydase.utils.warnings import ( - warn_if_instance_class_does_not_inherit_from_data_service, -) if TYPE_CHECKING: from pathlib import Path @@ -70,7 +71,7 @@ class DataService(rpyc.Service, AbstractDataService): # every class defined by the user should inherit from DataService if it is # assigned to a public attribute if not __name.startswith("_"): - warn_if_instance_class_does_not_inherit_from_data_service(__value) + self.__warn_if_not_observable(__value) # Set the attribute super().__setattr__(__name, __value) @@ -100,12 +101,28 @@ class DataService(rpyc.Service, AbstractDataService): ) ) + def __warn_if_not_observable(self, __value: Any) -> None: + value_class = __value if inspect.isclass(__value) else __value.__class__ + + if not issubclass( + value_class, (int | float | bool | str | Enum | u.Quantity | Observable) + ): + logger.warning( + "Class '%s' does not inherit from DataService. This may lead to" + " unexpected behaviour!", + value_class.__name__, + ) + def __check_instance_classes(self) -> None: for attr_name, attr_value in get_class_and_instance_attributes(self).items(): # every class defined by the user should inherit from DataService if it is # assigned to a public attribute - if not attr_name.startswith("_"): - warn_if_instance_class_does_not_inherit_from_data_service(attr_value) + if ( + not attr_name.startswith("_") + and not inspect.isfunction(attr_value) + and not isinstance(attr_value, property) + ): + self.__warn_if_not_observable(attr_value) def __set_attribute_based_on_type( # noqa: PLR0913 self, diff --git a/src/pydase/utils/warnings.py b/src/pydase/utils/warnings.py deleted file mode 100644 index 2e9cb30..0000000 --- a/src/pydase/utils/warnings.py +++ /dev/null @@ -1,28 +0,0 @@ -import logging - -from pydase.utils.helpers import get_component_class_names - -logger = logging.getLogger(__name__) - - -def warn_if_instance_class_does_not_inherit_from_data_service(__value: object) -> None: - base_class_name = __value.__class__.__base__.__name__ - module_name = __value.__class__.__module__ - - if ( - module_name - not in [ - "builtins", - "__builtin__", - "asyncio.unix_events", - "_abc", - ] - and base_class_name - not in ["DataService", "list", "Enum", *get_component_class_names()] - and type(__value).__name__ not in ["CallbackManager", "TaskManager", "Quantity"] - ): - logger.warning( - "Class '%s' does not inherit from DataService. This may lead to unexpected " - "behaviour!", - type(__value).__name__, - ) diff --git a/tests/utils/test_warnings.py b/tests/utils/test_warnings.py deleted file mode 100644 index 01fc6ae..0000000 --- a/tests/utils/test_warnings.py +++ /dev/null @@ -1,50 +0,0 @@ -from pydase import DataService -from pytest import LogCaptureFixture - - -def test_class_attr_inheritance_warning(caplog: LogCaptureFixture) -> None: - class SubClass: - name = "Hello" - - class ServiceClass(DataService): - attr_1 = SubClass() - - ServiceClass() - - assert ( - "Class 'SubClass' does not inherit from DataService. This may lead to " - "unexpected behaviour!" - ) in caplog.text - - -def test_instance_attr_inheritance_warning(caplog: LogCaptureFixture) -> None: - class SubClass: - name = "Hello" - - class ServiceClass(DataService): - def __init__(self) -> None: - super().__init__() - self.attr_1 = SubClass() - - ServiceClass() - - assert ( - "Class 'SubClass' does not inherit from DataService. This may lead to " - "unexpected behaviour!" - ) in caplog.text - - -def test_protected_attribute_warning(caplog: LogCaptureFixture) -> None: - class SubClass: - name = "Hello" - - class ServiceClass(DataService): - def __init__(self) -> None: - super().__init__() - self._subclass = SubClass - - ServiceClass() - - assert ( - "Warning: Class SubClass does not inherit from DataService." not in caplog.text - )