From 9757c7967a27831c9dc955e781015c9d19962ba1 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 10:13:25 -0800 Subject: [PATCH 1/8] chore: remove python 3.7 support --- README.rst | 19 ++++++++++++------- setup.py | 6 +----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index e058f2471..5cfa19a81 100644 --- a/README.rst +++ b/README.rst @@ -35,15 +35,16 @@ Note that the extras pyopenssl and enterprise_cert should not be used together b Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.7 +Python >= 3.8 **NOTE**: -Python 3.7 was marked as `unsupported`_ by the python community in June 2023. -We recommend that all developers upgrade to Python 3.8 and newer as soon as -they can. Support for Python 3.7 will be removed from this library after -January 1 2024. Previous releases that support Python 3.7 will continue to be available -for download, but releases after January 1 2024 will only target Python 3.8 and -newer. +Python 3.8 and Python 3.9 were marked as `unsupported`_ by the python community in +October 2024 and October 2025 respectively. +We recommend that all developers upgrade to Python 3.10 and newer as soon as +they can. Support for end-of-life Python runtimes will be removed from this +library in future updates. +Previous releases that support end-of-life Python versions will continue to be available +for download, but future releases will only target supported versions. .. _unsupported: https://devguide.python.org/versions/#unsupported-versions @@ -58,6 +59,10 @@ Unsupported Python Versions - Python 3.6: The last version of this library with support for Python 3.6 was `google.auth == 2.22.0`. +- 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/setup.py b/setup.py index 3db2d8cf9..74036339a 100644 --- a/setup.py +++ b/setup.py @@ -26,11 +26,8 @@ "rsa>=3.1.4,<5", ) -# TODO(https://github.com/googleapis/google-auth-library-python/issues/1737): Unit test fails with -# `No module named 'cryptography.hazmat.backends.openssl.x509' for Python 3.7``. cryptography_base_require = [ "cryptography >= 38.0.3", - "cryptography < 39.0.0; python_version < '3.8'", ] requests_extra_require = ["requests >= 2.20.0, < 3.0.0"] @@ -116,12 +113,11 @@ package_data={"google.auth": ["py.typed"], "google.oauth2": ["py.typed"]}, install_requires=DEPENDENCIES, extras_require=extras, - python_requires=">=3.7", + python_requires=">=3.8", license="Apache 2.0", keywords="google auth oauth client", classifiers=[ "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From 04471281c7eb8f47afbf9df266a452bdfbefc64c Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 10:36:22 -0800 Subject: [PATCH 2/8] updated warning --- google/auth/__init__.py | 18 +++++++++++------- google/oauth2/__init__.py | 18 +++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/google/auth/__init__.py b/google/auth/__init__.py index 765bbd705..2217558a4 100644 --- a/google/auth/__init__.py +++ b/google/auth/__init__.py @@ -41,13 +41,17 @@ class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER pass -# Checks if the current runtime is Python 3.7. -if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER - message = ( - "After January 1, 2024, new releases of this library will drop support " - "for Python 3.7." - ) - warnings.warn(message, Python37DeprecationWarning) +# Raise warnings for deprecated versions +eol_message = """ + You are using a Python version {} past its end of life. Google will update + google-auth with critical bug fixes on a best-effort basis, but not + with any other fixes or features. Please upgrade your Python version, + and then update google-auth. + """ +if sys.version_info.major == 3 and sys.version_info.minor == 8: # pragma: NO COVER + warnings.warn(eol_message.format("3.8"), FutureWarning) +elif sys.version_info.major == 3 and sys.version_info.minor == 9: # pragma: NO COVER + warnings.warn(eol_message.format("3.9"), FutureWarning) # Set default logging handler to avoid "No handler found" warnings. logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/google/oauth2/__init__.py b/google/oauth2/__init__.py index accae9657..18b8ada67 100644 --- a/google/oauth2/__init__.py +++ b/google/oauth2/__init__.py @@ -27,10 +27,14 @@ class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER pass -# Checks if the current runtime is Python 3.7. -if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER - message = ( - "After January 1, 2024, new releases of this library will drop support " - "for Python 3.7." - ) - warnings.warn(message, Python37DeprecationWarning) +# Raise warnings for deprecated versions +eol_message = """ + You are using a Python version {} past its end of life. Google will update + google-auth with critical bug fixes on a best-effort basis, but not + with any other fixes or features. Please upgrade your Python version, + and then update google-auth. + """ +if sys.version_info.major == 3 and sys.version_info.minor == 8: # pragma: NO COVER + warnings.warn(eol_message.format("3.8"), FutureWarning) +elif sys.version_info.major == 3 and sys.version_info.minor == 9: # pragma: NO COVER + warnings.warn(eol_message.format("3.9"), FutureWarning) From a439b11e14c50c93e9d540a8ffb9ec7050e438af Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 10:40:40 -0800 Subject: [PATCH 3/8] updated CONTRIBUTING.md --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 3975a3d2a..a186da7d4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -19,7 +19,7 @@ A few notes on making changes to ``google-auth-library-python``. using ``nox -s docs``. - The change must work fully on the following CPython versions: - 3.7, 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13 across macOS, Linux, and Windows. + 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14 across macOS, Linux, and Windows. - The codebase *must* have 100% test statement coverage after each commit. You can test coverage via ``nox -e cover``. From fd79ff5050d2418a210156b3a67ca0bd0423415e Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 10:40:48 -0800 Subject: [PATCH 4/8] removed python 2 error --- google/auth/pluggable.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/google/auth/pluggable.py b/google/auth/pluggable.py index 87d03e737..b7d832da9 100644 --- a/google/auth/pluggable.py +++ b/google/auth/pluggable.py @@ -201,11 +201,6 @@ def retrieve_subject_token(self, request): else: return subject_token - if not _helpers.is_python_3(): - raise exceptions.RefreshError( - "Pluggable auth is only supported for python 3.7+" - ) - # Inject env vars. env = os.environ.copy() self._inject_env_variables(env) @@ -263,11 +258,6 @@ def revoke(self, request): ) self._validate_running_mode() - if not _helpers.is_python_3(): - raise exceptions.RefreshError( - "Pluggable auth is only supported for python 3.7+" - ) - # Inject variables env = os.environ.copy() self._inject_env_variables(env) From 66b9985b602ab0e87df24a5a134668a5e38f8771 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 11:05:28 -0800 Subject: [PATCH 5/8] removed python 2 tests --- tests/test_pluggable.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/tests/test_pluggable.py b/tests/test_pluggable.py index ba1b780de..b2764361b 100644 --- a/tests/test_pluggable.py +++ b/tests/test_pluggable.py @@ -1230,16 +1230,6 @@ def test_revoke_successfully(self): ) _ = credentials.revoke(None) - @mock.patch.dict(os.environ, {"GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES": "1"}) - def test_retrieve_subject_token_python_2(self): - with mock.patch("sys.version_info", (2, 7)): - credentials = self.make_pluggable(credential_source=self.CREDENTIAL_SOURCE) - - with pytest.raises(exceptions.RefreshError) as excinfo: - _ = credentials.retrieve_subject_token(None) - - assert excinfo.match(r"Pluggable auth is only supported for python 3.7+") - @mock.patch.dict(os.environ, {"GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES": "1"}) def test_retrieve_subject_token_with_quoted_command(self): command_with_spaces = '"/path/with spaces/to/executable" "arg with spaces"' @@ -1269,17 +1259,3 @@ def test_retrieve_subject_token_with_quoted_command(self): stderr=subprocess.STDOUT, env=mock.ANY, ) - - @mock.patch.dict(os.environ, {"GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES": "1"}) - def test_revoke_subject_token_python_2(self): - with mock.patch("sys.version_info", (2, 7)): - credentials = self.make_pluggable( - audience=WORKFORCE_AUDIENCE, - credential_source=self.CREDENTIAL_SOURCE, - interactive=True, - ) - - with pytest.raises(exceptions.RefreshError) as excinfo: - _ = credentials.revoke(None) - - assert excinfo.match(r"Pluggable auth is only supported for python 3.7+") From d7d43809c5006635872de7c556a85ff8813c8ae8 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 11:28:32 -0800 Subject: [PATCH 6/8] added test for version warning --- tests/test_version_warnings.py | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tests/test_version_warnings.py diff --git a/tests/test_version_warnings.py b/tests/test_version_warnings.py new file mode 100644 index 000000000..d8acf7b66 --- /dev/null +++ b/tests/test_version_warnings.py @@ -0,0 +1,63 @@ +# Copyright 2026 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 importlib +import sys +import warnings +from unittest import mock + +import pytest + +import google.auth +import google.oauth2 + + +@pytest.mark.parametrize("module", [google.auth, google.oauth2]) +@pytest.mark.parametrize( + "version, expected_warning", + [ + ((3, 8), True), + ((3, 9), True), + ((3, 10), False), + ((3, 13), False), + ], +) +def test_python_version_warnings(module, version, expected_warning): + # Mock sys.version_info + # We use a MagicMock that has major and minor attributes + mock_version = mock.Mock() + mock_version.major = version[0] + mock_version.minor = version[1] + + with mock.patch.object(sys, "version_info", mock_version): + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + importlib.reload(module) + + future_warnings = [ + w + for w in caught_warnings + if issubclass(w.category, FutureWarning) + and "past its end of life" in str(w.message) + ] + + if expected_warning: + assert ( + len(future_warnings) > 0 + ), f"Expected FutureWarning for Python {version} in {module.__name__}" + assert str(version[1]) in str(future_warnings[0].message) + else: + assert ( + len(future_warnings) == 0 + ), f"Did not expect FutureWarning for Python {version} in {module.__name__}" From 6e34ed7667a75bc294fa14d93b5c8d862b6829f6 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 11:34:53 -0800 Subject: [PATCH 7/8] fixed lint --- google/auth/_helpers.py | 3 ++- tests/test_version_warnings.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/google/auth/_helpers.py b/google/auth/_helpers.py index 4a69d4c61..e9033ca8c 100644 --- a/google/auth/_helpers.py +++ b/google/auth/_helpers.py @@ -334,7 +334,8 @@ def is_python_3(): Returns: bool: True if the Python interpreter is Python 3 and False otherwise. """ - return sys.version_info > (3, 0) + + return sys.version_info > (3, 0) # pragma: NO COVER def _hash_sensitive_info(data: Union[dict, list]) -> Union[dict, list, str]: diff --git a/tests/test_version_warnings.py b/tests/test_version_warnings.py index d8acf7b66..d975221c4 100644 --- a/tests/test_version_warnings.py +++ b/tests/test_version_warnings.py @@ -14,8 +14,8 @@ import importlib import sys -import warnings from unittest import mock +import warnings import pytest From 08312f56b0cbebb5e394a9bfa0a8eb50226687dd Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 6 Jan 2026 12:04:56 -0800 Subject: [PATCH 8/8] Update README.rst Co-authored-by: Victor Chudnovsky --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 5cfa19a81..45da8044d 100644 --- a/README.rst +++ b/README.rst @@ -39,7 +39,7 @@ Python >= 3.8 **NOTE**: Python 3.8 and Python 3.9 were marked as `unsupported`_ by the python community in -October 2024 and October 2025 respectively. +October 2024 and October 2025, respectively. We recommend that all developers upgrade to Python 3.10 and newer as soon as they can. Support for end-of-life Python runtimes will be removed from this library in future updates.