diff options
author | Haibo Huang <hhb@google.com> | 2020-01-07 14:06:28 -0800 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2020-01-07 14:06:28 -0800 |
commit | 5492dc4462f38ec23ff1cd58f66f8d19cd23f04b (patch) | |
tree | 6072009c262a4bd31720d0c97d20d3a5dbffbb0c /uritemplate | |
parent | b7137cc2f5b626d8d644ccd8866c4dab837bbd99 (diff) | |
parent | eab8cbc70cc7907afb0105d11ebf812aa99c11d0 (diff) | |
download | uritemplates-5492dc4462f38ec23ff1cd58f66f8d19cd23f04b.tar.gz |
Upgrade python/uritemplates to 3.0.1
am: eab8cbc70c
Change-Id: Ib1cf1d8c27befad71731abd470cb3eb7e73044ed
Diffstat (limited to 'uritemplate')
-rw-r--r-- | uritemplate/__init__.py | 2 | ||||
-rw-r--r-- | uritemplate/api.py | 4 | ||||
-rw-r--r-- | uritemplate/orderedset.py | 90 | ||||
-rw-r--r-- | uritemplate/template.py | 8 | ||||
-rw-r--r-- | uritemplate/variable.py | 42 |
5 files changed, 121 insertions, 25 deletions
diff --git a/uritemplate/__init__.py b/uritemplate/__init__.py index 40c0320..5352520 100644 --- a/uritemplate/__init__.py +++ b/uritemplate/__init__.py @@ -16,7 +16,7 @@ __title__ = 'uritemplate' __author__ = 'Ian Cordasco' __license__ = 'Modified BSD or Apache License, Version 2.0' __copyright__ = 'Copyright 2013 Ian Cordasco' -__version__ = '3.0.0' +__version__ = '3.0.1' __version_info__ = tuple(int(i) for i in __version__.split('.') if i.isdigit()) from uritemplate.api import ( diff --git a/uritemplate/api.py b/uritemplate/api.py index 37c7c45..5ad2815 100644 --- a/uritemplate/api.py +++ b/uritemplate/api.py @@ -6,6 +6,8 @@ uritemplate.api This module contains the very simple API provided by uritemplate. """ + +from uritemplate.orderedset import OrderedSet from uritemplate.template import URITemplate @@ -68,4 +70,4 @@ def variables(uri): # => {'username', 'repository'} """ - return set(URITemplate(uri).variable_names) + return OrderedSet(URITemplate(uri).variable_names) diff --git a/uritemplate/orderedset.py b/uritemplate/orderedset.py new file mode 100644 index 0000000..f21c9cb --- /dev/null +++ b/uritemplate/orderedset.py @@ -0,0 +1,90 @@ +# From: https://github.com/ActiveState/code/blob/master/recipes/Python/576696_OrderedSet_with_Weakrefs/ # noqa + +from weakref import proxy + +try: + import collections.abc as collections_abc +except ImportError: + import collections as collections_abc + + +class Link(object): + __slots__ = 'prev', 'next', 'key', '__weakref__' + + +class OrderedSet(collections_abc.MutableSet): + 'Set the remembers the order elements were added' + # Big-O running times for all methods are the same as for regular sets. + # The internal self.__map dictionary maps keys to links in a doubly linked + # list. The circular doubly linked list starts and ends with a sentinel + # element. The sentinel element never gets deleted (this simplifies the + # algorithm). The prev/next links are weakref proxies (to prevent circular + # references). Individual links are kept alive by the hard reference in + # self.__map. Those hard references disappear when a key is deleted from + # an OrderedSet. + + def __init__(self, iterable=None): + self.__root = root = Link() # sentinel node for doubly linked list + root.prev = root.next = root + self.__map = {} # key --> link + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.__map) + + def __contains__(self, key): + return key in self.__map + + def add(self, key): + # Store new key in a new link at the end of the linked list + if key not in self.__map: + self.__map[key] = link = Link() + root = self.__root + last = root.prev + link.prev, link.next, link.key = last, root, key + last.next = root.prev = proxy(link) + + def discard(self, key): + # Remove an existing item using self.__map to find the link which is + # then removed by updating the links in the predecessor and successors. + if key in self.__map: + link = self.__map.pop(key) + link.prev.next = link.next + link.next.prev = link.prev + + def __iter__(self): + # Traverse the linked list in order. + root = self.__root + curr = root.next + while curr is not root: + yield curr.key + curr = curr.next + + def __reversed__(self): + # Traverse the linked list in reverse order. + root = self.__root + curr = root.prev + while curr is not root: + yield curr.key + curr = curr.prev + + def pop(self, last=True): + if not self: + raise KeyError('set is empty') + key = next(reversed(self)) if last else next(iter(self)) + self.discard(key) + return key + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __str__(self): + return self.__repr__() + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return not self.isdisjoint(other) diff --git a/uritemplate/template.py b/uritemplate/template.py index c9d7c7e..0df0da6 100644 --- a/uritemplate/template.py +++ b/uritemplate/template.py @@ -16,9 +16,10 @@ What do you do? """ import re +from uritemplate.orderedset import OrderedSet from uritemplate.variable import URIVariable -template_re = re.compile('{([^\}]+)}') +template_re = re.compile('{([^}]+)}') def _merge(var_dict, overrides): @@ -71,9 +72,10 @@ class URITemplate(object): URIVariable(m.groups()[0]) for m in template_re.finditer(self.uri) ] #: A set of variable names in the URI. - self.variable_names = set() + self.variable_names = OrderedSet() for variable in self.variables: - self.variable_names.update(variable.variable_names) + for name in variable.variable_names: + self.variable_names.add(name) def __repr__(self): return 'URITemplate("%s")' % self diff --git a/uritemplate/variable.py b/uritemplate/variable.py index 1842830..ce3f652 100644 --- a/uritemplate/variable.py +++ b/uritemplate/variable.py @@ -15,12 +15,16 @@ What do you do? """ -import collections import sys -if (2, 6) <= sys.version_info < (2, 8): +try: + import collections.abc as collections_abc +except ImportError: + import collections as collections_abc + +if sys.version_info.major == 2: import urllib -elif (3, 3) <= sys.version_info < (4, 0): +elif sys.version_info.major == 3: import urllib.parse as urllib @@ -149,11 +153,11 @@ class URIVariable(object): return None if explode: return self.join_str.join( - '%s=%s' % (name, quote(v, safe)) for v in value + '{}={}'.format(name, quote(v, safe)) for v in value ) else: value = ','.join(quote(v, safe) for v in value) - return '%s=%s' % (name, value) + return '{}={}'.format(name, value) if dict_test(value) or tuples: if not value: @@ -161,21 +165,21 @@ class URIVariable(object): items = items or sorted(value.items()) if explode: return self.join_str.join( - '%s=%s' % ( + '{}={}'.format( quote(k, safe), quote(v, safe) ) for k, v in items ) else: value = ','.join( - '%s,%s' % ( + '{},{}'.format( quote(k, safe), quote(v, safe) ) for k, v in items ) - return '%s=%s' % (name, value) + return '{}={}'.format(name, value) if value: value = value[:prefix] if prefix else value - return '%s=%s' % (name, quote(value, safe)) + return '{}={}'.format(name, quote(value, safe)) return name + '=' def _label_path_expansion(self, name, value, explode, prefix): @@ -196,10 +200,8 @@ class URIVariable(object): if not explode: join_str = ',' - expanded = join_str.join( - quote(v, safe) for v in value if value is not None - ) - return expanded if expanded else None + fragments = [quote(v, safe) for v in value if v is not None] + return join_str.join(fragments) if fragments else None if dict_test(value) or tuples: items = items or sorted(value.items()) @@ -234,35 +236,35 @@ class URIVariable(object): if list_test(value) and not tuples: if explode: expanded = join_str.join( - '%s=%s' % ( + '{}={}'.format( name, quote(v, safe) ) for v in value if v is not None ) return expanded if expanded else None else: value = ','.join(quote(v, safe) for v in value) - return '%s=%s' % (name, value) + return '{}={}'.format(name, value) if dict_test(value) or tuples: items = items or sorted(value.items()) if explode: return join_str.join( - '%s=%s' % ( + '{}={}'.format( quote(k, safe), quote(v, safe) ) for k, v in items if v is not None ) else: expanded = ','.join( - '%s,%s' % ( + '{},{}'.format( quote(k, safe), quote(v, safe) ) for k, v in items if v is not None ) - return '%s=%s' % (name, expanded) + return '{}={}'.format(name, expanded) value = value[:prefix] if prefix else value if value: - return '%s=%s' % (name, quote(value, safe)) + return '{}={}'.format(name, quote(value, safe)) return name @@ -360,7 +362,7 @@ def list_test(value): def dict_test(value): - return isinstance(value, (dict, collections.MutableMapping)) + return isinstance(value, (dict, collections_abc.MutableMapping)) try: |