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 |