def test_from_si(self): assert Unit("1").from_si( decimal.Decimal("10")) == decimal.Decimal("10") assert Unit("10").from_si( decimal.Decimal("10")) == decimal.Decimal("1") assert Unit("1E-3").from_si( decimal.Decimal("10")) == decimal.Decimal("1E+4")
class Pressure(AbstractMeasure): pascal = MetricUnit("1", ["pa"], ["pa"], ["pascal"]) bar = Unit("100000") atmosphere = Unit("101325", ["atm"]) technical_atmosphere = Unit("98066.5", ["at"]) torr = Unit("133.322") psi = Unit("6894.757293168", ["pounds per square inch"])
def div(numerator, denomminator): for numerator_name, numerator_unit in numerator._units.items(): for (denomminator_name, denomminator_unit,) in denomminator._units.items(): name = f"{numerator_name}/{denomminator_name}" factor = numerator_unit.factor / denomminator_unit.factor unit = Unit(factor=factor) unit.name = name yield name, unit
class Speed(AbstractMeasure, metaclass=FractionMeasureBase): __numerator__ = Distance __denominator__ = Time mph = Unit("0.44704") kph = Unit(1 / decimal.Decimal("3.6")) @classmethod def _attr_to_unit(cls, name): return super()._attr_to_unit(name.replace("__", "/"))
class Area(AbstractMeasure, metaclass=AreaBase): """ An area is defined as :class:`Distance` multipled by :class:`Distance`. This is why you can multiply two :class:`Distances<Distance>` to get an :class:`Area` or divide an :class:`Area` to get a :class:`Distance`: >>> from measurement import measures >>> measures.Distance('2 m') * measures.Distance('3 m') Area(metre²="6") >>> measures.Area('6 m²') / measures.Distance('2 m') Distance(metre="3") If you multiply a :class:`Area` with a :class:`Distance`, you will get a :class:`Volume`: >>> measures.Area('6 m²') * measures.Distance('2 m') Volume(metre³="12") """ __factors__ = (Distance, Distance) acre = Unit( (decimal.Decimal("43560") * (Distance(ft=decimal.Decimal(1)).m ** 2)), ["Acre"], ) hectare = Unit("10000", ["Hectare", "ha"]) @classmethod def _attr_to_unit(cls, name): if name[:3] in ["sq_", "sq "]: name = f"{name[3:]}²" elif name[:7] in ["square_", "square "]: name = f"{name[7:]}²" return super()._attr_to_unit(name) def __truediv__(self, other): if isinstance(other, Distance): return Distance(metre=self.si_value / other.si_value) return super().__truediv__(other) def __mul__(self, other): if isinstance(other, Distance): return Volume(cubic_metre=self.si_value * other.si_value) return super().__mul__(other)
class VolumetricFlowRate(AbstractMeasure, metaclass=FractionMeasureBase): """Volumetric Flow measurements (generally for water flow).""" __numerator__ = Volume __denominator__ = Time cms = Unit("1", ["cumecs", "CMS"]) cfs = Unit(1 / decimal.Decimal("35.31466672148859025043801035"), ["CFS"]) miners_inch_50 = Unit("566.33693184e-6", ["mi_50"]) miners_inch_40 = Unit("707.9211648e-6", ["mi_40"]) miners_inch_38_4 = Unit("737.41788e-6", ["mi_38_4"]) @classmethod def _attr_to_unit(cls, name): return super()._attr_to_unit(name.replace("__", "/"))
class Frequency(AbstractMeasure): hertz = MetricUnit("1", ["Hz", "Hertz"], ["Hz"], ["hertz"]) rpm = Unit( decimal.Decimal("1.0") / decimal.Decimal("60"), ["RPM", "bpm", "BPM"]) def __mul__(self, other): if isinstance(other, Time): return self.si_value * other.si_value return super().__mul__(other)
def test_get_symbols(self): inch = Unit("0.0254", ["in", "inches"]) inch.name = "inch" assert list(inch.get_symbols()) == [ ("inch", Unit("0.0254")), ("in", Unit("0.0254")), ("inches", Unit("0.0254")), ]
def test_get_symbols(self): metre = MetricUnit("1", ["m", "meter"], ["m"], ["metre", "meter"]) metre.name = "metre" symbols = list(metre.get_symbols()) assert ("metre", Unit("1")) in symbols assert ("m", Unit("1")) in symbols assert ("meter", Unit("1")) in symbols assert ("km", Unit("1E+3")) in symbols assert ("μm", Unit("1E-6")) in symbols assert ("Kilometre", Unit("1E+3")) in symbols assert ("kilometre", Unit("1E+3")) in symbols assert ("Kilometer", Unit("1E+3")) in symbols assert ("kilometer", Unit("1E+3")) in symbols assert ("nanometer", Unit("1E-9")) in symbols
class Time(AbstractMeasure): """ Time measurements (generally for multidimensional measures). Please do not use this for handling durations of time unrelated to measure classes -- python's built-in datetime module has much better functionality for handling intervals of time than this class provides. """ second = Unit("1", ["s", "sec", "seconds"]) minute = Unit("60", ["min", "minutes"]) hour = Unit("3600", ["hr", "h", "hours"]) day = Unit("86400", ["d", "days"]) julian_year = MetricUnit( "31557600", ["year", "a", "aj", "years", "annum", "Julian year"], ["a"], ["annum"], )
class Energy(AbstractMeasure): joule = MetricUnit("1", ["J", "Joule"], ["J"], ["joule"]) calorie = MetricUnit( "4184.0", ["c", "cal", "Cal", "Calorie", "C"], ["cal"], ["calorie"] ) electronvolt = MetricUnit( "1.602177e-19", ["eV", "electron-volt", "electron volt"], ["eV"], ["electronvolt"], ) tonne_tnt = Unit("4184000000")
class Mass(AbstractMeasure): gram = MetricUnit("1", ["g", "Gram"], ["g"], ["gram"]) tonne = Unit("1000000", ["t", "metric ton", "metric tonne"]) ounce = Unit("28.34952", ["oz"]) pound = Unit("453.59237", ["lb"]) stone = Unit("6350.293") short_ton = Unit("907185.0", ["ton"]) long_ton = Unit("1016000.0")
def square(klass): for name, unit in klass._units.items(): qs_unit = Unit(factor=unit.factor ** 2) qs_unit.name = f"{qs_unit.name}²" yield f"{name}²", qs_unit
class Distance(AbstractMeasure): """ Distance is a factor for both :class:`Area` and :class:`Volume`. If you multiply a :class:`Distance` with another :class:`Distance`, you will get a :class:`Area`: >>> from measurement import measures >>> measures.Distance('2 m') * measures.Distance('3 m') Area(metre²="6") If you multiply a :class:`Distance` with a :class:`Area` or two :class:`Distances<Distance>`, you will get a :class:`Volume`: >>> from measurement import measures >>> measures.Distance('2 m') * measures.Area('6 m²') Volume(metre³="12") You can also build the second and third power of a :class:`Distance`, to get a :class:`Area` or :class:`Volume`. >>> from measurement import measures >>> measures.Distance('2 m') ** 2 Area(metre²="4") >>> measures.Distance('2 m') ** 3 Volume(metre³="8") """ metre = MetricUnit("1", ["m", "meter", "Meter", "Metre"], ["m"], ["metre", "meter"]) parsec = MetricUnit("3.0857E+16", ["Parsec", "pc"], ["pc"], ["parsec"]) astronomical_unit = MetricUnit( "1.495978707E+11", ["au", "ua", "AU"], ["au", "ua", "AU"] ) foot = Unit("0.3048", ["ft", "feet", "Foot (International)"]) inch = Unit("0.0254", ["in", "inches"]) mile = Unit("1609.344", ["mi"]) chain = Unit("20.1168") chain_benoit = Unit("20.116782", ["Chain (Benoit)"]) chain_sears = Unit("20.1167645", ["Chain (Sears)"]) british_chain_benoit = Unit("20.1167824944", ["British chain (Benoit 1895 B)"]) british_chain_sears = Unit("20.1167651216", ["British chain (Sears 1922)"]) british_chain_sears_truncated = Unit( "20.116756", ["British chain (Sears 1922 truncated)"] ) british_foot = Unit( "0.304799471539", ["british_ft", "British foot", "British foot (Sears 1922)"] ) british_yard = Unit( "0.914398414616", ["british_yd", "British yard", "British yard (Sears 1922)"] ) clarke_ft = Unit("0.3047972654", ["Clarke's Foot"]) clarke_link = Unit("0.201166195164", ["Clarke's link"]) fathom = Unit("1.8288") german_meter = Unit("1.0000135965", ["german_m", "German legal metre"]) gold_coast_foot = Unit("0.304799710181508", ["gold_coast_ft", "Gold Coast foot"]) indian_yard = Unit("0.914398530744", ["indian_yd", "Indian yard", "Yard (Indian)"]) link = Unit("0.201168", ["Link"]) link_benoit = Unit("0.20116782", ["Link (Benoit)"]) link_sears = Unit("0.20116765", ["Link (Sears)"]) nautical_mile = Unit("1852", ["Nautical Mile", "NM", "nmi"]) nautical_mile_uk = Unit("1853.184", ["nm_uk", "Nautical Mile (UK)"]) rod = Unit("5.0292") sears_yard = Unit("0.91439841", ["sears_yd", "Yard (Sears"]) survey_foot = Unit("0.304800609601", ["survey_ft", "US survey foot", "U.S. Foot"]) yard = Unit("0.9144", ["yd"]) point = Unit(decimal.Decimal("25.4e-3") / 72, ["pt"]) def __mul__(self, other): if isinstance(other, Distance): return Area(sq_metre=self.si_value * other.si_value) if isinstance(other, Area): return Volume(cubic_metre=self.si_value * other.si_value) return super().__mul__(other) def __pow__(self, power, modulo=None): if power == 2: return self * self if power == 3: return self * self * self return NotImplemented
class Volume(AbstractMeasure, metaclass=VolumeBase): """ A volume is defined as :class:`Area` multipled by :class:`Distance`. This is why you can multiply three :class:`Distances<Distance>` to get a :class:`Volume`, multiply a :class:`Area` by a :class:`Distance` or divide a :class:`Volume` by both :class:`Distance` and :class:`Area`: >>> from measurement import measures >>> measures.Distance('2 m') * measures.Distance('3 m') * measures.Distance('4 m') Volume(metre³="24") >>> measures.Distance('2 m') * measures.Area('6 m²') Volume(metre³="12") >>> measures.Volume('12 m³') / measures.Area('6 m²') Distance(metre="2") >>> measures.Volume('12 m³') / measures.Distance('6 m') Area(metre²="2") """ __factors__ = (Distance, Distance, Distance) litre = MetricUnit( "1e-3", ["liter", "L", "l", "ℓ"], ["L", "l", "ℓ"], ["litre", "liter"] ) us_gallon = Unit( "3.785411784e-3", ["US gallon", "US gal", "US fluid gallon", "gallon (US)"] ) us_fluid_ounce = Unit("29.57353e-6", ["US oz", "US fl oz"]) us_fluid_ounce_food = Unit("30e-6", ["US fluid ounce (food nutrition labelling)"]) us_liquid_quart = Unit("0.946352946e-3", ["US liquid quart"]) us_liquid_pint = Unit("473.176473e-6") us_gill = Unit("118.29411825e-6") us_tablespoon = Unit("14.78676478125e-6", ["US tablespoon", "Us tbsp", "Us Tbsp"]) us_tsp = Unit("4.92892159375e-6", ["US tsp"]) us_fluid_darm = Unit("3.6966911953125e-6") us_dry_gallon = Unit( "4.40488377086e-3", ["US dry gallon", "corn gallon", "grain gallon"] ) us_dry_quart = Unit("1.101220942715e-3") us_dry_pint = Unit("550.6104713575e-6") us_bushel = Unit("35.23907016688e-3", ["US bsh", "US bu"]) cubic_inch = Unit("16.387064e-6", ["cu in"]) cubic_foot = Unit("0.02832", ["cu ft"]) imperial_gallon = Unit( "4.54609e-3", ["Imperial gallon", "Imperial gal", "gallon (Imperial)"] ) imperial_fluid_ounce = Unit("28.41306e-6", ["Imperial fluid ounce", "imp fl oz"]) imperial_quart = Unit("1.1365225e-6", ["Imperial quart"]) imperial_pint = Unit("568.26125e-6", ["Imperial pint"]) imperial_gill = Unit("142.0653125e-6", ["Imperial gill"]) imperial_bushel = Unit("36.36872e-3", ["imp bsh", "imp bu"]) imperial_fluid_darm = Unit("3.5516328125e-6", ["luid drachm"]) au_tablespoon = Unit("20e-6", ["Australian tablespoon", "Australian tbsp"]) au_teaspoon = Unit( "5e-6", [ "US tsp (food nutrition labelling)", "metic teaspoon", "metric tsp", "Australian tsp", ], ) oil_barrel = Unit("158.987294928e-3", ["oil bbl", "bbl"]) acre_in = Unit( "102.790153128960", ["ac in", "ac-in", "acre inches", "acre inch", "acre-inches", "acre-inch"], ) acre_ft = Unit( "1233.481837547520", ["ac ft", "ac-ft", "acre feet", "acre foot", "acre-feet", "acre-foot"], ) @classmethod def _attr_to_unit(cls, name): if name[:6] in ["cubic_", "cubic "]: name = f"{name[6:]}³" return super()._attr_to_unit(name) def __truediv__(self, other): if isinstance(other, Distance): return Area(sq_metre=self.si_value / other.si_value) if isinstance(other, Area): return Distance(metre=self.si_value / other.si_value) return super().__truediv__(other)
def cubic(klass): for name, unit in klass._units.items(): qs_unit = Unit(factor=unit.factor ** 3) qs_unit.name = f"{qs_unit.name}³" yield f"{name}³", qs_unit
def test_to_si(self): assert Unit("1").to_si(decimal.Decimal("10")) == decimal.Decimal("10") assert Unit("10").to_si(decimal.Decimal("10")) == decimal.Decimal("100") assert Unit("1E-3").to_si(decimal.Decimal("10")) == decimal.Decimal("1E-2")
def test_post_init(self): inch = Unit("0.0254", ["in", "inches"]) assert inch.factor == decimal.Decimal("0.0254")