diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-07 22:39:11 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-07 22:39:11 +0000 |
commit | e9b8a40534df1b0de66ee1d6581ce657a6f9eee9 (patch) | |
tree | 6072009c262a4bd31720d0c97d20d3a5dbffbb0c | |
parent | 7d28f9bfe052309499d1ce27aa16975697bb5904 (diff) | |
parent | 8bbe7cd57d5ac0d5d64cfd25c729dc190a407ee9 (diff) | |
download | uritemplates-e9b8a40534df1b0de66ee1d6581ce657a6f9eee9.tar.gz |
Upgrade python/uritemplates to 3.0.1 am: eab8cbc70c am: 5492dc4462 am: 8bbe7cd57dr_aml_301500702android-mainline-12.0.0_r55android-mainline-11.0.0_r9android-mainline-11.0.0_r8android-mainline-11.0.0_r7android-mainline-11.0.0_r6android-mainline-11.0.0_r5android-mainline-11.0.0_r45android-mainline-11.0.0_r44android-mainline-11.0.0_r43android-mainline-11.0.0_r42android-mainline-11.0.0_r41android-mainline-11.0.0_r40android-mainline-11.0.0_r4android-mainline-11.0.0_r39android-mainline-11.0.0_r38android-mainline-11.0.0_r37android-mainline-11.0.0_r36android-mainline-11.0.0_r35android-mainline-11.0.0_r34android-mainline-11.0.0_r33android-mainline-11.0.0_r32android-mainline-11.0.0_r31android-mainline-11.0.0_r30android-mainline-11.0.0_r3android-mainline-11.0.0_r29android-mainline-11.0.0_r28android-mainline-11.0.0_r27android-mainline-11.0.0_r26android-mainline-11.0.0_r25android-mainline-11.0.0_r24android-mainline-11.0.0_r23android-mainline-11.0.0_r22android-mainline-11.0.0_r21android-mainline-11.0.0_r20android-mainline-11.0.0_r2android-mainline-11.0.0_r19android-mainline-11.0.0_r18android-mainline-11.0.0_r17android-mainline-11.0.0_r16android-mainline-11.0.0_r15android-mainline-11.0.0_r14android-mainline-11.0.0_r13android-mainline-11.0.0_r12android-mainline-11.0.0_r10android-mainline-11.0.0_r1android-11.0.0_r9android-11.0.0_r8android-11.0.0_r7android-11.0.0_r48android-11.0.0_r47android-11.0.0_r46android-11.0.0_r45android-11.0.0_r44android-11.0.0_r43android-11.0.0_r42android-11.0.0_r41android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android-11.0.0_r37android-11.0.0_r36android-11.0.0_r35android-11.0.0_r34android-11.0.0_r33android-11.0.0_r32android-11.0.0_r31android-11.0.0_r30android-11.0.0_r29android-11.0.0_r28android-11.0.0_r27android-11.0.0_r26android-11.0.0_r24android-11.0.0_r23android-11.0.0_r22android-11.0.0_r21android-11.0.0_r20android-11.0.0_r19android-11.0.0_r18android-11.0.0_r16android-11.0.0_r15android-11.0.0_r14android-11.0.0_r13android-11.0.0_r12android-11.0.0_r11android-11.0.0_r10android11-qpr3-s1-releaseandroid11-qpr3-releaseandroid11-qpr2-releaseandroid11-qpr1-s2-releaseandroid11-qpr1-s1-releaseandroid11-qpr1-releaseandroid11-qpr1-d-s1-releaseandroid11-qpr1-d-releaseandroid11-qpr1-c-releaseandroid11-mainline-tethering-releaseandroid11-mainline-sparse-2021-jan-releaseandroid11-mainline-sparse-2020-dec-releaseandroid11-mainline-releaseandroid11-mainline-permission-releaseandroid11-mainline-os-statsd-releaseandroid11-mainline-networkstack-releaseandroid11-mainline-media-swcodec-releaseandroid11-mainline-media-releaseandroid11-mainline-extservices-releaseandroid11-mainline-documentsui-releaseandroid11-mainline-conscrypt-releaseandroid11-mainline-cellbroadcast-releaseandroid11-mainline-captiveportallogin-releaseandroid11-devandroid11-d2-releaseandroid11-d1-s7-releaseandroid11-d1-s6-releaseandroid11-d1-s5-releaseandroid11-d1-s1-releaseandroid11-d1-releaseandroid11-d1-b-release
Change-Id: I96fe751f9f4633adfdf4610a60536a5f2105ab92
-rw-r--r-- | .mailmap | 2 | ||||
-rw-r--r-- | .travis.yml | 10 | ||||
-rw-r--r-- | AUTHORS.rst | 13 | ||||
-rw-r--r-- | HISTORY.rst | 15 | ||||
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | METADATA | 12 | ||||
-rw-r--r-- | README.rst | 13 | ||||
-rw-r--r-- | old/uritemplate.py/uritemplatepy-setup.py | 5 | ||||
-rw-r--r-- | setup.py | 24 | ||||
-rw-r--r-- | tests/fixtures/extended-tests.json | 6 | ||||
-rw-r--r-- | tests/test_from_fixtures.py | 5 | ||||
-rw-r--r-- | tests/test_uritemplate.py | 68 | ||||
-rw-r--r-- | tox.ini | 8 | ||||
-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 |
18 files changed, 255 insertions, 74 deletions
diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..6f9a0eb --- /dev/null +++ b/.mailmap @@ -0,0 +1,2 @@ +Ian Stapleton Cordasco <graffatcolmingov@gmail.com> Ian Cordasco <graffatcolmingov@gmail.com> +Ian Stapleton Cordasco <graffatcolmingov@gmail.com> Ian Cordasco <sigmavirus24@users.noreply.github.com> diff --git a/.travis.yml b/.travis.yml index b7c9b48..ec4291e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,16 +3,18 @@ sudo: false matrix: include: - - python: 2.6 - env: TOXENV=py26 - python: 2.7 env: TOXENV=py27 - - python: 3.3 - env: TOXENV=py33 - python: 3.4 env: TOXENV=py34 - python: 3.5 env: TOXENV=py35 + - python: 3.6 + env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 + - python: 3.8 + env: TOXENV=py38 - env: TOXENV=pep8 install: diff --git a/AUTHORS.rst b/AUTHORS.rst index 55848f0..2581f4d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,4 +1,15 @@ Development Lead ---------------- -- Ian Cordasco <graffatcolmingov@gmail.com> +- Ian Stapleton Cordasco <graffatcolmingov@gmail.com> + +Contributors +------------ + +- Brett Cannon +- Daniel Imhoff +- Eugene Eeo +- Jeff Potter +- Philippe Ombredanne +- Thierry Bastian +- Thomas Grainger diff --git a/HISTORY.rst b/HISTORY.rst index f04a309..3a84017 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,19 @@ Changelog - uritemplate ======================= +3.0.1 - 2019-12-19 +------------------ + +- Update to Python 3.6, 3.7, and 3.8 +- Drop support for Python 2.6, 3.2, and 3.3 +- Ignore ``None`` in list argument expansion +- Handle a list with an empty string appropriately + +3.0.0 - 2016-08-29 +------------------ + +- Match major version number of uritemplate.py + 2.0.0 - 2016-08-29 ------------------ @@ -42,7 +55,7 @@ Changelog - uritemplate.py 0.3.0 - 2013-10-22 ------------------ -- Add ``#partial`` to partially expand templates and return new instances of +- Add ``#partial`` to partially expand templates and return new instances of ``URITemplate``. 0.2.0 - 2013-07-26 @@ -1,3 +1,3 @@ This software is made available under the terms of *either* of the licenses -found in LICENSE.APACHE or LICENSE.BSD. Contributions to uritemplate.py are +found in LICENSE.APACHE or LICENSE.BSD. Contributions to uritemplate are made under the terms of *both* these licenses. @@ -1,7 +1,5 @@ name: "uritemplate" -description: - "Simple python library to deal with URI Templates." - +description: "Simple python library to deal with URI Templates." third_party { url { type: HOMEPAGE @@ -11,6 +9,10 @@ third_party { type: GIT value: "https://github.com/python-hyper/uritemplate" } - version: "3.0.0" - last_upgrade_date { year: 2018 month: 6 day: 4 } + version: "3.0.1" + last_upgrade_date { + year: 2019 + month: 12 + day: 23 + } } @@ -1,7 +1,7 @@ uritemplate =========== -Documentation_ -- GitHub_ -- BitBucket_ -- Travis-CI_ +Documentation_ -- GitHub_ -- Travis-CI_ Simple python library to deal with `URI Templates`_. The API looks like @@ -48,7 +48,7 @@ Installing :: - pip install uritemplate.py + pip install uritemplate License ------- @@ -56,9 +56,8 @@ License Modified BSD license_ -.. _Documentation: http://uritemplate.rtfd.org/ -.. _GitHub: https://github.com/sigmavirus24/uritemplate -.. _BitBucket: https://bitbucket.org/icordasc/uritemplate -.. _Travis-CI: https://travis-ci.org/sigmavirus24/uritemplate +.. _Documentation: https://uritemplate.readthedocs.io/ +.. _GitHub: https://github.com/python-hyper/uritemplate +.. _Travis-CI: https://travis-ci.org/python-hyper/uritemplate .. _URI Templates: http://tools.ietf.org/html/rfc6570 -.. _license: https://github.com/sigmavirus24/uritemplate/blob/master/LICENSE +.. _license: https://github.com/python-hyper/uritemplate/blob/master/LICENSE diff --git a/old/uritemplate.py/uritemplatepy-setup.py b/old/uritemplate.py/uritemplatepy-setup.py index 430d519..ebececb 100644 --- a/old/uritemplate.py/uritemplatepy-setup.py +++ b/old/uritemplate.py/uritemplatepy-setup.py @@ -11,6 +11,7 @@ setup( author_email="graffatcolmingov@gmail.com", url="https://uritemplate.readthedocs.org", install_requires=["uritemplate>=2.0"], + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved', @@ -19,13 +20,11 @@ setup( 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', ], ) @@ -1,3 +1,5 @@ +from io import open + from setuptools import setup from uritemplate import __version__ @@ -6,19 +8,27 @@ packages = [ 'uritemplate' ] +with open("README.rst", encoding="utf-8") as file: + readme = file.read() + +with open("HISTORY.rst", encoding="utf-8") as file: + history = file.read() + setup( name="uritemplate", version=__version__, description='URI templates', - long_description="\n\n".join([open("README.rst").read(), - open("HISTORY.rst").read()]), + long_description="\n\n".join([readme, history]), + long_description_content_type="text/x-rst", license="BSD 3-Clause License or Apache License, Version 2.0", - author="Ian Cordasco", + author="Ian Stapleton Cordasco", author_email="graffatcolmingov@gmail.com", url="https://uritemplate.readthedocs.org", packages=packages, - package_data={'': ['LICENSE', 'AUTHORS.rst']}, + package_data={'': ['LICENSE', 'LICENSE.APACHE', 'LICENSE.BSD', + 'AUTHORS.rst']}, include_package_data=True, + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved', @@ -27,13 +37,13 @@ setup( 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', ], ) diff --git a/tests/fixtures/extended-tests.json b/tests/fixtures/extended-tests.json index fd69744..ad43ad6 100644 --- a/tests/fixtures/extended-tests.json +++ b/tests/fixtures/extended-tests.json @@ -11,7 +11,7 @@ "lang" : "en", "geocode" : ["37.76","-122.427"], "first_name" : "John", - "last.name" : "Doe", + "last.name" : "Doe", "Some%20Thing" : "foo", "number" : 6, "long" : 37.76, @@ -28,7 +28,7 @@ "testcases":[ [ "{/id*}" , "/person" ], - [ "{/id*}{?fields,first_name,last.name,token}" , [ + [ "{/id*}{?fields,first_name,last.name,token}" , [ "/person?fields=id,name,picture&first_name=John&last.name=Doe&token=12345", "/person?fields=id,picture,name&first_name=John&last.name=Doe&token=12345", "/person?fields=picture,name,id&first_name=John&last.name=Doe&token=12345", @@ -68,7 +68,7 @@ "testcases":[ [ "{/id*}" , ["/person/albums","/albums/person"] ], - [ "{/id*}{?fields,token}" , [ + [ "{/id*}{?fields,token}" , [ "/person/albums?fields=id,name,picture&token=12345", "/person/albums?fields=id,picture,name&token=12345", "/person/albums?fields=picture,name,id&token=12345", diff --git a/tests/test_from_fixtures.py b/tests/test_from_fixtures.py index 70d6553..d6c9810 100644 --- a/tests/test_from_fixtures.py +++ b/tests/test_from_fixtures.py @@ -1,3 +1,4 @@ +import io import json import os.path @@ -12,7 +13,7 @@ def fixture_file_path(filename): def load_examples(filename): path = fixture_file_path(filename) - with open(path, 'r') as examples_file: + with io.open(path, 'r', encoding="utf-8") as examples_file: examples = json.load(examples_file) return examples @@ -20,7 +21,7 @@ def load_examples(filename): def expected_set(expected): if isinstance(expected, list): return set(expected) - return set([expected]) + return {expected} class FixtureMixin(object): diff --git a/tests/test_uritemplate.py b/tests/test_uritemplate.py index b1abc96..f67ad26 100644 --- a/tests/test_uritemplate.py +++ b/tests/test_uritemplate.py @@ -464,6 +464,52 @@ class TestURITemplate(RFCTemplateExamples('RFCMeta', (TestCase,), {})): None ) + def test_label_path_expansion_explode_slash(self): + t = URITemplate('{/foo*}') + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', [], True, '/'), None + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', [None], True, '/'), None + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', [None, None], True, '/'), None + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', ['one'], True, '/'), 'one' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', ['one', 'two'], True, '/'), 'one/two' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', ['one', None, 'two'], True, '/'), 'one/two' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', [''], True, '/'), '' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', ['', ''], True, '/'), '/' + ) + + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {}, True, '/'), None + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {'one': ''}, True, '/'), 'one=' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {'one': '', 'two': ''}, True, '/'), 'one=/two=' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {'one': None}, True, '/'), None + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {'one': None, 'two': 'two'}, True, '/'), 'two=two' + ) + self.assertEqual(t.variables[0]._label_path_expansion( + 'foo', {'one': None, 'two': None}, True, '/'), None + ) + def test_semi_path_expansion(self): t = URITemplate('{foo}') v = t.variables[0] @@ -544,24 +590,24 @@ class TestURIVariable(TestCase): class TestVariableModule(TestCase): def test_is_list_of_tuples(self): - l = [(1, 2), (3, 4)] - self.assertEqual(variable.is_list_of_tuples(l), (True, l)) + a_list = [(1, 2), (3, 4)] + self.assertEqual(variable.is_list_of_tuples(a_list), (True, a_list)) - l = [1, 2, 3, 4] - self.assertEqual(variable.is_list_of_tuples(l), (False, None)) + a_list = [1, 2, 3, 4] + self.assertEqual(variable.is_list_of_tuples(a_list), (False, None)) def test_list_test(self): - l = [1, 2, 3, 4] - self.assertEqual(variable.list_test(l), True) + a_list = [1, 2, 3, 4] + self.assertEqual(variable.list_test(a_list), True) - l = str([1, 2, 3, 4]) - self.assertEqual(variable.list_test(l), False) + a_list = str([1, 2, 3, 4]) + self.assertEqual(variable.list_test(a_list), False) def test_list_of_tuples_test(self): - l = [(1, 2), (3, 4)] - self.assertEqual(variable.dict_test(l), False) + a_list = [(1, 2), (3, 4)] + self.assertEqual(variable.dict_test(a_list), False) - d = dict(l) + d = dict(a_list) self.assertEqual(variable.dict_test(d), True) @@ -1,17 +1,17 @@ [tox] envlist = - py26, py27, - py32, - py33, py34, py35, + py36, + py37, + py38, pep8, [testenv] deps = pytest -commands = py.test {posargs} +commands = pytest {posargs} [testenv:pep8] deps = 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: |