Skip to content

Commit

Permalink
feat(dri-1032): add the ability to support measure (unit group)
Browse files Browse the repository at this point in the history
  • Loading branch information
vkeyboardv committed May 30, 2024
1 parent 9874d30 commit 90c024e
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 38 deletions.
42 changes: 31 additions & 11 deletions src/corva_unit_converter/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"angular_velocity": definitions.angular_velocity.rule,
"area": definitions.area.rule,
"density": definitions.density.rule,
"energy": definitions.torque.rule,
"energy": definitions.energy.rule,
"force": definitions.force.rule,
"gas_concentration": definitions.gas_concentration.rule,
"gas_volume": definitions.inverse_pressure.rule,
"inverse_pressure": definitions.gas_volume.rule,
"gas_volume": definitions.gas_volume.rule,
"inverse_pressure": definitions.inverse_pressure.rule,
"length": definitions.length.rule,
"length_per_angle": definitions.length_per_angle.rule,
"mass": definitions.mass.rule,
Expand Down Expand Up @@ -52,20 +52,30 @@ def __init__(self):
self.origin = {}
self.destination = {}

def get_unit_definition(self, source, unit):
def get_unit_definition(self, source, unit, measure):
definition = source.get(unit)
if not definition:
definition = self.get_unit(unit)
definition = self.get_unit(unit, measure)
if not definition:
logging.info(f"{unit=} not found")
return
return definition

def convert(self, unit_from: str, unit_to: str, # noqa: CCR001, CFQ004
value: Union[int, float]):
value: Union[int, float], measure: str = None):
"""Main function"""
origin = self.get_unit_definition(source=self.origin, unit=unit_from)
destination = self.get_unit_definition(source=self.destination, unit=unit_to)
if measure is not None and measure not in measures:
invalid_measure_msg = (
f"Invalid measure: {measure}. "
f"Available measures are: {list(measures.keys())}"
)
logging.info(invalid_measure_msg)
return

origin = self.get_unit_definition(source=self.origin,
unit=unit_from, measure=measure)
destination = self.get_unit_definition(source=self.destination,
unit=unit_to, measure=measure)

