| """ |
| |
| uritemplate.template |
| ==================== |
| |
| This module contains the essential inner workings of uritemplate. |
| |
| What treasures await you: |
| |
| - URITemplate class |
| |
| You see a treasure chest of knowledge in front of you. |
| What do you do? |
| > |
| |
| """ |
| |
| import re |
| from uritemplate.variable import URIVariable |
| |
| template_re = re.compile('{([^\}]+)}') |
| |
| |
| def _merge(var_dict, overrides): |
| if var_dict: |
| opts = var_dict.copy() |
| opts.update(overrides) |
| return opts |
| return overrides |
| |
| |
| class URITemplate(object): |
| |
| """This parses the template and will be used to expand it. |
| |
| This is the most important object as the center of the API. |
| |
| Example:: |
| |
| from uritemplate import URITemplate |
| import requests |
| |
| |
| t = URITemplate( |
| 'https://api.github.com/users/sigmavirus24/gists{/gist_id}' |
| ) |
| uri = t.expand(gist_id=123456) |
| resp = requests.get(uri) |
| for gist in resp.json(): |
| print(gist['html_url']) |
| |
| Please note:: |
| |
| str(t) |
| # 'https://api.github.com/users/sigmavirus24/gists{/gistid}' |
| repr(t) # is equivalent to |
| # URITemplate(str(t)) |
| # Where str(t) is interpreted as the URI string. |
| |
| Also, ``URITemplates`` are hashable so they can be used as keys in |
| dictionaries. |
| |
| """ |
| |
| def __init__(self, uri): |
| #: The original URI to be parsed. |
| self.uri = uri |
| #: A list of the variables in the URI. They are stored as |
| #: :class:`URIVariable`\ s |
| self.variables = [ |
| URIVariable(m.groups()[0]) for m in template_re.finditer(self.uri) |
| ] |
| #: A set of variable names in the URI. |
| self.variable_names = set() |
| for variable in self.variables: |
| self.variable_names.update(variable.variable_names) |
| |
| def __repr__(self): |
| return 'URITemplate("%s")' % self |
| |
| def __str__(self): |
| return self.uri |
| |
| def __eq__(self, other): |
| return self.uri == other.uri |
| |
| def __hash__(self): |
| return hash(self.uri) |
| |
| def _expand(self, var_dict, replace): |
| if not self.variables: |
| return self.uri |
| |
| expansion = var_dict |
| expanded = {} |
| for v in self.variables: |
| expanded.update(v.expand(expansion)) |
| |
| def replace_all(match): |
| return expanded.get(match.groups()[0], '') |
| |
| def replace_partial(match): |
| match = match.groups()[0] |
| var = '{%s}' % match |
| return expanded.get(match) or var |
| |
| replace = replace_partial if replace else replace_all |
| |
| return template_re.sub(replace, self.uri) |
| |
| def expand(self, var_dict=None, **kwargs): |
| """Expand the template with the given parameters. |
| |
| :param dict var_dict: Optional dictionary with variables and values |
| :param kwargs: Alternative way to pass arguments |
| :returns: str |
| |
| Example:: |
| |
| t = URITemplate('https://api.github.com{/end}') |
| t.expand({'end': 'users'}) |
| t.expand(end='gists') |
| |
| .. note:: Passing values by both parts, may override values in |
| ``var_dict``. For example:: |
| |
| expand('https://{var}', {'var': 'val1'}, var='val2') |
| |
| ``val2`` will be used instead of ``val1``. |
| |
| """ |
| return self._expand(_merge(var_dict, kwargs), False) |
| |
| def partial(self, var_dict=None, **kwargs): |
| """Partially expand the template with the given parameters. |
| |
| If all of the parameters for the template are not given, return a |
| partially expanded template. |
| |
| :param dict var_dict: Optional dictionary with variables and values |
| :param kwargs: Alternative way to pass arguments |
| :returns: :class:`URITemplate` |
| |
| Example:: |
| |
| t = URITemplate('https://api.github.com{/end}') |
| t.partial() # => URITemplate('https://api.github.com{/end}') |
| |
| """ |
| return URITemplate(self._expand(_merge(var_dict, kwargs), True)) |