Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
d2ccdf6
ci: remove Python 3.7 from run_single_test.sh
chalmerlowe May 1, 2026
09ad9e1
chore(templates): update python version in mypy.ini.j2 to 3.8
chalmerlowe May 1, 2026
ea3801e
docs(gapic-generator): update Python version in index.rst to 3.8+
chalmerlowe May 1, 2026
e57206d
docs(gapic-generator): update Python version in bazel.rst to 3.8+
chalmerlowe May 1, 2026
8279e27
docs(gapic-generator): update Python version in _verifying.rst to 3.8
chalmerlowe May 1, 2026
f377a01
chore(templates): update Python version requirement and clean up __in…
chalmerlowe May 1, 2026
042e3ef
chore(templates): update Python version requirement and clean up vers…
chalmerlowe May 1, 2026
e75c0f6
chore(gapic-generator): remove outdated comment in options.py
chalmerlowe May 1, 2026
0eb3b09
chore(gapic): update Python version requirement to 3.10 in setup.py a…
chalmerlowe May 1, 2026
830c66f
chore(gapic): use functools.cache instead of lru_cache in wrappers.py
chalmerlowe May 1, 2026
eb01050
chore(gapic): update Python version in setup and mypy templates
chalmerlowe May 1, 2026
9a6dece
chore(gapic): clean up Python version guards and imports in templates
chalmerlowe May 1, 2026
3f6a95c
ci: update Python version comment in run_conditional_tests.sh
chalmerlowe May 1, 2026
37f8f6a
chore(gapic): drop Python 3.8 and 3.9 from CI shell scripts
chalmerlowe May 1, 2026
9770d83
chore(gapic): remove Python 3.9 from generated noxfile templates
chalmerlowe May 1, 2026
8017018
chore(gapic): update target version in generator and clean up test ma…
chalmerlowe May 1, 2026
e7a2039
docs(gapic-generator): update Python version to 3.10 in getting-start…
chalmerlowe May 1, 2026
c4951de
chore(gapic): clean up imports in ads-templates test template
chalmerlowe May 1, 2026
8917093
chore(gapic): add ignore pragmas for false positives
chalmerlowe May 1, 2026
57281c3
chore(gapic): use ignore-next-line pragma in Dockerfile
chalmerlowe May 1, 2026
9ae1839
chore(gapic): remove Python 3.9 templates and update workflow matrix
chalmerlowe May 1, 2026
490f52a
chore(gapic-generator): update goldens for asset
chalmerlowe May 4, 2026
8ff40d8
chore(gapic-generator): update goldens for credentials
chalmerlowe May 4, 2026
1bc0023
chore(gapic-generator): update goldens for eventarc
chalmerlowe May 4, 2026
f43aa3b
chore(gapic-generator): update goldens for logging
chalmerlowe May 4, 2026
4ecc6e4
chore(gapic-generator): update goldens for logging_internal
chalmerlowe May 4, 2026
6dc61c2
chore(gapic-generator): update goldens for redis
chalmerlowe May 4, 2026
fd96a82
chore(gapic-generator): update goldens for redis_selective
chalmerlowe May 4, 2026
486e4ee
chore(gapic-generator): remove leftover constraints file for redis_se…
chalmerlowe May 4, 2026
43464e7
fix(gapic-generator): handle empty constraints in noxfile template
chalmerlowe May 4, 2026
3816029
chore(gapic-generator): update noxfile in credentials golden
chalmerlowe May 4, 2026
25b4715
chore(gapic-generator): update noxfile in eventarc golden
chalmerlowe May 4, 2026
e500947
chore(gapic-generator): update noxfile in logging golden
chalmerlowe May 4, 2026
22726f4
chore(gapic-generator): update noxfile in logging_internal golden
chalmerlowe May 4, 2026
af490d4
chore(gapic-generator): update noxfile in redis golden
chalmerlowe May 4, 2026
75846ff
chore(gapic-generator): update noxfile in redis_selective golden
chalmerlowe May 4, 2026
7b7de4f
fix(gapic-generator): populate constraints files with versions in tem…
chalmerlowe May 4, 2026
9ccb209
chore(gapic-generator): update goldens for credentials with versioned…
chalmerlowe May 4, 2026
902da33
chore(gapic-generator): update goldens for eventarc with versioned co…
chalmerlowe May 4, 2026
645a7ff
chore(gapic-generator): update goldens for logging with versioned con…
chalmerlowe May 4, 2026
2a7cd4a
chore(gapic-generator): update goldens for logging_internal with vers…
chalmerlowe May 4, 2026
c3e96a6
chore(gapic-generator): update goldens for redis with versioned const…
chalmerlowe May 4, 2026
5f1b6dc
chore(gapic-generator): update goldens for redis_selective with versi…
chalmerlowe May 4, 2026
12332fa
fix(gapic-generator): update constraints templates for Python 3.10
chalmerlowe May 4, 2026
d44cbe6
chore(gapic-generator): update goldens for Python 3.10 constraints
chalmerlowe May 4, 2026
1a68d5f
chore(gapic-generator): format credentials golden files
chalmerlowe May 4, 2026
a8bbee5
fix(gapic-generator): remove duplicate import of sys in __init__.py t…
chalmerlowe May 4, 2026
8132257
chore(gapic-generator): update goldens to remove duplicate import of sys
chalmerlowe May 4, 2026
dcdc8a1
chore(gapic-generator): revert formatting in credentials golden to ma…
chalmerlowe May 4, 2026
c19fc42
chore(gapic-generator): update goldens for asset API
chalmerlowe May 4, 2026
101047c
fix(gapic-generator): skip Python 3.9 unit tests temporarily
chalmerlowe May 4, 2026
bbf78ce
fix(ci): allow Python 3.9 unit tests to run (and be skipped)
chalmerlowe May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .generator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ RUN unzip protoc-25.3-linux-x86_64.zip -d protoc

