From 560cf1ed02a900436c5d9e0a0fb3f94b5fd98c55 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Tue, 3 Aug 2021 16:35:54 -0400 Subject: [PATCH] fix!: drop support for Python 2.7 (#778) Drop use of 'six' wrapper library. Drop 'u"' prefixes. Drop support for app_engine 'classic' mode (Python 2.7-only). Release-As: 2.0.0b1 Closes #777. --- CONTRIBUTING.rst | 4 +- README.rst | 12 +- google/auth/_cloud_sdk.py | 4 +- google/auth/_credentials_async.py | 11 +- google/auth/_default.py | 8 +- google/auth/_default_async.py | 8 +- google/auth/_helpers.py | 17 +-- google/auth/_oauth2client.py | 6 +- google/auth/_service_account_info.py | 4 +- google/auth/aws.py | 9 +- google/auth/compute_engine/_metadata.py | 12 +- google/auth/compute_engine/credentials.py | 8 +- google/auth/credentials.py | 11 +- google/auth/crypt/__init__.py | 4 +- google/auth/crypt/_python_rsa.py | 9 +- google/auth/crypt/base.py | 11 +- google/auth/external_account.py | 7 +- google/auth/iam.py | 5 +- google/auth/identity_pool.py | 6 +- google/auth/impersonated_credentials.py | 8 +- google/auth/jwt.py | 28 ++-- google/auth/transport/__init__.py | 12 +- google/auth/transport/_aiohttp_requests.py | 5 +- google/auth/transport/_http_client.py | 12 +- google/auth/transport/_mtls_helper.py | 6 +- google/auth/transport/grpc.py | 16 +-- google/auth/transport/mtls.py | 6 +- google/auth/transport/requests.py | 19 +-- google/auth/transport/urllib3.py | 19 +-- google/oauth2/_client.py | 18 ++- google/oauth2/_client_async.py | 16 +-- google/oauth2/_id_token_async.py | 12 +- google/oauth2/_reauth_async.py | 2 - google/oauth2/challenges.py | 5 +- google/oauth2/credentials.py | 4 +- google/oauth2/id_token.py | 12 +- google/oauth2/reauth.py | 2 - google/oauth2/sts.py | 7 +- google/oauth2/utils.py | 5 +- noxfile.py | 24 +--- setup.py | 25 ++-- system_tests/noxfile.py | 46 +----- .../app_engine_test_app/.gitignore | 1 - .../app_engine_test_app/app.yaml | 12 -- .../app_engine_test_app/appengine_config.py | 30 ---- .../app_engine_test_app/main.py | 133 ------------------ .../app_engine_test_app/requirements.txt | 3 - .../system_tests_sync/test_app_engine.py | 22 --- .../test_external_accounts.py | 14 +- testing/constraints-3.6.txt | 1 - tests/compute_engine/test__metadata.py | 20 +-- tests/crypt/test__cryptography_rsa.py | 6 +- tests/crypt/test__python_rsa.py | 10 +- tests/crypt/test_es256.py | 6 +- tests/oauth2/test__client.py | 15 +- tests/oauth2/test_sts.py | 24 ++-- tests/test__helpers.py | 12 +- tests/test__oauth2client.py | 8 +- tests/test__service_account_info.py | 3 +- tests/test_aws.py | 74 +++++----- tests/test_external_account.py | 66 ++++----- tests/test_iam.py | 6 +- tests/test_identity_pool.py | 12 +- tests/test_impersonated_credentials.py | 34 ++--- tests/test_jwt.py | 8 +- tests/transport/compliance.py | 14 +- tests/transport/test_requests.py | 22 +-- tests/transport/test_urllib3.py | 12 +- tests_async/oauth2/test__client_async.py | 15 +- tests_async/transport/async_compliance.py | 16 +-- 70 files changed, 350 insertions(+), 714 deletions(-) delete mode 100644 system_tests/system_tests_sync/app_engine_test_app/.gitignore delete mode 100644 system_tests/system_tests_sync/app_engine_test_app/app.yaml delete mode 100644 system_tests/system_tests_sync/app_engine_test_app/appengine_config.py delete mode 100644 system_tests/system_tests_sync/app_engine_test_app/main.py delete mode 100644 system_tests/system_tests_sync/app_engine_test_app/requirements.txt delete mode 100644 system_tests/system_tests_sync/test_app_engine.py diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 175e76634..84108995d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -18,8 +18,8 @@ A few notes on making changes to ``google-auth-library-python``. documentation (in ``docs/``). You can re-generate the reference documentation using ``nox -s docgen``. -- The change must work fully on the following CPython versions: 2.7, - 3.5, 3.6, 3.7, 3.8 across macOS, Linux, and Windows. +- The change must work fully on the following CPython versions: + 3.6, 3.7, 3.8, 3.9 across macOS, Linux, and Windows. - The codebase *must* have 100% test statement coverage after each commit. You can test coverage via ``nox -e cover``. diff --git a/README.rst b/README.rst index 10de0ac06..35ebe8bf0 100644 --- a/README.rst +++ b/README.rst @@ -24,11 +24,15 @@ For more information on setting up your Python development environment, please r Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.5 +Python >= 3.6 -Deprecated Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Python == 2.7. Python 2.7 support will be removed on January 1, 2020. +Unsupported Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Python == 2.7: The last version of this library with support for Python 2.7 + was `google.auth == 1.34.0`. + +- Python 3.5: The last version of this library with support for Python 3.5 + was `google.auth == 1.23.0`. Documentation ------------- diff --git a/google/auth/_cloud_sdk.py b/google/auth/_cloud_sdk.py index 40e6aec13..1f13ad420 100644 --- a/google/auth/_cloud_sdk.py +++ b/google/auth/_cloud_sdk.py @@ -18,8 +18,6 @@ import os import subprocess -import six - from google.auth import environment_vars from google.auth import exceptions @@ -156,4 +154,4 @@ def get_auth_access_token(account=None): new_exc = exceptions.UserAccessTokenError( "Failed to obtain access token", caught_exc ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc diff --git a/google/auth/_credentials_async.py b/google/auth/_credentials_async.py index d4d4e2c0e..760758d85 100644 --- a/google/auth/_credentials_async.py +++ b/google/auth/_credentials_async.py @@ -18,13 +18,10 @@ import abc import inspect -import six - from google.auth import credentials -@six.add_metaclass(abc.ABCMeta) -class Credentials(credentials.Credentials): +class Credentials(credentials.Credentials, metaclass=abc.ABCMeta): """Async inherited credentials class from google.auth.credentials. The added functionality is the before_request call which requires async/await syntax. @@ -84,8 +81,7 @@ class AnonymousCredentials(credentials.AnonymousCredentials, Credentials): """ -@six.add_metaclass(abc.ABCMeta) -class ReadOnlyScoped(credentials.ReadOnlyScoped): +class ReadOnlyScoped(credentials.ReadOnlyScoped, metaclass=abc.ABCMeta): """Interface for credentials whose scopes can be queried. OAuth 2.0-based credentials allow limiting access using scopes as described @@ -171,6 +167,5 @@ def with_scopes_if_required(credentials, scopes): return credentials -@six.add_metaclass(abc.ABCMeta) -class Signing(credentials.Signing): +class Signing(credentials.Signing, metaclass=abc.ABCMeta): """Interface for credentials that can cryptographically sign messages.""" diff --git a/google/auth/_default.py b/google/auth/_default.py index f7e308f3e..7da77a28f 100644 --- a/google/auth/_default.py +++ b/google/auth/_default.py @@ -23,8 +23,6 @@ import os import warnings -import six - from google.auth import environment_vars from google.auth import exceptions import google.auth.transport._http_client @@ -115,7 +113,7 @@ def load_credentials_from_file( new_exc = exceptions.DefaultCredentialsError( "File {} is not a valid json file.".format(filename), caught_exc ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc # The type key should indicate that the file is either a service account # credentials file or an authorized user credentials file. @@ -131,7 +129,7 @@ def load_credentials_from_file( except ValueError as caught_exc: msg = "Failed to load authorized user credentials from {}".format(filename) new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc if quota_project_id: credentials = credentials.with_quota_project(quota_project_id) if not credentials.quota_project_id: @@ -148,7 +146,7 @@ def load_credentials_from_file( except ValueError as caught_exc: msg = "Failed to load service account credentials from {}".format(filename) new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc if quota_project_id: credentials = credentials.with_quota_project(quota_project_id) return credentials, info.get("project_id") diff --git a/google/auth/_default_async.py b/google/auth/_default_async.py index d12a642af..82e6c432d 100644 --- a/google/auth/_default_async.py +++ b/google/auth/_default_async.py @@ -21,8 +21,6 @@ import json import os -import six - from google.auth import _default from google.auth import environment_vars from google.auth import exceptions @@ -63,7 +61,7 @@ def load_credentials_from_file(filename, scopes=None, quota_project_id=None): new_exc = exceptions.DefaultCredentialsError( "File {} is not a valid json file.".format(filename), caught_exc ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc # The type key should indicate that the file is either a service account # credentials file or an authorized user credentials file. @@ -79,7 +77,7 @@ def load_credentials_from_file(filename, scopes=None, quota_project_id=None): except ValueError as caught_exc: msg = "Failed to load authorized user credentials from {}".format(filename) new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc if not credentials.quota_project_id: _default._warn_about_problematic_credentials(credentials) return credentials, None @@ -94,7 +92,7 @@ def load_credentials_from_file(filename, scopes=None, quota_project_id=None): except ValueError as caught_exc: msg = "Failed to load service account credentials from {}".format(filename) new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc return credentials, info.get("project_id") else: diff --git a/google/auth/_helpers.py b/google/auth/_helpers.py index 21c987a73..09f32f84e 100644 --- a/google/auth/_helpers.py +++ b/google/auth/_helpers.py @@ -17,9 +17,7 @@ import base64 import calendar import datetime - -import six -from six.moves import urllib +import urllib CLOCK_SKEW_SECS = 10 # 10 seconds @@ -84,9 +82,6 @@ def datetime_to_secs(value): def to_bytes(value, encoding="utf-8"): """Converts a string value to bytes, if necessary. - Unfortunately, ``six.b`` is insufficient for this task since in - Python 2 because it does not modify ``unicode`` objects. - Args: value (Union[str, bytes]): The value to be converted. encoding (str): The encoding to use to convert unicode to bytes. @@ -99,8 +94,8 @@ def to_bytes(value, encoding="utf-8"): Raises: ValueError: If the value could not be converted to bytes. """ - result = value.encode(encoding) if isinstance(value, six.text_type) else value - if isinstance(result, six.binary_type): + result = value.encode(encoding) if isinstance(value, str) else value + if isinstance(result, bytes): return result else: raise ValueError("{0!r} could not be converted to bytes".format(value)) @@ -119,8 +114,8 @@ def from_bytes(value): Raises: ValueError: If the value could not be converted to unicode. """ - result = value.decode("utf-8") if isinstance(value, six.binary_type) else value - if isinstance(result, six.text_type): + result = value.decode("utf-8") if isinstance(value, bytes) else value + if isinstance(result, str): return result else: raise ValueError("{0!r} could not be converted to unicode".format(value)) @@ -162,7 +157,7 @@ def update_query(url, params, remove=None): query_params.update(params) # Remove any values specified in remove. query_params = { - key: value for key, value in six.iteritems(query_params) if key not in remove + key: value for key, value in query_params.items() if key not in remove } # Re-encoded the query string. new_query = urllib.parse.urlencode(query_params, doseq=True) diff --git a/google/auth/_oauth2client.py b/google/auth/_oauth2client.py index 95a9876f3..3512e1d11 100644 --- a/google/auth/_oauth2client.py +++ b/google/auth/_oauth2client.py @@ -21,8 +21,6 @@ from __future__ import absolute_import -import six - from google.auth import _helpers import google.auth.app_engine import google.auth.compute_engine @@ -34,7 +32,7 @@ import oauth2client.contrib.gce import oauth2client.service_account except ImportError as caught_exc: - six.raise_from(ImportError("oauth2client is not installed."), caught_exc) + raise ImportError("oauth2client is not installed.") from caught_exc try: import oauth2client.contrib.appengine # pytype: disable=import-error @@ -166,4 +164,4 @@ def convert(credentials): return _CLASS_CONVERSION_MAP[credentials_class](credentials) except KeyError as caught_exc: new_exc = ValueError(_CONVERT_ERROR_TMPL.format(credentials_class)) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc diff --git a/google/auth/_service_account_info.py b/google/auth/_service_account_info.py index 3d340c78d..54a40e9da 100644 --- a/google/auth/_service_account_info.py +++ b/google/auth/_service_account_info.py @@ -17,8 +17,6 @@ import io import json -import six - from google.auth import crypt @@ -43,7 +41,7 @@ def from_dict(data, require=None): """ keys_needed = set(require if require is not None else []) - missing = keys_needed.difference(six.iterkeys(data)) + missing = keys_needed.difference(data) if missing: raise ValueError( diff --git a/google/auth/aws.py b/google/auth/aws.py index c2b521c36..2f2a1359b 100644 --- a/google/auth/aws.py +++ b/google/auth/aws.py @@ -39,13 +39,12 @@ import hashlib import hmac +import http.client import io import json import os import re - -from six.moves import http_client -from six.moves import urllib +import urllib from google.auth import _helpers from google.auth import environment_vars @@ -627,7 +626,7 @@ def _get_metadata_security_credentials(self, request, role_name): else response.data ) - if response.status != http_client.OK: + if response.status != http.client.OK: raise exceptions.RefreshError( "Unable to retrieve AWS security credentials", response_body ) @@ -666,7 +665,7 @@ def _get_metadata_role_name(self, request): else response.data ) - if response.status != http_client.OK: + if response.status != http.client.OK: raise exceptions.RefreshError( "Unable to retrieve AWS role name", response_body ) diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py index 5687a42f9..ee6fec623 100644 --- a/google/auth/compute_engine/_metadata.py +++ b/google/auth/compute_engine/_metadata.py @@ -18,13 +18,11 @@ """ import datetime +import http.client import json import logging import os - -import six -from six.moves import http_client -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse from google.auth import _helpers from google.auth import environment_vars @@ -91,7 +89,7 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3): metadata_flavor = response.headers.get(_METADATA_FLAVOR_HEADER) return ( - response.status == http_client.OK + response.status == http.client.OK and metadata_flavor == _METADATA_FLAVOR_VALUE ) @@ -165,7 +163,7 @@ def get( "metadata service. Compute Engine Metadata server unavailable".format(url) ) - if response.status == http_client.OK: + if response.status == http.client.OK: content = _helpers.from_bytes(response.data) if response.headers["content-type"] == "application/json": try: @@ -175,7 +173,7 @@ def get( "Received invalid JSON from the Google Compute Engine" "metadata service: {:.20}".format(content) ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc else: return content else: diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py index 167165620..cb4e0f0a0 100644 --- a/google/auth/compute_engine/credentials.py +++ b/google/auth/compute_engine/credentials.py @@ -21,8 +21,6 @@ import datetime -import six - from google.auth import _helpers from google.auth import credentials from google.auth import exceptions @@ -38,7 +36,7 @@ class Credentials(credentials.Scoped, credentials.CredentialsWithQuotaProject): These credentials use the Google Compute Engine metadata server to obtain OAuth 2.0 access tokens associated with the instance's service account, and are also used for Cloud Run, Flex and App Engine (except for the Python - 2.7 runtime). + 2.7 runtime, which is supported only on older versions of this library). For more information about Compute Engine authentication, including how to configure scopes, see the `Compute Engine authentication @@ -114,7 +112,7 @@ def refresh(self, request): ) except exceptions.TransportError as caught_exc: new_exc = exceptions.RefreshError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc @property def service_account_email(self): @@ -352,7 +350,7 @@ def _call_metadata_identity_endpoint(self, request): id_token = _metadata.get(request, path, params=params) except exceptions.TransportError as caught_exc: new_exc = exceptions.RefreshError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc _, payload, _, _ = jwt._unverified_decode(id_token) return id_token, datetime.datetime.fromtimestamp(payload["exp"]) diff --git a/google/auth/credentials.py b/google/auth/credentials.py index 7d3c798b1..6356f5434 100644 --- a/google/auth/credentials.py +++ b/google/auth/credentials.py @@ -17,13 +17,10 @@ import abc -import six - from google.auth import _helpers -@six.add_metaclass(abc.ABCMeta) -class Credentials(object): +class Credentials(object, metaclass=abc.ABCMeta): """Base class for all credentials. All credentials have a :attr:`token` that is used for authentication and @@ -187,8 +184,7 @@ def before_request(self, request, method, url, headers): """Anonymous credentials do nothing to the request.""" -@six.add_metaclass(abc.ABCMeta) -class ReadOnlyScoped(object): +class ReadOnlyScoped(object, metaclass=abc.ABCMeta): """Interface for credentials whose scopes can be queried. OAuth 2.0-based credentials allow limiting access using scopes as described @@ -329,8 +325,7 @@ def with_scopes_if_required(credentials, scopes, default_scopes=None): return credentials -@six.add_metaclass(abc.ABCMeta) -class Signing(object): +class Signing(object, metaclass=abc.ABCMeta): """Interface for credentials that can cryptographically sign messages.""" @abc.abstractmethod diff --git a/google/auth/crypt/__init__.py b/google/auth/crypt/__init__.py index 15ac95068..97e9d81d5 100644 --- a/google/auth/crypt/__init__.py +++ b/google/auth/crypt/__init__.py @@ -37,8 +37,6 @@ version is at least 1.4.0. """ -import six - from google.auth.crypt import base from google.auth.crypt import rsa @@ -90,7 +88,7 @@ class to use for verification. This can be used to select different Returns: bool: True if the signature is valid, otherwise False. """ - if isinstance(certs, (six.text_type, six.binary_type)): + if isinstance(certs, (str, bytes)): certs = [certs] for cert in certs: diff --git a/google/auth/crypt/_python_rsa.py b/google/auth/crypt/_python_rsa.py index ec30dd09a..1c4a9dab8 100644 --- a/google/auth/crypt/_python_rsa.py +++ b/google/auth/crypt/_python_rsa.py @@ -21,12 +21,13 @@ from __future__ import absolute_import +import io + from pyasn1.codec.der import decoder from pyasn1_modules import pem from pyasn1_modules.rfc2459 import Certificate from pyasn1_modules.rfc5208 import PrivateKeyInfo import rsa -import six from google.auth import _helpers from google.auth.crypt import base @@ -52,9 +53,9 @@ def _bit_list_to_bytes(bit_list): """ num_bits = len(bit_list) byte_vals = bytearray() - for start in six.moves.xrange(0, num_bits, 8): + for start in range(0, num_bits, 8): curr_bits = bit_list[start : start + 8] - char_val = sum(val * digit for val, digit in six.moves.zip(_POW2, curr_bits)) + char_val = sum(val * digit for val, digit in zip(_POW2, curr_bits)) byte_vals.append(char_val) return bytes(byte_vals) @@ -152,7 +153,7 @@ def from_string(cls, key, key_id=None): """ key = _helpers.from_bytes(key) # PEM expects str in Python 3 marker_id, key_bytes = pem.readPemBlocksFromFile( - six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER + io.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER ) # Key is in pkcs1 format. diff --git a/google/auth/crypt/base.py b/google/auth/crypt/base.py index c98d5bf64..0bda9c345 100644 --- a/google/auth/crypt/base.py +++ b/google/auth/crypt/base.py @@ -18,15 +18,12 @@ import io import json -import six - _JSON_FILE_PRIVATE_KEY = "private_key" _JSON_FILE_PRIVATE_KEY_ID = "private_key_id" -@six.add_metaclass(abc.ABCMeta) -class Verifier(object): +class Verifier(object, metaclass=abc.ABCMeta): """Abstract base class for crytographic signature verifiers.""" @abc.abstractmethod @@ -46,8 +43,7 @@ def verify(self, message, signature): raise NotImplementedError("Verify must be implemented") -@six.add_metaclass(abc.ABCMeta) -class Signer(object): +class Signer(object, metaclass=abc.ABCMeta): """Abstract base class for cryptographic signers.""" @abc.abstractproperty @@ -70,8 +66,7 @@ def sign(self, message): raise NotImplementedError("Sign must be implemented") -@six.add_metaclass(abc.ABCMeta) -class FromServiceAccountMixin(object): +class FromServiceAccountMixin(object, metaclass=abc.ABCMeta): """Mix-in to enable factory constructors for a Signer.""" @abc.abstractmethod diff --git a/google/auth/external_account.py b/google/auth/external_account.py index 1f3034ac3..24b93b423 100644 --- a/google/auth/external_account.py +++ b/google/auth/external_account.py @@ -33,8 +33,6 @@ import json import re -import six - from google.auth import _helpers from google.auth import credentials from google.auth import exceptions @@ -52,8 +50,9 @@ _CLOUD_RESOURCE_MANAGER = "https://cloudresourcemanager.googleapis.com/v1/projects/" -@six.add_metaclass(abc.ABCMeta) -class Credentials(credentials.Scoped, credentials.CredentialsWithQuotaProject): +class Credentials( + credentials.Scoped, credentials.CredentialsWithQuotaProject, metaclass=abc.ABCMeta +): """Base class for all external account credentials. This is used to instantiate Credentials for exchanging external account diff --git a/google/auth/iam.py b/google/auth/iam.py index 5d63dc5d8..277f4b7f3 100644 --- a/google/auth/iam.py +++ b/google/auth/iam.py @@ -20,10 +20,9 @@ """ import base64 +import http.client import json -from six.moves import http_client - from google.auth import _helpers from google.auth import crypt from google.auth import exceptions @@ -77,7 +76,7 @@ def _make_signing_request(self, message): self._credentials.before_request(self._request, method, url, headers) response = self._request(url=url, method=method, body=body, headers=headers) - if response.status != http_client.OK: + if response.status != http.client.OK: raise exceptions.TransportError( "Error calling the IAM signBlob API: {}".format(response.data) ) diff --git a/google/auth/identity_pool.py b/google/auth/identity_pool.py index 536219955..c331e0921 100644 --- a/google/auth/identity_pool.py +++ b/google/auth/identity_pool.py @@ -33,11 +33,7 @@ access tokens. """ -try: - from collections.abc import Mapping -# Python 2.7 compatibility -except ImportError: # pragma: NO COVER - from collections import Mapping +from collections.abc import Mapping import io import json import os diff --git a/google/auth/impersonated_credentials.py b/google/auth/impersonated_credentials.py index b8a6c49a1..2704bfdd2 100644 --- a/google/auth/impersonated_credentials.py +++ b/google/auth/impersonated_credentials.py @@ -28,11 +28,9 @@ import base64 import copy from datetime import datetime +import http.client import json -import six -from six.moves import http_client - from google.auth import _helpers from google.auth import credentials from google.auth import exceptions @@ -100,7 +98,7 @@ def _make_iam_token_request( else response.data ) - if response.status != http_client.OK: + if response.status != http.client.OK: exceptions.RefreshError(_REFRESH_ERROR, response_body) try: @@ -117,7 +115,7 @@ def _make_iam_token_request( ), response_body, ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc class Credentials(credentials.CredentialsWithQuotaProject, credentials.Signing): diff --git a/google/auth/jwt.py b/google/auth/jwt.py index e9f4f69ca..d931bf7b9 100644 --- a/google/auth/jwt.py +++ b/google/auth/jwt.py @@ -40,18 +40,13 @@ """ -try: - from collections.abc import Mapping -# Python 2.7 compatibility -except ImportError: # pragma: NO COVER - from collections import Mapping +from collections.abc import Mapping import copy import datetime import json +import urllib import cachetools -import six -from six.moves import urllib from google.auth import _helpers from google.auth import _service_account_info @@ -123,7 +118,7 @@ def _decode_jwt_segment(encoded_section): return json.loads(section_bytes.decode("utf-8")) except ValueError as caught_exc: new_exc = ValueError("Can't parse segment: {0}".format(section_bytes)) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc def _unverified_decode(token): @@ -241,19 +236,16 @@ def decode(token, certs=None, verify=True, audience=None): try: verifier_cls = _ALGORITHM_TO_VERIFIER_CLASS[key_alg] - except KeyError as exc: + except KeyError as caught_exc: if key_alg in _CRYPTOGRAPHY_BASED_ALGORITHMS: - six.raise_from( - ValueError( - "The key algorithm {} requires the cryptography package " - "to be installed.".format(key_alg) - ), - exc, + msg = ( + "The key algorithm {} requires the cryptography package " + "to be installed." ) else: - six.raise_from( - ValueError("Unsupported signature algorithm {}".format(key_alg)), exc - ) + msg = "Unsupported signature algorithm {}" + new_exc = ValueError(msg.format(key_alg)) + raise new_exc from caught_exc # If certs is specified as a dictionary of key IDs to certificates, then # use the certificate identified by the key ID in the token header. diff --git a/google/auth/transport/__init__.py b/google/auth/transport/__init__.py index 374e7b4d7..d1b035df9 100644 --- a/google/auth/transport/__init__.py +++ b/google/auth/transport/__init__.py @@ -25,11 +25,9 @@ """ import abc +import http.client -import six -from six.moves import http_client - -DEFAULT_REFRESH_STATUS_CODES = (http_client.UNAUTHORIZED,) +DEFAULT_REFRESH_STATUS_CODES = (http.client.UNAUTHORIZED,) """Sequence[int]: Which HTTP status code indicate that credentials should be refreshed and a request should be retried. """ @@ -38,8 +36,7 @@ """int: How many times to refresh the credentials and retry a request.""" -@six.add_metaclass(abc.ABCMeta) -class Response(object): +class Response(object, metaclass=abc.ABCMeta): """HTTP Response data.""" @abc.abstractproperty @@ -58,8 +55,7 @@ def data(self): raise NotImplementedError("data must be implemented.") -@six.add_metaclass(abc.ABCMeta) -class Request(object): +class Request(object, metaclass=abc.ABCMeta): """Interface for a callable that makes HTTP requests. Specific transport implementations should provide an implementation of diff --git a/google/auth/transport/_aiohttp_requests.py b/google/auth/transport/_aiohttp_requests.py index ab7dfef67..ee9404330 100644 --- a/google/auth/transport/_aiohttp_requests.py +++ b/google/auth/transport/_aiohttp_requests.py @@ -24,7 +24,6 @@ import functools import aiohttp -import six import urllib3 from google.auth import exceptions @@ -191,11 +190,11 @@ async def __call__( except aiohttp.ClientError as caught_exc: new_exc = exceptions.TransportError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc except asyncio.TimeoutError as caught_exc: new_exc = exceptions.TransportError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc class AuthorizedSession(aiohttp.ClientSession): diff --git a/google/auth/transport/_http_client.py b/google/auth/transport/_http_client.py index c153763ef..679087f06 100644 --- a/google/auth/transport/_http_client.py +++ b/google/auth/transport/_http_client.py @@ -14,12 +14,10 @@ """Transport adapter for http.client, for internal use only.""" +import http.client import logging import socket - -import six -from six.moves import http_client -from six.moves import urllib +import urllib from google.auth import exceptions from google.auth import transport @@ -98,7 +96,7 @@ def __call__( "was specified".format(parts.scheme) ) - connection = http_client.HTTPConnection(parts.netloc, timeout=timeout) + connection = http.client.HTTPConnection(parts.netloc, timeout=timeout) try: _LOGGER.debug("Making request: %s %s", method, url) @@ -107,9 +105,9 @@ def __call__( response = connection.getresponse() return Response(response) - except (http_client.HTTPException, socket.error) as caught_exc: + except (http.client.HTTPException, socket.error) as caught_exc: new_exc = exceptions.TransportError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc finally: connection.close() diff --git a/google/auth/transport/_mtls_helper.py b/google/auth/transport/_mtls_helper.py index 4dccb1062..1b9b9c285 100644 --- a/google/auth/transport/_mtls_helper.py +++ b/google/auth/transport/_mtls_helper.py @@ -20,8 +20,6 @@ import re import subprocess -import six - from google.auth import exceptions CONTEXT_AWARE_METADATA_PATH = "~/.secureConnect/context_aware_metadata.json" @@ -82,7 +80,7 @@ def _read_dca_metadata_file(metadata_path): metadata = json.load(f) except ValueError as caught_exc: new_exc = exceptions.ClientCertError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc return metadata @@ -110,7 +108,7 @@ def _run_cert_provider_command(command, expect_encrypted_key=False): stdout, stderr = process.communicate() except OSError as caught_exc: new_exc = exceptions.ClientCertError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc # Check cert provider command execution error. if process.returncode != 0: diff --git a/google/auth/transport/grpc.py b/google/auth/transport/grpc.py index c47cb3dda..160dc946b 100644 --- a/google/auth/transport/grpc.py +++ b/google/auth/transport/grpc.py @@ -19,8 +19,6 @@ import logging import os -import six - from google.auth import environment_vars from google.auth import exceptions from google.auth.transport import _mtls_helper @@ -29,13 +27,11 @@ try: import grpc except ImportError as caught_exc: # pragma: NO COVER - six.raise_from( - ImportError( - "gRPC is not installed, please install the grpcio package " - "to use the gRPC transport." - ), - caught_exc, + new_exc = ImportError( + "gRPC is not installed, please install the grpcio package " + "to use the gRPC transport." ) + raise new_exc from caught_exc _LOGGER = logging.getLogger(__name__) @@ -88,7 +84,7 @@ def _get_authorization_headers(self, context): self._request, context.method_name, context.service_url, headers ) - return list(six.iteritems(headers)) + return list(headers.items()) def __call__(self, context, callback): """Passes authorization metadata into the given callback. @@ -337,7 +333,7 @@ def ssl_credentials(self): ) except exceptions.ClientCertError as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc else: self._ssl_credentials = grpc.ssl_channel_credentials() diff --git a/google/auth/transport/mtls.py b/google/auth/transport/mtls.py index b40bfbedf..c5707617f 100644 --- a/google/auth/transport/mtls.py +++ b/google/auth/transport/mtls.py @@ -14,8 +14,6 @@ """Utilites for mutual TLS.""" -import six - from google.auth import exceptions from google.auth.transport import _mtls_helper @@ -53,7 +51,7 @@ def callback(): _, cert_bytes, key_bytes = _mtls_helper.get_client_cert_and_key() except (OSError, RuntimeError, ValueError) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc return cert_bytes, key_bytes @@ -98,7 +96,7 @@ def callback(): key_file.write(key_bytes) except (exceptions.ClientCertError, OSError) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc return cert_path, key_path, passphrase_bytes diff --git a/google/auth/transport/requests.py b/google/auth/transport/requests.py index 817176bef..2cb694247 100644 --- a/google/auth/transport/requests.py +++ b/google/auth/transport/requests.py @@ -25,21 +25,16 @@ try: import requests except ImportError as caught_exc: # pragma: NO COVER - import six - - six.raise_from( - ImportError( - "The requests library is not installed, please install the " - "requests package to use the requests transport." - ), - caught_exc, + new_exc = ImportError( + "The requests library is not installed, please install the " + "requests package to use the requests transport." ) + raise new_exc from caught_exc import requests.adapters # pylint: disable=ungrouped-imports import requests.exceptions # pylint: disable=ungrouped-imports from requests.packages.urllib3.util.ssl_ import ( create_urllib3_context, ) # pylint: disable=ungrouped-imports -import six # pylint: disable=ungrouped-imports from google.auth import environment_vars from google.auth import exceptions @@ -186,7 +181,7 @@ def __call__( return _Response(response) except requests.exceptions.RequestException as caught_exc: new_exc = exceptions.TransportError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc class _MutualTlsAdapter(requests.adapters.HTTPAdapter): @@ -396,7 +391,7 @@ def configure_mtls_channel(self, client_cert_callback=None): import OpenSSL except ImportError as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc try: ( @@ -416,7 +411,7 @@ def configure_mtls_channel(self, client_cert_callback=None): OpenSSL.crypto.Error, ) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc def request( self, diff --git a/google/auth/transport/urllib3.py b/google/auth/transport/urllib3.py index 6a2504d97..aa7188c55 100644 --- a/google/auth/transport/urllib3.py +++ b/google/auth/transport/urllib3.py @@ -34,16 +34,11 @@ try: import urllib3 except ImportError as caught_exc: # pragma: NO COVER - import six - - six.raise_from( - ImportError( - "The urllib3 library is not installed, please install the " - "urllib3 package to use the urllib3 transport." - ), - caught_exc, + new_exc = ImportError( + "The urllib3 library is not installed, please install the " + "urllib3 package to use the urllib3 transport." ) -import six + raise new_exc from caught_exc import urllib3.exceptions # pylint: disable=ungrouped-imports from google.auth import environment_vars @@ -142,7 +137,7 @@ def __call__( return _Response(response) except urllib3.exceptions.HTTPError as caught_exc: new_exc = exceptions.TransportError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc def _make_default_http(): @@ -334,7 +329,7 @@ def configure_mtls_channel(self, client_cert_callback=None): import OpenSSL except ImportError as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc try: found_cert_key, cert, key = transport._mtls_helper.get_client_cert_and_key( @@ -351,7 +346,7 @@ def configure_mtls_channel(self, client_cert_callback=None): OpenSSL.crypto.Error, ) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc if self._has_user_provided_http: self._has_user_provided_http = False diff --git a/google/oauth2/_client.py b/google/oauth2/_client.py index 2f4e8474b..f819371af 100644 --- a/google/oauth2/_client.py +++ b/google/oauth2/_client.py @@ -24,11 +24,9 @@ """ import datetime +import http.client import json - -import six -from six.moves import http_client -from six.moves import urllib +import urllib from google.auth import _helpers from google.auth import exceptions @@ -120,7 +118,7 @@ def _token_endpoint_request_no_throw( ) response_data = json.loads(response_body) - if response.status == http_client.OK: + if response.status == http.client.OK: break else: error_desc = response_data.get("error_description") or "" @@ -131,9 +129,9 @@ def _token_endpoint_request_no_throw( ): retry += 1 continue - return response.status == http_client.OK, response_data + return response.status == http.client.OK, response_data - return response.status == http_client.OK, response_data + return response.status == http.client.OK, response_data def _token_endpoint_request( @@ -196,7 +194,7 @@ def jwt_grant(request, token_uri, assertion): access_token = response_data["access_token"] except KeyError as caught_exc: new_exc = exceptions.RefreshError("No access token in response.", response_data) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc expiry = _parse_expiry(response_data) @@ -236,7 +234,7 @@ def id_token_jwt_grant(request, token_uri, assertion): id_token = response_data["id_token"] except KeyError as caught_exc: new_exc = exceptions.RefreshError("No ID token in response.", response_data) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc payload = jwt.decode(id_token, verify=False) expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) @@ -265,7 +263,7 @@ def _handle_refresh_grant_response(response_data, refresh_token): access_token = response_data["access_token"] except KeyError as caught_exc: new_exc = exceptions.RefreshError("No access token in response.", response_data) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc refresh_token = response_data.get("refresh_token", refresh_token) expiry = _parse_expiry(response_data) diff --git a/google/oauth2/_client_async.py b/google/oauth2/_client_async.py index cf5121137..8849023e7 100644 --- a/google/oauth2/_client_async.py +++ b/google/oauth2/_client_async.py @@ -24,11 +24,9 @@ """ import datetime +import http.client import json - -import six -from six.moves import http_client -from six.moves import urllib +import urllib from google.auth import exceptions from google.auth import jwt @@ -85,7 +83,7 @@ async def _token_endpoint_request_no_throw( response_data = json.loads(response_body) - if response.status == http_client.OK: + if response.status == http.client.OK: break else: error_desc = response_data.get("error_description") or "" @@ -96,9 +94,9 @@ async def _token_endpoint_request_no_throw( ): retry += 1 continue - return response.status == http_client.OK, response_data + return response.status == http.client.OK, response_data - return response.status == http_client.OK, response_data + return response.status == http.client.OK, response_data async def _token_endpoint_request( @@ -161,7 +159,7 @@ async def jwt_grant(request, token_uri, assertion): access_token = response_data["access_token"] except KeyError as caught_exc: new_exc = exceptions.RefreshError("No access token in response.", response_data) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc expiry = client._parse_expiry(response_data) @@ -201,7 +199,7 @@ async def id_token_jwt_grant(request, token_uri, assertion): id_token = response_data["id_token"] except KeyError as caught_exc: new_exc = exceptions.RefreshError("No ID token in response.", response_data) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc payload = jwt.decode(id_token, verify=False) expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) diff --git a/google/oauth2/_id_token_async.py b/google/oauth2/_id_token_async.py index ab681a9cb..a4a526dc0 100644 --- a/google/oauth2/_id_token_async.py +++ b/google/oauth2/_id_token_async.py @@ -58,12 +58,10 @@ .. _CacheControl: https://cachecontrol.readthedocs.io """ +import http.client import json import os -import six -from six.moves import http_client - from google.auth import environment_vars from google.auth import exceptions from google.auth import jwt @@ -88,7 +86,7 @@ async def _fetch_certs(request, certs_url): """ response = await request(certs_url, method="GET") - if response.status != http_client.OK: + if response.status != http.client.OK: raise exceptions.TransportError( "Could not fetch certificates at {}".format(certs_url) ) @@ -243,10 +241,10 @@ async def fetch_id_token(request, audience): "GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.", caught_exc, ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc - # 2. Try to fetch ID token from metada server if it exists. The code works for GAE and - # Cloud Run metadata server as well. + # 2. Try to fetch ID token from metada server if it exists. The code works + # for GAE and Cloud Run metadata server as well. try: from google.auth import compute_engine from google.auth.compute_engine import _metadata diff --git a/google/oauth2/_reauth_async.py b/google/oauth2/_reauth_async.py index 09e076090..510578bf7 100644 --- a/google/oauth2/_reauth_async.py +++ b/google/oauth2/_reauth_async.py @@ -34,8 +34,6 @@ import sys -from six.moves import range - from google.auth import exceptions from google.oauth2 import _client from google.oauth2 import _client_async diff --git a/google/oauth2/challenges.py b/google/oauth2/challenges.py index d0b070eda..7756a8057 100644 --- a/google/oauth2/challenges.py +++ b/google/oauth2/challenges.py @@ -20,8 +20,6 @@ import getpass import sys -import six - from google.auth import _helpers from google.auth import exceptions @@ -44,8 +42,7 @@ def get_user_password(text): return getpass.getpass(text) -@six.add_metaclass(abc.ABCMeta) -class ReauthChallenge(object): +class ReauthChallenge(object, metaclass=abc.ABCMeta): """Base class for reauth challenges.""" @property diff --git a/google/oauth2/credentials.py b/google/oauth2/credentials.py index 158249ed5..98fd71b04 100644 --- a/google/oauth2/credentials.py +++ b/google/oauth2/credentials.py @@ -35,8 +35,6 @@ import io import json -import six - from google.auth import _cloud_sdk from google.auth import _helpers from google.auth import credentials @@ -336,7 +334,7 @@ def from_authorized_user_info(cls, info, scopes=None): ValueError: If the info is not in the expected format. """ keys_needed = set(("refresh_token", "client_id", "client_secret")) - missing = keys_needed.difference(six.iterkeys(info)) + missing = keys_needed.difference(info) if missing: raise ValueError( diff --git a/google/oauth2/id_token.py b/google/oauth2/id_token.py index 540ccd125..25492ca6c 100644 --- a/google/oauth2/id_token.py +++ b/google/oauth2/id_token.py @@ -55,12 +55,10 @@ .. _CacheControl: https://cachecontrol.readthedocs.io """ +import http.client import json import os -import six -from six.moves import http_client - from google.auth import environment_vars from google.auth import exceptions from google.auth import jwt @@ -97,7 +95,7 @@ def _fetch_certs(request, certs_url): """ response = request(certs_url, method="GET") - if response.status != http_client.OK: + if response.status != http.client.OK: raise exceptions.TransportError( "Could not fetch certificates at {}".format(certs_url) ) @@ -242,10 +240,10 @@ def fetch_id_token(request, audience): "GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.", caught_exc, ) - six.raise_from(new_exc, caught_exc) + raise new_exc from caught_exc - # 2. Try to fetch ID token from metada server if it exists. The code works for GAE and - # Cloud Run metadata server as well. + # 2. Try to fetch ID token from metada server if it exists. The code + # works for GAE and Cloud Run metadata server as well. try: from google.auth import compute_engine from google.auth.compute_engine import _metadata diff --git a/google/oauth2/reauth.py b/google/oauth2/reauth.py index d914fe9a7..fc2629e82 100644 --- a/google/oauth2/reauth.py +++ b/google/oauth2/reauth.py @@ -34,8 +34,6 @@ import sys -from six.moves import range - from google.auth import exceptions from google.oauth2 import _client from google.oauth2 import challenges diff --git a/google/oauth2/sts.py b/google/oauth2/sts.py index ae3c0146b..9f2d68af3 100644 --- a/google/oauth2/sts.py +++ b/google/oauth2/sts.py @@ -31,10 +31,9 @@ .. _rfc8693 section 2.2.1: https://tools.ietf.org/html/rfc8693#section-2.2.1 """ +import http.client import json - -from six.moves import http_client -from six.moves import urllib +import urllib from google.oauth2 import utils @@ -146,7 +145,7 @@ def exchange_token( ) # If non-200 response received, translate to OAuthError exception. - if response.status != http_client.OK: + if response.status != http.client.OK: utils.handle_error_response(response_body) response_data = json.loads(response_body) diff --git a/google/oauth2/utils.py b/google/oauth2/utils.py index 593f03236..c57833daf 100644 --- a/google/oauth2/utils.py +++ b/google/oauth2/utils.py @@ -45,8 +45,6 @@ import enum import json -import six - from google.auth import exceptions @@ -77,8 +75,7 @@ def __init__(self, client_auth_type, client_id, client_secret=None): self.client_secret = client_secret -@six.add_metaclass(abc.ABCMeta) -class OAuthClientAuthHandler(object): +class OAuthClientAuthHandler(object, metaclass=abc.ABCMeta): """Abstract class for handling client authentication in OAuth-based operations. """ diff --git a/noxfile.py b/noxfile.py index 94661df31..d375b03d1 100644 --- a/noxfile.py +++ b/noxfile.py @@ -58,7 +58,7 @@ @nox.session(python="3.7") def lint(session): session.install("flake8", "flake8-import-order", "docutils", BLACK_VERSION) - session.install(".") + session.install("-e", ".") session.run("black", "--check", *BLACK_PATHS) session.run( "flake8", @@ -94,7 +94,7 @@ def unit(session): add_constraints = ["-c", constraints_path] session.install(*(TEST_DEPENDENCIES + add_constraints)) session.install(*(ASYNC_DEPENDENCIES + add_constraints)) - session.install(".", *add_constraints) + session.install("-e", ".", *add_constraints) session.run( "pytest", f"--junitxml=unit_{session.python}_sponge_log.xml", @@ -107,25 +107,11 @@ def unit(session): ) -@nox.session(python=["2.7"]) -def unit_prev_versions(session): - session.install(".") - session.install(*TEST_DEPENDENCIES) - session.run( - "pytest", - f"--junitxml=unit_{session.python}_sponge_log.xml", - "--cov=google.auth", - "--cov=google.oauth2", - "--cov=tests", - "tests", - ) - - @nox.session(python="3.7") def cover(session): session.install(*TEST_DEPENDENCIES) session.install(*(ASYNC_DEPENDENCIES)) - session.install(".") + session.install("-e", ".") session.run( "pytest", "--cov=google.auth", @@ -144,7 +130,7 @@ def docgen(session): session.env["SPHINX_APIDOC_OPTIONS"] = "members,inherited-members,show-inheritance" session.install(*TEST_DEPENDENCIES) session.install("sphinx") - session.install(".") + session.install("-e", ".") session.run("rm", "-r", "docs/reference") session.run( "sphinx-apidoc", @@ -184,7 +170,7 @@ def docs(session): def pypy(session): session.install(*TEST_DEPENDENCIES) session.install(*ASYNC_DEPENDENCIES) - session.install(".") + session.install("-e", ".") session.run( "pytest", f"--junitxml=unit_{session.python}_sponge_log.xml", diff --git a/setup.py b/setup.py index a9bfc9738..54a2c900b 100644 --- a/setup.py +++ b/setup.py @@ -20,23 +20,16 @@ DEPENDENCIES = ( - "cachetools>=2.0.0,<5.0", - "pyasn1-modules>=0.2.1", - # rsa==4.5 is the last version to support 2.7 - # https://github.com/sybrenstuvel/python-rsa/issues/152#issuecomment-643470233 - 'rsa<4.6; python_version < "3.6"', - 'rsa>=3.1.4,<5; python_version >= "3.6"', - "setuptools>=40.3.0", - "six>=1.9.0", + "cachetools >= 2.0.0, < 5.0", + "pyasn1-modules >= 0.2.1", + "rsa >= 3.1.4, < 5", + "setuptools >= 40.3.0", ) extras = { - "aiohttp": [ - "aiohttp >= 3.6.2, < 4.0.0dev; python_version>='3.6'", - "requests >= 2.20.0, < 3.0.0dev", - ], - "pyopenssl": "pyopenssl>=20.0.0", - "reauth": "pyu2f>=0.1.5", + "aiohttp": ["aiohttp >= 3.6.2, < 4.0.0dev", "requests >= 2.20.0, < 3.0.0dev"], + "pyopenssl": "pyopenssl >= 20.0.0", + "reauth": "pyu2f >= 0.1.5", } with io.open("README.rst", "r") as fh: @@ -61,12 +54,10 @@ namespace_packages=("google",), install_requires=DEPENDENCIES, extras_require=extras, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*", + python_requires=">= 3.6", license="Apache 2.0", keywords="google auth oauth client", classifiers=[ - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", diff --git a/system_tests/noxfile.py b/system_tests/noxfile.py index 11c398b97..33e49c37f 100644 --- a/system_tests/noxfile.py +++ b/system_tests/noxfile.py @@ -171,7 +171,7 @@ def configure_cloud_sdk(session, application_default_credentials, project=False) TEST_DEPENDENCIES_ASYNC = ["aiohttp", "pytest-asyncio", "nest-asyncio"] TEST_DEPENDENCIES_SYNC = ["pytest", "requests", "mock"] PYTHON_VERSIONS_ASYNC = ["3.7"] -PYTHON_VERSIONS_SYNC = ["2.7", "3.7"] +PYTHON_VERSIONS_SYNC = ["3.7"] def default(session, *test_paths): @@ -287,50 +287,6 @@ def compute_engine(session): ) -@nox.session(python=["2.7"]) -def app_engine(session): - if SKIP_GAE_TEST_ENV in os.environ: - session.log("Skipping App Engine tests.") - return - - session.install(LIBRARY_DIR) - # Unlike the default tests above, the App Engine system test require a - # 'real' gcloud sdk installation that is configured to deploy to an - # app engine project. - # Grab the project ID from the cloud sdk. - project_id = ( - subprocess.check_output( - ["gcloud", "config", "list", "project", "--format", "value(core.project)"] - ) - .decode("utf-8") - .strip() - ) - - if not project_id: - session.error( - "The Cloud SDK must be installed and configured to deploy to App " "Engine." - ) - - application_url = GAE_APP_URL_TMPL.format(GAE_TEST_APP_SERVICE, project_id) - - # Vendor in the test application's dependencies - session.chdir(os.path.join(HERE, "system_tests_sync/app_engine_test_app")) - session.install(*TEST_DEPENDENCIES_SYNC) - session.run( - "pip", "install", "--target", "lib", "-r", "requirements.txt", silent=True - ) - - # Deploy the application. - session.run("gcloud", "app", "deploy", "-q", "app.yaml") - - # Run the tests - session.env["TEST_APP_URL"] = application_url - session.chdir(HERE) - default( - session, "system_tests_sync/test_app_engine.py", - ) - - @nox.session(python=PYTHON_VERSIONS_SYNC) def grpc(session): session.install(LIBRARY_DIR) diff --git a/system_tests/system_tests_sync/app_engine_test_app/.gitignore b/system_tests/system_tests_sync/app_engine_test_app/.gitignore deleted file mode 100644 index a65b41774..000000000 --- a/system_tests/system_tests_sync/app_engine_test_app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -lib diff --git a/system_tests/system_tests_sync/app_engine_test_app/app.yaml b/system_tests/system_tests_sync/app_engine_test_app/app.yaml deleted file mode 100644 index 872efb37b..000000000 --- a/system_tests/system_tests_sync/app_engine_test_app/app.yaml +++ /dev/null @@ -1,12 +0,0 @@ -api_version: 1 -service: google-auth-system-tests -runtime: python27 -threadsafe: true - -handlers: -- url: .* - script: main.app - -libraries: -- name: ssl - version: 2.7.11 diff --git a/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py b/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py deleted file mode 100644 index 5a832ac6f..000000000 --- a/system_tests/system_tests_sync/app_engine_test_app/appengine_config.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2016 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from google.appengine.ext import vendor - -# Add any libraries installed in the "lib" folder. -vendor.add("lib") - - -# Patch os.path.expanduser. This should be fixed in GAE -# versions released after Nov 2016. -import os.path - - -def patched_expanduser(path): - return path - - -os.path.expanduser = patched_expanduser diff --git a/system_tests/system_tests_sync/app_engine_test_app/main.py b/system_tests/system_tests_sync/app_engine_test_app/main.py deleted file mode 100644 index 33e61d07b..000000000 --- a/system_tests/system_tests_sync/app_engine_test_app/main.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2016 Google LLC All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""App Engine standard application that runs basic system tests for -google.auth.app_engine. - -This application has to run tests manually instead of using pytest because -pytest currently doesn't work on App Engine standard. -""" - -import contextlib -import json -import sys -from StringIO import StringIO -import traceback - -from google.appengine.api import app_identity -import google.auth -from google.auth import _helpers -from google.auth import app_engine -import google.auth.transport.urllib3 -import urllib3.contrib.appengine -import webapp2 - -FAILED_TEST_TMPL = """ -Test {} failed: {} - -Stacktrace: -{} - -Captured output: -{} -""" -TOKEN_INFO_URL = "https://www.googleapis.com/oauth2/v3/tokeninfo" -EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email" -HTTP = urllib3.contrib.appengine.AppEngineManager() -HTTP_REQUEST = google.auth.transport.urllib3.Request(HTTP) - - -def test_credentials(): - credentials = app_engine.Credentials() - scoped_credentials = credentials.with_scopes([EMAIL_SCOPE]) - - scoped_credentials.refresh(None) - - assert scoped_credentials.valid - assert scoped_credentials.token is not None - - # Get token info and verify scope - url = _helpers.update_query( - TOKEN_INFO_URL, {"access_token": scoped_credentials.token} - ) - response = HTTP_REQUEST(url=url, method="GET") - token_info = json.loads(response.data.decode("utf-8")) - - assert token_info["scope"] == EMAIL_SCOPE - - -def test_default(): - credentials, project_id = google.auth.default() - - assert isinstance(credentials, app_engine.Credentials) - assert project_id == app_identity.get_application_id() - - -@contextlib.contextmanager -def capture(): - """Context manager that captures stderr and stdout.""" - oldout, olderr = sys.stdout, sys.stderr - try: - out = StringIO() - sys.stdout, sys.stderr = out, out - yield out - finally: - sys.stdout, sys.stderr = oldout, olderr - - -def run_test_func(func): - with capture() as capsys: - try: - func() - return True, "" - except Exception as exc: - output = FAILED_TEST_TMPL.format( - func.func_name, exc, traceback.format_exc(), capsys.getvalue() - ) - return False, output - - -def run_tests(): - """Runs all tests. - - Returns: - Tuple[bool, str]: A tuple containing True if all tests pass, False - otherwise, and any captured output from the tests. - """ - status = True - output = "" - - tests = (test_credentials, test_default) - - for test in tests: - test_status, test_output = run_test_func(test) - status = status and test_status - output += test_output - - return status, output - - -class MainHandler(webapp2.RequestHandler): - def get(self): - self.response.headers["content-type"] = "text/plain" - - status, output = run_tests() - - if not status: - self.response.status = 500 - - self.response.write(output) - - -app = webapp2.WSGIApplication([("/", MainHandler)], debug=True) diff --git a/system_tests/system_tests_sync/app_engine_test_app/requirements.txt b/system_tests/system_tests_sync/app_engine_test_app/requirements.txt deleted file mode 100644 index bd5c476ab..000000000 --- a/system_tests/system_tests_sync/app_engine_test_app/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -urllib3 -# Relative path to google-auth-python's source. -../../.. diff --git a/system_tests/system_tests_sync/test_app_engine.py b/system_tests/system_tests_sync/test_app_engine.py deleted file mode 100644 index 45a1989a4..000000000 --- a/system_tests/system_tests_sync/test_app_engine.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2016 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -TEST_APP_URL = os.environ["TEST_APP_URL"] - - -def test_live_application(http_request): - response = http_request(method="GET", url=TEST_APP_URL) - assert response.status == 200, response.data.decode("utf-8") diff --git a/system_tests/system_tests_sync/test_external_accounts.py b/system_tests/system_tests_sync/test_external_accounts.py index e24c7b40a..c2855a2c3 100644 --- a/system_tests/system_tests_sync/test_external_accounts.py +++ b/system_tests/system_tests_sync/test_external_accounts.py @@ -32,19 +32,21 @@ # original service account key. +from http.server import BaseHTTPRequestHandler +from http.server import HTTPServer import json import os import socket +import sys from tempfile import NamedTemporaryFile import threading -import sys +import pytest +from mock import patch + import google.auth from googleapiclient import discovery -from six.moves import BaseHTTPServer from google.oauth2 import service_account -import pytest -from mock import patch # Populate values from the output of scripts/setup_external_accounts.sh. _AUDIENCE_OIDC = "//iam.googleapis.com/projects/79992041559/locations/global/workloadIdentityPools/pool-73wslmxn/providers/oidc-73wslmxn" @@ -175,7 +177,7 @@ def test_file_based_external_account( # This test makes sure that setting up an http server to provide credentials # works to allow access to Google resources. def test_url_based_external_account(dns_access, oidc_credentials, service_account_info): - class TestResponseHandler(BaseHTTPServer.BaseHTTPRequestHandler): + class TestResponseHandler(BaseHTTPRequestHandler): def do_GET(self): if self.headers["my-header"] != "expected-value": self.send_response(400) @@ -199,7 +201,7 @@ def do_GET(self): json.dumps({"access_token": oidc_credentials.token}).encode("utf-8") ) - class TestHTTPServer(BaseHTTPServer.HTTPServer, object): + class TestHTTPServer(HTTPServer, object): def __init__(self): self.port = self._find_open_port() super(TestHTTPServer, self).__init__(("", self.port), TestResponseHandler) diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index ad6f59846..6c4dd2e8c 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -8,7 +8,6 @@ cachetools==2.0.0 pyasn1-modules==0.2.1 setuptools==40.3.0 -six==1.9.0 rsa==3.1.4 aiohttp==3.6.2 requests==2.20.0 diff --git a/tests/compute_engine/test__metadata.py b/tests/compute_engine/test__metadata.py index 852822dc0..0bb07b007 100644 --- a/tests/compute_engine/test__metadata.py +++ b/tests/compute_engine/test__metadata.py @@ -13,13 +13,13 @@ # limitations under the License. import datetime +import http.client +import importlib import json import os import mock import pytest -from six.moves import http_client -from six.moves import reload_module from google.auth import _helpers from google.auth import environment_vars @@ -30,7 +30,7 @@ PATH = "instance/service-accounts/default" -def make_request(data, status=http_client.OK, headers=None, retry=False): +def make_request(data, status=http.client.OK, headers=None, retry=False): response = mock.create_autospec(transport.Response, instance=True) response.status = status response.data = _helpers.to_bytes(data) @@ -90,13 +90,13 @@ def test_ping_success_custom_root(): fake_ip = "1.2.3.4" os.environ[environment_vars.GCE_METADATA_IP] = fake_ip - reload_module(_metadata) + importlib.reload(_metadata) try: assert _metadata.ping(request) finally: del os.environ[environment_vars.GCE_METADATA_IP] - reload_module(_metadata) + importlib.reload(_metadata) request.assert_called_once_with( method="GET", @@ -203,13 +203,13 @@ def test_get_success_custom_root_new_variable(): fake_root = "another.metadata.service" os.environ[environment_vars.GCE_METADATA_HOST] = fake_root - reload_module(_metadata) + importlib.reload(_metadata) try: _metadata.get(request, PATH) finally: del os.environ[environment_vars.GCE_METADATA_HOST] - reload_module(_metadata) + importlib.reload(_metadata) request.assert_called_once_with( method="GET", @@ -223,13 +223,13 @@ def test_get_success_custom_root_old_variable(): fake_root = "another.metadata.service" os.environ[environment_vars.GCE_METADATA_ROOT] = fake_root - reload_module(_metadata) + importlib.reload(_metadata) try: _metadata.get(request, PATH) finally: del os.environ[environment_vars.GCE_METADATA_ROOT] - reload_module(_metadata) + importlib.reload(_metadata) request.assert_called_once_with( method="GET", @@ -239,7 +239,7 @@ def test_get_success_custom_root_old_variable(): def test_get_failure(): - request = make_request("Metadata error", status=http_client.NOT_FOUND) + request = make_request("Metadata error", status=http.client.NOT_FOUND) with pytest.raises(exceptions.TransportError) as excinfo: _metadata.get(request, PATH) diff --git a/tests/crypt/test__cryptography_rsa.py b/tests/crypt/test__cryptography_rsa.py index dbf07c780..41dfc3693 100644 --- a/tests/crypt/test__cryptography_rsa.py +++ b/tests/crypt/test__cryptography_rsa.py @@ -60,7 +60,7 @@ class TestRSAVerifier(object): - def test_verify_success(self): + def test_verify_bytes_success(self): to_sign = b"foo" signer = _cryptography_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) @@ -68,8 +68,8 @@ def test_verify_success(self): verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) assert verifier.verify(to_sign, actual_signature) - def test_verify_unicode_success(self): - to_sign = u"foo" + def test_verify_text_success(self): + to_sign = "foo" signer = _cryptography_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) diff --git a/tests/crypt/test__python_rsa.py b/tests/crypt/test__python_rsa.py index 886ee55a2..9ef29ee15 100644 --- a/tests/crypt/test__python_rsa.py +++ b/tests/crypt/test__python_rsa.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import io import json import os @@ -19,7 +20,6 @@ from pyasn1_modules import pem import pytest import rsa -import six from google.auth import _helpers from google.auth.crypt import _python_rsa @@ -63,7 +63,7 @@ class TestRSAVerifier(object): - def test_verify_success(self): + def test_verify_bytes_success(self): to_sign = b"foo" signer = _python_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) @@ -71,8 +71,8 @@ def test_verify_success(self): verifier = _python_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) assert verifier.verify(to_sign, actual_signature) - def test_verify_unicode_success(self): - to_sign = u"foo" + def test_verify_text_success(self): + to_sign = "foo" signer = _python_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) @@ -141,7 +141,7 @@ def test_from_string_pkcs8(self): def test_from_string_pkcs8_extra_bytes(self): key_bytes = PKCS8_KEY_BYTES _, pem_bytes = pem.readPemBlocksFromFile( - six.StringIO(_helpers.from_bytes(key_bytes)), _python_rsa._PKCS8_MARKER + io.StringIO(_helpers.from_bytes(key_bytes)), _python_rsa._PKCS8_MARKER ) key_info, remaining = None, "extra" diff --git a/tests/crypt/test_es256.py b/tests/crypt/test_es256.py index 5bb9050cd..720f74ca2 100644 --- a/tests/crypt/test_es256.py +++ b/tests/crypt/test_es256.py @@ -50,7 +50,7 @@ class TestES256Verifier(object): - def test_verify_success(self): + def test_verify_bytes_success(self): to_sign = b"foo" signer = es256.ES256Signer.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) @@ -58,8 +58,8 @@ def test_verify_success(self): verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) assert verifier.verify(to_sign, actual_signature) - def test_verify_unicode_success(self): - to_sign = u"foo" + def test_verify_text_success(self): + to_sign = "foo" signer = es256.ES256Signer.from_string(PRIVATE_KEY_BYTES) actual_signature = signer.sign(to_sign) diff --git a/tests/oauth2/test__client.py b/tests/oauth2/test__client.py index 54686df59..690a87bc4 100644 --- a/tests/oauth2/test__client.py +++ b/tests/oauth2/test__client.py @@ -13,14 +13,13 @@ # limitations under the License. import datetime +import http.client import json import os +import urllib import mock import pytest -import six -from six.moves import http_client -from six.moves import urllib from google.auth import _helpers from google.auth import crypt @@ -75,7 +74,7 @@ def test__parse_expiry_none(): assert _client._parse_expiry({}) is None -def make_request(response_data, status=http_client.OK): +def make_request(response_data, status=http.client.OK): response = mock.create_autospec(transport.Response, instance=True) response.status = status response.data = json.dumps(response_data).encode("utf-8") @@ -130,7 +129,7 @@ def test__token_endpoint_request_use_json(): def test__token_endpoint_request_error(): - request = make_request({}, status=http_client.BAD_REQUEST) + request = make_request({}, status=http.client.BAD_REQUEST) with pytest.raises(exceptions.RefreshError): _client._token_endpoint_request(request, "http://example.com", {}) @@ -138,7 +137,7 @@ def test__token_endpoint_request_error(): def test__token_endpoint_request_internal_failure_error(): request = make_request( - {"error_description": "internal_failure"}, status=http_client.BAD_REQUEST + {"error_description": "internal_failure"}, status=http.client.BAD_REQUEST ) with pytest.raises(exceptions.RefreshError): @@ -147,7 +146,7 @@ def test__token_endpoint_request_internal_failure_error(): ) request = make_request( - {"error": "internal_failure"}, status=http_client.BAD_REQUEST + {"error": "internal_failure"}, status=http.client.BAD_REQUEST ) with pytest.raises(exceptions.RefreshError): @@ -160,7 +159,7 @@ def verify_request_params(request, params): request_body = request.call_args[1]["body"].decode("utf-8") request_params = urllib.parse.parse_qs(request_body) - for key, value in six.iteritems(params): + for key, value in params.items(): assert request_params[key][0] == value diff --git a/tests/oauth2/test_sts.py b/tests/oauth2/test_sts.py index e8e008df5..b516c8a5b 100644 --- a/tests/oauth2/test_sts.py +++ b/tests/oauth2/test_sts.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import http.client import json +import urllib import mock import pytest -from six.moves import http_client -from six.moves import urllib from google.auth import exceptions from google.auth import transport @@ -67,7 +67,7 @@ def make_client(cls, client_auth=None): return sts.Client(cls.TOKEN_EXCHANGE_ENDPOINT, client_auth) @classmethod - def make_mock_request(cls, data, status=http_client.OK): + def make_mock_request(cls, data, status=http.client.OK): response = mock.create_autospec(transport.Response, instance=True) response.status = status response.data = json.dumps(data).encode("utf-8") @@ -110,7 +110,7 @@ def test_exchange_token_full_success_without_auth(self): "options": urllib.parse.quote(json.dumps(self.ADDON_OPTIONS)), } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -145,7 +145,7 @@ def test_exchange_token_partial_success_without_auth(self): "subject_token_type": self.SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -165,7 +165,7 @@ def test_exchange_token_non200_without_auth(self): """ client = self.make_client() request = self.make_mock_request( - status=http_client.BAD_REQUEST, data=self.ERROR_RESPONSE + status=http.client.BAD_REQUEST, data=self.ERROR_RESPONSE ) with pytest.raises(exceptions.OAuthError) as excinfo: @@ -209,7 +209,7 @@ def test_exchange_token_full_success_with_basic_auth(self): "options": urllib.parse.quote(json.dumps(self.ADDON_OPTIONS)), } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -247,7 +247,7 @@ def test_exchange_token_partial_success_with_basic_auth(self): "subject_token_type": self.SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -268,7 +268,7 @@ def test_exchange_token_non200_with_basic_auth(self): """ client = self.make_client(self.CLIENT_AUTH_BASIC) request = self.make_mock_request( - status=http_client.BAD_REQUEST, data=self.ERROR_RESPONSE + status=http.client.BAD_REQUEST, data=self.ERROR_RESPONSE ) with pytest.raises(exceptions.OAuthError) as excinfo: @@ -313,7 +313,7 @@ def test_exchange_token_full_success_with_reqbody_auth(self): "client_secret": CLIENT_SECRET, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -350,7 +350,7 @@ def test_exchange_token_partial_success_with_reqbody_auth(self): "client_secret": CLIENT_SECRET, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) response = client.exchange_token( @@ -371,7 +371,7 @@ def test_exchange_token_non200_with_reqbody_auth(self): """ client = self.make_client(self.CLIENT_AUTH_REQUEST_BODY) request = self.make_mock_request( - status=http_client.BAD_REQUEST, data=self.ERROR_RESPONSE + status=http.client.BAD_REQUEST, data=self.ERROR_RESPONSE ) with pytest.raises(exceptions.OAuthError) as excinfo: diff --git a/tests/test__helpers.py b/tests/test__helpers.py index 0c0bad2d2..906cf126e 100644 --- a/tests/test__helpers.py +++ b/tests/test__helpers.py @@ -13,9 +13,9 @@ # limitations under the License. import datetime +import urllib import pytest -from six.moves import urllib from google.auth import _helpers @@ -65,8 +65,8 @@ def test_to_bytes_with_bytes(): assert _helpers.to_bytes(value) == value -def test_to_bytes_with_unicode(): - value = u"string-val" +def test_to_bytes_with_text(): + value = "string-val" encoded_value = b"string-val" assert _helpers.to_bytes(value) == encoded_value @@ -76,14 +76,14 @@ def test_to_bytes_with_nonstring_type(): _helpers.to_bytes(object()) -def test_from_bytes_with_unicode(): - value = u"bytes-val" +def test_from_bytes_with_text(): + value = "bytes-val" assert _helpers.from_bytes(value) == value def test_from_bytes_with_bytes(): value = b"string-val" - decoded_value = u"string-val" + decoded_value = "string-val" assert _helpers.from_bytes(value) == decoded_value diff --git a/tests/test__oauth2client.py b/tests/test__oauth2client.py index 6b1112b50..aa06eced2 100644 --- a/tests/test__oauth2client.py +++ b/tests/test__oauth2client.py @@ -13,6 +13,7 @@ # limitations under the License. import datetime +import importlib import os import sys @@ -21,7 +22,6 @@ import oauth2client.contrib.gce import oauth2client.service_account import pytest -from six.moves import reload_module from google.auth import _oauth2client @@ -152,19 +152,19 @@ def test_convert_not_found(): @pytest.fixture def reset__oauth2client_module(): """Reloads the _oauth2client module after a test.""" - reload_module(_oauth2client) + importlib.reload(_oauth2client) def test_import_has_app_engine( mock_oauth2client_gae_imports, reset__oauth2client_module ): - reload_module(_oauth2client) + importlib.reload(_oauth2client) assert _oauth2client._HAS_APPENGINE def test_import_without_oauth2client(monkeypatch, reset__oauth2client_module): monkeypatch.setitem(sys.modules, "oauth2client", None) with pytest.raises(ImportError) as excinfo: - reload_module(_oauth2client) + importlib.reload(_oauth2client) assert excinfo.match("oauth2client") diff --git a/tests/test__service_account_info.py b/tests/test__service_account_info.py index 13b2f85a2..fd2d8c8be 100644 --- a/tests/test__service_account_info.py +++ b/tests/test__service_account_info.py @@ -16,7 +16,6 @@ import os import pytest -import six from google.auth import _service_account_info from google.auth import crypt @@ -55,7 +54,7 @@ def test_from_dict_bad_format(): def test_from_filename(): info, signer = _service_account_info.from_filename(SERVICE_ACCOUNT_JSON_FILE) - for key, value in six.iteritems(SERVICE_ACCOUNT_INFO): + for key, value in SERVICE_ACCOUNT_INFO.items(): assert info[key] == value assert isinstance(signer, crypt.RSASigner) diff --git a/tests/test_aws.py b/tests/test_aws.py index 9ca08d5b2..86594376e 100644 --- a/tests/test_aws.py +++ b/tests/test_aws.py @@ -13,12 +13,12 @@ # limitations under the License. import datetime +import http.client import json +import urllib import mock import pytest -from six.moves import http_client -from six.moves import urllib from google.auth import _helpers from google.auth import aws @@ -952,11 +952,11 @@ def test_retrieve_subject_token_success_temp_creds_no_environment_vars( self.AWS_SIGNATURE_TIME, "%Y-%m-%dT%H:%M:%SZ" ) request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, ) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) @@ -987,9 +987,9 @@ def test_retrieve_subject_token_success_temp_creds_no_environment_vars( # Retrieve subject_token again. Region should not be queried again. new_request = self.make_mock_request( - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, ) @@ -1020,11 +1020,11 @@ def test_retrieve_subject_token_success_permanent_creds_no_environment_vars( self.AWS_SIGNATURE_TIME, "%Y-%m-%dT%H:%M:%SZ" ) request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=security_creds_response, ) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) @@ -1136,7 +1136,7 @@ def test_retrieve_subject_token_success_environment_vars_except_region( ) # Region will be queried since it is not found in envvars. request = self.make_mock_request( - region_status=http_client.OK, region_name=self.AWS_REGION + region_status=http.client.OK, region_name=self.AWS_REGION ) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) @@ -1152,7 +1152,7 @@ def test_retrieve_subject_token_success_environment_vars_except_region( def test_retrieve_subject_token_error_determining_aws_region(self): # Simulate error in retrieving the AWS region. - request = self.make_mock_request(region_status=http_client.BAD_REQUEST) + request = self.make_mock_request(region_status=http.client.BAD_REQUEST) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) with pytest.raises(exceptions.RefreshError) as excinfo: @@ -1163,9 +1163,9 @@ def test_retrieve_subject_token_error_determining_aws_region(self): def test_retrieve_subject_token_error_determining_aws_role(self): # Simulate error in retrieving the AWS role name. request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.BAD_REQUEST, + role_status=http.client.BAD_REQUEST, ) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) @@ -1180,7 +1180,7 @@ def test_retrieve_subject_token_error_determining_security_creds_url(self): credential_source = self.CREDENTIAL_SOURCE.copy() credential_source.pop("url") request = self.make_mock_request( - region_status=http_client.OK, region_name=self.AWS_REGION + region_status=http.client.OK, region_name=self.AWS_REGION ) credentials = self.make_credentials(credential_source=credential_source) @@ -1194,11 +1194,11 @@ def test_retrieve_subject_token_error_determining_security_creds_url(self): def test_retrieve_subject_token_error_determining_aws_security_creds(self): # Simulate error in retrieving the AWS security credentials. request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.BAD_REQUEST, + security_credentials_status=http.client.BAD_REQUEST, ) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) @@ -1232,13 +1232,13 @@ def test_refresh_success_without_impersonation_ignore_default_scopes(self, utcno "subject_token_type": SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, - token_status=http_client.OK, + token_status=http.client.OK, token_data=self.SUCCESS_RESPONSE, ) credentials = self.make_credentials( @@ -1288,13 +1288,13 @@ def test_refresh_success_without_impersonation_use_default_scopes(self, utcnow): "subject_token_type": SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, - token_status=http_client.OK, + token_status=http.client.OK, token_data=self.SUCCESS_RESPONSE, ) credentials = self.make_credentials( @@ -1362,15 +1362,15 @@ def test_refresh_success_with_impersonation_ignore_default_scopes(self, utcnow): "lifetime": "3600s", } request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, - token_status=http_client.OK, + token_status=http.client.OK, token_data=self.SUCCESS_RESPONSE, - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) credentials = self.make_credentials( @@ -1446,15 +1446,15 @@ def test_refresh_success_with_impersonation_use_default_scopes(self, utcnow): "lifetime": "3600s", } request = self.make_mock_request( - region_status=http_client.OK, + region_status=http.client.OK, region_name=self.AWS_REGION, - role_status=http_client.OK, + role_status=http.client.OK, role_name=self.AWS_ROLE, - security_credentials_status=http_client.OK, + security_credentials_status=http.client.OK, security_credentials_data=self.AWS_SECURITY_CREDENTIALS_RESPONSE, - token_status=http_client.OK, + token_status=http.client.OK, token_data=self.SUCCESS_RESPONSE, - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) credentials = self.make_credentials( @@ -1488,7 +1488,7 @@ def test_refresh_success_with_impersonation_use_default_scopes(self, utcnow): assert credentials.default_scopes == SCOPES def test_refresh_with_retrieve_subject_token_error(self): - request = self.make_mock_request(region_status=http_client.BAD_REQUEST) + request = self.make_mock_request(region_status=http.client.BAD_REQUEST) credentials = self.make_credentials(credential_source=self.CREDENTIAL_SOURCE) with pytest.raises(exceptions.RefreshError) as excinfo: diff --git a/tests/test_external_account.py b/tests/test_external_account.py index 7390fb980..e8297dab6 100644 --- a/tests/test_external_account.py +++ b/tests/test_external_account.py @@ -13,12 +13,12 @@ # limitations under the License. import datetime +import http.client import json +import urllib import mock import pytest -from six.moves import http_client -from six.moves import urllib from google.auth import _helpers from google.auth import exceptions @@ -149,7 +149,7 @@ def make_credentials( @classmethod def make_mock_request( cls, - status=http_client.OK, + status=http.client.OK, data=None, impersonation_status=None, impersonation_data=None, @@ -474,7 +474,7 @@ def test_refresh_without_client_auth_success(self, unused_utcnow): "subject_token": "subject_token_0", "subject_token_type": self.SUBJECT_TOKEN_TYPE, } - request = self.make_mock_request(status=http_client.OK, data=response) + request = self.make_mock_request(status=http.client.OK, data=response) credentials = self.make_credentials() credentials.refresh(request) @@ -519,9 +519,9 @@ def test_refresh_impersonation_without_client_auth_success(self): # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=token_response, - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) # Initialize credentials with service account impersonation. @@ -562,7 +562,7 @@ def test_refresh_without_client_auth_success_explicit_user_scopes_ignore_default "subject_token_type": self.SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials( scopes=["scope1", "scope2"], @@ -590,7 +590,7 @@ def test_refresh_without_client_auth_success_explicit_default_scopes_only(self): "subject_token_type": self.SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials( scopes=None, @@ -608,7 +608,7 @@ def test_refresh_without_client_auth_success_explicit_default_scopes_only(self): def test_refresh_without_client_auth_error(self): request = self.make_mock_request( - status=http_client.BAD_REQUEST, data=self.ERROR_RESPONSE + status=http.client.BAD_REQUEST, data=self.ERROR_RESPONSE ) credentials = self.make_credentials() @@ -623,9 +623,9 @@ def test_refresh_without_client_auth_error(self): def test_refresh_impersonation_without_client_auth_error(self): request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE, - impersonation_status=http_client.BAD_REQUEST, + impersonation_status=http.client.BAD_REQUEST, impersonation_data=self.IMPERSONATION_ERROR_RESPONSE, ) credentials = self.make_credentials( @@ -653,7 +653,7 @@ def test_refresh_with_client_auth_success(self): "subject_token_type": self.SUBJECT_TOKEN_TYPE, } request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials( client_id=CLIENT_ID, client_secret=CLIENT_SECRET @@ -703,9 +703,9 @@ def test_refresh_impersonation_with_client_auth_success_ignore_default_scopes(se # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=token_response, - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) # Initialize credentials with service account impersonation and basic auth. @@ -774,9 +774,9 @@ def test_refresh_impersonation_with_client_auth_success_use_default_scopes(self) # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=token_response, - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) # Initialize credentials with service account impersonation and basic auth. @@ -811,7 +811,7 @@ def test_refresh_impersonation_with_client_auth_success_use_default_scopes(self) def test_apply_without_quota_project_id(self): headers = {} request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials() @@ -834,9 +834,9 @@ def test_apply_impersonation_without_quota_project_id(self): # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) # Initialize credentials with service account impersonation. @@ -856,7 +856,7 @@ def test_apply_impersonation_without_quota_project_id(self): def test_apply_with_quota_project_id(self): headers = {"other": "header-value"} request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials(quota_project_id=self.QUOTA_PROJECT_ID) @@ -881,9 +881,9 @@ def test_apply_impersonation_with_quota_project_id(self): # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) # Initialize credentials with service account impersonation. @@ -906,7 +906,7 @@ def test_apply_impersonation_with_quota_project_id(self): def test_before_request(self): headers = {"other": "header-value"} request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials() @@ -938,9 +938,9 @@ def test_before_request_impersonation(self): # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) headers = {"other": "header-value"} @@ -968,7 +968,7 @@ def test_before_request_impersonation(self): def test_before_request_expired(self, utcnow): headers = {} request = self.make_mock_request( - status=http_client.OK, data=self.SUCCESS_RESPONSE + status=http.client.OK, data=self.SUCCESS_RESPONSE ) credentials = self.make_credentials() credentials.token = "token" @@ -1014,9 +1014,9 @@ def test_before_request_impersonation_expired(self, utcnow): # Initialize mock request to handle token exchange and service account # impersonation request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, ) credentials = self.make_credentials( @@ -1132,11 +1132,11 @@ def test_get_project_id_cloud_resource_manager_success(self): # Initialize mock request to handle token exchange, service account # impersonation and cloud resource manager request. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - impersonation_status=http_client.OK, + impersonation_status=http.client.OK, impersonation_data=impersonation_response, - cloud_resource_manager_status=http_client.OK, + cloud_resource_manager_status=http.client.OK, cloud_resource_manager_data=self.CLOUD_RESOURCE_MANAGER_SUCCESS_RESPONSE, ) credentials = self.make_credentials( @@ -1190,9 +1190,9 @@ def test_get_project_id_cloud_resource_manager_error(self): # Simulate resource doesn't have sufficient permissions to access # cloud resource manager. request = self.make_mock_request( - status=http_client.OK, + status=http.client.OK, data=self.SUCCESS_RESPONSE.copy(), - cloud_resource_manager_status=http_client.UNAUTHORIZED, + cloud_resource_manager_status=http.client.UNAUTHORIZED, ) credentials = self.make_credentials(scopes=self.SCOPES) diff --git a/tests/test_iam.py b/tests/test_iam.py index 382713b9b..30ce2279f 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -14,11 +14,11 @@ import base64 import datetime +import http.client import json import mock import pytest -from six.moves import http_client from google.auth import _helpers from google.auth import exceptions @@ -81,7 +81,7 @@ def test_key_id(self): def test_sign_bytes(self): signature = b"DEADBEEF" encoded_signature = base64.b64encode(signature).decode("utf-8") - request = make_request(http_client.OK, data={"signedBlob": encoded_signature}) + request = make_request(http.client.OK, data={"signedBlob": encoded_signature}) credentials = make_credentials() signer = iam.Signer(request, credentials, mock.sentinel.service_account_email) @@ -93,7 +93,7 @@ def test_sign_bytes(self): assert kwargs["headers"]["Content-Type"] == "application/json" def test_sign_bytes_failure(self): - request = make_request(http_client.UNAUTHORIZED) + request = make_request(http.client.UNAUTHORIZED) credentials = make_credentials() signer = iam.Signer(request, credentials, mock.sentinel.service_account_email) diff --git a/tests/test_identity_pool.py b/tests/test_identity_pool.py index b529268fb..efe11b082 100644 --- a/tests/test_identity_pool.py +++ b/tests/test_identity_pool.py @@ -13,13 +13,13 @@ # limitations under the License. import datetime +import http.client import json import os +import urllib import mock import pytest -from six.moves import http_client -from six.moves import urllib from google.auth import _helpers from google.auth import exceptions @@ -87,7 +87,7 @@ def make_mock_response(cls, status, data): @classmethod def make_mock_request( - cls, token_status=http_client.OK, token_data=None, *extra_requests + cls, token_status=http.client.OK, token_data=None, *extra_requests ): responses = [] responses.append(cls.make_mock_response(token_status, token_data)) @@ -208,14 +208,14 @@ def assert_underlying_credentials_refresh( # service account impersonation request. requests = [] if credential_data: - requests.append((http_client.OK, credential_data)) + requests.append((http.client.OK, credential_data)) token_request_index = len(requests) - requests.append((http_client.OK, token_response)) + requests.append((http.client.OK, token_response)) if service_account_impersonation_url: impersonation_request_index = len(requests) - requests.append((http_client.OK, impersonation_response)) + requests.append((http.client.OK, impersonation_response)) request = cls.make_mock_request(*[el for req in requests for el in req]) diff --git a/tests/test_impersonated_credentials.py b/tests/test_impersonated_credentials.py index 90de704a2..126c4c344 100644 --- a/tests/test_impersonated_credentials.py +++ b/tests/test_impersonated_credentials.py @@ -13,12 +13,12 @@ # limitations under the License. import datetime +import http.client import json import os import mock import pytest -from six.moves import http_client from google.auth import _helpers from google.auth import crypt @@ -79,7 +79,7 @@ def mock_authorizedsession_sign(): "google.auth.transport.requests.AuthorizedSession.request", autospec=True ) as auth_session: data = {"keyId": "1", "signedBlob": "c2lnbmF0dXJl"} - auth_session.return_value = MockResponse(data, http_client.OK) + auth_session.return_value = MockResponse(data, http.client.OK) yield auth_session @@ -89,7 +89,7 @@ def mock_authorizedsession_idtoken(): "google.auth.transport.requests.AuthorizedSession.request", autospec=True ) as auth_session: data = {"token": ID_TOKEN_DATA} - auth_session.return_value = MockResponse(data, http_client.OK) + auth_session.return_value = MockResponse(data, http.client.OK) yield auth_session @@ -141,7 +141,7 @@ def test_default_state(self): def make_request( self, data, - status=http_client.OK, + status=http.client.OK, headers=None, side_effect=None, use_data_bytes=True, @@ -169,7 +169,7 @@ def test_refresh_success(self, use_data_bytes, mock_donor_credentials): request = self.make_request( data=json.dumps(response_body), - status=http_client.OK, + status=http.client.OK, use_data_bytes=use_data_bytes, ) @@ -194,7 +194,7 @@ def test_refresh_success_iam_endpoint_override( request = self.make_request( data=json.dumps(response_body), - status=http_client.OK, + status=http.client.OK, use_data_bytes=use_data_bytes, ) @@ -229,7 +229,7 @@ def test_refresh_source_credentials(self, time_skew): ).isoformat("T") + "Z" response_body = {"accessToken": "token", "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) @@ -254,7 +254,7 @@ def test_refresh_failure_malformed_expire_time(self, mock_donor_credentials): response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) with pytest.raises(exceptions.RefreshError) as excinfo: @@ -277,7 +277,7 @@ def test_refresh_failure_unauthorzed(self, mock_donor_credentials): } request = self.make_request( - data=json.dumps(response_body), status=http_client.UNAUTHORIZED + data=json.dumps(response_body), status=http.client.UNAUTHORIZED ) with pytest.raises(exceptions.RefreshError) as excinfo: @@ -294,7 +294,7 @@ def test_refresh_failure_http_error(self, mock_donor_credentials): response_body = {} request = self.make_request( - data=json.dumps(response_body), status=http_client.HTTPException + data=json.dumps(response_body), status=http.client.HTTPException ) with pytest.raises(exceptions.RefreshError) as excinfo: @@ -331,7 +331,7 @@ def test_sign_bytes(self, mock_donor_credentials, mock_authorizedsession_sign): token_response_body = {"accessToken": token, "expireTime": expire_time} response = mock.create_autospec(transport.Response, instance=False) - response.status = http_client.OK + response.status = http.client.OK response.data = _helpers.to_bytes(json.dumps(token_response_body)) request = mock.create_autospec(transport.Request, instance=False) @@ -369,7 +369,7 @@ def test_with_quota_project_iam_endpoint_override( request = self.make_request( data=json.dumps(response_body), - status=http_client.OK, + status=http.client.OK, use_data_bytes=use_data_bytes, ) @@ -394,7 +394,7 @@ def test_id_token_success( response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) @@ -423,7 +423,7 @@ def test_id_token_from_credential( response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) @@ -453,7 +453,7 @@ def test_id_token_with_target_audience( response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) @@ -494,7 +494,7 @@ def test_id_token_with_include_email( response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) @@ -523,7 +523,7 @@ def test_id_token_with_quota_project( response_body = {"accessToken": token, "expireTime": expire_time} request = self.make_request( - data=json.dumps(response_body), status=http_client.OK + data=json.dumps(response_body), status=http.client.OK ) credentials.refresh(request) diff --git a/tests/test_jwt.py b/tests/test_jwt.py index 39c45bd23..0dd7fa968 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -258,9 +258,9 @@ def test_decode_no_key_id(token_factory): def test_decode_unknown_alg(): - headers = json.dumps({u"kid": u"1", u"alg": u"fakealg"}) + headers = json.dumps({"kid": "1", "alg": "fakealg"}) token = b".".join( - map(lambda seg: base64.b64encode(seg.encode("utf-8")), [headers, u"{}", u"sig"]) + map(lambda seg: base64.b64encode(seg.encode("utf-8")), [headers, "{}", "sig"]) ) with pytest.raises(ValueError) as excinfo: @@ -270,9 +270,9 @@ def test_decode_unknown_alg(): def test_decode_missing_crytography_alg(monkeypatch): monkeypatch.delitem(jwt._ALGORITHM_TO_VERIFIER_CLASS, "ES256") - headers = json.dumps({u"kid": u"1", u"alg": u"ES256"}) + headers = json.dumps({"kid": "1", "alg": "ES256"}) token = b".".join( - map(lambda seg: base64.b64encode(seg.encode("utf-8")), [headers, u"{}", u"sig"]) + map(lambda seg: base64.b64encode(seg.encode("utf-8")), [headers, "{}", "sig"]) ) with pytest.raises(ValueError) as excinfo: diff --git a/tests/transport/compliance.py b/tests/transport/compliance.py index e093d761d..a5cb678c3 100644 --- a/tests/transport/compliance.py +++ b/tests/transport/compliance.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import http.client import time import flask import pytest from pytest_localserver.http import WSGIServer -from six.moves import http_client from google.auth import exceptions @@ -43,11 +43,11 @@ def server(self): def index(): header_value = flask.request.headers.get("x-test-header", "value") headers = {"X-Test-Header": header_value} - return "Basic Content", http_client.OK, headers + return "Basic Content", http.client.OK, headers @app.route("/server_error") def server_error(): - return "Error", http_client.INTERNAL_SERVER_ERROR + return "Error", http.client.INTERNAL_SERVER_ERROR @app.route("/wait") def wait(): @@ -65,7 +65,7 @@ def test_request_basic(self, server): request = self.make_request() response = request(url=server.url + "/basic", method="GET") - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "value" assert response.data == b"Basic Content" @@ -73,7 +73,7 @@ def test_request_with_timeout_success(self, server): request = self.make_request() response = request(url=server.url + "/basic", method="GET", timeout=2) - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "value" assert response.data == b"Basic Content" @@ -91,7 +91,7 @@ def test_request_headers(self, server): headers={"x-test-header": "hello world"}, ) - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "hello world" assert response.data == b"Basic Content" @@ -99,7 +99,7 @@ def test_request_error(self, server): request = self.make_request() response = request(url=server.url + "/server_error", method="GET") - assert response.status == http_client.INTERNAL_SERVER_ERROR + assert response.status == http.client.INTERNAL_SERVER_ERROR assert response.data == b"Error" def test_connection_error(self): diff --git a/tests/transport/test_requests.py b/tests/transport/test_requests.py index ed9300d76..8b57e0b4e 100644 --- a/tests/transport/test_requests.py +++ b/tests/transport/test_requests.py @@ -14,6 +14,7 @@ import datetime import functools +import http.client import os import sys @@ -23,7 +24,6 @@ import pytest import requests import requests.adapters -from six.moves import http_client from google.auth import environment_vars from google.auth import exceptions @@ -188,7 +188,7 @@ def test_import_error(self): ) -def make_response(status=http_client.OK, data=None): +def make_response(status=http.client.OK, data=None): response = requests.Response() response.status_code = status response._content = data @@ -249,10 +249,10 @@ def test_request_no_refresh(self): def test_request_refresh(self): credentials = mock.Mock(wraps=CredentialsStub()) - final_response = make_response(status=http_client.OK) + final_response = make_response(status=http.client.OK) # First request will 401, second request will succeed. adapter = AdapterStub( - [make_response(status=http_client.UNAUTHORIZED), final_response] + [make_response(status=http.client.UNAUTHORIZED), final_response] ) authed_session = google.auth.transport.requests.AuthorizedSession( @@ -282,7 +282,7 @@ def test_request_max_allowed_time_timeout_error(self, frozen_time): wraps=TimeTickCredentialsStub(time_tick=tick_one_second) ) adapter = TimeTickAdapterStub( - time_tick=tick_one_second, responses=[make_response(status=http_client.OK)] + time_tick=tick_one_second, responses=[make_response(status=http.client.OK)] ) authed_session = google.auth.transport.requests.AuthorizedSession(credentials) @@ -304,8 +304,8 @@ def test_request_max_allowed_time_w_transport_timeout_no_error(self, frozen_time adapter = TimeTickAdapterStub( time_tick=tick_one_second, responses=[ - make_response(status=http_client.UNAUTHORIZED), - make_response(status=http_client.OK), + make_response(status=http.client.UNAUTHORIZED), + make_response(status=http.client.OK), ], ) @@ -328,8 +328,8 @@ def test_request_max_allowed_time_w_refresh_timeout_no_error(self, frozen_time): adapter = TimeTickAdapterStub( time_tick=tick_one_second, responses=[ - make_response(status=http_client.UNAUTHORIZED), - make_response(status=http_client.OK), + make_response(status=http.client.UNAUTHORIZED), + make_response(status=http.client.OK), ], ) @@ -355,8 +355,8 @@ def test_request_timeout_w_refresh_timeout_timeout_error(self, frozen_time): adapter = TimeTickAdapterStub( time_tick=tick_one_second, responses=[ - make_response(status=http_client.UNAUTHORIZED), - make_response(status=http_client.OK), + make_response(status=http.client.UNAUTHORIZED), + make_response(status=http.client.OK), ], ) diff --git a/tests/transport/test_urllib3.py b/tests/transport/test_urllib3.py index e3848c177..995d3dccd 100644 --- a/tests/transport/test_urllib3.py +++ b/tests/transport/test_urllib3.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import http.client import os import sys import mock import OpenSSL import pytest -from six.moves import http_client import urllib3 from google.auth import environment_vars @@ -84,7 +84,7 @@ def urlopen(self, method, url, body=None, headers=None, **kwargs): class ResponseStub(object): - def __init__(self, status=http_client.OK, data=None): + def __init__(self, status=http.client.OK, data=None): self.status = status self.data = data @@ -141,12 +141,12 @@ def test_urlopen_no_refresh(self): def test_urlopen_refresh(self): credentials = mock.Mock(wraps=CredentialsStub()) - final_response = ResponseStub(status=http_client.OK) + final_response = ResponseStub(status=http.client.OK) # First request will 401, second request will succeed. - http = HttpStub([ResponseStub(status=http_client.UNAUTHORIZED), final_response]) + stub = HttpStub([ResponseStub(status=http.client.UNAUTHORIZED), final_response]) authed_http = google.auth.transport.urllib3.AuthorizedHttp( - credentials, http=http + credentials, http=stub ) authed_http = authed_http.urlopen("GET", "http://example.com") @@ -154,7 +154,7 @@ def test_urlopen_refresh(self): assert authed_http == final_response assert credentials.before_request.call_count == 2 assert credentials.refresh.called - assert http.requests == [ + assert stub.requests == [ ("GET", self.TEST_URL, None, {"authorization": "token"}, {}), ("GET", self.TEST_URL, None, {"authorization": "token1"}, {}), ] diff --git a/tests_async/oauth2/test__client_async.py b/tests_async/oauth2/test__client_async.py index 6e48c4590..66338d56c 100644 --- a/tests_async/oauth2/test__client_async.py +++ b/tests_async/oauth2/test__client_async.py @@ -13,13 +13,12 @@ # limitations under the License. import datetime +import http.client import json +import urllib import mock import pytest -import six -from six.moves import http_client -from six.moves import urllib from google.auth import _helpers from google.auth import _jwt_async as jwt @@ -29,7 +28,7 @@ from tests.oauth2 import test__client as test_client -def make_request(response_data, status=http_client.OK): +def make_request(response_data, status=http.client.OK): response = mock.AsyncMock(spec=["transport.Response"]) response.status = status data = json.dumps(response_data).encode("utf-8") @@ -93,7 +92,7 @@ async def test__token_endpoint_request_json(): @pytest.mark.asyncio async def test__token_endpoint_request_error(): - request = make_request({}, status=http_client.BAD_REQUEST) + request = make_request({}, status=http.client.BAD_REQUEST) with pytest.raises(exceptions.RefreshError): await _client._token_endpoint_request(request, "http://example.com", {}) @@ -102,7 +101,7 @@ async def test__token_endpoint_request_error(): @pytest.mark.asyncio async def test__token_endpoint_request_internal_failure_error(): request = make_request( - {"error_description": "internal_failure"}, status=http_client.BAD_REQUEST + {"error_description": "internal_failure"}, status=http.client.BAD_REQUEST ) with pytest.raises(exceptions.RefreshError): @@ -111,7 +110,7 @@ async def test__token_endpoint_request_internal_failure_error(): ) request = make_request( - {"error": "internal_failure"}, status=http_client.BAD_REQUEST + {"error": "internal_failure"}, status=http.client.BAD_REQUEST ) with pytest.raises(exceptions.RefreshError): @@ -124,7 +123,7 @@ def verify_request_params(request, params): request_body = request.call_args[1]["body"].decode("utf-8") request_params = urllib.parse.parse_qs(request_body) - for key, value in six.iteritems(params): + for key, value in params.items(): assert request_params[key][0] == value diff --git a/tests_async/transport/async_compliance.py b/tests_async/transport/async_compliance.py index 9c4b173c2..385a9236a 100644 --- a/tests_async/transport/async_compliance.py +++ b/tests_async/transport/async_compliance.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import http.client import time import flask import pytest from pytest_localserver.http import WSGIServer -from six.moves import http_client from google.auth import exceptions from tests.transport import compliance @@ -41,11 +41,11 @@ def server(self): def index(): header_value = flask.request.headers.get("x-test-header", "value") headers = {"X-Test-Header": header_value} - return "Basic Content", http_client.OK, headers + return "Basic Content", http.client.OK, headers @app.route("/server_error") def server_error(): - return "Error", http_client.INTERNAL_SERVER_ERROR + return "Error", http.client.INTERNAL_SERVER_ERROR @app.route("/wait") def wait(): @@ -63,7 +63,7 @@ def wait(): async def test_request_basic(self, server): request = self.make_request() response = await request(url=server.url + "/basic", method="GET") - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "value" # Use 13 as this is the length of the data written into the stream. @@ -75,7 +75,7 @@ async def test_request_basic(self, server): async def test_request_basic_with_http(self, server): request = self.make_with_parameter_request() response = await request(url=server.url + "/basic", method="GET") - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "value" # Use 13 as this is the length of the data written into the stream. @@ -88,7 +88,7 @@ async def test_request_with_timeout_success(self, server): request = self.make_request() response = await request(url=server.url + "/basic", method="GET", timeout=2) - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "value" data = await response.data.read(13) @@ -110,7 +110,7 @@ async def test_request_headers(self, server): headers={"x-test-header": "hello world"}, ) - assert response.status == http_client.OK + assert response.status == http.client.OK assert response.headers["x-test-header"] == "hello world" data = await response.data.read(13) @@ -121,7 +121,7 @@ async def test_request_error(self, server): request = self.make_request() response = await request(url=server.url + "/server_error", method="GET") - assert response.status == http_client.INTERNAL_SERVER_ERROR + assert response.status == http.client.INTERNAL_SERVER_ERROR data = await response.data.read(5) assert data == b"Error"