-
-
Notifications
You must be signed in to change notification settings - Fork 84
/
Copy pathmarshallers.py
116 lines (93 loc) · 3.08 KB
/
marshallers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Copyright 2018 Simone Orsi
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
import html
def marshal_request_values(values):
"""Transform given request values using marshallers.
Available marshallers:
* `:int` transform to integer
* `:float` transform to float
* `:list` transform to list of values
* `:dict` transform to dictionary of values
"""
# TODO: add docs
# TODO: support combinations like `:list:int` or `:dict:int`
res = {}
for k, v in values.items():
if k in ("csrf_token",):
continue
if k.endswith(":esc"):
k, v = marshal_esc(values, k, v)
res[k] = v
continue
# fields w/ multiple values
if k.endswith(":list"):
k, v = marshal_list(values, k, v)
res[k] = v
continue
if k.endswith(":dict"):
k, v = marshal_dict(values, k, v)
res[k] = v
continue
if k.endswith(":int"):
k, v = marshal_int(values, k, v)
res[k] = v
continue
if k.endswith(":float"):
k, v = marshal_float(values, k, v)
res[k] = v
continue
res[k] = v
return res
def marshal_esc(values, orig_key, orig_value):
"""Transform `foo:esc` inputs to escaped value."""
k = orig_key[: -len(":esc")]
v = html.escape(orig_value)
return k, v
def marshal_list(values, orig_key, orig_value):
"""Transform `foo:list` inputs to list of values."""
k = orig_key[: -len(":list")]
v = values.getlist(orig_key)
return k, v
def marshal_int(values, orig_key, orig_value):
"""Transform `foo:int` inputs to integer values."""
k = orig_key[: -len(":int")]
v = int(orig_value) if orig_value and orig_value.isdigit() else orig_value
return k, v
def marshal_float(values, orig_key, orig_value):
"""Transform `foo:float` inputs to float values."""
k = orig_key[: -len(":float")]
try:
v = float(orig_value.replace(",", "."))
except (ValueError, TypeError):
v = orig_value
return k, v
def marshal_dict(values, orig_key, orig_value):
"""Transform `foo:dict` inputs to dictionary values.
`orig_key` must be formatted like:
`$fname.$dict_key:dict`
Every request key matching `$fname` prefix
will be merged into a dict whereas keys will match all `$dict_key`.
Example:
values = [
('foo.a:dict', '1'),
('foo.b:dict', '2'),
('foo.c:dict', '3'),
]
will be translated to:
values['foo'] = {
'a': '1',
'b': '2',
'c': '3',
}
"""
res = {}
key = orig_key.split(".")[0]
for _k, _v in values.items():
# get all the keys matching fname
if not _k.startswith(key):
continue
# TODO: `__` will be to support extra marshallers, like:
# foo.1:dict:int -> get a dictionary w/ integer values
full_key, _, __ = _k.partition(":dict")
res[full_key.split(".")[-1]] = _v
return key, res