# Download/extract pandoc
# Pandoc is required by gapic-generator-python for parsing documentation
# version-scanner: ignore-next-line
ENV PANDOC_VERSION=3.8.2
RUN mkdir pandoc-binary
RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .generator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def _run_post_processor(output: str, library_id: str, is_mono_repo: bool):
# TODO(https://github.com/googleapis/google-cloud-python/issues/15538):
# Investigate if a `target_version needs to be maintained
# or can be eliminated.
target_version = "py39"
target_version = "py310"
common_args = [
f"--target-version={target_version}",
"--line-length=88",
Expand Down
2 changes: 1 addition & 1 deletion .generator/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ def test_run_individual_session_success(mocker, caplog, is_mono_repo):
"cli.subprocess.run", return_value=MagicMock(returncode=0)
)

test_session = "unit-3.9"
test_session = "unit-3.10"
test_library_id = "test-library"
repo = "repo"
_run_individual_session(test_session, test_library_id, repo, is_mono_repo)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gapic-generator-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env:
SHOWCASE_VERSION: 0.35.0
PROTOC_VERSION: 3.20.2
LATEST_STABLE_PYTHON: 3.14
ALL_PYTHON: "['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']"
ALL_PYTHON: "['3.10', '3.11', '3.12', '3.13', '3.14']"

jobs:
check_changes:
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ repos:
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
rev: 3.9.2 # version-scanner: ignore
hooks:
- id: flake8
2 changes: 1 addition & 1 deletion ci/run_conditional_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# `BUILD_TYPE` should be one of ["presubmit", "continuous"]
# `TEST_TYPE` should be one of ["docs", "docfx", "prerelease", "unit"]
# or match the name of the nox session that you want to run.
# `PY_VERSION` should be one of ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
# `PY_VERSION` should be one of ["3.10", "3.11", "3.12"]

# `TEST_TYPE` and `PY_VERSION` are required by the script `ci/run_single_test.sh`

Expand Down
10 changes: 1 addition & 9 deletions ci/run_single_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# This script requires the following environment variables to be set:
# `TEST_TYPE` should be one of ["lint", "lint_setup_py", "docs", "docfx", "prerelease"]
# `PY_VERSION` should be one of ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
# `PY_VERSION` should be one of ["3.10", "3.11", "3.12", "3.13"]

# This script is called by the `ci/run_conditional_tests.sh` script.
# A specific `nox` session will be run, depending on the value of
Expand Down Expand Up @@ -70,14 +70,6 @@ case ${TEST_TYPE} in
;;
unit)
case ${PY_VERSION} in
"3.7")
nox -s unit-3.7
retval=$?
;;
"3.8")
nox -s unit-3.8
retval=$?
;;
"3.9")
nox -s unit-3.9
retval=$?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Create a virtual environment for the library:

.. code-block:: shell
$ virtualenv ~/.local/client-lib --python=`which python3.7`
$ virtualenv ~/.local/client-lib --python=`which python3.10`
$ source ~/.local/client-lib/bin/activate
Next, install the library:
Expand Down
2 changes: 1 addition & 1 deletion packages/gapic-generator/docs/getting-started/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ install it is simply downloading the binary and making it executable:
Python and Dependencies
~~~~~~~~~~~~~~~~~~~~~~~
Bazel build is mostly hermetic, with a few exceptions for Python generator.
Specifically it expects Python 3.7+ with the python dev packages to be installed.
Specifically it expects Python 3.10+ with the python dev packages to be installed.

