From 76563f8ffac07ab23b1f0299183332ccfb90bbb0 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 15 Jun 2026 09:07:56 -0400 Subject: [PATCH 1/5] feat(auth): clean python 3.7 EOL false positives and refactor metrics telemetry --- packages/google-auth/README.rst | 1 + packages/google-auth/google/auth/metrics.py | 22 +++---- .../auth/transport/_aiohttp_requests.py | 2 +- .../google-auth/google/oauth2/credentials.py | 2 +- .../tests/compute_engine/test__metadata.py | 4 +- .../tests/compute_engine/test_credentials.py | 4 +- .../google-auth/tests/oauth2/test__client.py | 4 +- .../google-auth/tests/oauth2/test_reauth.py | 6 +- packages/google-auth/tests/test__default.py | 8 ++- packages/google-auth/tests/test_aws.py | 16 ++--- .../tests/test_external_account.py | 36 +++++----- .../google-auth/tests/test_identity_pool.py | 2 +- .../tests/test_impersonated_credentials.py | 4 +- packages/google-auth/tests/test_metrics.py | 65 ++++++++----------- .../tests_async/test__default_async.py | 8 ++- 15 files changed, 89 insertions(+), 95 deletions(-) diff --git a/packages/google-auth/README.rst b/packages/google-auth/README.rst index f160ef818979..2b40c6212d83 100644 --- a/packages/google-auth/README.rst +++ b/packages/google-auth/README.rst @@ -48,6 +48,7 @@ Unsupported Python Versions - Python 3.6: The last version of this library with support for Python 3.6 was `google.auth == 2.22.0`. +.. version-scanner: ignore-next-line - Python 3.7: The last version of this library with support for Python 3.7 was `google.auth == 2.45.0`. diff --git a/packages/google-auth/google/auth/metrics.py b/packages/google-auth/google/auth/metrics.py index 5511f581f658..89a15d740d7e 100644 --- a/packages/google-auth/google/auth/metrics.py +++ b/packages/google-auth/google/auth/metrics.py @@ -50,7 +50,7 @@ def python_and_auth_lib_version(): # x-goog-api-client header value for access token request via metadata server. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/mds" +# Example: "gl-python/ auth/ auth-request-type/at cred-type/mds" def token_request_access_token_mds(): return "{} {} {}".format( python_and_auth_lib_version(), REQUEST_TYPE_ACCESS_TOKEN, CRED_TYPE_SA_MDS @@ -58,7 +58,7 @@ def token_request_access_token_mds(): # x-goog-api-client header value for ID token request via metadata server. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/mds" +# Example: "gl-python/ auth/ auth-request-type/it cred-type/mds" def token_request_id_token_mds(): return "{} {} {}".format( python_and_auth_lib_version(), REQUEST_TYPE_ID_TOKEN, CRED_TYPE_SA_MDS @@ -66,7 +66,7 @@ def token_request_id_token_mds(): # x-goog-api-client header value for impersonated credentials access token request. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" +# Example: "gl-python/ auth/ auth-request-type/at cred-type/imp" def token_request_access_token_impersonate(): return "{} {} {}".format( python_and_auth_lib_version(), @@ -76,7 +76,7 @@ def token_request_access_token_impersonate(): # x-goog-api-client header value for impersonated credentials ID token request. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/imp" +# Example: "gl-python/ auth/ auth-request-type/it cred-type/imp" def token_request_id_token_impersonate(): return "{} {} {}".format( python_and_auth_lib_version(), REQUEST_TYPE_ID_TOKEN, CRED_TYPE_SA_IMPERSONATE @@ -85,7 +85,7 @@ def token_request_id_token_impersonate(): # x-goog-api-client header value for service account credentials access token # request (assertion flow). -# Example: "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/sa" +# Example: "gl-python/ auth/ auth-request-type/at cred-type/sa" def token_request_access_token_sa_assertion(): return "{} {} {}".format( python_and_auth_lib_version(), REQUEST_TYPE_ACCESS_TOKEN, CRED_TYPE_SA_ASSERTION @@ -94,7 +94,7 @@ def token_request_access_token_sa_assertion(): # x-goog-api-client header value for service account credentials ID token # request (assertion flow). -# Example: "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/sa" +# Example: "gl-python/ auth/ auth-request-type/it cred-type/sa" def token_request_id_token_sa_assertion(): return "{} {} {}".format( python_and_auth_lib_version(), REQUEST_TYPE_ID_TOKEN, CRED_TYPE_SA_ASSERTION @@ -102,7 +102,7 @@ def token_request_id_token_sa_assertion(): # x-goog-api-client header value for user credentials token request. -# Example: "gl-python/3.7 auth/1.1 cred-type/u" +# Example: "gl-python/ auth/ cred-type/u" def token_request_user(): return "{} {}".format(python_and_auth_lib_version(), CRED_TYPE_USER) @@ -111,25 +111,25 @@ def token_request_user(): # x-goog-api-client header value for metadata server ping. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/mds" +# Example: "gl-python/ auth/ auth-request-type/mds" def mds_ping(): return "{} {}".format(python_and_auth_lib_version(), REQUEST_TYPE_MDS_PING) # x-goog-api-client header value for reauth start endpoint calls. -# Example: "gl-python/3.7 auth/1.1 auth-request-type/re-start" +# Example: "gl-python/ auth/ auth-request-type/re-start" def reauth_start(): return "{} {}".format(python_and_auth_lib_version(), REQUEST_TYPE_REAUTH_START) # x-goog-api-client header value for reauth continue endpoint calls. -# Example: "gl-python/3.7 auth/1.1 cred-type/re-cont" +# Example: "gl-python/ auth/ cred-type/re-cont" def reauth_continue(): return "{} {}".format(python_and_auth_lib_version(), REQUEST_TYPE_REAUTH_CONTINUE) # x-goog-api-client header value for BYOID calls to the Security Token Service exchange token endpoint. -# Example: "gl-python/3.7 auth/1.1 google-byoid-sdk source/aws sa-impersonation/true sa-impersonation/true" +# Example: "gl-python/ auth/ google-byoid-sdk source/aws sa-impersonation/true sa-impersonation/true" def byoid_metrics_header(metrics_options): header = "{} {}".format(python_and_auth_lib_version(), BYOID_HEADER_SECTION) for key, value in metrics_options.items(): diff --git a/packages/google-auth/google/auth/transport/_aiohttp_requests.py b/packages/google-auth/google/auth/transport/_aiohttp_requests.py index e8321965e0db..283ab66912ad 100644 --- a/packages/google-auth/google/auth/transport/_aiohttp_requests.py +++ b/packages/google-auth/google/auth/transport/_aiohttp_requests.py @@ -143,7 +143,7 @@ class Request(transport.Request): """ def __init__(self, session=None): - # TODO: Use auto_decompress property for aiohttp 3.7+ + # TODO: Use auto_decompress property for aiohttp 3.7+ # version-scanner: ignore if session is not None and session._auto_decompress: raise exceptions.InvalidOperation( "Client sessions with auto_decompress=True are not supported." diff --git a/packages/google-auth/google/oauth2/credentials.py b/packages/google-auth/google/oauth2/credentials.py index 724cf98bcad2..5edea697bfdc 100644 --- a/packages/google-auth/google/oauth2/credentials.py +++ b/packages/google-auth/google/oauth2/credentials.py @@ -167,7 +167,7 @@ def __init__( def __getstate__(self): """A __getstate__ method must exist for the __setstate__ to be called This is identical to the default implementation. - See https://docs.python.org/3.7/library/pickle.html#object.__setstate__ + See https://docs.python.org/3/library/pickle.html#object.__setstate__ """ state_dict = self.__dict__.copy() # Remove _refresh_handler function as there are limitations pickling and diff --git a/packages/google-auth/tests/compute_engine/test__metadata.py b/packages/google-auth/tests/compute_engine/test__metadata.py index b27e7f7f4fb5..2cf755d1d02e 100644 --- a/packages/google-auth/tests/compute_engine/test__metadata.py +++ b/packages/google-auth/tests/compute_engine/test__metadata.py @@ -64,9 +64,9 @@ ) ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/mds" + "gl-python/ auth/ auth-request-type/at cred-type/mds" ) -MDS_PING_METRICS_HEADER_VALUE = "gl-python/3.7 auth/1.1 auth-request-type/mds" +MDS_PING_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/mds" MDS_PING_REQUEST_HEADER = { "metadata-flavor": "Google", "x-goog-api-client": MDS_PING_METRICS_HEADER_VALUE, diff --git a/packages/google-auth/tests/compute_engine/test_credentials.py b/packages/google-auth/tests/compute_engine/test_credentials.py index 7fb2b8b504fc..5a4d6d1c6b10 100644 --- a/packages/google-auth/tests/compute_engine/test_credentials.py +++ b/packages/google-auth/tests/compute_engine/test_credentials.py @@ -44,10 +44,10 @@ ) ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/mds" + "gl-python/ auth/ auth-request-type/at cred-type/mds" ) ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/mds" + "gl-python/ auth/ auth-request-type/it cred-type/mds" ) FAKE_SERVICE_ACCOUNT_EMAIL = "foo@bar.com" FAKE_QUOTA_PROJECT_ID = "fake-quota-project" diff --git a/packages/google-auth/tests/oauth2/test__client.py b/packages/google-auth/tests/oauth2/test__client.py index b20a8042d5f5..77253e5c2d5e 100644 --- a/packages/google-auth/tests/oauth2/test__client.py +++ b/packages/google-auth/tests/oauth2/test__client.py @@ -47,10 +47,10 @@ ) ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/sa" + "gl-python/ auth/ auth-request-type/at cred-type/sa" ) ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/sa" + "gl-python/ auth/ auth-request-type/it cred-type/sa" ) diff --git a/packages/google-auth/tests/oauth2/test_reauth.py b/packages/google-auth/tests/oauth2/test_reauth.py index ef19e4c8492c..402611bc428f 100644 --- a/packages/google-auth/tests/oauth2/test_reauth.py +++ b/packages/google-auth/tests/oauth2/test_reauth.py @@ -40,11 +40,11 @@ "encodedProofOfReauthToken": "new_rapt_token", } -REAUTH_START_METRICS_HEADER_VALUE = "gl-python/3.7 auth/1.1 auth-request-type/re-start" +REAUTH_START_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/re-start" REAUTH_CONTINUE_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/re-cont" + "gl-python/ auth/ auth-request-type/re-cont" ) -TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/3.7 auth/1.1 cred-type/u" +TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ cred-type/u" class MockChallenge(object): diff --git a/packages/google-auth/tests/test__default.py b/packages/google-auth/tests/test__default.py index 9690377cc624..cb6368b3afda 100644 --- a/packages/google-auth/tests/test__default.py +++ b/packages/google-auth/tests/test__default.py @@ -14,6 +14,7 @@ import json import os +import sys from unittest import mock import warnings @@ -773,7 +774,7 @@ def test__get_gae_credentials_gen1(app_identity): @mock.patch.dict(os.environ) def test__get_gae_credentials_gen2(): - os.environ["GAE_RUNTIME"] = "python37" + os.environ["GAE_RUNTIME"] = f"python{sys.version_info.major}{sys.version_info.minor}" credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None @@ -783,8 +784,9 @@ def test__get_gae_credentials_gen2(): def test__get_gae_credentials_gen2_backwards_compat(): # compat helpers may copy GAE_RUNTIME to APPENGINE_RUNTIME # for backwards compatibility with code that relies on it - os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python37" - os.environ["GAE_RUNTIME"] = "python37" + current_runtime = f"python{sys.version_info.major}{sys.version_info.minor}" + os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = current_runtime + os.environ["GAE_RUNTIME"] = current_runtime credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None diff --git a/packages/google-auth/tests/test_aws.py b/packages/google-auth/tests/test_aws.py index b6b1ca2319ed..b034814a7d5f 100644 --- a/packages/google-auth/tests/test_aws.py +++ b/packages/google-auth/tests/test_aws.py @@ -29,10 +29,10 @@ from google.auth.credentials import DEFAULT_UNIVERSE_DOMAIN IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" + "gl-python/ auth/ auth-request-type/at cred-type/imp" ) -LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/3.7 auth/1.1" +LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/ auth/" CLIENT_ID = "username" CLIENT_SECRET = "password" @@ -1913,7 +1913,7 @@ def test_refresh_success_without_impersonation_ignore_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false source/aws", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false source/aws", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1972,7 +1972,7 @@ def test_refresh_success_without_impersonation_use_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false source/aws", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false source/aws", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2038,7 +2038,7 @@ def test_refresh_success_with_impersonation_ignore_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false source/aws", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false source/aws", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2133,7 +2133,7 @@ def test_refresh_success_with_impersonation_use_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false source/aws", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false source/aws", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2328,7 +2328,7 @@ def test_refresh_success_with_supplier_with_impersonation( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false source/programmatic", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false source/programmatic", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2414,7 +2414,7 @@ def test_refresh_success_with_supplier(self, utcnow, mock_auth_lib_value): token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + BASIC_AUTH_ENCODING, - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false source/programmatic", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false source/programmatic", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", diff --git a/packages/google-auth/tests/test_external_account.py b/packages/google-auth/tests/test_external_account.py index 870b07d47b6e..4609bba0b814 100644 --- a/packages/google-auth/tests/test_external_account.py +++ b/packages/google-auth/tests/test_external_account.py @@ -28,9 +28,9 @@ from google.auth.credentials import TokenState IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" + "gl-python/ auth/ auth-request-type/at cred-type/imp" ) -LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/3.7 auth/1.1" +LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/ auth/" CLIENT_ID = "username" CLIENT_SECRET = "password" @@ -686,7 +686,7 @@ def test_refresh_without_client_auth_success( ) headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -751,7 +751,7 @@ def test_refresh_with_mtls( ) headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -790,7 +790,7 @@ def test_refresh_workforce_without_client_auth_success( ) headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -832,7 +832,7 @@ def test_refresh_workforce_with_client_auth_success( headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic {}".format(BASIC_AUTH_ENCODING), - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -874,7 +874,7 @@ def test_refresh_workforce_with_client_auth_and_no_workforce_project_success( headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic {}".format(BASIC_AUTH_ENCODING), - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -919,7 +919,7 @@ def test_refresh_impersonation_without_client_auth_success( token_response = self.SUCCESS_RESPONSE.copy() token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1059,7 +1059,7 @@ def test_refresh_impersonation_with_mtls_success( token_response = self.SUCCESS_RESPONSE.copy() token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1142,7 +1142,7 @@ def test_refresh_workforce_impersonation_without_client_auth_success( token_response = self.SUCCESS_RESPONSE.copy() token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1213,7 +1213,7 @@ def test_refresh_without_client_auth_success_explicit_user_scopes_ignore_default ): headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1250,7 +1250,7 @@ def test_refresh_without_client_auth_success_explicit_default_scopes_only( ): headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1349,7 +1349,7 @@ def test_refresh_with_client_auth_success(self, mock_auth_lib_value): headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic {}".format(BASIC_AUTH_ENCODING), - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1393,7 +1393,7 @@ def test_refresh_impersonation_with_client_auth_success_ignore_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic {}".format(BASIC_AUTH_ENCODING), - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1476,7 +1476,7 @@ def test_refresh_impersonation_with_client_auth_success_use_default_scopes( token_headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic {}".format(BASIC_AUTH_ENCODING), - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1967,7 +1967,7 @@ def test_get_project_id_cloud_resource_manager_success( token_response = self.SUCCESS_RESPONSE.copy() token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2064,7 +2064,7 @@ def test_workforce_pool_get_project_id_cloud_resource_manager_success( # STS token exchange request/response. token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/false config-lifetime/false", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/false config-lifetime/false", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -2145,7 +2145,7 @@ def test_refresh_impersonation_with_lifetime( token_response = self.SUCCESS_RESPONSE.copy() token_headers = { "Content-Type": "application/x-www-form-urlencoded", - "x-goog-api-client": "gl-python/3.7 auth/1.1 google-byoid-sdk sa-impersonation/true config-lifetime/true", + "x-goog-api-client": "gl-python/ auth/ google-byoid-sdk sa-impersonation/true config-lifetime/true", } token_request_data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", diff --git a/packages/google-auth/tests/test_identity_pool.py b/packages/google-auth/tests/test_identity_pool.py index c68fac64708d..410bfa5b2bd2 100644 --- a/packages/google-auth/tests/test_identity_pool.py +++ b/packages/google-auth/tests/test_identity_pool.py @@ -369,7 +369,7 @@ def assert_underlying_credentials_refresh( ) metrics_header_value = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" + "gl-python/ auth/ auth-request-type/at cred-type/imp" ) if service_account_impersonation_url: # Service account impersonation request/response. diff --git a/packages/google-auth/tests/test_impersonated_credentials.py b/packages/google-auth/tests/test_impersonated_credentials.py index c286e3010f38..59ab731ef452 100644 --- a/packages/google-auth/tests/test_impersonated_credentials.py +++ b/packages/google-auth/tests/test_impersonated_credentials.py @@ -60,10 +60,10 @@ TOKEN_URI = "https://example.com/oauth2/token" ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" + "gl-python/ auth/ auth-request-type/at cred-type/imp" ) ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/imp" + "gl-python/ auth/ auth-request-type/it cred-type/imp" ) diff --git a/packages/google-auth/tests/test_metrics.py b/packages/google-auth/tests/test_metrics.py index c2e4014a06c7..b4ce0064c9bd 100644 --- a/packages/google-auth/tests/test_metrics.py +++ b/packages/google-auth/tests/test_metrics.py @@ -15,6 +15,8 @@ import platform from unittest import mock +import pytest + from google.auth import metrics from google.auth import version @@ -33,63 +35,50 @@ def test_add_metric_header(): assert headers == {"x-goog-api-client": "bar"} -@mock.patch.object(platform, "python_version", return_value="3.7") +@mock.patch.object(platform, "python_version", return_value="") def test_versions(mock_python_version): version_save = version.__version__ - version.__version__ = "1.1" - assert metrics.python_and_auth_lib_version() == "gl-python/3.7 auth/1.1" + version.__version__ = "" + assert metrics.python_and_auth_lib_version() == "gl-python/ auth/" version.__version__ = version_save +@pytest.mark.parametrize( + "func, expected_suffix", + [ + (metrics.token_request_access_token_mds, "auth-request-type/at cred-type/mds"), + (metrics.token_request_id_token_mds, "auth-request-type/it cred-type/mds"), + (metrics.token_request_access_token_impersonate, "auth-request-type/at cred-type/imp"), + (metrics.token_request_id_token_impersonate, "auth-request-type/it cred-type/imp"), + (metrics.token_request_access_token_sa_assertion, "auth-request-type/at cred-type/sa"), + (metrics.token_request_id_token_sa_assertion, "auth-request-type/it cred-type/sa"), + (metrics.token_request_user, "cred-type/u"), + (metrics.mds_ping, "auth-request-type/mds"), + (metrics.reauth_start, "auth-request-type/re-start"), + (metrics.reauth_continue, "auth-request-type/re-cont"), + ], +) @mock.patch( "google.auth.metrics.python_and_auth_lib_version", - return_value="gl-python/3.7 auth/1.1", + return_value="gl-python/ auth/", ) -def test_metric_values(mock_python_and_auth_lib_version): - assert ( - metrics.token_request_access_token_mds() - == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/mds" - ) - assert ( - metrics.token_request_id_token_mds() - == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/mds" - ) - assert ( - metrics.token_request_access_token_impersonate() - == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" - ) - assert ( - metrics.token_request_id_token_impersonate() - == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/imp" - ) - assert ( - metrics.token_request_access_token_sa_assertion() - == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/sa" - ) - assert ( - metrics.token_request_id_token_sa_assertion() - == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/sa" - ) - assert metrics.token_request_user() == "gl-python/3.7 auth/1.1 cred-type/u" - assert metrics.mds_ping() == "gl-python/3.7 auth/1.1 auth-request-type/mds" - assert metrics.reauth_start() == "gl-python/3.7 auth/1.1 auth-request-type/re-start" - assert ( - metrics.reauth_continue() == "gl-python/3.7 auth/1.1 auth-request-type/re-cont" - ) +def test_metric_values(mock_version, func, expected_suffix): + expected = f"gl-python/ auth/ {expected_suffix}".strip() + assert func() == expected @mock.patch( "google.auth.metrics.python_and_auth_lib_version", - return_value="gl-python/3.7 auth/1.1", + return_value="gl-python/ auth/", ) def test_byoid_metric_header(mock_python_and_auth_lib_version): metrics_options = {} assert ( metrics.byoid_metrics_header(metrics_options) - == "gl-python/3.7 auth/1.1 google-byoid-sdk" + == "gl-python/ auth/ google-byoid-sdk" ) metrics_options["testKey"] = "testValue" assert ( metrics.byoid_metrics_header(metrics_options) - == "gl-python/3.7 auth/1.1 google-byoid-sdk testKey/testValue" + == "gl-python/ auth/ google-byoid-sdk testKey/testValue" ) diff --git a/packages/google-auth/tests_async/test__default_async.py b/packages/google-auth/tests_async/test__default_async.py index a1268bdc05db..88d511247a98 100644 --- a/packages/google-auth/tests_async/test__default_async.py +++ b/packages/google-auth/tests_async/test__default_async.py @@ -14,6 +14,7 @@ import json import os +import sys from unittest import mock import pytest # type: ignore @@ -306,7 +307,7 @@ def test__get_gae_credentials_gen1(app_identity): @mock.patch.dict(os.environ) def test__get_gae_credentials_gen2(): - os.environ["GAE_RUNTIME"] = "python37" + os.environ["GAE_RUNTIME"] = f"python{sys.version_info.major}{sys.version_info.minor}" credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None @@ -316,8 +317,9 @@ def test__get_gae_credentials_gen2(): def test__get_gae_credentials_gen2_backwards_compat(): # compat helpers may copy GAE_RUNTIME to APPENGINE_RUNTIME # for backwards compatibility with code that relies on it - os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = "python37" - os.environ["GAE_RUNTIME"] = "python37" + current_runtime = f"python{sys.version_info.major}{sys.version_info.minor}" + os.environ[environment_vars.LEGACY_APPENGINE_RUNTIME] = current_runtime + os.environ["GAE_RUNTIME"] = current_runtime credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None From 98e676e99aebb4e19f3659ca6a91c6143c3b88c6 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 15 Jun 2026 09:33:57 -0400 Subject: [PATCH 2/5] docs: remove legacy unsupported versions from README and clean up aiohttp transport --- packages/google-auth/README.rst | 14 -------------- .../google/auth/transport/_aiohttp_requests.py | 3 +-- .../tests_async/transport/test_aiohttp_requests.py | 4 ++-- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/packages/google-auth/README.rst b/packages/google-auth/README.rst index 2b40c6212d83..61ea9a2302ac 100644 --- a/packages/google-auth/README.rst +++ b/packages/google-auth/README.rst @@ -37,20 +37,6 @@ Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ Python >= 3.10 -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`. - -- Python 3.6: The last version of this library with support for Python 3.6 - was `google.auth == 2.22.0`. - -.. version-scanner: ignore-next-line -- Python 3.7: The last version of this library with support for Python 3.7 - was `google.auth == 2.45.0`. Documentation diff --git a/packages/google-auth/google/auth/transport/_aiohttp_requests.py b/packages/google-auth/google/auth/transport/_aiohttp_requests.py index 283ab66912ad..1270744fa877 100644 --- a/packages/google-auth/google/auth/transport/_aiohttp_requests.py +++ b/packages/google-auth/google/auth/transport/_aiohttp_requests.py @@ -143,8 +143,7 @@ class Request(transport.Request): """ def __init__(self, session=None): - # TODO: Use auto_decompress property for aiohttp 3.7+ # version-scanner: ignore - if session is not None and session._auto_decompress: + if session is not None and session.auto_decompress: raise exceptions.InvalidOperation( "Client sessions with auto_decompress=True are not supported." ) diff --git a/packages/google-auth/tests_async/transport/test_aiohttp_requests.py b/packages/google-auth/tests_async/transport/test_aiohttp_requests.py index d6a24da2e302..68abd41940b9 100644 --- a/packages/google-auth/tests_async/transport/test_aiohttp_requests.py +++ b/packages/google-auth/tests_async/transport/test_aiohttp_requests.py @@ -123,7 +123,7 @@ async def test_unsupported_session(self): def test_timeout(self): http = mock.create_autospec( - aiohttp.ClientSession, instance=True, _auto_decompress=False + aiohttp.ClientSession, instance=True, auto_decompress=False ) request = aiohttp_requests.Request(http) request(url="http://example.com", method="GET", timeout=5) @@ -153,7 +153,7 @@ async def test_constructor(self): @pytest.mark.asyncio async def test_constructor_with_auth_request(self): http = mock.create_autospec( - aiohttp.ClientSession, instance=True, _auto_decompress=False + aiohttp.ClientSession, instance=True, auto_decompress=False ) auth_request = aiohttp_requests.Request(http) From 12dba1b7e892597e12f3a65c27c1aadfe5caebb3 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 15 Jun 2026 10:08:30 -0400 Subject: [PATCH 3/5] test(auth): add explanatory mock comments and rename parameters in test_metrics.py --- packages/google-auth/tests/test_metrics.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/google-auth/tests/test_metrics.py b/packages/google-auth/tests/test_metrics.py index b4ce0064c9bd..5ba1d47d894c 100644 --- a/packages/google-auth/tests/test_metrics.py +++ b/packages/google-auth/tests/test_metrics.py @@ -62,7 +62,9 @@ def test_versions(mock_python_version): "google.auth.metrics.python_and_auth_lib_version", return_value="gl-python/ auth/", ) -def test_metric_values(mock_version, func, expected_suffix): +def test_metric_values(mock_python_and_auth_lib_version, func, expected_suffix): + # mock_python_and_auth_lib_version is injected by mock.patch but is not + # explicitly referenced in the test body as the mock behaves as configured. expected = f"gl-python/ auth/ {expected_suffix}".strip() assert func() == expected @@ -72,6 +74,8 @@ def test_metric_values(mock_version, func, expected_suffix): return_value="gl-python/ auth/", ) def test_byoid_metric_header(mock_python_and_auth_lib_version): + # mock_python_and_auth_lib_version is injected by mock.patch but is not + # explicitly referenced in the test body as the mock behaves as configured. metrics_options = {} assert ( metrics.byoid_metrics_header(metrics_options) From 21c1679d1f55fc54383ab956cfb08e28529dca1c Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 15 Jun 2026 10:11:19 -0400 Subject: [PATCH 4/5] style(auth): format metrics and GAE default tests using black --- .../tests/compute_engine/test__metadata.py | 6 ++-- .../tests/compute_engine/test_credentials.py | 8 ++--- .../google-auth/tests/oauth2/test__client.py | 8 ++--- .../google-auth/tests/oauth2/test_reauth.py | 8 +++-- packages/google-auth/tests/test__default.py | 4 ++- packages/google-auth/tests/test_aws.py | 4 +-- .../tests/test_external_account.py | 4 +-- .../google-auth/tests/test_identity_pool.py | 4 +-- .../tests/test_impersonated_credentials.py | 8 ++--- packages/google-auth/tests/test_metrics.py | 29 +++++++++++++++---- .../tests_async/test__default_async.py | 4 ++- 11 files changed, 47 insertions(+), 40 deletions(-) diff --git a/packages/google-auth/tests/compute_engine/test__metadata.py b/packages/google-auth/tests/compute_engine/test__metadata.py index 2cf755d1d02e..199683f7b8c2 100644 --- a/packages/google-auth/tests/compute_engine/test__metadata.py +++ b/packages/google-auth/tests/compute_engine/test__metadata.py @@ -63,10 +63,10 @@ b"-----END CERTIFICATE-----\n" ) -ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/mds" +ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/mds" +MDS_PING_METRICS_HEADER_VALUE = ( + "gl-python/ auth/ auth-request-type/mds" ) -MDS_PING_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/mds" MDS_PING_REQUEST_HEADER = { "metadata-flavor": "Google", "x-goog-api-client": MDS_PING_METRICS_HEADER_VALUE, diff --git a/packages/google-auth/tests/compute_engine/test_credentials.py b/packages/google-auth/tests/compute_engine/test_credentials.py index 5a4d6d1c6b10..de37656dcee3 100644 --- a/packages/google-auth/tests/compute_engine/test_credentials.py +++ b/packages/google-auth/tests/compute_engine/test_credentials.py @@ -43,12 +43,8 @@ b"bsxbLa6Fp0SYeYwO8ifEnkRvasVpc1WTQqfRB2JCj5pTBDzJpIpFCMmnQ" ) -ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/mds" -) -ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/it cred-type/mds" -) +ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/mds" +ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/it cred-type/mds" FAKE_SERVICE_ACCOUNT_EMAIL = "foo@bar.com" FAKE_QUOTA_PROJECT_ID = "fake-quota-project" FAKE_SCOPES = ["scope1", "scope2"] diff --git a/packages/google-auth/tests/oauth2/test__client.py b/packages/google-auth/tests/oauth2/test__client.py index 77253e5c2d5e..0d17b3317856 100644 --- a/packages/google-auth/tests/oauth2/test__client.py +++ b/packages/google-auth/tests/oauth2/test__client.py @@ -46,12 +46,8 @@ " https://www.googleapis.com/auth/logging.write" ) -ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/sa" -) -ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/it cred-type/sa" -) +ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/sa" +ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/it cred-type/sa" @pytest.mark.parametrize("retryable", [True, False]) diff --git a/packages/google-auth/tests/oauth2/test_reauth.py b/packages/google-auth/tests/oauth2/test_reauth.py index 402611bc428f..0949def39528 100644 --- a/packages/google-auth/tests/oauth2/test_reauth.py +++ b/packages/google-auth/tests/oauth2/test_reauth.py @@ -40,11 +40,15 @@ "encodedProofOfReauthToken": "new_rapt_token", } -REAUTH_START_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/re-start" +REAUTH_START_METRICS_HEADER_VALUE = ( + "gl-python/ auth/ auth-request-type/re-start" +) REAUTH_CONTINUE_METRICS_HEADER_VALUE = ( "gl-python/ auth/ auth-request-type/re-cont" ) -TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ cred-type/u" +TOKEN_REQUEST_METRICS_HEADER_VALUE = ( + "gl-python/ auth/ cred-type/u" +) class MockChallenge(object): diff --git a/packages/google-auth/tests/test__default.py b/packages/google-auth/tests/test__default.py index cb6368b3afda..fa2de3b9084e 100644 --- a/packages/google-auth/tests/test__default.py +++ b/packages/google-auth/tests/test__default.py @@ -774,7 +774,9 @@ def test__get_gae_credentials_gen1(app_identity): @mock.patch.dict(os.environ) def test__get_gae_credentials_gen2(): - os.environ["GAE_RUNTIME"] = f"python{sys.version_info.major}{sys.version_info.minor}" + os.environ[ + "GAE_RUNTIME" + ] = f"python{sys.version_info.major}{sys.version_info.minor}" credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None diff --git a/packages/google-auth/tests/test_aws.py b/packages/google-auth/tests/test_aws.py index b034814a7d5f..ce578af7b871 100644 --- a/packages/google-auth/tests/test_aws.py +++ b/packages/google-auth/tests/test_aws.py @@ -28,9 +28,7 @@ from google.auth import transport from google.auth.credentials import DEFAULT_UNIVERSE_DOMAIN -IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/imp" -) +IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/imp" LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/ auth/" diff --git a/packages/google-auth/tests/test_external_account.py b/packages/google-auth/tests/test_external_account.py index 4609bba0b814..77d4ff0b327a 100644 --- a/packages/google-auth/tests/test_external_account.py +++ b/packages/google-auth/tests/test_external_account.py @@ -27,9 +27,7 @@ from google.auth.credentials import DEFAULT_UNIVERSE_DOMAIN from google.auth.credentials import TokenState -IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/imp" -) +IMPERSONATE_ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/imp" LANG_LIBRARY_METRICS_HEADER_VALUE = "gl-python/ auth/" CLIENT_ID = "username" diff --git a/packages/google-auth/tests/test_identity_pool.py b/packages/google-auth/tests/test_identity_pool.py index 410bfa5b2bd2..18e5ca9abd62 100644 --- a/packages/google-auth/tests/test_identity_pool.py +++ b/packages/google-auth/tests/test_identity_pool.py @@ -368,9 +368,7 @@ def assert_underlying_credentials_refresh( json.dumps({"userProject": workforce_pool_user_project}) ) - metrics_header_value = ( - "gl-python/ auth/ auth-request-type/at cred-type/imp" - ) + metrics_header_value = "gl-python/ auth/ auth-request-type/at cred-type/imp" if service_account_impersonation_url: # Service account impersonation request/response. expire_time = ( diff --git a/packages/google-auth/tests/test_impersonated_credentials.py b/packages/google-auth/tests/test_impersonated_credentials.py index 59ab731ef452..e7b0327ca040 100644 --- a/packages/google-auth/tests/test_impersonated_credentials.py +++ b/packages/google-auth/tests/test_impersonated_credentials.py @@ -59,12 +59,8 @@ SIGNER = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, "1") TOKEN_URI = "https://example.com/oauth2/token" -ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/at cred-type/imp" -) -ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = ( - "gl-python/ auth/ auth-request-type/it cred-type/imp" -) +ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/at cred-type/imp" +ID_TOKEN_REQUEST_METRICS_HEADER_VALUE = "gl-python/ auth/ auth-request-type/it cred-type/imp" @pytest.fixture diff --git a/packages/google-auth/tests/test_metrics.py b/packages/google-auth/tests/test_metrics.py index 5ba1d47d894c..dc8789b2fe34 100644 --- a/packages/google-auth/tests/test_metrics.py +++ b/packages/google-auth/tests/test_metrics.py @@ -39,7 +39,10 @@ def test_add_metric_header(): def test_versions(mock_python_version): version_save = version.__version__ version.__version__ = "" - assert metrics.python_and_auth_lib_version() == "gl-python/ auth/" + assert ( + metrics.python_and_auth_lib_version() + == "gl-python/ auth/" + ) version.__version__ = version_save @@ -48,10 +51,22 @@ def test_versions(mock_python_version): [ (metrics.token_request_access_token_mds, "auth-request-type/at cred-type/mds"), (metrics.token_request_id_token_mds, "auth-request-type/it cred-type/mds"), - (metrics.token_request_access_token_impersonate, "auth-request-type/at cred-type/imp"), - (metrics.token_request_id_token_impersonate, "auth-request-type/it cred-type/imp"), - (metrics.token_request_access_token_sa_assertion, "auth-request-type/at cred-type/sa"), - (metrics.token_request_id_token_sa_assertion, "auth-request-type/it cred-type/sa"), + ( + metrics.token_request_access_token_impersonate, + "auth-request-type/at cred-type/imp", + ), + ( + metrics.token_request_id_token_impersonate, + "auth-request-type/it cred-type/imp", + ), + ( + metrics.token_request_access_token_sa_assertion, + "auth-request-type/at cred-type/sa", + ), + ( + metrics.token_request_id_token_sa_assertion, + "auth-request-type/it cred-type/sa", + ), (metrics.token_request_user, "cred-type/u"), (metrics.mds_ping, "auth-request-type/mds"), (metrics.reauth_start, "auth-request-type/re-start"), @@ -65,7 +80,9 @@ def test_versions(mock_python_version): def test_metric_values(mock_python_and_auth_lib_version, func, expected_suffix): # mock_python_and_auth_lib_version is injected by mock.patch but is not # explicitly referenced in the test body as the mock behaves as configured. - expected = f"gl-python/ auth/ {expected_suffix}".strip() + expected = ( + f"gl-python/ auth/ {expected_suffix}".strip() + ) assert func() == expected diff --git a/packages/google-auth/tests_async/test__default_async.py b/packages/google-auth/tests_async/test__default_async.py index 88d511247a98..ebdd2c1b0184 100644 --- a/packages/google-auth/tests_async/test__default_async.py +++ b/packages/google-auth/tests_async/test__default_async.py @@ -307,7 +307,9 @@ def test__get_gae_credentials_gen1(app_identity): @mock.patch.dict(os.environ) def test__get_gae_credentials_gen2(): - os.environ["GAE_RUNTIME"] = f"python{sys.version_info.major}{sys.version_info.minor}" + os.environ[ + "GAE_RUNTIME" + ] = f"python{sys.version_info.major}{sys.version_info.minor}" credentials, project_id = _default._get_gae_credentials() assert credentials is None assert project_id is None From 6e0e666e078999380107f88cfea9ca76968faefa Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 15 Jun 2026 10:19:57 -0400 Subject: [PATCH 5/5] fix(auth): make auto_decompress check mock-safe for custom user session classes --- .../google-auth/google/auth/transport/_aiohttp_requests.py | 2 +- .../tests_async/transport/test_aiohttp_requests.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/transport/_aiohttp_requests.py b/packages/google-auth/google/auth/transport/_aiohttp_requests.py index 1270744fa877..470647b0690a 100644 --- a/packages/google-auth/google/auth/transport/_aiohttp_requests.py +++ b/packages/google-auth/google/auth/transport/_aiohttp_requests.py @@ -143,7 +143,7 @@ class Request(transport.Request): """ def __init__(self, session=None): - if session is not None and session.auto_decompress: + if session is not None and getattr(session, "auto_decompress", None) is True: raise exceptions.InvalidOperation( "Client sessions with auto_decompress=True are not supported." ) diff --git a/packages/google-auth/tests_async/transport/test_aiohttp_requests.py b/packages/google-auth/tests_async/transport/test_aiohttp_requests.py index 68abd41940b9..7d1215ef71ea 100644 --- a/packages/google-auth/tests_async/transport/test_aiohttp_requests.py +++ b/packages/google-auth/tests_async/transport/test_aiohttp_requests.py @@ -121,6 +121,13 @@ async def test_unsupported_session(self): with pytest.raises(ValueError): await aiohttp_requests.Request(http) + def test_mock_session_unspecified_auto_decompress(self): + # A plain mock object (without spec) will return a mock on attribute access. + # Ensure this does not trigger InvalidOperation. + http = mock.Mock() + request = aiohttp_requests.Request(http) + assert request.session == http + def test_timeout(self): http = mock.create_autospec( aiohttp.ClientSession, instance=True, auto_decompress=False