1""" 2 3uritemplate.template 4==================== 5 6This module contains the essential inner workings of uritemplate. 7 8What treasures await you: 9 10- URITemplate class 11 12You see a treasure chest of knowledge in front of you. 13What do you do? 14> 15 16""" 17 18import re 19from uritemplate.variable import URIVariable 20 21template_re = re.compile('{([^\}]+)}') 22 23 24def _merge(var_dict, overrides): 25 if var_dict: 26 opts = var_dict.copy() 27 opts.update(overrides) 28 return opts 29 return overrides 30 31 32class URITemplate(object): 33 34 """This parses the template and will be used to expand it. 35 36 This is the most important object as the center of the API. 37 38 Example:: 39 40 from uritemplate import URITemplate 41 import requests 42 43 44 t = URITemplate( 45 'https://api.github.com/users/sigmavirus24/gists{/gist_id}' 46 ) 47 uri = t.expand(gist_id=123456) 48 resp = requests.get(uri) 49 for gist in resp.json(): 50 print(gist['html_url']) 51 52 Please note:: 53 54 str(t) 55 # 'https://api.github.com/users/sigmavirus24/gists{/gistid}' 56 repr(t) # is equivalent to 57 # URITemplate(str(t)) 58 # Where str(t) is interpreted as the URI string. 59 60 Also, ``URITemplates`` are hashable so they can be used as keys in 61 dictionaries. 62 63 """ 64 65 def __init__(self, uri): 66 #: The original URI to be parsed. 67 self.uri = uri 68 #: A list of the variables in the URI. They are stored as 69 #: :class:`URIVariable`\ s 70 self.variables = [ 71 URIVariable(m.groups()[0]) for m in template_re.finditer(self.uri) 72 ] 73 #: A set of variable names in the URI. 74 self.variable_names = set() 75 for variable in self.variables: 76 self.variable_names.update(variable.variable_names) 77 78 def __repr__(self): 79 return 'URITemplate("%s")' % self 80 81 def __str__(self): 82 return self.uri 83 84 def __eq__(self, other): 85 return self.uri == other.uri 86 87 def __hash__(self): 88 return hash(self.uri) 89 90 def _expand(self, var_dict, replace): 91 if not self.variables: 92 return self.uri 93 94 expansion = var_dict 95 expanded = {} 96 for v in self.variables: 97 expanded.update(v.expand(expansion)) 98 99 def replace_all(match): 100 return expanded.get(match.groups()[0], '') 101 102 def replace_partial(match): 103 match = match.groups()[0] 104 var = '{%s}' % match 105 return expanded.get(match) or var 106 107 replace = replace_partial if replace else replace_all 108 109 return template_re.sub(replace, self.uri) 110 111 def expand(self, var_dict=None, **kwargs): 112 """Expand the template with the given parameters. 113 114 :param dict var_dict: Optional dictionary with variables and values 115 :param kwargs: Alternative way to pass arguments 116 :returns: str 117 118 Example:: 119 120 t = URITemplate('https://api.github.com{/end}') 121 t.expand({'end': 'users'}) 122 t.expand(end='gists') 123 124 .. note:: Passing values by both parts, may override values in 125 ``var_dict``. For example:: 126 127 expand('https://{var}', {'var': 'val1'}, var='val2') 128 129 ``val2`` will be used instead of ``val1``. 130 131 """ 132 return self._expand(_merge(var_dict, kwargs), False) 133 134 def partial(self, var_dict=None, **kwargs): 135 """Partially expand the template with the given parameters. 136 137 If all of the parameters for the template are not given, return a 138 partially expanded template. 139 140 :param dict var_dict: Optional dictionary with variables and values 141 :param kwargs: Alternative way to pass arguments 142 :returns: :class:`URITemplate` 143 144 Example:: 145 146 t = URITemplate('https://api.github.com{/end}') 147 t.partial() # => URITemplate('https://api.github.com{/end}') 148 149 """ 150 return URITemplate(self._expand(_merge(var_dict, kwargs), True)) 151