OLD | NEW |
| (Empty) |
1 # Early, and incomplete implementation of -04. | |
2 # | |
3 import re | |
4 import urllib | |
5 | |
6 RESERVED = ":/?#[]@!$&'()*+,;=" | |
7 OPERATOR = "+./;?|!@" | |
8 EXPLODE = "*+" | |
9 MODIFIER = ":^" | |
10 TEMPLATE = re.compile(r"{(?P<operator>[\+\./;\?|!@])?(?P<varlist>[^}]+)}", re.UN
ICODE) | |
11 VAR = re.compile(r"^(?P<varname>[^=\+\*:\^]+)((?P<explode>[\+\*])|(?P<partial>[:
\^]-?[0-9]+))?(=(?P<default>.*))?$", re.UNICODE) | |
12 | |
13 def _tostring(varname, value, explode, operator, safe=""): | |
14 if type(value) == type([]): | |
15 if explode == "+": | |
16 return ",".join([varname + "." + urllib.quote(x, safe) for x in value]) | |
17 else: | |
18 return ",".join([urllib.quote(x, safe) for x in value]) | |
19 if type(value) == type({}): | |
20 keys = value.keys() | |
21 keys.sort() | |
22 if explode == "+": | |
23 return ",".join([varname + "." + urllib.quote(key, safe) + "," + urllib.qu
ote(value[key], safe) for key in keys]) | |
24 else: | |
25 return ",".join([urllib.quote(key, safe) + "," + urllib.quote(value[key],
safe) for key in keys]) | |
26 else: | |
27 return urllib.quote(value, safe) | |
28 | |
29 | |
30 def _tostring_path(varname, value, explode, operator, safe=""): | |
31 joiner = operator | |
32 if type(value) == type([]): | |
33 if explode == "+": | |
34 return joiner.join([varname + "." + urllib.quote(x, safe) for x in value]) | |
35 elif explode == "*": | |
36 return joiner.join([urllib.quote(x, safe) for x in value]) | |
37 else: | |
38 return ",".join([urllib.quote(x, safe) for x in value]) | |
39 elif type(value) == type({}): | |
40 keys = value.keys() | |
41 keys.sort() | |
42 if explode == "+": | |
43 return joiner.join([varname + "." + urllib.quote(key, safe) + joiner + url
lib.quote(value[key], safe) for key in keys]) | |
44 elif explode == "*": | |
45 return joiner.join([urllib.quote(key, safe) + joiner + urllib.quote(value[
key], safe) for key in keys]) | |
46 else: | |
47 return ",".join([urllib.quote(key, safe) + "," + urllib.quote(value[key],
safe) for key in keys]) | |
48 else: | |
49 if value: | |
50 return urllib.quote(value, safe) | |
51 else: | |
52 return "" | |
53 | |
54 def _tostring_query(varname, value, explode, operator, safe=""): | |
55 joiner = operator | |
56 varprefix = "" | |
57 if operator == "?": | |
58 joiner = "&" | |
59 varprefix = varname + "=" | |
60 if type(value) == type([]): | |
61 if 0 == len(value): | |
62 return "" | |
63 if explode == "+": | |
64 return joiner.join([varname + "=" + urllib.quote(x, safe) for x in value]) | |
65 elif explode == "*": | |
66 return joiner.join([urllib.quote(x, safe) for x in value]) | |
67 else: | |
68 return varprefix + ",".join([urllib.quote(x, safe) for x in value]) | |
69 elif type(value) == type({}): | |
70 if 0 == len(value): | |
71 return "" | |
72 keys = value.keys() | |
73 keys.sort() | |
74 if explode == "+": | |
75 return joiner.join([varname + "." + urllib.quote(key, safe) + "=" + urllib
.quote(value[key], safe) for key in keys]) | |
76 elif explode == "*": | |
77 return joiner.join([urllib.quote(key, safe) + "=" + urllib.quote(value[key
], safe) for key in keys]) | |
78 else: | |
79 return varprefix + ",".join([urllib.quote(key, safe) + "," + urllib.quote(
value[key], safe) for key in keys]) | |
80 else: | |
81 if value: | |
82 return varname + "=" + urllib.quote(value, safe) | |
83 else: | |
84 return varname | |
85 | |
86 TOSTRING = { | |
87 "" : _tostring, | |
88 "+": _tostring, | |
89 ";": _tostring_query, | |
90 "?": _tostring_query, | |
91 "/": _tostring_path, | |
92 ".": _tostring_path, | |
93 } | |
94 | |
95 | |
96 def expand(template, vars): | |
97 def _sub(match): | |
98 groupdict = match.groupdict() | |
99 operator = groupdict.get('operator') | |
100 if operator is None: | |
101 operator = '' | |
102 varlist = groupdict.get('varlist') | |
103 | |
104 safe = "@" | |
105 if operator == '+': | |
106 safe = RESERVED | |
107 varspecs = varlist.split(",") | |
108 varnames = [] | |
109 defaults = {} | |
110 for varspec in varspecs: | |
111 m = VAR.search(varspec) | |
112 groupdict = m.groupdict() | |
113 varname = groupdict.get('varname') | |
114 explode = groupdict.get('explode') | |
115 partial = groupdict.get('partial') | |
116 default = groupdict.get('default') | |
117 if default: | |
118 defaults[varname] = default | |
119 varnames.append((varname, explode, partial)) | |
120 | |
121 retval = [] | |
122 joiner = operator | |
123 prefix = operator | |
124 if operator == "+": | |
125 prefix = "" | |
126 joiner = "," | |
127 if operator == "?": | |
128 joiner = "&" | |
129 if operator == "": | |
130 joiner = "," | |
131 for varname, explode, partial in varnames: | |
132 if varname in vars: | |
133 value = vars[varname] | |
134 #if not value and (type(value) == type({}) or type(value) == type([])) a
nd varname in defaults: | |
135 if not value and value != "" and varname in defaults: | |
136 value = defaults[varname] | |
137 elif varname in defaults: | |
138 value = defaults[varname] | |
139 else: | |
140 continue | |
141 retval.append(TOSTRING[operator](varname, value, explode, operator, safe=s
afe)) | |
142 if "".join(retval): | |
143 return prefix + joiner.join(retval) | |
144 else: | |
145 return "" | |
146 | |
147 return TEMPLATE.sub(_sub, template) | |
OLD | NEW |