qnty 0.0.7__py3-none-any.whl → 0.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qnty/equation.py +81 -0
- qnty/expression.py +119 -58
- qnty/variable.py +37 -0
- qnty/variable_types/expression_variable.py +38 -0
- {qnty-0.0.7.dist-info → qnty-0.0.8.dist-info}/METADATA +1 -1
- {qnty-0.0.7.dist-info → qnty-0.0.8.dist-info}/RECORD +7 -7
- {qnty-0.0.7.dist-info → qnty-0.0.8.dist-info}/WHEEL +0 -0
qnty/equation.py
CHANGED
@@ -117,7 +117,88 @@ class Equation:
|
|
117
117
|
except Exception:
|
118
118
|
return False
|
119
119
|
|
120
|
+
def _discover_variables_from_scope(self) -> dict[str, TypeSafeVariable]:
|
121
|
+
"""Automatically discover variables from the calling scope."""
|
122
|
+
import inspect
|
123
|
+
|
124
|
+
# Get the frame that called this method (skip through __str__ calls)
|
125
|
+
frame = inspect.currentframe()
|
126
|
+
try:
|
127
|
+
# Skip frames until we find one outside the equation system
|
128
|
+
while frame and (
|
129
|
+
frame.f_code.co_filename.endswith(('equation.py', 'expression.py')) or
|
130
|
+
frame.f_code.co_name in ['__str__', '__repr__']
|
131
|
+
):
|
132
|
+
frame = frame.f_back
|
133
|
+
|
134
|
+
if not frame:
|
135
|
+
return {}
|
136
|
+
|
137
|
+
# Combine local and global variables
|
138
|
+
all_vars = {**frame.f_globals, **frame.f_locals}
|
139
|
+
|
140
|
+
# Find TypeSafeVariable objects that match our required variables
|
141
|
+
required_vars = self.variables
|
142
|
+
discovered = {}
|
143
|
+
|
144
|
+
for var_name in required_vars:
|
145
|
+
for name, obj in all_vars.items():
|
146
|
+
if hasattr(obj, 'symbol') and obj.symbol == var_name:
|
147
|
+
discovered[var_name] = obj
|
148
|
+
break
|
149
|
+
elif hasattr(obj, 'name') and obj.name == var_name:
|
150
|
+
discovered[var_name] = obj
|
151
|
+
break
|
152
|
+
|
153
|
+
return discovered
|
154
|
+
|
155
|
+
finally:
|
156
|
+
del frame
|
157
|
+
|
158
|
+
def _can_auto_solve(self) -> tuple[bool, str, dict[str, TypeSafeVariable]]:
|
159
|
+
"""Check if equation can be auto-solved from scope."""
|
160
|
+
try:
|
161
|
+
discovered = self._discover_variables_from_scope()
|
162
|
+
|
163
|
+
# Check if this is a simple assignment equation (one unknown)
|
164
|
+
unknowns = []
|
165
|
+
knowns = []
|
166
|
+
|
167
|
+
for var_name in self.variables:
|
168
|
+
if var_name in discovered:
|
169
|
+
var = discovered[var_name]
|
170
|
+
if hasattr(var, 'is_known') and not var.is_known:
|
171
|
+
unknowns.append(var_name)
|
172
|
+
elif hasattr(var, 'quantity') and var.quantity is not None:
|
173
|
+
knowns.append(var_name)
|
174
|
+
else:
|
175
|
+
unknowns.append(var_name) # Assume unknown if no quantity
|
176
|
+
else:
|
177
|
+
return False, "", {} # Missing variable
|
178
|
+
|
179
|
+
# Can only auto-solve if there's exactly one unknown
|
180
|
+
if len(unknowns) == 1:
|
181
|
+
return True, unknowns[0], discovered
|
182
|
+
|
183
|
+
return False, "", {}
|
184
|
+
|
185
|
+
except Exception:
|
186
|
+
return False, "", {}
|
187
|
+
|
188
|
+
def _try_auto_solve(self) -> bool:
|
189
|
+
"""Try to automatically solve the equation if possible."""
|
190
|
+
try:
|
191
|
+
can_solve, target_var, variables = self._can_auto_solve()
|
192
|
+
if can_solve:
|
193
|
+
self.solve_for(target_var, variables)
|
194
|
+
return True
|
195
|
+
return False
|
196
|
+
except Exception:
|
197
|
+
return False
|
198
|
+
|
120
199
|
def __str__(self) -> str:
|
200
|
+
# Try to auto-solve if possible before displaying
|
201
|
+
self._try_auto_solve()
|
121
202
|
return f"{self.lhs} = {self.rhs}"
|
122
203
|
|
123
204
|
def __repr__(self) -> str:
|
qnty/expression.py
CHANGED
@@ -62,6 +62,80 @@ class Expression(ABC):
|
|
62
62
|
def __str__(self) -> str:
|
63
63
|
pass
|
64
64
|
|
65
|
+
def _discover_variables_from_scope(self) -> dict[str, 'TypeSafeVariable']:
|
66
|
+
"""Automatically discover variables from the calling scope."""
|
67
|
+
import inspect
|
68
|
+
|
69
|
+
# Get the frame that called this method (skip through __str__ calls)
|
70
|
+
frame = inspect.currentframe()
|
71
|
+
try:
|
72
|
+
# Skip frames until we find one outside the expression system
|
73
|
+
while frame and (
|
74
|
+
frame.f_code.co_filename.endswith('expression.py') or
|
75
|
+
frame.f_code.co_name in ['__str__', '__repr__']
|
76
|
+
):
|
77
|
+
frame = frame.f_back
|
78
|
+
|
79
|
+
if not frame:
|
80
|
+
return {}
|
81
|
+
|
82
|
+
# Combine local and global variables
|
83
|
+
all_vars = {**frame.f_globals, **frame.f_locals}
|
84
|
+
|
85
|
+
# Find TypeSafeVariable objects that match our required variables
|
86
|
+
required_vars = self.get_variables()
|
87
|
+
discovered = {}
|
88
|
+
|
89
|
+
for var_name in required_vars:
|
90
|
+
for name, obj in all_vars.items():
|
91
|
+
# Check if this is a TypeSafeVariable with matching symbol/name
|
92
|
+
if hasattr(obj, 'symbol') and obj.symbol == var_name:
|
93
|
+
discovered[var_name] = obj
|
94
|
+
break
|
95
|
+
elif hasattr(obj, 'name') and obj.name == var_name:
|
96
|
+
discovered[var_name] = obj
|
97
|
+
break
|
98
|
+
# Check if this is an Expression that can be evaluated to get the variable
|
99
|
+
elif hasattr(obj, 'get_variables') and name == var_name:
|
100
|
+
# This is an expression named after our variable - try to evaluate it
|
101
|
+
try:
|
102
|
+
if hasattr(obj, '_can_auto_evaluate'):
|
103
|
+
can_eval, expr_vars = obj._can_auto_evaluate()
|
104
|
+
if can_eval:
|
105
|
+
result = obj.evaluate(expr_vars)
|
106
|
+
# Create a temporary variable to hold the result
|
107
|
+
from .variables import Length # Import here to avoid circular import
|
108
|
+
temp_var = Length(result.value, result.unit.symbol, f"temp_{var_name}")
|
109
|
+
temp_var.symbol = var_name
|
110
|
+
discovered[var_name] = temp_var
|
111
|
+
break
|
112
|
+
except Exception:
|
113
|
+
pass
|
114
|
+
|
115
|
+
return discovered
|
116
|
+
|
117
|
+
finally:
|
118
|
+
del frame
|
119
|
+
|
120
|
+
def _can_auto_evaluate(self) -> tuple[bool, dict[str, 'TypeSafeVariable']]:
|
121
|
+
"""Check if expression can be auto-evaluated from scope."""
|
122
|
+
try:
|
123
|
+
discovered = self._discover_variables_from_scope()
|
124
|
+
required_vars = self.get_variables()
|
125
|
+
|
126
|
+
# Check if all required variables are available and have values
|
127
|
+
for var_name in required_vars:
|
128
|
+
if var_name not in discovered:
|
129
|
+
return False, {}
|
130
|
+
var = discovered[var_name]
|
131
|
+
if not hasattr(var, 'quantity') or var.quantity is None:
|
132
|
+
return False, {}
|
133
|
+
|
134
|
+
return True, discovered
|
135
|
+
|
136
|
+
except Exception:
|
137
|
+
return False, {}
|
138
|
+
|
65
139
|
def __add__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'Expression':
|
66
140
|
return BinaryOperation('+', self, wrap_operand(other))
|
67
141
|
|
@@ -93,17 +167,17 @@ class Expression(ABC):
|
|
93
167
|
return BinaryOperation('**', wrap_operand(other), self)
|
94
168
|
|
95
169
|
# Comparison operators for conditional expressions
|
96
|
-
def __lt__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> '
|
97
|
-
return
|
170
|
+
def __lt__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'BinaryOperation':
|
171
|
+
return BinaryOperation('<', self, self._wrap_operand(other))
|
98
172
|
|
99
|
-
def __le__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> '
|
100
|
-
return
|
173
|
+
def __le__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'BinaryOperation':
|
174
|
+
return BinaryOperation('<=', self, self._wrap_operand(other))
|
101
175
|
|
102
|
-
def __gt__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> '
|
103
|
-
return
|
176
|
+
def __gt__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'BinaryOperation':
|
177
|
+
return BinaryOperation('>', self, self._wrap_operand(other))
|
104
178
|
|
105
|
-
def __ge__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> '
|
106
|
-
return
|
179
|
+
def __ge__(self, other: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'BinaryOperation':
|
180
|
+
return BinaryOperation('>=', self, self._wrap_operand(other))
|
107
181
|
|
108
182
|
@staticmethod
|
109
183
|
def _wrap_operand(operand: Union['Expression', 'TypeSafeVariable', 'FastQuantity', int, float]) -> 'Expression':
|
@@ -167,6 +241,7 @@ class Constant(Expression):
|
|
167
241
|
self.value = value
|
168
242
|
|
169
243
|
def evaluate(self, variable_values: dict[str, 'TypeSafeVariable']) -> 'FastQuantity':
|
244
|
+
del variable_values # Suppress unused variable warning
|
170
245
|
return self.value
|
171
246
|
|
172
247
|
def get_variables(self) -> set[str]:
|
@@ -214,6 +289,30 @@ class BinaryOperation(Expression):
|
|
214
289
|
return FastQuantity(result_value, left_val.unit)
|
215
290
|
else:
|
216
291
|
raise ValueError("Exponent must be dimensionless number")
|
292
|
+
elif self.operator in ['<', '<=', '>', '>=', '==', '!=']:
|
293
|
+
# Comparison operations - return dimensionless 1.0 or 0.0
|
294
|
+
# Convert to same units for comparison if possible
|
295
|
+
try:
|
296
|
+
if left_val._dimension_sig == right_val._dimension_sig and left_val.unit != right_val.unit:
|
297
|
+
right_val = right_val.to(left_val.unit)
|
298
|
+
except (ValueError, TypeError, AttributeError):
|
299
|
+
pass
|
300
|
+
|
301
|
+
result = False # Initialize result
|
302
|
+
if self.operator == '<':
|
303
|
+
result = left_val.value < right_val.value
|
304
|
+
elif self.operator == '<=':
|
305
|
+
result = left_val.value <= right_val.value
|
306
|
+
elif self.operator == '>':
|
307
|
+
result = left_val.value > right_val.value
|
308
|
+
elif self.operator == '>=':
|
309
|
+
result = left_val.value >= right_val.value
|
310
|
+
elif self.operator == '==':
|
311
|
+
result = abs(left_val.value - right_val.value) < 1e-10
|
312
|
+
elif self.operator == '!=':
|
313
|
+
result = abs(left_val.value - right_val.value) >= 1e-10
|
314
|
+
|
315
|
+
return FastQuantity(1.0 if result else 0.0, DimensionlessUnits.dimensionless)
|
217
316
|
else:
|
218
317
|
raise ValueError(f"Unknown operator: {self.operator}")
|
219
318
|
except Exception as e:
|
@@ -241,8 +340,17 @@ class BinaryOperation(Expression):
|
|
241
340
|
return BinaryOperation(self.operator, left_simplified, right_simplified)
|
242
341
|
|
243
342
|
def __str__(self) -> str:
|
343
|
+
# Try to auto-evaluate if all variables are available
|
344
|
+
can_eval, variables = self._can_auto_evaluate()
|
345
|
+
if can_eval:
|
346
|
+
try:
|
347
|
+
result = self.evaluate(variables)
|
348
|
+
return str(result)
|
349
|
+
except Exception:
|
350
|
+
pass # Fall back to symbolic representation
|
351
|
+
|
244
352
|
# Handle operator precedence for cleaner string representation
|
245
|
-
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '**': 3}
|
353
|
+
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '**': 3, '<': 0, '<=': 0, '>': 0, '>=': 0, '==': 0, '!=': 0}
|
246
354
|
left_str = str(self.left)
|
247
355
|
right_str = str(self.right)
|
248
356
|
|
@@ -260,60 +368,13 @@ class BinaryOperation(Expression):
|
|
260
368
|
# Need parentheses if:
|
261
369
|
# - Right has lower precedence, OR
|
262
370
|
# - Same precedence and current operator is left-associative (- or /)
|
263
|
-
if (right_prec < curr_prec or
|
371
|
+
if (right_prec < curr_prec or
|
264
372
|
(right_prec == curr_prec and self.operator in ['-', '/'])):
|
265
373
|
right_str = f"({right_str})"
|
266
374
|
|
267
375
|
return f"{left_str} {self.operator} {right_str}"
|
268
376
|
|
269
377
|
|
270
|
-
class ComparisonExpression(Expression):
|
271
|
-
"""Comparison expression for conditional logic."""
|
272
|
-
|
273
|
-
def __init__(self, operator: str, left: Expression, right: Expression):
|
274
|
-
self.operator = operator
|
275
|
-
self.left = left
|
276
|
-
self.right = right
|
277
|
-
|
278
|
-
def evaluate(self, variable_values: dict[str, 'TypeSafeVariable']) -> 'FastQuantity':
|
279
|
-
"""Evaluate comparison and return dimensionless result (1.0 for True, 0.0 for False)."""
|
280
|
-
|
281
|
-
left_val = self.left.evaluate(variable_values)
|
282
|
-
right_val = self.right.evaluate(variable_values)
|
283
|
-
|
284
|
-
# Convert to same units for comparison if possible
|
285
|
-
try:
|
286
|
-
if left_val._dimension_sig == right_val._dimension_sig and left_val.unit != right_val.unit:
|
287
|
-
right_val = right_val.to(left_val.unit)
|
288
|
-
except (ValueError, TypeError, AttributeError):
|
289
|
-
pass
|
290
|
-
|
291
|
-
if self.operator == '<':
|
292
|
-
result = left_val.value < right_val.value
|
293
|
-
elif self.operator == '<=':
|
294
|
-
result = left_val.value <= right_val.value
|
295
|
-
elif self.operator == '>':
|
296
|
-
result = left_val.value > right_val.value
|
297
|
-
elif self.operator == '>=':
|
298
|
-
result = left_val.value >= right_val.value
|
299
|
-
elif self.operator == '==':
|
300
|
-
result = abs(left_val.value - right_val.value) < 1e-10
|
301
|
-
elif self.operator == '!=':
|
302
|
-
result = abs(left_val.value - right_val.value) >= 1e-10
|
303
|
-
else:
|
304
|
-
raise ValueError(f"Unknown comparison operator: {self.operator}")
|
305
|
-
|
306
|
-
return FastQuantity(1.0 if result else 0.0, DimensionlessUnits.dimensionless)
|
307
|
-
|
308
|
-
def get_variables(self) -> set[str]:
|
309
|
-
return self.left.get_variables() | self.right.get_variables()
|
310
|
-
|
311
|
-
def simplify(self) -> Expression:
|
312
|
-
return ComparisonExpression(self.operator, self.left.simplify(), self.right.simplify())
|
313
|
-
|
314
|
-
def __str__(self) -> str:
|
315
|
-
return f"({self.left} {self.operator} {self.right})"
|
316
|
-
|
317
378
|
|
318
379
|
class UnaryFunction(Expression):
|
319
380
|
"""Unary mathematical function expression."""
|
@@ -453,7 +514,7 @@ def exp(expr: Union[Expression, 'TypeSafeVariable', 'FastQuantity', int, float])
|
|
453
514
|
"""Exponential function."""
|
454
515
|
return UnaryFunction('exp', Expression._wrap_operand(expr))
|
455
516
|
|
456
|
-
def cond_expr(condition: Union[Expression, '
|
517
|
+
def cond_expr(condition: Union[Expression, 'BinaryOperation'],
|
457
518
|
true_expr: Union[Expression, 'TypeSafeVariable', 'FastQuantity', int, float],
|
458
519
|
false_expr: Union[Expression, 'TypeSafeVariable', 'FastQuantity', int, float]) -> ConditionalExpression:
|
459
520
|
"""Conditional expression: if condition then true_expr else false_expr."""
|
qnty/variable.py
CHANGED
@@ -257,6 +257,43 @@ class TypeSafeVariable(Generic[DimensionType]):
|
|
257
257
|
self.is_known = True
|
258
258
|
return self
|
259
259
|
|
260
|
+
def update(self, value=None, unit=None, quantity=None, is_known=None):
|
261
|
+
"""Update variable properties flexibly."""
|
262
|
+
if quantity is not None:
|
263
|
+
self.quantity = quantity
|
264
|
+
elif value is not None:
|
265
|
+
# Create setter and call the appropriate unit property
|
266
|
+
setter = self.set(value)
|
267
|
+
if unit is not None:
|
268
|
+
# Try to find the unit property on the setter
|
269
|
+
if hasattr(setter, unit):
|
270
|
+
getattr(setter, unit)
|
271
|
+
elif hasattr(setter, unit + 's'): # Handle singular/plural
|
272
|
+
getattr(setter, unit + 's')
|
273
|
+
elif unit.endswith('s') and hasattr(setter, unit[:-1]): # Handle plural to singular
|
274
|
+
getattr(setter, unit[:-1])
|
275
|
+
else:
|
276
|
+
raise ValueError(f"Unit '{unit}' not found for {self.__class__.__name__}")
|
277
|
+
else:
|
278
|
+
# If no unit specified, we can't automatically choose a unit
|
279
|
+
# The caller should specify either a unit or a quantity
|
280
|
+
raise ValueError("Must specify either 'unit' with 'value' or provide 'quantity' directly")
|
281
|
+
if is_known is not None:
|
282
|
+
self.is_known = is_known
|
283
|
+
return self # For method chaining
|
284
|
+
|
285
|
+
def mark_known(self, quantity=None):
|
286
|
+
"""Mark variable as known, optionally updating its value."""
|
287
|
+
self.is_known = True
|
288
|
+
if quantity is not None:
|
289
|
+
self.quantity = quantity
|
290
|
+
return self # For method chaining
|
291
|
+
|
292
|
+
def mark_unknown(self):
|
293
|
+
"""Mark variable as unknown."""
|
294
|
+
self.is_known = False
|
295
|
+
return self # For method chaining
|
296
|
+
|
260
297
|
def __str__(self):
|
261
298
|
return f"{self.name}: {self.quantity}" if self.quantity else f"{self.name}: unset"
|
262
299
|
|
@@ -66,3 +66,41 @@ class ExpressionVariable(TypeSafeVariable):
|
|
66
66
|
def __rpow__(self, other: FastQuantity | int | float) -> Expression:
|
67
67
|
"""Reverse power for this variable."""
|
68
68
|
return wrap_operand(other) ** wrap_operand(self)
|
69
|
+
|
70
|
+
# Comparison methods
|
71
|
+
def lt(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
72
|
+
"""Less than comparison (<)."""
|
73
|
+
from ..expression import BinaryOperation
|
74
|
+
return BinaryOperation('<', wrap_operand(self), wrap_operand(other))
|
75
|
+
|
76
|
+
def leq(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
77
|
+
"""Less than or equal comparison (<=)."""
|
78
|
+
from ..expression import BinaryOperation
|
79
|
+
return BinaryOperation('<=', wrap_operand(self), wrap_operand(other))
|
80
|
+
|
81
|
+
def geq(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
82
|
+
"""Greater than or equal comparison (>=)."""
|
83
|
+
from ..expression import BinaryOperation
|
84
|
+
return BinaryOperation('>=', wrap_operand(self), wrap_operand(other))
|
85
|
+
|
86
|
+
def gt(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
87
|
+
"""Greater than comparison (>)."""
|
88
|
+
from ..expression import BinaryOperation
|
89
|
+
return BinaryOperation('>', wrap_operand(self), wrap_operand(other))
|
90
|
+
|
91
|
+
# Python comparison operators
|
92
|
+
def __lt__(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
93
|
+
"""Less than comparison (<) operator."""
|
94
|
+
return self.lt(other)
|
95
|
+
|
96
|
+
def __le__(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
97
|
+
"""Less than or equal comparison (<=) operator."""
|
98
|
+
return self.leq(other)
|
99
|
+
|
100
|
+
def __gt__(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
101
|
+
"""Greater than comparison (>) operator."""
|
102
|
+
return self.gt(other)
|
103
|
+
|
104
|
+
def __ge__(self, other: TypeSafeVariable | FastQuantity | int | float) -> Expression:
|
105
|
+
"""Greater than or equal comparison (>=) operator."""
|
106
|
+
return self.geq(other)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qnty
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.8
|
4
4
|
Summary: High-performance unit system library for Python with dimensional safety and fast unit conversions
|
5
5
|
License: Apache-2.0
|
6
6
|
Keywords: units,dimensional analysis,engineering,physics,quantities,measurements
|
@@ -1,19 +1,19 @@
|
|
1
1
|
qnty/__init__.py,sha256=o9rtuo8QAdC3ppaD7ev1jqjrWbCvpdFbi_yZwUBuc6Q,5551
|
2
2
|
qnty/dimension.py,sha256=yc4zSJ5KCzgihya2MZX4lfP3E4YNg97mP8Sw_ajO2Pg,11117
|
3
|
-
qnty/equation.py,sha256=
|
4
|
-
qnty/expression.py,sha256=
|
3
|
+
qnty/equation.py,sha256=RRe3pJBn3ZrM3LtSnioG_i7gKmBnNVsIxc9KXf5UrTg,12278
|
4
|
+
qnty/expression.py,sha256=pbQ8fB2xc7VVi4LTqw8PbJFqG7XW4U36wI2pe6P4yto,24609
|
5
5
|
qnty/prefixes.py,sha256=bRwcNbE_nX9gXI_WnJZLL-i7kQncIOZivCCSN8dur2g,6000
|
6
6
|
qnty/unit.py,sha256=V3rQY-fYAnYC8Ed2r9FlCCkMOZ4zQQvGaVPS4VH-K9c,5585
|
7
7
|
qnty/unit_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
qnty/unit_types/base.py,sha256=Gk2Ab4TE-SfGBn-ko_p0vDI178PG9SyZOJ0cBOYEpdg,1620
|
9
9
|
qnty/units.py,sha256=8swGhiJQfrA_-gas2e2cbwKTXf4g0xmBbeVibYsqCHk,302897
|
10
|
-
qnty/variable.py,sha256=
|
10
|
+
qnty/variable.py,sha256=y2rQnGKeErC7_NKz9Z3WLV_cEn2Ya3ZvBEEPwioHrSo,13091
|
11
11
|
qnty/variable_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
qnty/variable_types/base.py,sha256=Otm7FOvuvi1gdlZm-djlTwqhlsSdzPIL46AXnB2cd18,1735
|
13
|
-
qnty/variable_types/expression_variable.py,sha256=
|
13
|
+
qnty/variable_types/expression_variable.py,sha256=xTHTSqITZt9h5vas3M_pZsQeE8Bm5cJxZBr7Q1EdhUs,4838
|
14
14
|
qnty/variable_types/typed_variable.py,sha256=kjw8VOShMaE7iorc3mqCIApYaFgOfvv-jSu_tmT1DgM,4227
|
15
15
|
qnty/variables.py,sha256=boClctOkzemu18yMv2rzuVq96MNCVFR-MOVVO1InBQc,142715
|
16
16
|
qnty/variables.pyi,sha256=KYPDJ-Qh_LPP4vHsafzrV6ZAUeepErY-RwRpOTieuhk,219690
|
17
|
-
qnty-0.0.
|
18
|
-
qnty-0.0.
|
19
|
-
qnty-0.0.
|
17
|
+
qnty-0.0.8.dist-info/METADATA,sha256=uo_wncOYHiRWJYeie3RWMWMOeAVbWBnQMquWnYLPGAs,12113
|
18
|
+
qnty-0.0.8.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
19
|
+
qnty-0.0.8.dist-info/RECORD,,
|
File without changes
|