diff --git a/src/pydase/components/number_slider.py b/src/pydase/components/number_slider.py index 6417a28..b1cb138 100644 --- a/src/pydase/components/number_slider.py +++ b/src/pydase/components/number_slider.py @@ -1,5 +1,4 @@ import logging -from typing import Any, Literal from pydase.data_service.data_service import DataService @@ -21,15 +20,12 @@ class NumberSlider(DataService): The maximum value of the slider. Defaults to 100. step_size (float, optional): The increment/decrement step size of the slider. Defaults to 1.0. - type (Literal["int", "float"], optional): - The type of the slider value. Determines if the value is an integer or float. - Defaults to "float". Example: -------- ```python class MyService(DataService): - voltage = NumberSlider(1, 0, 10, 0.1, "int") + voltage = NumberSlider(1, 0, 10, 0.1) # Modifying or accessing the voltage value: my_service = MyService() @@ -38,29 +34,51 @@ class NumberSlider(DataService): ``` """ - def __init__( # noqa: PLR0913 + def __init__( self, value: float = 0, min_: float = 0.0, max_: float = 100.0, step_size: float = 1.0, - type_: Literal["int", "float"] = "float", ) -> None: super().__init__() - if type_ not in {"float", "int"}: - logger.error("Unknown type '%s'. Using 'float'.", type_) - type_ = "float" + self._step_size = step_size + self._value = value + self._min = min_ + self._max = max_ - self._type = type_ - self.step_size = step_size - self.value = value - self.min = min_ - self.max = max_ + @property + def min(self) -> float: + """The min property.""" + return self._min - def __setattr__(self, name: str, value: Any) -> None: - if name in ["value", "step_size"]: - value = int(value) if self._type == "int" else float(value) - elif not name.startswith("_"): - value = float(value) + @min.setter + def min(self, value: float) -> None: + self._min = value - return super().__setattr__(name, value) + @property + def max(self) -> float: + """The min property.""" + return self._max + + @max.setter + def max(self, value: float) -> None: + self._max = value + + @property + def step_size(self) -> float: + """The min property.""" + return self._step_size + + @step_size.setter + def step_size(self, value: float) -> None: + self._step_size = value + + @property + def value(self) -> float: + """The value property.""" + return self._value + + @value.setter + def value(self, value: float) -> None: + self._value = value diff --git a/tests/components/test_number_slider.py b/tests/components/test_number_slider.py index 44679bf..619fcd9 100644 --- a/tests/components/test_number_slider.py +++ b/tests/components/test_number_slider.py @@ -1,46 +1,71 @@ +import logging +from collections.abc import Callable + from pydase.components.number_slider import NumberSlider from pydase.data_service.data_service import DataService from pydase.data_service.data_service_observer import DataServiceObserver from pydase.data_service.state_manager import StateManager from pytest import LogCaptureFixture +from tests.utils.test_serializer import pytest -def test_NumberSlider(caplog: LogCaptureFixture) -> None: - class ServiceClass(DataService): - number_slider = NumberSlider(1, 0, 10, 1) - int_number_slider = NumberSlider(1, 0, 10, 1, "int") +logger = logging.getLogger(__name__) - service_instance = ServiceClass() + +def test_number_slider(caplog: LogCaptureFixture) -> None: + class MySlider(NumberSlider): + def __init__( + self, + value: float = 0, + min_: float = 0, + max_: float = 100, + step_size: float = 1, + callback: Callable[..., None] = lambda: None, + ) -> None: + super().__init__(value, min_, max_, step_size) + self._callback = callback + + @property + def value(self) -> float: + return self._value + + @value.setter + def value(self, value: float) -> None: + self._callback(value) + self._value = value + + @property + def min(self) -> float: + return super().min + + class MyService(DataService): + def __init__(self) -> None: + super().__init__() + self.my_slider = MySlider(callback=self.some_method) + + def some_method(self, slider_value: float) -> None: + logger.info("Slider changed to '%s'", slider_value) + + service_instance = MyService() state_manager = StateManager(service_instance) DataServiceObserver(state_manager) - assert service_instance.number_slider.value == 1 - assert isinstance(service_instance.number_slider.value, float) - assert service_instance.number_slider.min == 0 - assert isinstance(service_instance.number_slider.min, float) - assert service_instance.number_slider.max == 10 - assert isinstance(service_instance.number_slider.max, float) - assert service_instance.number_slider.step_size == 1 - assert isinstance(service_instance.number_slider.step_size, float) + service_instance.my_slider.value = 10.0 - assert service_instance.int_number_slider.value == 1 - assert isinstance(service_instance.int_number_slider.value, int) - assert service_instance.int_number_slider.step_size == 1 - assert isinstance(service_instance.int_number_slider.step_size, int) - - service_instance.number_slider.value = 10.0 - service_instance.int_number_slider.value = 10.1 - - assert "'number_slider.value' changed to '10.0'" in caplog.text - assert "'int_number_slider.value' changed to '10'" in caplog.text + assert "'my_slider.value' changed to '10.0'" in caplog.text + assert "Slider changed to '10.0'" in caplog.text caplog.clear() - service_instance.number_slider.min = 1.1 + service_instance.my_slider.max = 12.0 - assert "'number_slider.min' changed to '1.1'" in caplog.text + assert "'my_slider.max' changed to '12.0'" in caplog.text + caplog.clear() + service_instance.my_slider.step_size = 0.1 -def test_init_error(caplog: LogCaptureFixture) -> None: - number_slider = NumberSlider(type_="str") # type: ignore # noqa + assert "'my_slider.step_size' changed to '0.1'" in caplog.text + caplog.clear() - assert "Unknown type 'str'. Using 'float'" in caplog.text + # by overriding the getter only you can make the property read-only + with pytest.raises(AttributeError): + service_instance.my_slider.min = 1.1 # type: ignore[reportGeneralTypeIssues]