diff --git a/noxfile.py b/noxfile.py index d497f5305..f4b909cff 100644 --- a/noxfile.py +++ b/noxfile.py @@ -30,7 +30,7 @@ "grpcio", ] -ASYNC_DEPENDENCIES = ["pytest-asyncio", "aioresponses"] +ASYNC_DEPENDENCIES = ["pytest-asyncio", "aioresponses", "asynctest"] BLACK_VERSION = "black==19.3b0" BLACK_PATHS = [ @@ -64,9 +64,7 @@ def lint(session): @nox.session(python="3.6") def blacken(session): """Run black. - Format code to uniform standard. - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. That run uses an image that doesn't have 3.6 installed. Before updating this check the state of the `gcp_ubuntu_config` we use for that Kokoro run. diff --git a/setup.py b/setup.py index d3b740a62..522b98103 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,6 @@ DEPENDENCIES = ( "cachetools>=2.0.0,<5.0", - 'enum34; python_version < "3.4"', "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 @@ -28,7 +27,6 @@ 'rsa>=3.1.4,<5; python_version >= "3.5"', "setuptools>=40.3.0", "six>=1.9.0", - 'aiohttp >= 3.6.2, < 4.0.0dev; python_version>="3.6"', ) extras = {"aiohttp": "aiohttp >= 3.6.2, < 4.0.0dev; python_version>='3.6'"} diff --git a/tests/test_identity_pool.py b/tests/test_identity_pool.py index 07a6ee6f1..26da3804a 100644 --- a/tests/test_identity_pool.py +++ b/tests/test_identity_pool.py @@ -72,19 +72,20 @@ class TestCredentials(object): @classmethod def make_mock_request( cls, - data, - status=http_client.OK, - impersonation_data=None, + token_status=http_client.OK, + token_data=None, impersonation_status=None, + impersonation_data=None, ): + responses = [] # STS token exchange request. token_response = mock.create_autospec(transport.Response, instance=True) - token_response.status = status - token_response.data = json.dumps(data).encode("utf-8") - responses = [token_response] + token_response.status = token_status + token_response.data = json.dumps(token_data).encode("utf-8") + responses.append(token_response) # If service account impersonation is requested, mock the expected response. - if impersonation_status and impersonation_status: + if impersonation_status: impersonation_response = mock.create_autospec( transport.Response, instance=True ) @@ -169,8 +170,6 @@ def assert_underlying_credentials_refresh( "subject_token": subject_token, "subject_token_type": subject_token_type, } - if token_scopes == "": - token_request_data.pop("scope", None) # Service account impersonation request/response. impersonation_response = { "accessToken": "SA_ACCESS_TOKEN", @@ -180,8 +179,6 @@ def assert_underlying_credentials_refresh( "Content-Type": "application/json", "authorization": "Bearer {}".format(token_response["access_token"]), } - if quota_project_id: - impersonation_headers["x-goog-user-project"] = quota_project_id impersonation_request_data = { "delegates": None, "scope": scopes, @@ -190,8 +187,8 @@ def assert_underlying_credentials_refresh( # Initialize mock request to handle token exchange and service account # impersonation request. request = cls.make_mock_request( - status=http_client.OK, - data=token_response, + token_status=http_client.OK, + token_data=token_response, impersonation_status=impersonation_status, impersonation_data=impersonation_response, ) @@ -243,7 +240,8 @@ def make_credentials( scopes=scopes, ) - def test_from_info_full_options(self): + @mock.patch.object(identity_pool.Credentials, "__init__", return_value=None) + def test_from_info_full_options(self, mock_init): credentials = identity_pool.Credentials.from_info( { "audience": AUDIENCE, @@ -259,18 +257,19 @@ def test_from_info_full_options(self): # Confirm identity_pool.Credentials instantiated with expected attributes. assert isinstance(credentials, identity_pool.Credentials) - self.assert_underlying_credentials_refresh( - credentials=credentials, + mock_init.assert_called_once_with( audience=AUDIENCE, - subject_token=TEXT_FILE_SUBJECT_TOKEN, subject_token_type=SUBJECT_TOKEN_TYPE, token_url=TOKEN_URL, service_account_impersonation_url=SERVICE_ACCOUNT_IMPERSONATION_URL, - basic_auth_encoding=BASIC_AUTH_ENCODING, + client_id=CLIENT_ID, + client_secret=CLIENT_SECRET, + credential_source=self.CREDENTIAL_SOURCE_TEXT, quota_project_id=QUOTA_PROJECT_ID, ) - def test_from_info_required_options_only(self): + @mock.patch.object(identity_pool.Credentials, "__init__", return_value=None) + def test_from_info_required_options_only(self, mock_init): credentials = identity_pool.Credentials.from_info( { "audience": AUDIENCE, @@ -282,15 +281,19 @@ def test_from_info_required_options_only(self): # Confirm identity_pool.Credentials instantiated with expected attributes. assert isinstance(credentials, identity_pool.Credentials) - self.assert_underlying_credentials_refresh( - credentials=credentials, + mock_init.assert_called_once_with( audience=AUDIENCE, - subject_token=TEXT_FILE_SUBJECT_TOKEN, subject_token_type=SUBJECT_TOKEN_TYPE, token_url=TOKEN_URL, + service_account_impersonation_url=None, + client_id=None, + client_secret=None, + credential_source=self.CREDENTIAL_SOURCE_TEXT, + quota_project_id=None, ) - def test_from_file_full_options(self, tmpdir): + @mock.patch.object(identity_pool.Credentials, "__init__", return_value=None) + def test_from_file_full_options(self, mock_init, tmpdir): info = { "audience": AUDIENCE, "subject_token_type": SUBJECT_TOKEN_TYPE, @@ -307,18 +310,19 @@ def test_from_file_full_options(self, tmpdir): # Confirm identity_pool.Credentials instantiated with expected attributes. assert isinstance(credentials, identity_pool.Credentials) - self.assert_underlying_credentials_refresh( - credentials=credentials, + mock_init.assert_called_once_with( audience=AUDIENCE, - subject_token=TEXT_FILE_SUBJECT_TOKEN, subject_token_type=SUBJECT_TOKEN_TYPE, token_url=TOKEN_URL, service_account_impersonation_url=SERVICE_ACCOUNT_IMPERSONATION_URL, - basic_auth_encoding=BASIC_AUTH_ENCODING, + client_id=CLIENT_ID, + client_secret=CLIENT_SECRET, + credential_source=self.CREDENTIAL_SOURCE_TEXT, quota_project_id=QUOTA_PROJECT_ID, ) - def test_from_file_required_options_only(self, tmpdir): + @mock.patch.object(identity_pool.Credentials, "__init__", return_value=None) + def test_from_file_required_options_only(self, mock_init, tmpdir): info = { "audience": AUDIENCE, "subject_token_type": SUBJECT_TOKEN_TYPE, @@ -331,12 +335,15 @@ def test_from_file_required_options_only(self, tmpdir): # Confirm identity_pool.Credentials instantiated with expected attributes. assert isinstance(credentials, identity_pool.Credentials) - self.assert_underlying_credentials_refresh( - credentials=credentials, + mock_init.assert_called_once_with( audience=AUDIENCE, - subject_token=TEXT_FILE_SUBJECT_TOKEN, subject_token_type=SUBJECT_TOKEN_TYPE, token_url=TOKEN_URL, + service_account_impersonation_url=None, + client_id=None, + client_secret=None, + credential_source=self.CREDENTIAL_SOURCE_TEXT, + quota_project_id=None, ) def test_constructor_invalid_options(self):