Revision 1462
Added by Aaron Marcuse-Kubitza almost 13 years ago
format.py | ||
---|---|---|
1 |
# Value to string conversion |
|
1 |
# Value to string conversion |
|
2 |
# This file's encoding must be UTF-8Y with BOM so Python will auto-detect UTF-8 |
|
2 | 3 |
|
3 | 4 |
import locale |
5 |
import re |
|
4 | 6 |
|
7 |
import strings |
|
8 |
import util |
|
9 |
|
|
5 | 10 |
locale.setlocale(locale.LC_ALL, '') # needed to initialize locale |
6 | 11 |
|
12 |
##### String parsing |
|
13 |
|
|
14 |
def clean_numeric(val): |
|
15 |
'''Removes embedded whitespace. e.g "1, 000"''' |
|
16 |
return re.sub(r'(?<=[,.]) +', r'', val) |
|
17 |
|
|
18 |
def str2int(val): return locale.atoi(clean_numeric(val)) |
|
19 |
|
|
20 |
def str2float(val): return locale.atof(clean_numeric(val)) |
|
21 |
|
|
22 |
##### Value formatting |
|
23 |
|
|
7 | 24 |
def format_str(format, val): |
8 | 25 |
return locale.format_string(format, val, grouping=True) |
9 | 26 |
|
10 | 27 |
def int2str(val): return format_str('%d', val) |
11 | 28 |
|
29 |
def float2str(val): return format_str('%f', val) |
|
30 |
|
|
12 | 31 |
def to_percent(val, sig_figs=2): |
13 | 32 |
if val >= 1: sig_figs += 1 |
14 | 33 |
return format_str('%#.'+str(sig_figs)+'g', val*100)+'%' |
... | ... | |
18 | 37 |
prefix = '' |
19 | 38 |
if val < 1: prefix = 'm'; val *= 1000 |
20 | 39 |
return format_str('%#.'+str(sig_figs)+'g', val)+' '+prefix |
40 |
|
|
41 |
##### Units |
|
42 |
|
|
43 |
class MissingUnitsException(Exception): |
|
44 |
def __init__(self, value): |
|
45 |
Exception.__init__(self, 'Value has no units: '+value) |
|
46 |
|
|
47 |
def std_units(units): |
|
48 |
if units == None: return units |
|
49 |
else: return strings.remove_suffix('.', units) # for abbr ending in '.' |
|
50 |
# TODO: deal with '"° and abbrs |
|
51 |
|
|
52 |
def parse_units(value): |
|
53 |
'''@return tuple (number float, units str|None)''' |
|
54 |
number = value |
|
55 |
units = None |
|
56 |
if not value.isdigit(): # optimization to avoid regexp for simple cases |
|
57 |
match = re.match(ur'(?i)^\s*(.*?\d\.?)\s*([a-z\'"°][\w.*/^-]*?)?\s*$', |
|
58 |
value) |
|
59 |
if match: # has units |
|
60 |
number, units = match.groups() |
|
61 |
units = std_units(util.none_if(units, u'')) |
|
62 |
return (str2float(number), units) |
|
63 |
|
|
64 |
def cleanup_units(value, default_units=None): |
|
65 |
'''Cleans up units so the number is separated from the units by one space. |
|
66 |
@param default_units Units to add if value has no units. If None, raises |
|
67 |
MissingUnitsException if value has no units. |
|
68 |
''' |
|
69 |
number, units = parse_units(value) |
|
70 |
if units == None: |
|
71 |
if default_units != None: units = default_units |
|
72 |
else: raise MissingUnitsException(value) |
|
73 |
return str(number)+' '+units |
Also available in: Unified diff
format.py: Added clean_numeric(), str2int(), str2float(). Added units-related functions. Added documentation labels to each section.