Better None-handling in convert and propertyeditor
[hooke.git] / hooke / util / convert.py
1 # Copyright
2
3 """Type conversion utilities.
4 """
5
6
7 ANALOGS = {
8     'file': 'string',
9     'path': 'string',
10     'point': 'int',
11     }
12 """Types that may be treated as other types.
13
14 These types may have optional special handling on the UI end
15 (e.g. file picker dialogs), but it is not required.
16 """
17
18 RAW_TYPES = [
19     'curve',
20     'dict',
21     'driver',
22     'function',
23     'object',
24     'playlist',
25     ]
26 """List of types that should not be converted.
27 """
28
29 def to_string(value, type, count=1):
30     """Convert `value` from `type` to a unicode string.
31     """
32     type = ANALOGS.get(type, type)
33     if type in RAW_TYPES:
34         return value
35     if count != 1:
36         values = [to_string(v, type) for v in value]
37         return '[%s]' % ', '.join(values)
38     return unicode(value)
39
40 def from_string(value, type, count=1):
41     """Convert `value` from a string to `type`.
42
43     Examples
44     --------
45     >>> from_string('abcde', type='string')
46     u'abcde'
47     >>> from_string('None', type='string')
48     >>> from_string(None, type='string')
49     >>> from_string('true', type='bool')
50     True
51     >>> from_string('false', type='bool')
52     False
53     >>> from_string(None, type='bool')
54     False
55     >>> from_string('123', type='int')
56     123
57     >>> from_string('123', type='float')
58     123.0
59     """
60     type = ANALOGS.get(type, type)
61     if type in RAW_TYPES:
62         return value
63     fn = globals()['_string_to_%s' % type]
64     if count != 1:
65         assert value.startswith('[') and value.endswith(']'), value
66         value = value[1:-1]  # strip off brackets
67         values = [from_string(v, type) for v in value.split(', ')]
68         assert count == -1 or len(values) == count, (
69             'array with %d != %d values: %s'
70             % (len(values), count, values))
71         return values
72     return fn(value)
73
74 def _string_to_string(value):
75     if value in [None, 'None'] or len(value) == 0:
76         return None
77     return unicode(value)
78
79 def _string_to_bool(value):
80     return hasattr(value, 'lower') and value.lower() == 'true'
81
82 def _string_to_int(value):
83     if value in [None, 'None']:
84         return None
85     return int(value)
86
87 def _string_to_float(value):
88     if value in [None, 'None']:
89         return None
90     return float(value)