On Linux, to install those, simply run:

Expand Down
2 changes: 1 addition & 1 deletion packages/gapic-generator/docs/getting-started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Getting Started
---------------

This code generator is implemented as a plugin to ``protoc``, the compiler
for `protocol buffers`_, and will run in any environment that Python 3.7+ and
for `protocol buffers`_, and will run in any environment that Python 3.10+ and
protocol buffers do.

It is recommended to install the tool locally and run it through ``protoc``.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ from {{package_path}} import gapic_version as package_version
__version__ = package_version.__version__


if sys.version_info < (3, 7):
raise ImportError('This module requires Python 3.7 or later.')
if sys.version_info < (3, 10):
raise ImportError('This module requires Python 3.10 or later.')


_lazy_type_to_package_map = {
Expand All @@ -37,14 +37,14 @@ _lazy_type_to_package_map = {


# Background on how this behaves: https://www.python.org/dev/peps/pep-0562/
def __getattr__(name): # Requires Python >= 3.7
def __getattr__(name):
if name == '__all__':
all_names = globals()['__all__'] = sorted(_lazy_type_to_package_map)
return all_names
elif name in _lazy_type_to_package_map:
module = importlib.import_module(f'{_lazy_type_to_package_map[name]}')
klass = getattr(module, name)
{# new_klass = type(name, (klass,), {'__doc__': klass.__doc__}) #}

globals()[name] = klass
return klass
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import importlib
import sys


if sys.version_info < (3, 7):
raise ImportError('This module requires Python 3.7 or later.')
if sys.version_info < (3, 10):
raise ImportError('This module requires Python 3.10 or later.')


_lazy_type_to_package_map = {
Expand All @@ -30,14 +30,14 @@ _lazy_type_to_package_map = {


# Background on how this behaves: https://www.python.org/dev/peps/pep-0562/
def __getattr__(name): # Requires Python >= 3.7
def __getattr__(name):
if name == '__all__':
all_names = globals()['__all__'] = sorted(_lazy_type_to_package_map)
return all_names
elif name in _lazy_type_to_package_map:
module = importlib.import_module(f'{_lazy_type_to_package_map[name]}')
klass = getattr(module, name)
{# new_klass = type(name, (klass,), {'__doc__': klass.__doc__}) #}

globals()[name] = klass
return klass
else:
Expand Down
2 changes: 1 addition & 1 deletion packages/gapic-generator/gapic/ads-templates/mypy.ini.j2
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[mypy]
python_version = 3.7
python_version = 3.10
namespace_packages = True
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import nox # type: ignore
# Add tests for Python 3.15 alpha1
# https://peps.python.org/pep-0790/
ALL_PYTHON = [
"3.9",
"3.10",
"3.11",
"3.12",
Expand Down
3 changes: 1 addition & 2 deletions packages/gapic-generator/gapic/ads-templates/setup.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ setuptools.setup(
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -75,7 +74,7 @@ setuptools.setup(
],
platforms="Posix; MacOS X; Windows",
packages=packages,
python_requires=">=3.9",
python_requires=">=3.10",
install_requires=dependencies,
include_package_data=True,
zip_safe=False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import os
{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|list %}
import re
{% endif %}
# try/except added for compatibility with python < 3.8
try:
from unittest import mock
from unittest.mock import AsyncMock # pragma: NO COVER
except ImportError: # pragma: NO COVER
import mock
from unittest import mock
from unittest.mock import AsyncMock

import grpc
from grpc.experimental import aio
Expand Down
10 changes: 2 additions & 8 deletions packages/gapic-generator/gapic/schema/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1284,19 +1284,13 @@ def _to_regex(self, path_template: str) -> Pattern:
return re.compile(f"^{self._convert_to_regex(path_template)}$")

# Use caching to avoid repeated computation
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2161):
# Use `@functools.cache` instead of `@functools.lru_cache` once python 3.8 is dropped.
# https://docs.python.org/3/library/functools.html#functools.cache
@functools.lru_cache(maxsize=None)
@functools.cache
def to_regex(self) -> Pattern:
return self._to_regex(self.path_template)

@property
# Use caching to avoid repeated computation
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2161):
# Use `@functools.cache` instead of `@functools.lru_cache` once python 3.8 is dropped.
# https://docs.python.org/3/library/functools.html#functools.cache
@functools.lru_cache(maxsize=None)
@functools.cache
def key(self) -> Union[str, None]:
if self.path_template == "":
return self.field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ import sys

__version__ = package_version.__version__

if sys.version_info >= (3, 8): # pragma: NO COVER
from importlib import metadata
else: # pragma: NO COVER
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
# this code path once we drop support for Python 3.7
import importlib_metadata as metadata
from importlib import metadata

{# Import subpackages. -#}
{% for subpackage, _ in api.subpackages|dictsort %}
Expand Down Expand Up @@ -61,24 +56,15 @@ else: # pragma: NO COVER
# functions above. We do equivalent checks manually.
try:
import warnings
import sys

_py_version_str = sys.version.split()[0]
_package_label = "{{package_path}}"
if sys.version_info < (3, 9):
if sys.version_info < (3, 10):
warnings.warn("You are using a non-supported Python version " +
f"({_py_version_str}). Google will not post any further " +
f"updates to {_package_label} supporting this Python version. " +
"Please upgrade to the latest Python version, or at " +
f"least to Python 3.9, and then update {_package_label}.",
FutureWarning)
if sys.version_info[:2] == (3, 9):
warnings.warn(f"You are using a Python version ({_py_version_str}) " +
f"which Google will stop supporting in {_package_label} in " +
"January 2026. Please " +
"upgrade to the latest Python version, or at " +
"least to Python 3.10, before then, and " +
f"then update {_package_label}.",
f"least to Python 3.10, and then update {_package_label}.",
FutureWarning)

def parse_version_to_tuple(version_string: str):
Expand Down
1 change: 0 additions & 1 deletion packages/gapic-generator/gapic/templates/noxfile.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ if os.path.isdir("samples"):
LINT_PATHS.append("samples")

ALL_PYTHON = [
"3.9",
"3.10",
"3.11",
"3.12",
Expand Down
3 changes: 1 addition & 2 deletions packages/gapic-generator/gapic/templates/setup.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ setuptools.setup(
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -100,7 +99,7 @@ setuptools.setup(
],
platforms="Posix; MacOS X; Windows",
packages=packages,
python_requires=">=3.9",
python_requires=">=3.10",
install_requires=dependencies,
extras_require=extras,
include_package_data=True,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
# -*- coding: utf-8 -*-
{% block constraints %}
{% include "testing/_default_constraints.j2" %}
{% endblock %}
{% from '_pypi_packages.j2' import pypi_packages %}
# This constraints file is used to check that lower bounds
# are correct in setup.py
# List all library dependencies and extras in this file,
# pinning their versions to their lower bounds.
# For example, if setup.py has "google-cloud-foo >= 1.14.0, < 2.0.0",
# then this file should have google-cloud-foo==1.14.0
google-api-core==2.17.1
google-auth==2.14.1
grpcio==1.44.0
proto-plus==1.22.3
protobuf==4.25.8
{% for package_tuple, package_info in pypi_packages.items() %}
{# Quick check to make sure `package_info.package_name` is not the package being generated so we don't circularly include this package in its own constraints file. #}
{% if api.naming.warehouse_package_name != package_info.package_name %}
{% if api.requires_package(package_tuple) %}
{{ package_info.package_name }}=={{ package_info.lower_bound }}
{% endif %}
{% endif %}
{% endfor %}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ import os
{% if api.all_method_settings.values()|map(attribute="auto_populated_fields", default=[])|list %}
import re
{% endif %}
# try/except added for compatibility with python < 3.8
try:
from unittest import mock
from unittest.mock import AsyncMock # pragma: NO COVER
except ImportError: # pragma: NO COVER
import mock
from unittest import mock
from unittest.mock import AsyncMock

import grpc
from grpc.experimental import aio
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,9 +1005,7 @@ async def test_{{ method_name }}_async_pages():
{% endif %}
)
pages = []
# Workaround issue in python 3.9 related to code coverage by adding `# pragma: no branch`
# See https://github.com/googleapis/gapic-generator-python/pull/1174#issuecomment-1025132372
async for page_ in ( # pragma: no branch
async for page_ in (
await client.{{ method_name }}(request={})
).pages:
pages.append(page_)
Expand Down
2 changes: 1 addition & 1 deletion packages/gapic-generator/gapic/utils/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Options:
OPT_FLAGS: FrozenSet[str] = frozenset(
(
"add-iam-methods", # microgenerator implementation for `reroute_to_grpc_interface`
"lazy-import", # requires >= 3.7
"lazy-import",
"metadata", # generate GAPIC metadata JSON file
"old-naming", # TODO(dovs): Come up with a better comment
"retry-config", # takes a path
Expand Down
Loading
Loading