99from collections .abc import Callable , Iterator
1010from dataclasses import dataclass
1111from datetime import datetime , timezone
12- from typing import Generic , Self , TypeVar , overload
12+ from typing import Generic , Self , SupportsFloat , TypeVar , overload
1313
14- from ._quantities import Power , QuantityT
14+ from ._quantities import Power
15+
16+ SupportsFloatT = TypeVar ("SupportsFloatT" , bound = SupportsFloat )
17+ """Type variable for types that support conversion to float."""
1518
1619UNIX_EPOCH = datetime .fromtimestamp (0.0 , tz = timezone .utc )
1720"""The UNIX epoch (in UTC)."""
1821
1922
2023@dataclass (frozen = True , order = True )
21- class Sample (Generic [QuantityT ]):
24+ class Sample (Generic [SupportsFloatT ]):
2225 """A measurement taken at a particular point in time.
2326
2427 The `value` could be `None` if a component is malfunctioning or data is
@@ -29,12 +32,12 @@ class Sample(Generic[QuantityT]):
2932 timestamp : datetime
3033 """The time when this sample was generated."""
3134
32- value : QuantityT | None = None
35+ value : SupportsFloatT | None = None
3336 """The value of this sample."""
3437
3538
3639@dataclass (frozen = True )
37- class Sample3Phase (Generic [QuantityT ]):
40+ class Sample3Phase (Generic [SupportsFloatT ]):
3841 """A 3-phase measurement made at a particular point in time.
3942
4043 Each of the `value` fields could be `None` if a component is malfunctioning
@@ -45,16 +48,16 @@ class Sample3Phase(Generic[QuantityT]):
4548
4649 timestamp : datetime
4750 """The time when this sample was generated."""
48- value_p1 : QuantityT | None
51+ value_p1 : SupportsFloatT | None
4952 """The value of the 1st phase in this sample."""
5053
51- value_p2 : QuantityT | None
54+ value_p2 : SupportsFloatT | None
5255 """The value of the 2nd phase in this sample."""
5356
54- value_p3 : QuantityT | None
57+ value_p3 : SupportsFloatT | None
5558 """The value of the 3rd phase in this sample."""
5659
57- def __iter__ (self ) -> Iterator [QuantityT | None ]:
60+ def __iter__ (self ) -> Iterator [SupportsFloatT | None ]:
5861 """Return an iterator that yields values from each of the phases.
5962
6063 Yields:
@@ -65,12 +68,12 @@ def __iter__(self) -> Iterator[QuantityT | None]:
6568 yield self .value_p3
6669
6770 @overload
68- def max (self , default : QuantityT ) -> QuantityT : ...
71+ def max (self , default : SupportsFloatT ) -> SupportsFloatT : ...
6972
7073 @overload
71- def max (self , default : None = None ) -> QuantityT | None : ...
74+ def max (self , default : None = None ) -> SupportsFloatT | None : ...
7275
73- def max (self , default : QuantityT | None = None ) -> QuantityT | None :
76+ def max (self , default : SupportsFloatT | None = None ) -> SupportsFloatT | None :
7477 """Return the max value among all phases, or default if they are all `None`.
7578
7679 Args:
@@ -81,19 +84,19 @@ def max(self, default: QuantityT | None = None) -> QuantityT | None:
8184 """
8285 if not any (self ):
8386 return default
84- value : QuantityT = functools .reduce (
85- lambda x , y : x if x > y else y ,
87+ value : SupportsFloatT = functools .reduce (
88+ lambda x , y : x if float ( x ) > float ( y ) else y ,
8689 filter (None , self ),
8790 )
8891 return value
8992
9093 @overload
91- def min (self , default : QuantityT ) -> QuantityT : ...
94+ def min (self , default : SupportsFloatT ) -> SupportsFloatT : ...
9295
9396 @overload
94- def min (self , default : None = None ) -> QuantityT | None : ...
97+ def min (self , default : None = None ) -> SupportsFloatT | None : ...
9598
96- def min (self , default : QuantityT | None = None ) -> QuantityT | None :
99+ def min (self , default : SupportsFloatT | None = None ) -> SupportsFloatT | None :
97100 """Return the min value among all phases, or default if they are all `None`.
98101
99102 Args:
@@ -104,16 +107,16 @@ def min(self, default: QuantityT | None = None) -> QuantityT | None:
104107 """
105108 if not any (self ):
106109 return default
107- value : QuantityT = functools .reduce (
108- lambda x , y : x if x < y else y ,
110+ value : SupportsFloatT = functools .reduce (
111+ lambda x , y : x if float ( x ) < float ( y ) else y ,
109112 filter (None , self ),
110113 )
111114 return value
112115
113116 def map (
114117 self ,
115- function : Callable [[QuantityT ], QuantityT ],
116- default : QuantityT | None = None ,
118+ function : Callable [[SupportsFloatT ], SupportsFloatT ],
119+ default : SupportsFloatT | None = None ,
117120 ) -> Self :
118121 """Apply the given function on each of the phase values and return the result.
119122
0 commit comments