qnty 0.0.5__py3-none-any.whl → 0.0.7__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/dimension.py +2 -2
- qnty/expression.py +15 -3
- qnty/unit.py +2 -2
- qnty/units.py +8 -8
- qnty/variable.py +2 -2
- qnty/variables.py +8 -7
- {qnty-0.0.5.dist-info → qnty-0.0.7.dist-info}/METADATA +1 -1
- {qnty-0.0.5.dist-info → qnty-0.0.7.dist-info}/RECORD +9 -9
- {qnty-0.0.5.dist-info → qnty-0.0.7.dist-info}/WHEEL +0 -0
qnty/dimension.py
CHANGED
@@ -28,7 +28,7 @@ class DimensionSignature:
|
|
28
28
|
"""Immutable dimension signature for zero-cost dimensional analysis."""
|
29
29
|
|
30
30
|
# Store as bit pattern for ultra-fast comparison
|
31
|
-
_signature: int = 1
|
31
|
+
_signature: int | float = 1
|
32
32
|
|
33
33
|
@classmethod
|
34
34
|
def create(cls, length=0, mass=0, time=0, current=0, temp=0, amount=0, luminosity=0):
|
@@ -55,7 +55,7 @@ class DimensionSignature:
|
|
55
55
|
return DimensionSignature(self._signature * other._signature)
|
56
56
|
|
57
57
|
def __truediv__(self, other):
|
58
|
-
return DimensionSignature(self._signature
|
58
|
+
return DimensionSignature(self._signature / other._signature)
|
59
59
|
|
60
60
|
def __pow__(self, power):
|
61
61
|
return DimensionSignature(self._signature ** power)
|
qnty/expression.py
CHANGED
@@ -246,11 +246,23 @@ class BinaryOperation(Expression):
|
|
246
246
|
left_str = str(self.left)
|
247
247
|
right_str = str(self.right)
|
248
248
|
|
249
|
-
# Add parentheses
|
249
|
+
# Add parentheses for left side when precedence is strictly lower
|
250
250
|
if isinstance(self.left, BinaryOperation) and precedence.get(self.left.operator, 0) < precedence.get(self.operator, 0):
|
251
251
|
left_str = f"({left_str})"
|
252
|
-
|
253
|
-
|
252
|
+
|
253
|
+
# CRITICAL FIX: For right side, add parentheses when:
|
254
|
+
# 1. Precedence is strictly lower, OR
|
255
|
+
# 2. Precedence is equal AND operation is left-associative (-, /)
|
256
|
+
if isinstance(self.right, BinaryOperation):
|
257
|
+
right_prec = precedence.get(self.right.operator, 0)
|
258
|
+
curr_prec = precedence.get(self.operator, 0)
|
259
|
+
|
260
|
+
# Need parentheses if:
|
261
|
+
# - Right has lower precedence, OR
|
262
|
+
# - Same precedence and current operator is left-associative (- or /)
|
263
|
+
if (right_prec < curr_prec or
|
264
|
+
(right_prec == curr_prec and self.operator in ['-', '/'])):
|
265
|
+
right_str = f"({right_str})"
|
254
266
|
|
255
267
|
return f"{left_str} {self.operator} {right_str}"
|
256
268
|
|
qnty/unit.py
CHANGED
@@ -64,8 +64,8 @@ class HighPerformanceRegistry:
|
|
64
64
|
def __init__(self):
|
65
65
|
self.units: dict[str, UnitDefinition] = {}
|
66
66
|
self.conversion_table: dict[tuple[str, str], float] = {} # (from_unit, to_unit) -> factor
|
67
|
-
self.dimensional_groups: dict[int, list[UnitDefinition]] = {}
|
68
|
-
self._dimension_cache: dict[int, UnitConstant] = {} # Cache for common dimension mappings
|
67
|
+
self.dimensional_groups: dict[int | float, list[UnitDefinition]] = {}
|
68
|
+
self._dimension_cache: dict[int | float, UnitConstant] = {} # Cache for common dimension mappings
|
69
69
|
self._finalized = False
|
70
70
|
self.base_units: dict[str, UnitDefinition] = {} # Track base units for prefix generation
|
71
71
|
self.prefixable_units: set[str] = set() # Track which units can have prefixes
|
qnty/units.py
CHANGED
@@ -22,6 +22,9 @@ from .dimension import (
|
|
22
22
|
CONCENTRATION,
|
23
23
|
DIMENSIONLESS,
|
24
24
|
DYNAMIC_FLUIDITY,
|
25
|
+
ELECTRICAL_CONDUCTANCE,
|
26
|
+
ELECTRICAL_PERMITTIVITY,
|
27
|
+
ELECTRICAL_RESISTIVITY,
|
25
28
|
ELECTRIC_CAPACITANCE,
|
26
29
|
ELECTRIC_CHARGE,
|
27
30
|
ELECTRIC_CURRENT_INTENSITY,
|
@@ -30,9 +33,6 @@ from .dimension import (
|
|
30
33
|
ELECTRIC_INDUCTANCE,
|
31
34
|
ELECTRIC_POTENTIAL,
|
32
35
|
ELECTRIC_RESISTANCE,
|
33
|
-
ELECTRICAL_CONDUCTANCE,
|
34
|
-
ELECTRICAL_PERMITTIVITY,
|
35
|
-
ELECTRICAL_RESISTIVITY,
|
36
36
|
ENERGY_FLUX,
|
37
37
|
ENERGY_HEAT_WORK,
|
38
38
|
ENERGY_PER_UNIT_AREA,
|
@@ -65,14 +65,14 @@ from .dimension import (
|
|
65
65
|
MASS_FLUX,
|
66
66
|
MASS_TRANSFER_COEFFICIENT,
|
67
67
|
MOLALITY_OF_SOLUTE_I,
|
68
|
+
MOLARITY_OF_I,
|
68
69
|
MOLAR_CONCENTRATION_BY_MASS,
|
69
70
|
MOLAR_FLOW_RATE,
|
70
71
|
MOLAR_FLUX,
|
71
72
|
MOLAR_HEAT_CAPACITY,
|
72
|
-
MOLARITY_OF_I,
|
73
|
-
MOMENT_OF_INERTIA,
|
74
73
|
MOMENTUM_FLOW_RATE,
|
75
74
|
MOMENTUM_FLUX,
|
75
|
+
MOMENT_OF_INERTIA,
|
76
76
|
NORMALITY_OF_SOLUTION,
|
77
77
|
PARTICLE_DENSITY,
|
78
78
|
PERMEABILITY,
|
@@ -109,7 +109,7 @@ from .dimension import (
|
|
109
109
|
VOLUMETRIC_FLOW_RATE,
|
110
110
|
VOLUMETRIC_FLUX,
|
111
111
|
VOLUMETRIC_MASS_FLOW_RATE,
|
112
|
-
WAVENUMBER
|
112
|
+
WAVENUMBER
|
113
113
|
)
|
114
114
|
|
115
115
|
# Comprehensive unit definitions organized by dimensional signature
|
@@ -7896,8 +7896,8 @@ UNIT_DEFINITIONS = {
|
|
7896
7896
|
|
7897
7897
|
def create_unit_class(class_name: str, dimension_data: dict) -> type:
|
7898
7898
|
"""Dynamically create a unit class with all unit constants as attributes."""
|
7899
|
-
from .prefixes import get_prefix_by_name
|
7900
7899
|
from .unit import UnitConstant, UnitDefinition
|
7900
|
+
from .prefixes import get_prefix_by_name
|
7901
7901
|
|
7902
7902
|
# Create a new class dynamically
|
7903
7903
|
unit_class = type(class_name, (), {})
|
@@ -7950,8 +7950,8 @@ def create_unit_class(class_name: str, dimension_data: dict) -> type:
|
|
7950
7950
|
|
7951
7951
|
def register_all_units(registry):
|
7952
7952
|
"""Register all unit definitions to the given registry with prefix support."""
|
7953
|
-
from .prefixes import PREFIXABLE_UNITS
|
7954
7953
|
from .unit import UnitDefinition
|
7954
|
+
from .prefixes import get_prefix_by_name, StandardPrefixes, PREFIXABLE_UNITS
|
7955
7955
|
|
7956
7956
|
# First pass: register base units with prefixes where applicable
|
7957
7957
|
for dimension_data in UNIT_DEFINITIONS.values():
|
qnty/variable.py
CHANGED
@@ -115,7 +115,7 @@ class FastQuantity:
|
|
115
115
|
return FastQuantity(self.value / other, self.unit)
|
116
116
|
|
117
117
|
# Fast dimensional analysis using cached signatures
|
118
|
-
result_dimension_sig = self._dimension_sig
|
118
|
+
result_dimension_sig = self._dimension_sig / other._dimension_sig
|
119
119
|
|
120
120
|
# Use cached SI factors for conversion
|
121
121
|
self_si_value = self.value * self._si_factor
|
@@ -128,7 +128,7 @@ class FastQuantity:
|
|
128
128
|
|
129
129
|
return FastQuantity(result_value, result_unit)
|
130
130
|
|
131
|
-
def _find_result_unit_fast(self, result_dimension_sig: int,
|
131
|
+
def _find_result_unit_fast(self, result_dimension_sig: int | float,
|
132
132
|
left_qty: FastQuantity, right_qty: FastQuantity) -> UnitConstant:
|
133
133
|
"""Ultra-fast unit finding using cached dimension signatures."""
|
134
134
|
|
qnty/variables.py
CHANGED
@@ -9,7 +9,6 @@ Auto-generated from unit_data.json and dimension_mapping.json.
|
|
9
9
|
|
10
10
|
from typing import Any
|
11
11
|
|
12
|
-
from . import units
|
13
12
|
from .dimension import (
|
14
13
|
ABSORBED_DOSE,
|
15
14
|
ACCELERATION,
|
@@ -25,6 +24,9 @@ from .dimension import (
|
|
25
24
|
CONCENTRATION,
|
26
25
|
DIMENSIONLESS,
|
27
26
|
DYNAMIC_FLUIDITY,
|
27
|
+
ELECTRICAL_CONDUCTANCE,
|
28
|
+
ELECTRICAL_PERMITTIVITY,
|
29
|
+
ELECTRICAL_RESISTIVITY,
|
28
30
|
ELECTRIC_CAPACITANCE,
|
29
31
|
ELECTRIC_CHARGE,
|
30
32
|
ELECTRIC_CURRENT_INTENSITY,
|
@@ -33,9 +35,6 @@ from .dimension import (
|
|
33
35
|
ELECTRIC_INDUCTANCE,
|
34
36
|
ELECTRIC_POTENTIAL,
|
35
37
|
ELECTRIC_RESISTANCE,
|
36
|
-
ELECTRICAL_CONDUCTANCE,
|
37
|
-
ELECTRICAL_PERMITTIVITY,
|
38
|
-
ELECTRICAL_RESISTIVITY,
|
39
38
|
ENERGY_FLUX,
|
40
39
|
ENERGY_HEAT_WORK,
|
41
40
|
ENERGY_PER_UNIT_AREA,
|
@@ -69,15 +68,15 @@ from .dimension import (
|
|
69
68
|
MASS_FRACTION_OF_I,
|
70
69
|
MASS_TRANSFER_COEFFICIENT,
|
71
70
|
MOLALITY_OF_SOLUTE_I,
|
71
|
+
MOLARITY_OF_I,
|
72
72
|
MOLAR_CONCENTRATION_BY_MASS,
|
73
73
|
MOLAR_FLOW_RATE,
|
74
74
|
MOLAR_FLUX,
|
75
75
|
MOLAR_HEAT_CAPACITY,
|
76
|
-
MOLARITY_OF_I,
|
77
76
|
MOLE_FRACTION_OF_I,
|
78
|
-
MOMENT_OF_INERTIA,
|
79
77
|
MOMENTUM_FLOW_RATE,
|
80
78
|
MOMENTUM_FLUX,
|
79
|
+
MOMENT_OF_INERTIA,
|
81
80
|
NORMALITY_OF_SOLUTION,
|
82
81
|
PARTICLE_DENSITY,
|
83
82
|
PERCENT,
|
@@ -111,14 +110,16 @@ from .dimension import (
|
|
111
110
|
VISCOSITY_DYNAMIC,
|
112
111
|
VISCOSITY_KINEMATIC,
|
113
112
|
VOLUME,
|
114
|
-
VOLUME_FRACTION_OF_I,
|
115
113
|
VOLUMETRIC_CALORIFIC_HEATING_VALUE,
|
116
114
|
VOLUMETRIC_COEFFICIENT_OF_EXPANSION,
|
117
115
|
VOLUMETRIC_FLOW_RATE,
|
118
116
|
VOLUMETRIC_FLUX,
|
119
117
|
VOLUMETRIC_MASS_FLOW_RATE,
|
118
|
+
VOLUME_FRACTION_OF_I,
|
120
119
|
WAVENUMBER,
|
121
120
|
)
|
121
|
+
from . import units
|
122
|
+
from .unit import UnitConstant, UnitDefinition
|
122
123
|
from .variable import FastQuantity, TypeSafeSetter
|
123
124
|
from .variable_types.typed_variable import TypedVariable
|
124
125
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qnty
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.7
|
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
|
-
qnty/dimension.py,sha256=
|
2
|
+
qnty/dimension.py,sha256=yc4zSJ5KCzgihya2MZX4lfP3E4YNg97mP8Sw_ajO2Pg,11117
|
3
3
|
qnty/equation.py,sha256=XgzM91jn__GomKbgslncoFJWPDJiMb4_VKD-8sdcFXc,9096
|
4
|
-
qnty/expression.py,sha256=
|
4
|
+
qnty/expression.py,sha256=WV0OfZYPZlNf_sBEgOrnG88KKzj-xvTn45YGMoZR1xc,21435
|
5
5
|
qnty/prefixes.py,sha256=bRwcNbE_nX9gXI_WnJZLL-i7kQncIOZivCCSN8dur2g,6000
|
6
|
-
qnty/unit.py,sha256=
|
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
|
-
qnty/units.py,sha256=
|
10
|
-
qnty/variable.py,sha256=
|
9
|
+
qnty/units.py,sha256=8swGhiJQfrA_-gas2e2cbwKTXf4g0xmBbeVibYsqCHk,302897
|
10
|
+
qnty/variable.py,sha256=TOdh30vCF_TQHQuCC2sjRkwlXibryHhteb9djoJt5Fc,11396
|
11
11
|
qnty/variable_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
qnty/variable_types/base.py,sha256=Otm7FOvuvi1gdlZm-djlTwqhlsSdzPIL46AXnB2cd18,1735
|
13
13
|
qnty/variable_types/expression_variable.py,sha256=sRQ4VUMLBEh6tPqOwh4gLtGQH9Y3XeeHGdLKo0E6mWc,2997
|
14
14
|
qnty/variable_types/typed_variable.py,sha256=kjw8VOShMaE7iorc3mqCIApYaFgOfvv-jSu_tmT1DgM,4227
|
15
|
-
qnty/variables.py,sha256=
|
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.7.dist-info/METADATA,sha256=vxA0YIrA0DDqVbKz9e9rfEHIBdJ-Pk7S7bfc4BRdKeM,12113
|
18
|
+
qnty-0.0.7.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
19
|
+
qnty-0.0.7.dist-info/RECORD,,
|
File without changes
|