Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e9a2be8
test: fix async showcase test
parthea Sep 20, 2025
3110a1c
fix test
parthea Sep 20, 2025
f86e4fb
more fixes related to metadata
parthea Sep 20, 2025
41f1dc4
fix test
parthea Sep 20, 2025
a572ff8
update comments
parthea Sep 22, 2025
5c4c76d
fix test
parthea Sep 22, 2025
0f78495
feat: check Python and dependency versions in generated GAPICs
vchudnov-g Jul 30, 2025
e7dee26
fix import
vchudnov-g Jul 30, 2025
ac92bc9
Update goldens
vchudnov-g Jul 31, 2025
af62f33
allow Python, dependency versions checks without upgrading api_core
vchudnov-g Jul 31, 2025
54a300d
Update goldens; allow for not found dependencies
vchudnov-g Aug 1, 2025
1da71a8
Update code & integration tests to work on all Python versions
vchudnov-g Aug 1, 2025
74c9eda
fix import errors
vchudnov-g Sep 2, 2025
52093a2
Install `packaging` package
vchudnov-g Sep 3, 2025
506a8c0
fix: skip type warnings for imports not present in older api_core
vchudnov-g Sep 3, 2025
a0de3f6
fix: exclude the backwards-compatibility code fro mcoverage checks
vchudnov-g Sep 3, 2025
b2c7ecc
fix: fix coverage skip pragmas
vchudnov-g Sep 3, 2025
4a9512d
Use warnings module instead of logging module
vchudnov-g Sep 10, 2025
9c366d7
Test tweaks
vchudnov-g Sep 11, 2025
a030044
fix miports
vchudnov-g Sep 12, 2025
afc1be1
WIP: expose the warnings in tests
vchudnov-g Sep 12, 2025
80de35e
try setting future warning
vchudnov-g Sep 12, 2025
950b18f
Update expected warnings....arbitrarily
vchudnov-g Sep 12, 2025
a47621d
Revert arbitrary change in test expectations: it caused more problems
vchudnov-g Sep 15, 2025
b08326f
fix: print the current package versions correctly
vchudnov-g Sep 15, 2025
0829ec5
fix: return package version as tuple of version tuple and string
vchudnov-g Sep 15, 2025
e84f42e
fix: filter MTLS deprecation tests for "mtls"
vchudnov-g Sep 16, 2025
4b688ed
fix tests
vchudnov-g Sep 16, 2025
39d1d9f
fix test: warning match string
vchudnov-g Sep 16, 2025
9b4164c
WIP trying to fix tests
vchudnov-g Sep 17, 2025
9d92e80
WIP: try to fix tests
vchudnov-g Sep 17, 2025
30581fd
fix tests
vchudnov-g Sep 17, 2025
66c9312
fix test_metadata_response_unary_async
vchudnov-g Sep 18, 2025
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
78 changes: 78 additions & 0 deletions gapic/templates/%namespace/%name_%version/%sub/__init__.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,84 @@ from {{package_path}} import gapic_version as package_version

__version__ = package_version.__version__


import google.api_core as api_core

if hasattr(api_core, "check_python_version") and hasattr(api_core, "check_dependency_versions"): # pragma: NO COVER
{# TODO(api_core): remove `type:ignore` below when minimum version of api_core makes the else clause unnecessary. #}
api_core.check_python_version("{{package_path}}") # type: ignore
api_core.check_dependency_versions("{{package_path}}") # type: ignore
else: # pragma: NO COVER
{# TODO(api_core): Remove this try-catch when we require api-core at a version that
supports the changes in https://github.com/googleapis/python-api-core/pull/832

In the meantime, please ensure the functionality here mirrors the
equivalent functionality in api_core, in those two functions above.
#}
# An older version of api_core is installed, which does not define the
# functions above. We do equivalent checks manually.

import warnings
import sys

_py_version_str = sys.version.split()[0]
_package_label = "{{package_path}}"
if sys.version_info < (3, 9):
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} when " +
"it reaches its end of life (October 2025). Please " +
"upgrade to the latest Python version, or at " +
"least Python 3.10, before then, and " +
f"then update {_package_label}.",
FutureWarning)

from packaging.version import parse as parse_version

if sys.version_info < (3, 8):
import pkg_resources

def _get_version(dependency_name):
try:
version_string = pkg_resources.get_distribution(dependency_name).version
return (parse_version(version_string), version_string)
except pkg_resources.DistributionNotFound:
return (None, "--")
else:
from importlib import metadata

def _get_version(dependency_name):
try:
version_string = metadata.version("requests")
parsed_version = parse_version(version_string)
return (parsed_version.release, version_string)
except metadata.PackageNotFoundError:
return (None, "--")

