Skip to content

Commit 3596c7f

Browse files
authored
Prevent count, radian, bit and dimensionless interconversion (#209)
1 parent 2a36a04 commit 3596c7f

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

gemd/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.18.2"
1+
__version__ = "1.18.3"

gemd/units/impl.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,20 @@ def convert_units(value: float, starting_unit: str, final_unit: str) -> float:
227227
if starting_unit == final_unit:
228228
return value # skip computation
229229
else:
230-
resolved_final_unit = _REGISTRY.parse_units(final_unit) # `to` bypasses preparser
231-
return _REGISTRY.Quantity(value, starting_unit).to(resolved_final_unit).magnitude
230+
resolved_value = _REGISTRY.Quantity(value, starting_unit)
231+
resolved_final_unit = _REGISTRY.parse_units(final_unit)
232+
# Make sure count, radian, bit, and non-dimensional don't accidentally interconvert
233+
# https://pint.readthedocs.io/en/0.23/user/angular_frequency.html
234+
root1 = _REGISTRY.get_root_units(resolved_value)[1]
235+
root2 = _REGISTRY.get_root_units(resolved_final_unit)[1]
236+
if root1 != root2:
237+
raise IncompatibleUnitsError(
238+
units1=resolved_value.units,
239+
dim1=_REGISTRY.get_dimensionality(resolved_final_unit),
240+
units2=final_unit,
241+
dim2=_REGISTRY.get_dimensionality(resolved_final_unit)
242+
)
243+
return resolved_value.to(resolved_final_unit).magnitude
232244

233245

234246
@register_unit_format("clean")

tests/units/test_parser.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import pytest
66

77
from gemd.units import parse_units, convert_units, get_base_units, change_definitions_file, \
8-
UndefinedUnitError, DefinitionSyntaxError
9-
from gemd.units.impl import DEFAULT_FILE
8+
UndefinedUnitError, DefinitionSyntaxError, IncompatibleUnitsError
109

1110

1211
@pytest.mark.parametrize("return_unit", [True, False])
@@ -144,6 +143,13 @@ def test_conversion():
144143
assert -1e-8 < convert_units(100, 'g / 100 mL', 'g/cc') - 1 < 1e-8
145144
assert -1e-8 < convert_units(1, "g / 2.5 cm", "g / 25 mm") - 1 < 1e-8
146145

146+
# Verify that convert_units throws exceptions
147+
with pytest.raises(IncompatibleUnitsError):
148+
convert_units(1, 'mL', 'g')
149+
with pytest.raises(IncompatibleUnitsError):
150+
# https://pint.readthedocs.io/en/0.23/user/angular_frequency.html
151+
convert_units(1, 'Hz', 'rpm')
152+
147153

148154
def test_get_base_units():
149155
"""Test that base units & conversions make sense."""

0 commit comments

Comments
 (0)