Skip to content

Commit e5ed472

Browse files
authored
fix(api-core): drop support for Python 3.9 (#16980)
This PR updates google-api-core to establish Python 3.10 as the minimum supported version, dropping support for Python 3.9 and below. ### Changes **Configuration**: Updated pyproject.toml and noxfile.py to require Python 3.10+ and remove references to Python 3.7, 3.8, and 3.9. Updated README.rst and CONTRIBUTING.rst to reflect the new support status. **Cleanup**: Removed aiter and anext polyfills in test_bidi_async.py and removed Python < 3.10 polyfills in _python_version_support.py. **Constraints & Dependencies**: * Created constraints-3.10.txt using the old 3.9 constraints as a baseline. * Bumped grpcio to 1.80.0 and requests to 2.33.0 to avoid issues with pkg_resources and six warnings on Python 3.10. * Bumped google-auth to 2.35.0 to satisfy async_rest requirements. Fixes internal issue: http://b/482126936 🦕
1 parent 3cddeb0 commit e5ed472

13 files changed

Lines changed: 67 additions & 100 deletions

packages/google-api-core/CONTRIBUTING.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ In order to add a feature:
2121
documentation.
2222

2323
- The feature must work fully on the following CPython versions:
24-
3.9, 3.10, 3.11, 3.12, 3.13 and 3.14 on both UNIX and Windows.
24+
3.10, 3.11, 3.12, 3.13 and 3.14 on both UNIX and Windows.
2525

2626
- The feature must not add unnecessary dependencies (where
2727
"unnecessary" is of course subjective, but new dependencies should
@@ -171,11 +171,11 @@ configure them just like the System Tests.
171171

172172
# Run all tests in a folder
173173
$ cd samples/snippets
174-
$ nox -s py-3.8
174+
$ nox -s py-3.10
175175

176176
# Run a single sample test
177177
$ cd samples/snippets
178-
$ nox -s py-3.8 -- -k <name of test>
178+
$ nox -s py-3.10 -- -k <name of test>
179179

180180
********************************************
181181
Note About ``README`` as it pertains to PyPI
@@ -197,14 +197,12 @@ Supported Python Versions
197197

198198
We support:
199199

200-
- `Python 3.9`_
201200
- `Python 3.10`_
202201
- `Python 3.11`_
203202
- `Python 3.12`_
204203
- `Python 3.13`_
205204
- `Python 3.14`_
206205

207-
.. _Python 3.9: https://docs.python.org/3.9/
208206
.. _Python 3.10: https://docs.python.org/3.10/
209207
.. _Python 3.11: https://docs.python.org/3.11/
210208
.. _Python 3.12: https://docs.python.org/3.12/

packages/google-api-core/README.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@ common helpers used by all Google API clients. For more information, see the
1616

1717
Supported Python Versions
1818
-------------------------
19-
Python >= 3.9
19+
Python >= 3.10
2020

2121

2222
Unsupported Python Versions
2323
---------------------------
24-
25-
Python == 2.7, Python == 3.5, Python == 3.6, Python == 3.7, Python == 3.8.
24+
Python <= 3.9
2625

2726
The last version of this library compatible with Python 2.7 and 3.5 is
2827
`google-api-core==1.31.1`.
@@ -32,3 +31,6 @@ The last version of this library compatible with Python 3.6 is
3231

3332
The last version of this library compatible with Python 3.7 and 3.8 is
3433
`google-api-core==2.29.0`.
34+
35+
The last version of this library compatible with Python 3.9 is
36+
`google-api-core==2.30.3`.

packages/google-api-core/google/api_core/_python_version_support.py

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import datetime
1818
import enum
1919
import functools
20+
from importlib import metadata
2021
import logging
2122
import warnings
2223
import sys
@@ -71,13 +72,6 @@ class VersionInfo(NamedTuple):
7172

7273
PYTHON_VERSIONS: List[VersionInfo] = [
7374
# Refer to https://devguide.python.org/versions/ and the PEPs linked therefrom.
74-
VersionInfo(
75-
version="3.9",
76-
python_beta=datetime.date(2020, 5, 18),
77-
python_start=datetime.date(2020, 10, 5),
78-
python_eol=datetime.date(2025, 10, 5),
79-
gapic_end=datetime.date(2025, 10, 5) + datetime.timedelta(days=90),
80-
),
8175
VersionInfo(
8276
version="3.10",
8377
python_beta=datetime.date(2021, 5, 3),
@@ -140,38 +134,26 @@ def _flatten_message(text: str) -> str:
140134
return " ".join(textwrap.dedent(text).strip().split())
141135

142136

143-
# TODO(https://github.com/googleapis/python-api-core/issues/835):
144-
# Remove once we no longer support Python 3.9.
145-
# `importlib.metadata.packages_distributions()` is only supported in Python 3.10 and newer
146-
# https://docs.python.org/3/library/importlib.metadata.html#importlib.metadata.packages_distributions
147-
if sys.version_info < (3, 10):
148-
149-
def _get_pypi_package_name(module_name): # pragma: NO COVER
150-
"""Determine the PyPI package name for a given module name."""
151-
return None
137+
@functools.cache
138+
def _cached_packages_distributions():
139+
return metadata.packages_distributions()
152140

153-
else:
154-
from importlib import metadata
155141

156-
@functools.cache
157-
def _cached_packages_distributions():
158-
return metadata.packages_distributions()
142+
def _get_pypi_package_name(module_name):
143+
"""Determine the PyPI package name for a given module name."""
144+
try:
145+
module_to_distributions = _cached_packages_distributions()
159146

160-
def _get_pypi_package_name(module_name):
161-
"""Determine the PyPI package name for a given module name."""
162-
try:
163-
module_to_distributions = _cached_packages_distributions()
164-
165-
if module_name in module_to_distributions: # pragma: NO COVER
166-
return module_to_distributions[module_name][0]
167-
except Exception as e: # pragma: NO COVER
168-
_LOGGER.info(
169-
"An error occurred while determining PyPI package name for %s: %s",
170-
module_name,
171-
e,
172-
)
147+
if module_name in module_to_distributions: # pragma: NO COVER
148+
return module_to_distributions[module_name][0]
149+
except Exception as e: # pragma: NO COVER
150+
_LOGGER.info(
151+
"An error occurred while determining PyPI package name for %s: %s",
152+
module_name,
153+
e,
154+
)
173155

174-
return None
156+
return None
175157

176158

177159
def _get_distribution_and_import_packages(import_package: str) -> Tuple[str, Any]:

packages/google-api-core/google/api_core/client_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class ClientInfo(object):
4545
4646
Args:
4747
python_version (str): The Python interpreter version, for example,
48-
``'3.9.6'``.
48+
``'3.10.0'``.
4949
grpc_version (Optional[str]): The gRPC library version.
5050
api_core_version (str): The google-api-core library version.
5151
gapic_version (Optional[str]): The version of gapic-generated client

packages/google-api-core/google/api_core/gapic_v1/client_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class ClientInfo(client_info.ClientInfo):
3333
3434
Args:
3535
python_version (str): The Python interpreter version, for example,
36-
``'3.9.6'``.
36+
``'3.10.0'``.
3737
grpc_version (Optional[str]): The gRPC library version.
3838
api_core_version (str): The google-api-core library version.
3939
gapic_version (Optional[str]): The version of gapic-generated client

packages/google-api-core/google/api_core/grpc_helpers_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""AsyncIO helpers for :mod:`grpc` supporting 3.7+.
15+
"""AsyncIO helpers for :mod:`grpc`.
1616
1717
Please combine more detailed docstring in grpc_helpers.py to use following
1818
functions. This module is implementing the same surface with AsyncIO semantics.

packages/google-api-core/noxfile.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
# Helpful notes for local usage:
1616
# unset PYENV_VERSION
17-
# pyenv local 3.14.1 3.13.10 3.12.11 3.11.4 3.10.12 3.9.17
17+
# pyenv local 3.14.1 3.13.10 3.12.11 3.11.4 3.10.12
1818
# PIP_INDEX_URL=https://pypi.org/simple nox
1919

2020
from __future__ import absolute_import
@@ -34,8 +34,8 @@
3434
# Black and flake8 clash on the syntax for ignoring flake8's F401 in this file.
3535
BLACK_EXCLUDES = ["--exclude", "^/google/api_core/operations_v1/__init__.py"]
3636

37-
ALL_PYTHON = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
38-
SUPPORTED_PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
37+
ALL_PYTHON = ["3.10", "3.11", "3.12", "3.13", "3.14"]
38+
SUPPORTED_PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14"]
3939

4040
DEFAULT_PYTHON_VERSION = "3.14"
4141
CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute()
@@ -303,7 +303,7 @@ def default(
303303
(
304304
True,
305305
False,
306-
["3.9", "3.10", "3.11"],
306+
["3.10", "3.11"],
307307
4,
308308
), # Run proto4 tests with grpcio/grpcio-gcp installed
309309
],
@@ -325,13 +325,13 @@ def unit(
325325
session.log(f"Skipping session for Python {session.python}")
326326
session.skip()
327327

328-
# TODO: consider converting the following into a `match` statement once
329-
# we drop Python 3.9 support.
330-
if legacy_proto:
331-
if legacy_proto == 4:
328+
match legacy_proto:
329+
case 4:
332330
# Pin protobuf to a 4.x version to ensure coverage for the legacy code path.
333331
session.install("protobuf>=4.25.8,<5.0.0")
334-
else:
332+
case None | False:
333+
pass
334+
case _:
335335
assert False, f"Unknown legacy_proto: {legacy_proto}"
336336

337337
default(

packages/google-api-core/pyproject.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ build-backend = "setuptools.build_meta"
2020
name = "google-api-core"
2121
authors = [{ name = "Google LLC", email = "googleapis-packages@google.com" }]
2222
license = { text = "Apache 2.0" }
23-
requires-python = ">=3.9"
23+
requires-python = ">=3.10"
2424
readme = "README.rst"
2525
description = "Google API client core library"
2626
classifiers = [
@@ -34,7 +34,6 @@ classifiers = [
3434
"Programming Language :: Python",
3535
"Programming Language :: Python :: 3",
3636

37-
"Programming Language :: Python :: 3.9",
3837
"Programming Language :: Python :: 3.10",
3938
"Programming Language :: Python :: 3.11",
4039
"Programming Language :: Python :: 3.12",
@@ -49,7 +48,7 @@ dependencies = [
4948
"proto-plus >= 1.22.3, < 2.0.0",
5049
"proto-plus >= 1.25.0, < 2.0.0; python_version >= '3.13'",
5150
"google-auth >= 2.14.1, < 3.0.0",
52-
"requests >= 2.20.0, < 3.0.0",
51+
"requests >= 2.25.0, < 3.0.0",
5352
]
5453
dynamic = ["version"]
5554

@@ -59,12 +58,12 @@ Documentation = "https://googleapis.dev/python/google-api-core/latest/"
5958
Repository = "https://github.com/googleapis/google-cloud-python"
6059

6160
[project.optional-dependencies]
62-
async_rest = ["google-auth[aiohttp] >= 2.35.0, < 3.0.0"]
61+
async_rest = ["google-auth[aiohttp] >= 2.14.1, < 3.0.0", "aiohttp >= 3.9.0"]
6362
grpc = [
64-
"grpcio >= 1.33.2, < 2.0.0",
63+
"grpcio >= 1.41.0, < 2.0.0",
6564
"grpcio >= 1.49.1, < 2.0.0; python_version >= '3.11'",
6665
"grpcio >= 1.75.1, < 2.0.0; python_version >= '3.14'",
67-
"grpcio-status >= 1.33.2, < 2.0.0",
66+
"grpcio-status >= 1.41.0, < 2.0.0",
6867
"grpcio-status >= 1.49.1, < 2.0.0; python_version >= '3.11'",
6968
"grpcio-status >= 1.75.1, < 2.0.0; python_version >= '3.14'",
7069
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This constraints file is used to check that lower bounds
2+
# are correct in pyproject.toml
3+
# List *all* library dependencies and extras in this file.
4+
# Pin the version to the lower bound.
5+
#
6+
# e.g., if pyproject.toml has "foo >= 1.14.0, < 2.0.0dev",
7+
# Then this file should have foo==1.14.0
8+
googleapis-common-protos==1.63.2
9+
protobuf==4.25.8
10+
google-auth==2.14.1
11+
requests==2.25.0
12+
grpcio==1.41.0
13+
grpcio-status==1.41.0
14+
proto-plus==1.22.3

packages/google-api-core/testing/constraints-3.9.txt renamed to packages/google-api-core/testing/constraints-async-rest-3.10.txt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
googleapis-common-protos==1.63.2
99
protobuf==4.25.8
1010
google-auth==2.14.1
11-
requests==2.20.0
12-
grpcio==1.33.2
13-
grpcio-status==1.33.2
11+
requests==2.25.0
12+
grpcio==1.41.0
13+
grpcio-status==1.41.0
1414
proto-plus==1.22.3
15+
# Note: We pin aiohttp to 3.9.0 to avoid deprecation warnings about '@coroutine'
16+
# decorators which were deprecated since Python 3.8. When older versions of aiohttp
17+
# load, because they used @coroutine deep inside their internals, the warnings
18+
# bubble up and cause our nox session to fail.
19+
aiohttp==3.9.0

0 commit comments

Comments
 (0)