_dependency_package = "google.protobuf"
_next_supported_version = "4.25.8"
_next_supported_version_tuple = (4, 25, 8)
(_version_used, _version_used_string) = _get_version(_dependency_package)
if _version_used and _version_used < _next_supported_version_tuple:
warnings.warn(f"Package {_package_label} depends on " +
f"{_dependency_package}, currently installed at version " +
f"{_version_used_string}. Future updates to " +
f"{_package_label} will require {_dependency_package} at " +
f"version {_next_supported_version} or higher. Please ensure " +
"that either (a) your Python environment doesn't pin the " +
f"version of {_dependency_package}, so that updates to " +
f"{_package_label} can require the higher version, or " +
"(b) you manually update your Python environment to use at " +
f"least version {_next_supported_version} of " +
f"{_dependency_package}.",
FutureWarning)

{# Import subpackages. -#}
{% for subpackage, _ in api.subpackages|dictsort %}
from . import {{ subpackage }}
Expand Down
1 change: 1 addition & 0 deletions gapic/templates/setup.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies = [
# Exclude incompatible versions of `google-auth`
# See https://github.com/googleapis/google-cloud-python/issues/12364
"google-auth >= 2.14.1, <3.0.0,!=2.24.0,!=2.25.0",
"packaging", # TODO: Remove once we require versions of api core that include this
"proto-plus >= 1.22.3, <2.0.0",
"proto-plus >= 1.25.0, <2.0.0; python_version >= '3.13'",
{# Explicitly exclude protobuf versions mentioned in https://cloud.google.com/support/bulletins#GCP-2022-019 #}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@ def test_{{ service.name|snake_case }}_grpc_asyncio_transport_channel():

# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
# removed from grpc/grpc_asyncio transport constructor.
@pytest.mark.filterwarnings("ignore::FutureWarning")
@pytest.mark.parametrize("transport_class", [transports.{{ service.grpc_transport_name }}, transports.{{ service.grpc_asyncio_transport_name }}])
def test_{{ service.name|snake_case }}_transport_channel_mtls_with_client_cert_source(
transport_class
Expand Down
8 changes: 8 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def unit(session):
"pyfakefs",
"grpcio-status",
"proto-plus",
"setuptools", # TODO: Remove when not needed in __init__.py.j2
"packaging", # TODO: Remove when not needed in __init__.py.j2
)
session.install("-e", ".")
session.run(
Expand Down Expand Up @@ -481,6 +483,8 @@ def run_showcase_unit_tests(session, fail_under=100, rest_async_io_enabled=False
"pytest-xdist",
"asyncmock; python_version < '3.8'",
"pytest-asyncio",
"setuptools", # TODO: Remove when not needed in __init__.py.j2
"packaging", # TODO: Remove when not needed in __init__.py.j2
)
# Run the tests.
# NOTE: async rest is not supported against the minimum supported version of google-api-core.
Expand Down Expand Up @@ -595,6 +599,8 @@ def showcase_mypy(
"types-protobuf",
"types-requests",
"types-dataclasses",
"setuptools", # TODO: Remove when not needed in __init__.py.j2
"packaging", # TODO: Remove when not needed in __init__.py.j2
)

with showcase_library(session, templates=templates, other_opts=other_opts) as lib:
Expand Down Expand Up @@ -725,6 +731,8 @@ def mypy(session):
"types-PyYAML",
"types-dataclasses",
"click==8.1.3",
"setuptools", # TODO: Remove when not needed in __init__.py.j2
"packaging", # TODO: Remove when not needed in __init__.py.j2
)
session.install(".")
session.run("mypy", "-p", "gapic")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,77 @@
__version__ = package_version.__version__


import google.api_core as api_core

if hasattr(api_core, "check_python_version") and hasattr(api_core, "check_dependency_versions"): # pragma: NO COVER
api_core.check_python_version("google.cloud.asset_v1") # type: ignore
api_core.check_dependency_versions("google.cloud.asset_v1") # type: ignore
else: # pragma: NO COVER
# An older version of api_core is installed, which does not define the
# functions above. We do equivalent checks manually.

import warnings
import sys

_py_version_str = sys.version.split()[0]
_package_label = "google.cloud.asset_v1"
if sys.version_info < (3, 9):
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} when " +
"it reaches its end of life (October 2025). Please " +
"upgrade to the latest Python version, or at " +
"least Python 3.10, before then, and " +
f"then update {_package_label}.",
FutureWarning)

from packaging.version import parse as parse_version

if sys.version_info < (3, 8):
import pkg_resources

def _get_version(dependency_name):
try:
version_string = pkg_resources.get_distribution(dependency_name).version
return (parse_version(version_string), version_string)
except pkg_resources.DistributionNotFound:
return (None, "--")
else:
from importlib import metadata

def _get_version(dependency_name):
try:
version_string = metadata.version("requests")
parsed_version = parse_version(version_string)
return (parsed_version.release, version_string)
except metadata.PackageNotFoundError:
return (None, "--")

_dependency_package = "google.protobuf"
_next_supported_version = "4.25.8"
_next_supported_version_tuple = (4, 25, 8)
(_version_used, _version_used_string) = _get_version(_dependency_package)
if _version_used and _version_used < _next_supported_version_tuple:
warnings.warn(f"Package {_package_label} depends on " +
f"{_dependency_package}, currently installed at version " +
f"{_version_used_string}. Future updates to " +
f"{_package_label} will require {_dependency_package} at " +
f"version {_next_supported_version} or higher. Please ensure " +
"that either (a) your Python environment doesn't pin the " +
f"version of {_dependency_package}, so that updates to " +
f"{_package_label} can require the higher version, or " +
"(b) you manually update your Python environment to use at " +
f"least version {_next_supported_version} of " +
f"{_dependency_package}.",
FutureWarning)


from .services.asset_service import AssetServiceClient
from .services.asset_service import AssetServiceAsyncClient

Expand Down
1 change: 1 addition & 0 deletions tests/integration/goldens/asset/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
# Exclude incompatible versions of `google-auth`
# See https://github.com/googleapis/google-cloud-python/issues/12364
"google-auth >= 2.14.1, <3.0.0,!=2.24.0,!=2.25.0",
"packaging", # TODO: Remove once we require versions of api core that include this
"proto-plus >= 1.22.3, <2.0.0",
"proto-plus >= 1.25.0, <2.0.0; python_version >= '3.13'",
"protobuf>=3.20.2,<7.0.0,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17712,6 +17712,7 @@ def test_asset_service_grpc_asyncio_transport_channel():

# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
# removed from grpc/grpc_asyncio transport constructor.
@pytest.mark.filterwarnings("ignore::FutureWarning")
@pytest.mark.parametrize("transport_class", [transports.AssetServiceGrpcTransport, transports.AssetServiceGrpcAsyncIOTransport])
def test_asset_service_transport_channel_mtls_with_client_cert_source(
transport_class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,77 @@
__version__ = package_version.__version__


import google.api_core as api_core

if hasattr(api_core, "check_python_version") and hasattr(api_core, "check_dependency_versions"): # pragma: NO COVER
api_core.check_python_version("google.iam.credentials_v1") # type: ignore
api_core.check_dependency_versions("google.iam.credentials_v1") # type: ignore
else: # pragma: NO COVER
# An older version of api_core is installed, which does not define the
# functions above. We do equivalent checks manually.

import warnings
import sys

_py_version_str = sys.version.split()[0]
_package_label = "google.iam.credentials_v1"
if sys.version_info < (3, 9):
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} when " +
"it reaches its end of life (October 2025). Please " +
"upgrade to the latest Python version, or at " +
"least Python 3.10, before then, and " +
f"then update {_package_label}.",
FutureWarning)

