Skip to content

Commit 546934a

Browse files
committed
Add validate to DataType to check value against min/max
1 parent e9b776b commit 546934a

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

src/fastcs/attributes.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from enum import Enum
55
from typing import Any, Generic, Protocol, runtime_checkable
66

7-
from .datatypes import ATTRIBUTE_TYPES, AttrCallback, DataType, T, validate_value
7+
from .datatypes import ATTRIBUTE_TYPES, AttrCallback, DataType, T
88

99

1010
class AttrMode(Enum):
@@ -126,15 +126,17 @@ def __init__(
126126
allowed_values=allowed_values, # type: ignore
127127
description=description,
128128
)
129-
self._value: T = datatype.dtype() if initial_value is None else initial_value
129+
self._value: T = (
130+
datatype.initial_value if initial_value is None else initial_value
131+
)
130132
self._update_callback: AttrCallback[T] | None = None
131133
self._updater = handler
132134

133135
def get(self) -> T:
134136
return self._value
135137

136138
async def set(self, value: T) -> None:
137-
self._value = self._datatype.dtype(validate_value(self._datatype, value))
139+
self._value = self._datatype.validate(value)
138140

139141
if self._update_callback is not None:
140142
await self._update_callback(self._value)
@@ -177,11 +179,11 @@ async def process(self, value: T) -> None:
177179

178180
async def process_without_display_update(self, value: T) -> None:
179181
if self._process_callback is not None:
180-
await self._process_callback(self._datatype.dtype(value))
182+
await self._process_callback(self._datatype.validate(value))
181183

182184
async def update_display_without_process(self, value: T) -> None:
183185
if self._write_display_callback is not None:
184-
await self._write_display_callback(self._datatype.dtype(value))
186+
await self._write_display_callback(self._datatype.validate(value))
185187

186188
def set_process_callback(self, callback: AttrCallback[T] | None) -> None:
187189
self._process_callback = callback
@@ -221,6 +223,6 @@ def __init__(
221223
)
222224

223225
async def process(self, value: T) -> None:
224-
await self.set(validate_value(self._datatype, value))
226+
await self.set(value)
225227

226228
await super().process(value) # type: ignore

src/fastcs/datatypes.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from dataclasses import dataclass
66
from typing import Generic, TypeVar
77

8+
T_Numerical = TypeVar("T_Numerical", int, float)
89
T = TypeVar("T", int, float, bool, str)
910
ATTRIBUTE_TYPES: tuple[type] = T.__constraints__ # type: ignore
1011

@@ -21,8 +22,13 @@ class DataType(Generic[T]):
2122
def dtype(self) -> type[T]: # Using property due to lack of Generic ClassVars
2223
pass
2324

25+
def validate(self, value: T) -> T:
26+
"""Validate a value against fields in the datatype."""
27+
return value
2428

25-
T_Numerical = TypeVar("T_Numerical", int, float)
29+
@property
30+
def initial_value(self) -> T:
31+
return self.dtype()
2632

2733

2834
@dataclass(frozen=True)
@@ -33,6 +39,13 @@ class _Numerical(DataType[T_Numerical]):
3339
min_alarm: int | None = None
3440
max_alarm: int | None = None
3541

42+
def validate(self, value: T_Numerical) -> T_Numerical:
43+
if self.min is not None and value < self.min:
44+
raise ValueError(f"Value {value} is less than minimum {self.min}")
45+
if self.max is not None and value > self.max:
46+
raise ValueError(f"Value {value} is greater than maximum {self.max}")
47+
return value
48+
3649

3750
@dataclass(frozen=True)
3851
class Int(_Numerical[int]):
@@ -73,15 +86,3 @@ class String(DataType[str]):
7386
@property
7487
def dtype(self) -> type[str]:
7588
return str
76-
77-
78-
def validate_value(datatype: DataType[T], value: T) -> T:
79-
"""Validate a value against a datatype."""
80-
81-
if isinstance(datatype, (Int | Float)):
82-
assert isinstance(value, (int | float)), f"Value {value} is not a number"
83-
if datatype.min is not None and value < datatype.min:
84-
raise ValueError(f"Value {value} is less than minimum {datatype.min}")
85-
if datatype.max is not None and value > datatype.max:
86-
raise ValueError(f"Value {value} is greater than maximum {datatype.max}")
87-
return value

0 commit comments

Comments
 (0)