Coverage for backend/pinch_service/OpenPinch/src/classes/value.py: 43%

81 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-11-06 23:27 +0000

1from pint import UnitRegistry 

2from ..lib.schema import ValueWithUnit 

3 

4ureg = UnitRegistry() 

5Q_ = ureg.Quantity 

6 

7 

8class Value: 

9 def __init__(self, data=None, unit: str = None): 

10 if data is None: 

11 self._quantity = Q_(0) 

12 elif isinstance(data, ValueWithUnit): 

13 self._quantity = Q_(data.value, data.units) 

14 try: 

15 self._quantity.to(unit) 

16 except: 

17 pass 

18 else: 

19 self._quantity = Q_(data, unit) if unit else Q_(data) 

20 

21 @property 

22 def value(self): 

23 return self._quantity.magnitude 

24 

25 @value.setter 

26 def value(self, data): 

27 self._quantity = Q_(data, self.unit) 

28 

29 @property 

30 def unit(self): 

31 return format(self._quantity.units, "~").replace("°","deg").replace(" ","") 

32 

33 @unit.setter 

34 def unit(self, unit_str): 

35 self._quantity = Q_(self.value, unit_str) 

36 

37 def to(self, new_unit: str) -> "Value": 

38 return Value(self._quantity.to(new_unit).magnitude, new_unit) 

39 

40 def __str__(self): 

41 return f"{self.value} {self.unit}" 

42 

43 def __repr__(self): 

44 return f"Value({self.value}, {repr(self.unit)})" 

45 

46 def __float__(self): 

47 return float(self.value) 

48 

49 def __int__(self): 

50 return int(self.value) 

51 

52 def __round__(self, ndigits=None): 

53 return round(self.value, ndigits) 

54 

55 def __eq__(self, other): 

56 try: 

57 if isinstance(other, (int, float)): 

58 return self._quantity.magnitude == other 

59 return self._quantity == self._to_quantity(other) 

60 except Exception: 

61 return False 

62 

63 def __lt__(self, other): 

64 return self._quantity < self._to_quantity(other) 

65 

66 def __le__(self, other): 

67 return self._quantity <= self._to_quantity(other) 

68 

69 def __gt__(self, other): 

70 return self._quantity > self._to_quantity(other) 

71 

72 def __ge__(self, other): 

73 return self._quantity >= self._to_quantity(other) 

74 

75 def __add__(self, other): 

76 return self._from_quantity(self._quantity + self._to_quantity(other)) 

77 

78 def __radd__(self, other): 

79 return self + other 

80 

81 def __sub__(self, other): 

82 return self._from_quantity(self._quantity - self._to_quantity(other)) 

83 

84 def __rsub__(self, other): 

85 return self._from_quantity(self._to_quantity(other) - self._quantity) 

86 

87 def __mul__(self, other): 

88 return self._from_quantity(self._quantity * self._to_quantity(other)) 

89 

90 def __rmul__(self, other): 

91 return self * other 

92 

93 def __truediv__(self, other): 

94 return self._from_quantity(self._quantity / self._to_quantity(other)) 

95 

96 def __rtruediv__(self, other): 

97 return self._from_quantity(self._to_quantity(other) / self._quantity) 

98 

99 def _to_quantity(self, other): 

100 if isinstance(other, Value): 

101 return other._quantity 

102 return Q_(other) 

103 

104 def _from_quantity(self, qty): 

105 return Value(qty.magnitude, format(qty.units, "~")) 

106 

107 def to_dict(self): 

108 return {"value": self.value, "unit": self.unit} 

109 

110 @classmethod 

111 def from_dict(cls, data): 

112 return cls(data["value"], data.get("unit")) 

113 

114 

115# @pd.api.extensions.register_series_accessor("as_value") 

116# class ValueAccessor: 

117# def __init__(self, series): 

118# self.series = series 

119 

120# def to(self, unit): 

121# return self.series.apply(lambda v: v.to(unit))