from packaging.version import parse as parse_version

if sys.version_info < (3, 8):
import pkg_resources

def _get_version(dependency_name):
try:
version_string = pkg_resources.get_distribution(dependency_name).version
return (parse_version(version_string), version_string)
except pkg_resources.DistributionNotFound:
return (None, "--")
else:
from importlib import metadata

def _get_version(dependency_name):
try:
version_string = metadata.version("requests")
parsed_version = parse_version(version_string)
return (parsed_version.release, version_string)
except metadata.PackageNotFoundError:
return (None, "--")

_dependency_package = "google.protobuf"
_next_supported_version = "4.25.8"
_next_supported_version_tuple = (4, 25, 8)
(_version_used, _version_used_string) = _get_version(_dependency_package)
if _version_used and _version_used < _next_supported_version_tuple:
warnings.warn(f"Package {_package_label} depends on " +
f"{_dependency_package}, currently installed at version " +
f"{_version_used_string}. Future updates to " +
f"{_package_label} will require {_dependency_package} at " +
f"version {_next_supported_version} or higher. Please ensure " +
"that either (a) your Python environment doesn't pin the " +
f"version of {_dependency_package}, so that updates to " +
f"{_package_label} can require the higher version, or " +
"(b) you manually update your Python environment to use at " +
f"least version {_next_supported_version} of " +
f"{_dependency_package}.",
FutureWarning)


from .services.iam_credentials import IAMCredentialsClient
from .services.iam_credentials import IAMCredentialsAsyncClient

Expand Down
1 change: 1 addition & 0 deletions tests/integration/goldens/credentials/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
# Exclude incompatible versions of `google-auth`
# See https://github.com/googleapis/google-cloud-python/issues/12364
"google-auth >= 2.14.1, <3.0.0,!=2.24.0,!=2.25.0",
"packaging", # TODO: Remove once we require versions of api core that include this
"proto-plus >= 1.22.3, <2.0.0",
"proto-plus >= 1.25.0, <2.0.0; python_version >= '3.13'",
"protobuf>=3.20.2,<7.0.0,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3972,6 +3972,7 @@ def test_iam_credentials_grpc_asyncio_transport_channel():

# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
# removed from grpc/grpc_asyncio transport constructor.
@pytest.mark.filterwarnings("ignore::FutureWarning")
@pytest.mark.parametrize("transport_class", [transports.IAMCredentialsGrpcTransport, transports.IAMCredentialsGrpcAsyncIOTransport])
def test_iam_credentials_transport_channel_mtls_with_client_cert_source(
transport_class
Expand Down
Loading
Loading