Skip to content

Commit

Permalink
Support converting from aliased to alias units
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxcode123 committed Apr 2, 2024
1 parent 11f37f2 commit 0ceeac0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/property_utils/tests/units/test_converter_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
Unit3,
Unit4,
Unit5,
Unit6,
Unit1Converter,
UnregisteredConverter,
Unit1_2Converter,
Unit1_314Converter,
Unit2_4Converter,
Unit3_2Converter,
Expand All @@ -38,6 +40,7 @@
Unit1Unit4FractionConverter,
Unit1_2Unit4_3Converter,
Unit5Converter,
Unit6Converter,
)


Expand Down Expand Up @@ -377,6 +380,28 @@ def test_from_B_to_b(self):
self.assertResultRaises(UnsupportedConverterError)


@add_to(ExponentiatedUnitConverter_test_suite)
class TestAliasExponentiatedUnitConverterConvert(TestCase):
def subject(self, value, from_descriptor, to_descriptor):
return Unit1_2Converter.convert(value, from_descriptor, to_descriptor)

@args({"value": 2, "from_descriptor": Unit1.A**2, "to_descriptor": Unit1.A**2})
def test_with_same_unit(self):
self.assertResult(2)

@args({"value": 5, "from_descriptor": Unit1.A**2, "to_descriptor": Unit1.a**2})
def test_with_same_unit_type(self):
self.assertResult(500)

@args({"value": 5, "from_descriptor": Unit1.A**2, "to_descriptor": Unit6.F})
def test_with_alias_units(self):
self.assertResult(250)

@args({"value": 10, "from_descriptor": Unit1.a**2, "to_descriptor": Unit6.f})
def test_with_alias_si_units(self):
self.assertResult(10)


@add_to(ExponentiatedUnitConverter_test_suite)
class TestExponentiatedUnitConverterGetFactor(TestCase):
def subject(self, from_descriptor, to_descriptor):
Expand Down
34 changes: 34 additions & 0 deletions src/property_utils/units/converter_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,12 @@ def get_factor(
f"invalid 'to_descriptor'; expected an instance of {cls.generic_unit_descriptor}. "
)
from_dimension = Dimension.from_descriptor(from_descriptor)

if isinstance(to_descriptor, AliasMeasurementUnit):
return cls._get_aliased_factor(from_dimension, to_descriptor)

to_dimension = Dimension.from_descriptor(to_descriptor)

try:
converter = get_converter(cls.generic_unit_descriptor.unit_type)
except UndefinedConverterError:
Expand All @@ -514,6 +519,35 @@ def get_factor(
factor = converter.get_factor(from_dimension.unit, to_dimension.unit)
return factor**to_dimension.power

@classmethod
def _get_aliased_factor(
cls, from_dimension: Dimension, to_descriptor: AliasMeasurementUnit
) -> float:
"""
Returns the conversion factor from an alias unit to its aliased.
The conversion happens in four steps:
1. Convert from the alias unit to the SI unit.
2. Convert from the SI unit to the aliased SI units (this step is not
implemented in code, because the conversion factor is 1)
3. Convert from the aliased SI units to the target units.
e.g. if you want to convert from cm^3 to L:
1. cm^3 -> m^3
2. m^3 -> kL (conversion factor 1)
3. kL -> L
"""
step_1_factor = cls.get_factor(from_dimension, from_dimension.si())

converter = get_converter(to_descriptor.to_generic())

step_3_factor = converter.convert(
1, to_descriptor.to_generic().to_si(), to_descriptor
)

return step_1_factor * step_3_factor


class CompositeUnitConverter(metaclass=ABCMeta):
"""
Expand Down

0 comments on commit 0ceeac0

Please sign in to comment.