29
def _make_dict(data, is_params=False):
30
"""If is_params is True then generates a TinyDict otherwise generates a valid
31
dictionary from the given data to be used with OpenERP.
33
@param data: data in the form of {'a': 1, 'b/x': 1, 'b/y': 2}
34
@param is_params: if True generate TinyDict instead of standard dict
36
@return: TinyDict or dict
29
crummy_pseudoliteral_matcher = re.compile('^(True|False|None|-?\d+(\.\d+)?|\[.*?\]|\(.*?\)|\{.*?\})$', re.M)
32
"""contextmanager that prevent TinyDict from doing evals"""
33
def __init__(self, d):
36
self.d.set_config_noeval(True)
38
def __exit__(self, exc_type, exc_val, exc_tb):
39
self.d.set_config_noeval(False)
40
return False # propage exception if any
43
"""A dictionary class that allows accessing it's items as it's attributes.
44
It also converts stringified Boolean, None, Number or secuence to python object.
45
This class is mainly used by Controllers to get special `_terp_` arguments and
46
to generate valid dictionary of data fields from the controller keyword arguments.
39
def make_dict_internal(data, is_params=False, previous_dict_ids=None):
48
__config_noeval = False
50
def __init__(self, **kwargs):
51
super(TinyDict, self).__init__()
52
for k, v in kwargs.items():
53
if (isinstance(v, dict) and not isinstance(v, TinyDict)):
57
def get_config_noeval(self):
58
return self._TinyDict__config_noeval
60
def set_config_noeval(self, value):
61
dict.__setattr__(self, '_TinyDict__config_noeval', value)
62
# recursively propagate the new value
63
for v in self.itervalues():
64
if isinstance(v, TinyDict):
65
v.set_config_noeval(value)
67
def build_new(self, is_params=True):
70
new_dict = type(self)()
71
# propagate noeval config flag
72
new_dict.set_config_noeval(self.get_config_noeval())
75
def build_dict(self, data, is_params=False, previous_dict_ids=None):
76
"""If is_params is True then generates a TinyDict otherwise generates a valid
77
dictionary from the given data to be used with OpenERP.
79
@param data: data in the form of {'a': 1, 'b/x': 1, 'b/y': 2}
80
@param is_params: if True generate TinyDict instead of standard dict
81
@param previous_dict_ids: set of dict instance to avoid recursion
83
@return: TinyDict or dict
85
if previous_dict_ids is None:
86
previous_dict_ids = set()
40
88
if id(data) in previous_dict_ids:
41
raise ValueError("Recursive dictionary detected, _make_dict does not handle recursive dictionaries.")
89
raise ValueError("Recursive dictionary detected, build_dict does not handle recursive dictionaries.")
42
90
previous_dict_ids.add(id(data))
44
res = (is_params or {}) and TinyDict()
92
res = self.build_new(is_params)
46
94
for name, value in data.items():
66
114
_id = v.pop('__id') or 0
69
values = _make_dict(v, is_params)
117
# build new dict without keeping previous_dict_ids references
118
values = self.build_dict(v, is_params, previous_dict_ids=None)
70
119
if values and any(values.itervalues()):
71
120
res[k] = [(_id and 1, _id, values)]
76
res[k] = make_dict_internal(v, is_params and isinstance(v, TinyDict), previous_dict_ids)
125
res[k] = self.build_dict(v, is_params and isinstance(v, TinyDict), previous_dict_ids)
78
127
previous_dict_ids.remove(id(data))
81
return make_dict_internal(data, is_params, set())
84
crummy_pseudoliteral_matcher = re.compile('^(True|False|None|-?\d+(\.\d+)?|\[.*?\]|\(.*?\)|\{.*?\})$', re.M)
86
"""A dictionary class that allows accessing it's items as it's attributes.
87
It also converts stringified Boolean, None, Number or secuence to python object.
88
This class is mainly used by Controllers to get special `_terp_` arguments and
89
to generate valid dictionary of data fields from the controller keyword arguments.
92
def __init__(self, **kwargs):
93
super(TinyDict, self).__init__()
95
for k, v in kwargs.items():
96
if (isinstance(v, dict) and not isinstance(v, TinyDict)):
100
130
def _eval(self, value):
131
if self.get_config_noeval():
132
# current behaviour is to store raw value without evaluating them
102
135
if isinstance(value, list):
103
136
for i, v in enumerate(value):
320
357
raise TinyFormError(name.replace('_terp_form/', ''), e.msg, e.value)
322
359
# Prevent auto conversion from TinyDict
323
_eval = TinyDict._eval
324
TinyDict._eval = lambda self, v: v
327
params, data = TinyDict.split(kw)
360
with noeval(TinyDict()) as converted_dict:
361
params, data = converted_dict.split_dict(kw)
328
362
params = params.form or {}
330
return TinyDict(**params)
333
TinyDict._eval = _eval
363
converted_dict.update(**params)
364
return converted_dict
335
366
def from_python(self):
336
367
return self._convert(False)