Index: third_party/uritemplate/uritemplate/__init__.py |
diff --git a/third_party/uritemplate/uritemplate/__init__.py b/third_party/uritemplate/uritemplate/__init__.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..712405d42d7710193ee9d118400cf8e9daaecf89 |
--- /dev/null |
+++ b/third_party/uritemplate/uritemplate/__init__.py |
@@ -0,0 +1,265 @@ |
+#!/usr/bin/env python |
+ |
+""" |
+URI Template (RFC6570) Processor |
+""" |
+ |
+__copyright__ = """\ |
+Copyright 2011-2013 Joe Gregorio |
+ |
+Licensed under the Apache License, Version 2.0 (the "License"); |
+you may not use this file except in compliance with the License. |
+You may obtain a copy of the License at |
+ |
+ http://www.apache.org/licenses/LICENSE-2.0 |
+ |
+Unless required by applicable law or agreed to in writing, software |
+distributed under the License is distributed on an "AS IS" BASIS, |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+See the License for the specific language governing permissions and |
+limitations under the License. |
+""" |
+ |
+import re |
+try: |
+ from urllib.parse import quote |
+except ImportError: |
+ from urllib import quote |
+ |
+ |
+ |
+__version__ = "0.6" |
+ |
+RESERVED = ":/?#[]@!$&'()*+,;=" |
+OPERATOR = "+#./;?&|!@" |
+MODIFIER = ":^" |
+TEMPLATE = re.compile("{([^\}]+)}") |
+ |
+ |
+def variables(template): |
+ '''Returns the set of keywords in a uri template''' |
+ vars = set() |
+ for varlist in TEMPLATE.findall(template): |
+ if varlist[0] in OPERATOR: |
+ varlist = varlist[1:] |
+ varspecs = varlist.split(',') |
+ for var in varspecs: |
+ # handle prefix values |
+ var = var.split(':')[0] |
+ # handle composite values |
+ if var.endswith('*'): |
+ var = var[:-1] |
+ vars.add(var) |
+ return vars |
+ |
+ |
+def _quote(value, safe, prefix=None): |
+ if prefix is not None: |
+ return quote(str(value)[:prefix], safe) |
+ return quote(str(value), safe) |
+ |
+ |
+def _tostring(varname, value, explode, prefix, operator, safe=""): |
+ if isinstance(value, list): |
+ return ",".join([_quote(x, safe) for x in value]) |
+ if isinstance(value, dict): |
+ keys = sorted(value.keys()) |
+ if explode: |
+ return ",".join([_quote(key, safe) + "=" + \ |
+ _quote(value[key], safe) for key in keys]) |
+ else: |
+ return ",".join([_quote(key, safe) + "," + \ |
+ _quote(value[key], safe) for key in keys]) |
+ elif value is None: |
+ return |
+ else: |
+ return _quote(value, safe, prefix) |
+ |
+ |
+def _tostring_path(varname, value, explode, prefix, operator, safe=""): |
+ joiner = operator |
+ if isinstance(value, list): |
+ if explode: |
+ out = [_quote(x, safe) for x in value if value is not None] |
+ else: |
+ joiner = "," |
+ out = [_quote(x, safe) for x in value if value is not None] |
+ if out: |
+ return joiner.join(out) |
+ else: |
+ return |
+ elif isinstance(value, dict): |
+ keys = sorted(value.keys()) |
+ if explode: |
+ out = [_quote(key, safe) + "=" + \ |
+ _quote(value[key], safe) for key in keys \ |
+ if value[key] is not None] |
+ else: |
+ joiner = "," |
+ out = [_quote(key, safe) + "," + \ |
+ _quote(value[key], safe) \ |
+ for key in keys if value[key] is not None] |
+ if out: |
+ return joiner.join(out) |
+ else: |
+ return |
+ elif value is None: |
+ return |
+ else: |
+ return _quote(value, safe, prefix) |
+ |
+ |
+def _tostring_semi(varname, value, explode, prefix, operator, safe=""): |
+ joiner = operator |
+ if operator == "?": |
+ joiner = "&" |
+ if isinstance(value, list): |
+ if explode: |
+ out = [varname + "=" + _quote(x, safe) \ |
+ for x in value if x is not None] |
+ if out: |
+ return joiner.join(out) |
+ else: |
+ return |
+ else: |
+ return varname + "=" + ",".join([_quote(x, safe) \ |
+ for x in value]) |
+ elif isinstance(value, dict): |
+ keys = sorted(value.keys()) |
+ if explode: |
+ return joiner.join([_quote(key, safe) + "=" + \ |
+ _quote(value[key], safe) \ |
+ for key in keys if key is not None]) |
+ else: |
+ return varname + "=" + ",".join([_quote(key, safe) + "," + \ |
+ _quote(value[key], safe) for key in keys \ |
+ if key is not None]) |
+ else: |
+ if value is None: |
+ return |
+ elif value: |
+ return (varname + "=" + _quote(value, safe, prefix)) |
+ else: |
+ return varname |
+ |
+ |
+def _tostring_query(varname, value, explode, prefix, operator, safe=""): |
+ joiner = operator |
+ if operator in ["?", "&"]: |
+ joiner = "&" |
+ if isinstance(value, list): |
+ if 0 == len(value): |
+ return None |
+ if explode: |
+ return joiner.join([varname + "=" + _quote(x, safe) \ |
+ for x in value]) |
+ else: |
+ return (varname + "=" + ",".join([_quote(x, safe) \ |
+ for x in value])) |
+ elif isinstance(value, dict): |
+ if 0 == len(value): |
+ return None |
+ keys = sorted(value.keys()) |
+ if explode: |
+ return joiner.join([_quote(key, safe) + "=" + \ |
+ _quote(value[key], safe) \ |
+ for key in keys]) |
+ else: |
+ return varname + "=" + \ |
+ ",".join([_quote(key, safe) + "," + \ |
+ _quote(value[key], safe) for key in keys]) |
+ else: |
+ if value is None: |
+ return |
+ elif value: |
+ return (varname + "=" + _quote(value, safe, prefix)) |
+ else: |
+ return (varname + "=") |
+ |
+ |
+TOSTRING = { |
+ "" : _tostring, |
+ "+": _tostring, |
+ "#": _tostring, |
+ ";": _tostring_semi, |
+ "?": _tostring_query, |
+ "&": _tostring_query, |
+ "/": _tostring_path, |
+ ".": _tostring_path, |
+ } |
+ |
+ |
+def expand(template, variables): |
+ """ |
+ Expand template as a URI Template using variables. |
+ """ |
+ def _sub(match): |
+ expression = match.group(1) |
+ operator = "" |
+ if expression[0] in OPERATOR: |
+ operator = expression[0] |
+ varlist = expression[1:] |
+ else: |
+ varlist = expression |
+ |
+ safe = "" |
+ if operator in ["+", "#"]: |
+ safe = RESERVED |
+ varspecs = varlist.split(",") |
+ varnames = [] |
+ defaults = {} |
+ for varspec in varspecs: |
+ default = None |
+ explode = False |
+ prefix = None |
+ if "=" in varspec: |
+ varname, default = tuple(varspec.split("=", 1)) |
+ else: |
+ varname = varspec |
+ if varname[-1] == "*": |
+ explode = True |
+ varname = varname[:-1] |
+ elif ":" in varname: |
+ try: |
+ prefix = int(varname[varname.index(":")+1:]) |
+ except ValueError: |
+ raise ValueError("non-integer prefix '{0}'".format( |
+ varname[varname.index(":")+1:])) |
+ varname = varname[:varname.index(":")] |
+ if default: |
+ defaults[varname] = default |
+ varnames.append((varname, explode, prefix)) |
+ |
+ retval = [] |
+ joiner = operator |
+ start = operator |
+ if operator == "+": |
+ start = "" |
+ joiner = "," |
+ if operator == "#": |
+ joiner = "," |
+ if operator == "?": |
+ joiner = "&" |
+ if operator == "&": |
+ start = "&" |
+ if operator == "": |
+ joiner = "," |
+ for varname, explode, prefix in varnames: |
+ if varname in variables: |
+ value = variables[varname] |
+ if not value and value != "" and varname in defaults: |
+ value = defaults[varname] |
+ elif varname in defaults: |
+ value = defaults[varname] |
+ else: |
+ continue |
+ expanded = TOSTRING[operator]( |
+ varname, value, explode, prefix, operator, safe=safe) |
+ if expanded is not None: |
+ retval.append(expanded) |
+ if len(retval) > 0: |
+ return start + joiner.join(retval) |
+ else: |
+ return "" |
+ |
+ return TEMPLATE.sub(_sub, template) |