Project

General

Profile

1 1468 aaronmk
# Quantities with units
2
# This file's encoding must be UTF-8Y with BOM so Python will auto-detect UTF-8
3
4
import re
5
6
import format
7
import strings
8
import util
9
10
class MissingUnitsException(Exception):
11 1476 aaronmk
    def __init__(self, quantity):
12
        Exception.__init__(self, 'Quantity has no units: '+quantity)
13 1468 aaronmk
14
def std_units(units):
15
    if units == None: return units
16
    else: return strings.remove_suffix('.', units) # for abbr ending in '.'
17
    # TODO: deal with '"° and abbrs
18
19 1471 aaronmk
class Quantity:
20
    def __init__(self, value='', units=None):
21
        self.value = value
22
        self.units = std_units(util.none_if(units, u''))
23
24
def quantity2str(quantity):
25
    str_ = quantity.value
26
    if quantity.units != None: str_ += ' '+quantity.units
27
    return str_
28
29
Quantity.__str__ = quantity2str
30
31
def str2quantity(str_):
32
    value = str_
33 1468 aaronmk
    units = None
34 1471 aaronmk
    if not str_.isdigit(): # optimization to avoid regexp for simple cases
35 1468 aaronmk
        match = re.match(ur'(?i)^\s*(.*?\d\.?)\s*([a-z\'"°][\w.*/^-]*?)?\s*$',
36 1471 aaronmk
            str_)
37
        if match: value, units = match.groups() # has units
38
    return Quantity(value, units)
39 1468 aaronmk
40 1471 aaronmk
def set_default_units(quantity, units):
41
    if quantity.units == None: quantity.units = units
42
43
def convert(quantity, units):
44
    units = std_units(units)
45
    if units == None: return Quantity(quantity.value, units) # remove units
46 1476 aaronmk
    elif quantity.units == units: return quantity # units already correct
47
    elif quantity.units == None: raise MissingUnitsException(quantity)
48
        # can't convert quantity with unknown units
49 1471 aaronmk
    else: raise NotImplementedError('Unit conversion not implemented yet')