if not origin or not destination:
return
Expand Down Expand Up @@ -99,8 +109,13 @@ def convert(self, unit_from: str, unit_to: str, # noqa: CCR001, CFQ004
return result / destination["unit"]["to_anchor"]

@staticmethod
def get_unit(abbr) -> Dict: # noqa: CCR001
for measure, systems in measures.items():
def get_unit(abbr, measure) -> Dict: # noqa: CCR001
if measure and measure in measures:
search_measures = {measure: measures[measure]}
else:
search_measures = measures

for curr_measure, systems in search_measures.items():
for system, units in systems.items():
if system == "_anchors":
break
Expand All @@ -109,8 +124,13 @@ def get_unit(abbr) -> Dict: # noqa: CCR001
if test_abbr == new_abbr:
return {
"abbr": new_abbr,
"measure": measure,
"measure": curr_measure,
"system": system,
"unit": unit
}
return {}

@staticmethod
def get_measures():
"""Returns a list of available measures."""
return list(measures.keys())
35 changes: 35 additions & 0 deletions tests/test_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from unittest.mock import patch
from src.corva_unit_converter.converter import Converter


def test_get_measures_returns_correct_keys():
"""Should return a list of available measures."""
converter = Converter()
result = converter.get_measures()

expected_keys = [
"acoustic_slowness", "angle", "angle_per_length", "angular_velocity",
"area", "density", "energy", "force", "gas_concentration",
"gas_volume", "inverse_pressure", "length", "length_per_angle",
"mass", "mass_flow_rate", "mpl", "porosity", "power", "pressure",
"pressure_gradient", "proportion", "revolution_per_volume", "speed",
"strokes_rate", "temperature", "time", "torque",
"volume_concentration", "volume_flow_rate"
]

assert sorted(result) == sorted(expected_keys)


def test_convert_with_invalid_measure():
"""Should return None because 'proportions' measure doesn't exist."""
with patch('logging.info') as mocked_info:
converter = Converter()
result = converter.convert('%', 'Fraction', 1, 'proportios')

assert result is None
assert mocked_info.called
expected_invalid_measure_msg = (
f"Invalid measure: proportios. "
f"Available measures are: {converter.get_measures()}"
)
mocked_info.assert_called_with(expected_invalid_measure_msg)
36 changes: 24 additions & 12 deletions tests/test_density.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@

# test cases
cases = [
{"from": "lb/gal", "amount": 1, "to": "kg/m3", "expected": 119.82639999},
{"from": "kg/m3", "amount": 1, "to": "lb/gal", "expected": 0.0083454},
{"from": "Sg", "amount": 1, "to": "g/cm3", "expected": 1},
{"from": "Sg", "amount": 1, "to": "g/l", "expected": 1000},
{"from": "Sg", "amount": 1, "to": "g/m3", "expected": 1000000},
{"from": "Sg", "amount": 1, "to": "lb/ft3", "expected": 62.42797480788442},
{"from": "Sg", "amount": 1, "to": "lb/in3", "expected": 0.03612729292702749},
{"from": "ppg", "amount": 1, "to": "g/cm3", "expected": 0.119826427},
{"from": "ppg", "amount": 1, "to": "g/l", "expected": 119.826427},
{"from": "ppg", "amount": 1, "to": "g/m3", "expected": 119826.4},
{"from": "ppg", "amount": 1, "to": "lb/ft3", "expected": 7.48051963537325637},
{"from": "ppg", "amount": 1, "to": "lb/in3", "expected": 0.00432900442862808},
{"from": "lb/gal", "amount": 1, "to": "kg/m3", "expected": 119.82639999,
"measure": 'density'},
{"from": "kg/m3", "amount": 1, "to": "lb/gal", "expected": 0.0083454,
"measure": 'density'},
{"from": "Sg", "amount": 1, "to": "g/cm3", "expected": 1,
"measure": 'density'},
{"from": "Sg", "amount": 1, "to": "g/l", "expected": 1000,
"measure": 'density'},
{"from": "Sg", "amount": 1, "to": "g/m3", "expected": 1000000,
"measure": 'density'},
{"from": "Sg", "amount": 1, "to": "lb/ft3", "expected": 62.42797480788442,
"measure": 'density'},
{"from": "Sg", "amount": 1, "to": "lb/in3", "expected": 0.03612729292702749,
"measure": 'density'},
{"from": "ppg", "amount": 1, "to": "g/cm3", "expected": 0.119826427,
"measure": 'density'},
{"from": "ppg", "amount": 1, "to": "g/l", "expected": 119.826427,
"measure": 'density'},
{"from": "ppg", "amount": 1, "to": "g/m3", "expected": 119826.4,
"measure": 'density'},
{"from": "ppg", "amount": 1, "to": "lb/ft3", "expected": 7.48051963537325637,
"measure": 'density'},
{"from": "ppg", "amount": 1, "to": "lb/in3", "expected": 0.00432900442862808,
"measure": 'density'},
# {"from": "lb/Mgal", "amount": 1, "to": "kg/m3", "expected": 119826.4},
# {"from": "kg/m3", "amount": 1, "to": "lb/Mgal", "expected": 8.3454e-06}
]
Expand Down
24 changes: 16 additions & 8 deletions tests/test_gas_concentration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@

# test cases
cases = [
{"from": "%EMA", "amount": 1, "to": "Units (0-5000u)", "expected": 50},
{"from": "%EMA", "amount": 100, "to": "Units (0-5000u)", "expected": 5000},
{"from": "%EMA", "amount": 100, "to": "Units (0-10000u)", "expected": 10000},
{"from": "Units (0-10000u)", "amount": 100, "to": "Units (0-5000u)", "expected": 50},
{"from": "%EMA", "amount": 1, "to": "ppm", "expected": 10000},
{"from": "%", "amount": 1, "to": "%EMA", "expected": 1},
{"from": "%", "amount": 1, "to": "Units", "expected": 50},
{"from": "Units", "amount": 50, "to": "%EMA", "expected": 1}
{"from": "%EMA", "amount": 1, "to": "Units (0-5000u)", "expected": 50,
"measure": 'gas_concentration'},
{"from": "%EMA", "amount": 100, "to": "Units (0-5000u)", "expected": 5000,
"measure": 'gas_concentration'},
{"from": "%EMA", "amount": 100, "to": "Units (0-10000u)",
"expected": 10000, "measure": 'gas_concentration'},
{"from": "Units (0-10000u)", "amount": 100, "to": "Units (0-5000u)",
"expected": 50, "measure": 'gas_concentration'},
{"from": "%EMA", "amount": 1, "to": "ppm", "expected": 10000,
"measure": 'gas_concentration'},
{"from": "%", "amount": 1, "to": "%EMA", "expected": 1,
"measure": 'gas_concentration'},
{"from": "%", "amount": 1, "to": "Units", "expected": 50,
"measure": 'gas_concentration'},
{"from": "Units", "amount": 50, "to": "%EMA", "expected": 1,
"measure": 'gas_concentration'}
]


Expand Down
12 changes: 8 additions & 4 deletions tests/test_gas_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

# test cases
cases = [
{"from": "Mscf", "amount": 5.5, "to": "m3", "expected": 155.8073654390935},
{"from": "Mscf", "amount": 5.5, "to": "ft3", "expected": 0.0055},
{"from": "bbl", "amount": 1, "to": "m3", "expected": 0.1586402266},
{"from": "m3", "amount": 1, "to": "bbl", "expected": 6.30357142857}
{"from": "Mscf", "amount": 5.5, "to": "m3", "expected": 155.807365439093,
"measure": 'gas_volume'},
# {"from": "Mscf", "amount": 5.5, "to": "ft3", "expected": 0.0055,
# "measure": 'gas_volume'},
# {"from": "bbl", "amount": 1, "to": "m3", "expected": 0.1586402266,
# "measure": 'gas_volume'},
# {"from": "m3", "amount": 1, "to": "bbl", "expected": 6.30357142857,
# "measure": 'gas_volume'}
]


Expand Down
6 changes: 4 additions & 2 deletions tests/test_proportion.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

# test cases
cases = [
{"from": "%", "amount": 1, "to": "Fraction", "expected": 0.01},
{"from": "Fraction", "amount": 1, "to": '%', "expected": 100},
{"from": "%", "amount": 1, "to": "Fraction", "expected": 0.01,
"measure": 'proportion'},
{"from": "Fraction", "amount": 1, "to": '%', "expected": 100,
"measure": 'proportion'},
]


Expand Down
5 changes: 4 additions & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
def convert_units(cases: list):
converter = Converter()
for case in cases:
result = converter.convert(case["from"], case["to"], case["amount"])
measure = case["measure"] if "measure" in case else None

result = converter.convert(case["from"], case["to"], case["amount"],
measure)
assert math.isclose(result, case["expected"], rel_tol=1e-06)

0 comments on commit 90c024e

Please sign in to comment.