From e982896920e553150edb72b9f3a3ab867cc4bf10 Mon Sep 17 00:00:00 2001 From: Arthur Besen Soprana Date: Sat, 12 Oct 2019 15:19:17 -0300 Subject: [PATCH] Refactored code, add new tests and avoid getting value from empty scalar passing a unit --- src/barril/units/_quantity.py | 8 +++---- src/barril/units/_scalar.py | 21 ++++++++++++------- src/barril/units/_tests/test_empty_scalar.py | 8 +++++-- src/barril/units/_tests/test_posc.py | 1 - .../_tests/test_posc_additional_units.py | 14 +++++++++++++ src/barril/units/_tests/test_quantity.py | 7 +++++++ src/barril/units/_tests/test_scalar.py | 21 ++++++++++++++++++- src/barril/units/posc.py | 4 ++-- 8 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/barril/units/_quantity.py b/src/barril/units/_quantity.py index 0faab7c..83dc508 100644 --- a/src/barril/units/_quantity.py +++ b/src/barril/units/_quantity.py @@ -584,6 +584,9 @@ def GetUnit(self): unit = property(GetUnit) + def IsEmpty(self): + return self == self._EMPTY_QUANTITY + def GetUnitName(self): """ :rtype: str @@ -684,10 +687,7 @@ def Convert(self, value, to_unit): ) except ComposedUnitError: return self._unit_database.Convert( - self._category, - self._CreateUnitsWithJoinedExponentsString(), - to_unit, - value, + self._category, self._unit, to_unit, value ) @classmethod diff --git a/src/barril/units/_scalar.py b/src/barril/units/_scalar.py index e9f3429..845142c 100644 --- a/src/barril/units/_scalar.py +++ b/src/barril/units/_scalar.py @@ -10,7 +10,7 @@ from ._abstractvaluewithquantity import AbstractValueWithQuantityObject from ._quantity import ObtainQuantity, Quantity from .interfaces import IQuantity, IScalar -from .unit_database import InvalidQuantityTypeError, UnitDatabase +from .unit_database import InvalidQuantityTypeError, UnitDatabase, UnitsError __all__ = ["Scalar"] @@ -109,6 +109,10 @@ def GetAbstractValue(self, unit=None): if unit is None: return self._value else: + if self._quantity.IsEmpty(): + raise UnitsError( + "Unable to get value for empty quantity, unit should be None." + ) return self._quantity.ConvertScalarValue(self._value, unit) GetValue = GetAbstractValue @@ -238,19 +242,21 @@ def GetFormatted(self, unit=None, value_format=None): ) # Compare -------------------------------------------------------------------------------------- - def _GetValueInDefaultUnit(self): + def _GetValueInBaseUnit(self): try: + if self._quantity.IsEmpty(): + return self._value return self.GetValue( - self._unit_database.GetDefaultUnit(self._quantity._category) + self._unit_database.GetBaseUnit(self._quantity._category) ) except InvalidQuantityTypeError: - return self._value + return (self._value, self._quantity._unit) def __eq__(self, other): return ( type(self) is type(other) and self._quantity._category == other._quantity._category - and self._GetValueInDefaultUnit() == other._GetValueInDefaultUnit() + and self._GetValueInBaseUnit() == other._GetValueInBaseUnit() ) def AlmostEqual(self, other, precision): @@ -258,14 +264,13 @@ def AlmostEqual(self, other, precision): type(self) is type(other) and self._quantity._category == other._quantity._category and round( - self._GetValueInDefaultUnit() - other._GetValueInDefaultUnit(), - precision, + self._GetValueInBaseUnit() - other._GetValueInBaseUnit(), precision ) == 0 ) def __hash__(self, *args, **kwargs): - return hash((self._quantity._category, self._GetValueInDefaultUnit())) + return hash((self._quantity._category, self._GetValueInBaseUnit())) def __lt__(self, other): if self.quantity_type != other.quantity_type: diff --git a/src/barril/units/_tests/test_empty_scalar.py b/src/barril/units/_tests/test_empty_scalar.py index 8550b2e..382188d 100644 --- a/src/barril/units/_tests/test_empty_scalar.py +++ b/src/barril/units/_tests/test_empty_scalar.py @@ -1,5 +1,5 @@ from barril.units import Scalar -from barril.units.unit_database import InvalidQuantityTypeError +from barril.units.unit_database import InvalidQuantityTypeError, UnitsError import pytest @@ -18,10 +18,14 @@ def testEmptyScalar(): def testEmptyScalarWithInitialValue(): # An empty scalar doesn't have a category defined scalar_1 = Scalar.CreateEmptyScalar(20.0) + scalar_2 = Scalar.CreateEmptyScalar(20.0) + assert scalar_1 == scalar_2 # When try to retrieve an empty scalar value using any unit a exception # is being raised - with pytest.raises(InvalidQuantityTypeError): + with pytest.raises( + UnitsError, match="Unable to get value for empty quantity, unit should be None." + ): _ = scalar_1.GetValue("m") assert scalar_1.GetUnit() == "" diff --git a/src/barril/units/_tests/test_posc.py b/src/barril/units/_tests/test_posc.py index 197aba1..129c949 100644 --- a/src/barril/units/_tests/test_posc.py +++ b/src/barril/units/_tests/test_posc.py @@ -304,7 +304,6 @@ def testDefaultCategories(unit_database_posc): "self inductance per length", "shear rate", "status", - "thermodynamic temperature", "volume per area", "volume per length", "volume per time per area", diff --git a/src/barril/units/_tests/test_posc_additional_units.py b/src/barril/units/_tests/test_posc_additional_units.py index 2162317..7d74cad 100644 --- a/src/barril/units/_tests/test_posc_additional_units.py +++ b/src/barril/units/_tests/test_posc_additional_units.py @@ -389,3 +389,17 @@ def testPerMicrometre(db): assert approx(per_inch.GetValue()) == 25400 assert per_metre == units.Scalar("per length", 10 ** 6, "1/m") assert per_inch == units.Scalar("per length", 25400.0, "1/in") + + +def testMassTemperaturePerMol(db): + value = units.Scalar("mass temperature per mol", 3.1415, "kg.K/mol") + + assert value.GetValue("kg.K/mol") == approx(3.1415) + assert value.GetValue("kg.degC/mol") == approx(3.1415) + assert value.GetValue("g.K/mol") == approx(3.1415 * 1e3) + assert value.GetValue("g.degC/mol") == approx(3.1415 * 1e3) + assert value.GetValue("kg.K/kmol") == approx(3.1415 * 1e3) + assert value.GetValue("kg.degC/kmol") == approx(3.1415 * 1e3) + assert value.GetValue("kg.degF/mol") == approx(3.1415 * 9 / 5) + assert value.GetValue("g.degF/mol") == approx(3.1415 * 9 / 5 * 1e3) + assert value.GetValue("kg.degF/kmol") == approx(3.1415 * 9 * 1e3 / 5) diff --git a/src/barril/units/_tests/test_quantity.py b/src/barril/units/_tests/test_quantity.py index 5abbded..13bdf39 100644 --- a/src/barril/units/_tests/test_quantity.py +++ b/src/barril/units/_tests/test_quantity.py @@ -112,3 +112,10 @@ def testDivision(): assert speed.GetUnit() == "m/s" assert speed.unit == "m/s" assert no_unit.GetUnit() == "" + + +def testEmptyQuantity(): + quantity = Quantity.CreateEmpty() + assert quantity.IsEmpty() + assert quantity.GetUnit() == "" + assert quantity.GetQuantityType() == "" diff --git a/src/barril/units/_tests/test_scalar.py b/src/barril/units/_tests/test_scalar.py index 0a9810a..9547afc 100644 --- a/src/barril/units/_tests/test_scalar.py +++ b/src/barril/units/_tests/test_scalar.py @@ -585,7 +585,10 @@ def testScalarCreationModes(): assert Scalar("length", 10, "m") == base assert Scalar((10.0, "m")) == base - with pytest.raises(AssertionError): + with pytest.raises( + AssertionError, + match="If category and value are given, the unit must be specified too.", + ): Scalar("length", 1.0) # missing unit @@ -633,6 +636,8 @@ class Fluid: def testComparison(): + from math import pi + a = Scalar(1, "m") b = Scalar(100, "cm") c = Scalar(99, "cm") @@ -659,3 +664,17 @@ def testComparison(): a = Scalar(q, 1.0) b = Scalar(q * q, 1.0) assert {a, b, b / a} == {b, a} + + for value in [0.0, pi, 0.33333333]: + a = Scalar("temperature", value, "degC") + b = Scalar("temperature", value * 1.8 + 32, "degF") + c = Scalar("temperature", value + 273.15, "K") + + assert a <= b <= c and c <= b <= a + + +def testHashing(): + m = Scalar(1, "m") + cm = Scalar(100, "cm") + assert m == cm + assert hash(m) == hash(cm) diff --git a/src/barril/units/posc.py b/src/barril/units/posc.py index e4f34a1..acddcf2 100644 --- a/src/barril/units/posc.py +++ b/src/barril/units/posc.py @@ -2665,7 +2665,7 @@ def FillUnitDatabaseWithPosc(db=None, fill_categories=True, override_categories= "degF", f_base_to_unit, f_unit_to_base, - default_category="thermodynamic temperature", + default_category=None, ) f_unit_to_base = MakeCustomaryToBase(0.0, 0.1761102, 1.0, 0.0) f_base_to_unit = MakeBaseToCustomary(0.0, 0.1761102, 1.0, 0.0) @@ -2755,7 +2755,7 @@ def FillUnitDatabaseWithPosc(db=None, fill_categories=True, override_categories= "degR", f_base_to_unit, f_unit_to_base, - default_category="thermodynamic temperature", + default_category=None, ) f_unit_to_base = MakeCustomaryToBase(0.0, 0.1, 1.0, 0.0) f_base_to_unit = MakeBaseToCustomary(0.0, 0.1, 1.0, 0.0)