From d4bb48d5d5d75e3f4ca826dbf051ea8f26b04f2e Mon Sep 17 00:00:00 2001 From: "P. Raj Kumar" Date: Tue, 31 Dec 2019 15:16:43 -0800 Subject: [PATCH 1/4] Add Python 3.7 build to Travis config --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa135e4e..5ffe7037 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,7 @@ python: - '3.4' - '3.5' - '3.6' - - '3.6-dev' - - '3.7-dev' + - '3.7' before_script: - pip install tox - if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then pip install flake8 flake8-bugbear; fi From 4e4f3b62ae63209c1fa0438804af2ba0cb818790 Mon Sep 17 00:00:00 2001 From: "P. Raj Kumar" Date: Tue, 31 Dec 2019 15:37:01 -0800 Subject: [PATCH 2/4] Import collection interfaces from collections.abc Starting with Python 3.8, these ABCs won't be accessible from the base package. In Python 3.7, this usage throws a deprecation warning. --- uplink/auth.py | 16 ++++++++++++---- uplink/clients/io/interfaces.py | 4 ++-- uplink/converters/__init__.py | 4 ++-- uplink/converters/typing_.py | 4 +++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/uplink/auth.py b/uplink/auth.py index a5946565..3334b72d 100644 --- a/uplink/auth.py +++ b/uplink/auth.py @@ -1,7 +1,7 @@ """This module implements the auth layer.""" # Standard library imports -import collections +from collections import abc # Third-party imports from requests import auth @@ -22,7 +22,7 @@ def get_auth(auth_object=None): if auth_object is None: return utils.no_op - elif isinstance(auth_object, collections.Iterable): + elif isinstance(auth_object, abc.Iterable): return BasicAuth(*auth_object) elif callable(auth_object): return auth_object @@ -55,6 +55,7 @@ def __init__(self, token): token_param = ExampleApiTokenParam(TOKEN) api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_param) """ + def __init__(self, param, token): self._param = param self._param_value = token @@ -97,6 +98,7 @@ def __init__(self, token): token_header = ExampleApiTokenHeader(TOKEN) api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_header) """ + _header = None _prefix = None @@ -161,6 +163,7 @@ class ProxyAuth(BasicAuth): ) github = GitHub(BASE_URL, auth=auth_methods) """ + _header = "Proxy-Authorization" @@ -226,8 +229,11 @@ class MultiAuth(object): for method in auth_methods: print(method.__class__.__name__) """ + def __init__(self, *auth_methods): - self._auth_methods = [get_auth(auth_method) for auth_method in auth_methods] + self._auth_methods = [ + get_auth(auth_method) for auth_method in auth_methods + ] def __call__(self, request_builder): for auth_method in self._auth_methods: @@ -243,4 +249,6 @@ def append(self, auth_method): self._auth_methods.append(get_auth(auth_method)) def extend(self, auth_methods): - self._auth_methods.extend([get_auth(auth_method) for auth_method in auth_methods]) + self._auth_methods.extend( + [get_auth(auth_method) for auth_method in auth_methods] + ) diff --git a/uplink/clients/io/interfaces.py b/uplink/clients/io/interfaces.py index f4e4173a..ff810824 100644 --- a/uplink/clients/io/interfaces.py +++ b/uplink/clients/io/interfaces.py @@ -1,5 +1,5 @@ # Standard library imports -import collections +from collections import abc # Local imports from uplink import compat @@ -69,7 +69,7 @@ def on_failure(self, exc_type, exc_val, exc_tb): raise NotImplementedError -class Executable(collections.Iterator): +class Executable(abc.Iterator): """An abstraction for iterating over the execution of a request.""" def __next__(self): diff --git a/uplink/converters/__init__.py b/uplink/converters/__init__.py index b9cd91fe..15b60356 100644 --- a/uplink/converters/__init__.py +++ b/uplink/converters/__init__.py @@ -1,5 +1,5 @@ # Standard library imports -import collections +from collections import abc # Local imports from uplink._extras import installer, plugin @@ -55,7 +55,7 @@ def __call__(self, *args, **kwargs): return converter -class ConverterFactoryRegistry(collections.Mapping): +class ConverterFactoryRegistry(abc.Mapping): """ A registry that chains together :py:class:`interfaces.ConverterFactory` instances. diff --git a/uplink/converters/typing_.py b/uplink/converters/typing_.py index 0e1c6dfc..dd29aa5b 100644 --- a/uplink/converters/typing_.py +++ b/uplink/converters/typing_.py @@ -2,6 +2,8 @@ import collections import functools +from collections import abc + # Local imports from uplink.converters import interfaces, register_default_converter_factory @@ -25,7 +27,7 @@ def set_chain(self, chain): self._elem_converter = chain(self._elem_type) or self._elem_type def convert(self, value): - if isinstance(value, collections.Sequence): + if isinstance(value, abc.Sequence): return list(map(self._elem_converter, value)) else: # TODO: Handle the case where the value is not an sequence. From 74f1f1cb49cc384333f2d420c4ff989c73a23619 Mon Sep 17 00:00:00 2001 From: "P. Raj Kumar" Date: Tue, 31 Dec 2019 16:11:10 -0800 Subject: [PATCH 3/4] Remove unnecessary commands from tox.ini For local development, setting up tox to use pipenv to run tests against two different versions of Python seems unnecessary, since the CI builds will run against the versions we want already. Further, there are some known constraints with running pipenv in a multi-python environment and the cost of getting this to work doesn't seem worth it. --- Pipfile | 1 - tox.ini | 10 ---------- uplink/auth.py | 8 ++++++-- uplink/clients/io/interfaces.py | 8 ++++++-- uplink/converters/__init__.py | 8 ++++++-- uplink/converters/typing_.py | 8 ++++++-- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Pipfile b/Pipfile index 257ff7d4..e94a592c 100644 --- a/Pipfile +++ b/Pipfile @@ -3,7 +3,6 @@ url = "https://pypi.org/simple" verify_ssl = true name = "pypi" - [dev-packages] pre-commit = "*" tox = "*" diff --git a/tox.ini b/tox.ini index 4e93a321..19b1c350 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,6 @@ # Configuration file for Tox, a general virtualenv managment tool. # Website (June 2016): http://tox.readthedocs.io/en/latest/ -[tox] -# These are all "default" test environments provided by Tox. -# They are automatically created upon invoking the "tox" CLI. -envlist = py27, py36 - [testenv] deps = pipenv commands = pipenv install --skip-lock @@ -13,8 +8,3 @@ commands = pipenv install --skip-lock --cov-config .coveragerc \ --cov=uplink \ {posargs} # Substitute with tox positional arguments - -# Ensure pipenv runs the tests against a clean virtual environment, -# for better parity between Travis CI builds and testing on a local -# machine during development. -setenv = PIPENV_IGNORE_VIRTUALENVS = 1 diff --git a/uplink/auth.py b/uplink/auth.py index 3334b72d..b62e1082 100644 --- a/uplink/auth.py +++ b/uplink/auth.py @@ -1,7 +1,11 @@ """This module implements the auth layer.""" # Standard library imports -from collections import abc +try: + from collections.abc import Iterable +except ImportError: + # Python 2.7 + from collections import Iterable # Third-party imports from requests import auth @@ -22,7 +26,7 @@ def get_auth(auth_object=None): if auth_object is None: return utils.no_op - elif isinstance(auth_object, abc.Iterable): + elif isinstance(auth_object, Iterable): return BasicAuth(*auth_object) elif callable(auth_object): return auth_object diff --git a/uplink/clients/io/interfaces.py b/uplink/clients/io/interfaces.py index ff810824..9dcfe0df 100644 --- a/uplink/clients/io/interfaces.py +++ b/uplink/clients/io/interfaces.py @@ -1,5 +1,9 @@ # Standard library imports -from collections import abc +try: + from collections.abc import Iterator +except ImportError: + # Python 2.7 + from collections import Iterator # Local imports from uplink import compat @@ -69,7 +73,7 @@ def on_failure(self, exc_type, exc_val, exc_tb): raise NotImplementedError -class Executable(abc.Iterator): +class Executable(Iterator): """An abstraction for iterating over the execution of a request.""" def __next__(self): diff --git a/uplink/converters/__init__.py b/uplink/converters/__init__.py index 15b60356..40adfa9c 100644 --- a/uplink/converters/__init__.py +++ b/uplink/converters/__init__.py @@ -1,5 +1,9 @@ # Standard library imports -from collections import abc +try: + from collections.abc import Mapping +except ImportError: + # Python 2.7 + from collections import Mapping # Local imports from uplink._extras import installer, plugin @@ -55,7 +59,7 @@ def __call__(self, *args, **kwargs): return converter -class ConverterFactoryRegistry(abc.Mapping): +class ConverterFactoryRegistry(Mapping): """ A registry that chains together :py:class:`interfaces.ConverterFactory` instances. diff --git a/uplink/converters/typing_.py b/uplink/converters/typing_.py index dd29aa5b..c3a12153 100644 --- a/uplink/converters/typing_.py +++ b/uplink/converters/typing_.py @@ -2,7 +2,11 @@ import collections import functools -from collections import abc +try: + from collections.abc import Sequence +except ImportError: + # Python 2.7 + from collections import Sequence # Local imports from uplink.converters import interfaces, register_default_converter_factory @@ -27,7 +31,7 @@ def set_chain(self, chain): self._elem_converter = chain(self._elem_type) or self._elem_type def convert(self, value): - if isinstance(value, abc.Sequence): + if isinstance(value, Sequence): return list(map(self._elem_converter, value)) else: # TODO: Handle the case where the value is not an sequence. From 6c68e4d7c9cc98d557a2ca54d10bae51616db4a6 Mon Sep 17 00:00:00 2001 From: "P. Raj Kumar" Date: Tue, 31 Dec 2019 17:06:57 -0800 Subject: [PATCH 4/4] Add Python 3.8 Travis build --- .travis.yml | 1 + uplink/auth.py | 8 ++------ uplink/clients/io/interfaces.py | 8 ++------ uplink/converters/__init__.py | 8 ++------ uplink/converters/typing_.py | 8 +------- 5 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ffe7037..ffbb2819 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ python: - '3.5' - '3.6' - '3.7' + - '3.8' before_script: - pip install tox - if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then pip install flake8 flake8-bugbear; fi diff --git a/uplink/auth.py b/uplink/auth.py index b62e1082..d5971ca1 100644 --- a/uplink/auth.py +++ b/uplink/auth.py @@ -1,11 +1,7 @@ """This module implements the auth layer.""" # Standard library imports -try: - from collections.abc import Iterable -except ImportError: - # Python 2.7 - from collections import Iterable +import collections # Third-party imports from requests import auth @@ -26,7 +22,7 @@ def get_auth(auth_object=None): if auth_object is None: return utils.no_op - elif isinstance(auth_object, Iterable): + elif isinstance(auth_object, collections.Iterable): return BasicAuth(*auth_object) elif callable(auth_object): return auth_object diff --git a/uplink/clients/io/interfaces.py b/uplink/clients/io/interfaces.py index 9dcfe0df..f4e4173a 100644 --- a/uplink/clients/io/interfaces.py +++ b/uplink/clients/io/interfaces.py @@ -1,9 +1,5 @@ # Standard library imports -try: - from collections.abc import Iterator -except ImportError: - # Python 2.7 - from collections import Iterator +import collections # Local imports from uplink import compat @@ -73,7 +69,7 @@ def on_failure(self, exc_type, exc_val, exc_tb): raise NotImplementedError -class Executable(Iterator): +class Executable(collections.Iterator): """An abstraction for iterating over the execution of a request.""" def __next__(self): diff --git a/uplink/converters/__init__.py b/uplink/converters/__init__.py index 40adfa9c..b9cd91fe 100644 --- a/uplink/converters/__init__.py +++ b/uplink/converters/__init__.py @@ -1,9 +1,5 @@ # Standard library imports -try: - from collections.abc import Mapping -except ImportError: - # Python 2.7 - from collections import Mapping +import collections # Local imports from uplink._extras import installer, plugin @@ -59,7 +55,7 @@ def __call__(self, *args, **kwargs): return converter -class ConverterFactoryRegistry(Mapping): +class ConverterFactoryRegistry(collections.Mapping): """ A registry that chains together :py:class:`interfaces.ConverterFactory` instances. diff --git a/uplink/converters/typing_.py b/uplink/converters/typing_.py index c3a12153..0e1c6dfc 100644 --- a/uplink/converters/typing_.py +++ b/uplink/converters/typing_.py @@ -2,12 +2,6 @@ import collections import functools -try: - from collections.abc import Sequence -except ImportError: - # Python 2.7 - from collections import Sequence - # Local imports from uplink.converters import interfaces, register_default_converter_factory @@ -31,7 +25,7 @@ def set_chain(self, chain): self._elem_converter = chain(self._elem_type) or self._elem_type def convert(self, value): - if isinstance(value, Sequence): + if isinstance(value, collections.Sequence): return list(map(self._elem_converter, value)) else: # TODO: Handle the case where the value is not an sequence.