|
|
|
import pint
|
|
|
|
|
|
|
|
|
|
|
|
class ConverterError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class Converter(object):
|
|
|
|
def __init__(self):
|
|
|
|
self.ureg = pint.UnitRegistry(autoconvert_offset_to_baseunit=True)
|
|
|
|
self.ureg.define('degreeC = kelvin; offset: 273.15 = °C = C')
|
|
|
|
self.ureg.define('degreeF = 5 / 9 * kelvin; offset: 255.372222 = °F = F')
|
|
|
|
self.default_units = {
|
|
|
|
self.ureg.degC: self.ureg.degreeF,
|
|
|
|
self.ureg.degreeC: self.ureg.degreeF,
|
|
|
|
self.ureg.degF: self.ureg.degreeC,
|
|
|
|
self.ureg.degreeF: self.ureg.degreeC,
|
|
|
|
self.ureg.kilometer: self.ureg.mile,
|
|
|
|
self.ureg.meter: self.ureg.foot,
|
|
|
|
self.ureg.centimeter: self.ureg.inch,
|
|
|
|
self.ureg.millimeter: self.ureg.inch,
|
|
|
|
self.ureg.mile: self.ureg.kilometer,
|
|
|
|
self.ureg.foot: self.ureg.meter,
|
|
|
|
self.ureg.inch: self.ureg.millimeter,
|
|
|
|
self.ureg.kilogram: self.ureg.pound,
|
|
|
|
self.ureg.pound: self.ureg.kilogram,
|
|
|
|
self.ureg.ounce: self.ureg.kilogram,
|
|
|
|
self.ureg.liter: self.ureg.gallon,
|
|
|
|
self.ureg.milliliter: self.ureg.floz,
|
|
|
|
self.ureg.gallon: self.ureg.liter,
|
|
|
|
self.ureg.floz: self.ureg.milliliter,
|
|
|
|
}
|
|
|
|
|
|
|
|
def update_currencies(self, base, rates):
|
|
|
|
self.ureg.define('{0} = [currency]'.format(base))
|
|
|
|
for currency, rate in rates.items():
|
|
|
|
self.ureg.define('{0} = {1} / {2}'.format(currency, base, rate))
|
|
|
|
|
|
|
|
def convert(self, expression, unit=None):
|
|
|
|
try:
|
|
|
|
q = self.ureg.parse_expression(expression)
|
|
|
|
except pint.errors.UndefinedUnitError:
|
|
|
|
raise ConverterError('unknown units')
|
|
|
|
try:
|
|
|
|
q.units
|
|
|
|
except AttributeError:
|
|
|
|
if unit is not None:
|
|
|
|
q = self.ureg.parse_expression(expression + unit)
|
|
|
|
unit = None
|
|
|
|
else:
|
|
|
|
raise ConverterError('unknown units')
|
|
|
|
try:
|
|
|
|
q.units
|
|
|
|
except AttributeError:
|
|
|
|
raise ConverterError('unknown units')
|
|
|
|
if unit is not None:
|
|
|
|
try:
|
|
|
|
u = self.ureg.parse_units(unit)
|
|
|
|
except pint.errors.UndefinedUnitError:
|
|
|
|
raise ConverterError('unknown units')
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
u = self.default_units[q.units]
|
|
|
|
except KeyError:
|
|
|
|
raise ConverterError('no target units specified')
|
|
|
|
try:
|
|
|
|
result = q.to(u)
|
|
|
|
except pint.errors.DimensionalityError:
|
|
|
|
raise ConverterError('invalid conversion')
|
|
|
|
return '{:0.5g~P}'.format(result)
|