Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit b90b18f

Browse files
committed
feat: implement async rest transport constructor
1 parent f5318d5 commit b90b18f

14 files changed

Lines changed: 311 additions & 140 deletions

File tree

gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
{# TODO: Remove the following condition for async rest transport once support for it is GA:
2+
# {% if rest_async_io_enabled %}
3+
# See related issue: https://github.com/googleapis/gapic-generator-python/issues/2121.
4+
#}
5+
{% set rest_async_io_enabled = api.all_library_settings[api.naming.proto_package].python_settings.experimental_features.rest_async_io_enabled %}
16
{% extends '_base.py.j2' %}
27

38
{% block content %}
@@ -62,6 +67,9 @@ from .transports.grpc_asyncio import {{ service.grpc_asyncio_transport_name }}
6267
{% endif %}
6368
{% if 'rest' in opts.transport %}
6469
from .transports.rest import {{ service.name }}RestTransport
70+
{% if rest_async_io_enabled %}
71+
from .transports.rest_asyncio import Async{{ service.name }}RestTransport
72+
{% endif %}{# if rest_async_io_enabled #}
6573
{% endif %}
6674

6775

@@ -79,6 +87,9 @@ class {{ service.client_name }}Meta(type):
7987
{% endif %}
8088
{% if "rest" in opts.transport %}
8189
_transport_registry["rest"] = {{ service.name }}RestTransport
90+
{% if rest_async_io_enabled %}
91+
_transport_registry["rest_asyncio"] = {{ service.name }}RestTransport
92+
{% endif %}{# if rest_async_io_enabled #}
8293
{% endif %}
8394

8495
def get_transport_class(cls,

gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest_asyncio.py.j2

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,87 @@
44
#}
55
{% set rest_async_io_enabled = api.all_library_settings[api.naming.proto_package].python_settings.experimental_features.rest_async_io_enabled %}
66
{% if rest_async_io_enabled %}
7+
{% extends '_base.py.j2' %}
8+
9+
{% block content %}
10+
11+
from google.api_core import gapic_v1
12+
13+
from typing import Any, Optional
14+
15+
from .rest_base import _Base{{ service.name }}RestTransport
16+
17+
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
18+
19+
{# TODO (ohmayr): determine the version of rest. aiohttp or google.auth.aio. #}
20+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
21+
gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
22+
grpc_version=None,
23+
rest_version=None,
24+
)
25+
26+
class Async{{service.name}}RestTransport(_Base{{ service.name }}RestTransport):
27+
"""Asynchronous REST backend transport for {{ service.name }}.
28+
29+
{{ service.meta.doc|rst(width=72, indent=4) }}
30+
31+
This class defines the same methods as the primary client, so the
32+
primary client can load the underlying transport implementation
33+
and call it.
34+
35+
It sends JSON representations of protocol buffers over HTTP/1.1
36+
"""
37+
def __init__(self, *,
38+
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
39+
{# TODO (ohmayr): Update the default type for credentials. #}
40+
credentials: Optional[Any] = None,
41+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
42+
url_scheme: str = 'https',
43+
) -> None:
44+
"""Instantiate the transport.
45+
46+
{% if not opts.rest_numeric_enums %}
47+
NOTE: This async REST transport functionality is currently in a beta
48+
state (preview). We welcome your feedback via a GitHub issue in
49+
this library's repository. Thank you!
50+
{% endif %}
51+
52+
Args:
53+
host ({% if service.host %}Optional[str]{% else %}str{% endif %}):
54+
{{ ' ' }}The hostname to connect to {% if service.host %}(default: '{{ service.host }}'){% endif %}.
55+
{# TODO (ohmayr): Update the default type for credentials. #}
56+
credentials (Optional[Any]): The
57+
authorization credentials to attach to requests. These
58+
credentials identify the application to the service; if none
59+
are specified, the client will attempt to ascertain the
60+
credentials from the environment.
61+
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
62+
The client info used to send a user-agent string along with
63+
API requests. If ``None``, then default info will be used.
64+
Generally, you only need to set this if you are developing
65+
your own client library.
66+
url_scheme: the protocol scheme for the API endpoint. Normally
67+
"https", but for testing or local servers,
68+
"http" can be specified.
69+
"""
70+
# Run the base constructor
71+
super().__init__(
72+
host=host,
73+
credentials=credentials,
74+
client_info=client_info,
75+
always_use_jwt_access=False,
76+
url_scheme=url_scheme,
77+
api_audience=None
78+
)
79+
80+
{# TODO (ohmayr): configure session once the following PR in google-auth-library-python
81+
i.e. https://github.com/googleapis/google-auth-library-python/pull/1577 is merged. #}
82+
{# TODO (ohmayr): call prep wrapped methods #}
83+
{# self._prep_wrapped_messages(client_info) #}
84+
85+
@property
86+
def kind(self) -> str:
87+
return "rest_asyncio"
88+
89+
{% endblock %}
790
{% endif %}{# if rest_async_io_enabled #}

gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
{# TODO: Remove the following condition for async rest transport once support for it is GA:
2+
# {% if rest_async_io_enabled %}
3+
# See related issue: https://github.com/googleapis/gapic-generator-python/issues/2121.
4+
#}
5+
{% set rest_async_io_enabled = api.all_library_settings[api.naming.proto_package].python_settings.experimental_features.rest_async_io_enabled %}
16
{% extends "_base.py.j2" %}
27

38
{% block content %}
@@ -1041,9 +1046,21 @@ def test_transport_adc(transport_class):
10411046
transport_class()
10421047
adc.assert_called_once()
10431048

1044-
{{ test_macros.transport_kind_test(service, opts) }}
1049+
{% set configs = [] %}
1050+
{% for transport_name in opts.transport %}
1051+
{% do configs.append({'service':service, 'transport_name':transport_name,'credentials':'ga_credentials.AnonymousCredentials()'}) %}
1052+
{# TODO: Remove the following guard once support for async REST is GA.
1053+
# See related issue: https://github.com/googleapis/gapic-generator-python/issues/2121.
1054+
#}
1055+
{% if 'grpc' in transport_name or rest_async_io_enabled %}
1056+
{% do configs.append({'service':service, 'transport_name':transport_name + "_asyncio",'credentials':'async_anonymous_credentials()'}) %}
1057+
{% endif %}
1058+
{% endfor %}
10451059

1046-
{{ test_macros.transport_kind_test(service, opts, is_async=True) }}
1060+
{% for conf in configs %}
1061+
{{ test_macros.transport_kind_test(**conf) }}
1062+
1063+
{% endfor %}
10471064

10481065
{% if 'grpc' in opts.transport %}
10491066
def test_transport_grpc_default():

gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,32 +1878,12 @@ def test_{{ method_name }}_empty_call():
18781878
{% endmacro %}
18791879

18801880

1881-
{% macro transport_kind_test(service, opts, is_async=False) %}
1882-
@pytest.mark.parametrize("transport_name", [
1883-
{% if is_async %}
1884-
{% if "grpc" in opts.transport %}
1885-
"grpc_asyncio",
1886-
{% endif %}
1887-
{% else %}{# if not is_async #}
1888-
{% if "grpc" in opts.transport%}
1889-
"grpc",
1890-
{% endif %}
1891-
{% if "rest" in opts.transport %}
1892-
"rest",
1893-
{% endif %}
1894-
{% endif %}{# is_async #}
1895-
])
1896-
{% if is_async %}
1897-
@pytest.mark.asyncio
1898-
async def test_transport_kind_async(transport_name):
1899-
transport = {{ service.async_client_name }}.get_transport_class(transport_name)(
1900-
credentials=async_anonymous_credentials(),
1901-
)
1902-
{% else %}
1903-
def test_transport_kind(transport_name):
1904-
transport = {{ service.client_name }}.get_transport_class(transport_name)(
1905-
credentials=ga_credentials.AnonymousCredentials(),
1881+
{% macro transport_kind_test(service, transport_name, credentials) %}
1882+
{%- set named_clients = { 'rest': service.client_name, 'grpc': service.client_name, 'grpc_asyncio': service.async_client_name, 'rest_asyncio': service.async_client_name}
1883+
-%}
1884+
def test_transport_kind_{{transport_name}}():
1885+
transport = {{ named_clients[transport_name] }}.get_transport_class("{{transport_name}}")(
1886+
credentials={{credentials}}
19061887
)
1907-
{% endif %}
1908-
assert transport.kind == transport_name
1909-
{% endmacro %}
1888+
assert transport.kind == "{{ transport_name }}"
1889+
{% endmacro %}

tests/integration/cloudasset_v1.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ authentication:
4444
- selector: google.longrunning.Operations.GetOperation
4545
oauth:
4646
canonical_scopes: |-
47-
https://www.googleapis.com/auth/cloud-platform
47+
https://www.googleapis.com/auth/cloud-platform
48+
49+
publishing:
50+
library_settings:
51+
- version: 'google.cloud.asset.v1'
52+
python_settings:
53+
experimental_features:
54+
rest_async_io_enabled: true

tests/integration/goldens/asset/google/cloud/asset_v1/services/asset_service/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from .transports.grpc import AssetServiceGrpcTransport
5151
from .transports.grpc_asyncio import AssetServiceGrpcAsyncIOTransport
5252
from .transports.rest import AssetServiceRestTransport
53+
from .transports.rest_asyncio import AsyncAssetServiceRestTransport
5354

5455

5556
class AssetServiceClientMeta(type):
@@ -63,6 +64,7 @@ class AssetServiceClientMeta(type):
6364
_transport_registry["grpc"] = AssetServiceGrpcTransport
6465
_transport_registry["grpc_asyncio"] = AssetServiceGrpcAsyncIOTransport
6566
_transport_registry["rest"] = AssetServiceRestTransport
67+
_transport_registry["rest_asyncio"] = AssetServiceRestTransport
6668

6769
def get_transport_class(cls,
6870
label: Optional[str] = None,
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2024 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
from google.api_core import gapic_v1
17+
18+
from typing import Any, Optional
19+
20+
from .rest_base import _BaseAssetServiceRestTransport
21+
22+
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
23+
24+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
25+
gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
26+
grpc_version=None,
27+
rest_version=None,
28+
)
29+
30+
class AsyncAssetServiceRestTransport(_BaseAssetServiceRestTransport):
31+
"""Asynchronous REST backend transport for AssetService.
32+
33+
Asset service definition.
34+
35+
This class defines the same methods as the primary client, so the
36+
primary client can load the underlying transport implementation
37+
and call it.
38+
39+
It sends JSON representations of protocol buffers over HTTP/1.1
40+
"""
41+
def __init__(self, *,
42+
host: str = 'cloudasset.googleapis.com',
43+
credentials: Optional[Any] = None,
44+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
45+
url_scheme: str = 'https',
46+
) -> None:
47+
"""Instantiate the transport.
48+
49+
NOTE: This async REST transport functionality is currently in a beta
50+
state (preview). We welcome your feedback via a GitHub issue in
51+
this library's repository. Thank you!
52+
53+
Args:
54+
host (Optional[str]):
55+
The hostname to connect to (default: 'cloudasset.googleapis.com').
56+
credentials (Optional[Any]): The
57+
authorization credentials to attach to requests. These
58+
credentials identify the application to the service; if none
59+
are specified, the client will attempt to ascertain the
60+
credentials from the environment.
61+
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
62+
The client info used to send a user-agent string along with
63+
API requests. If ``None``, then default info will be used.
64+
Generally, you only need to set this if you are developing
65+
your own client library.
66+
url_scheme: the protocol scheme for the API endpoint. Normally
67+
"https", but for testing or local servers,
68+
"http" can be specified.
69+
"""
70+
# Run the base constructor
71+
super().__init__(
72+
host=host,
73+
credentials=credentials,
74+
client_info=client_info,
75+
always_use_jwt_access=False,
76+
url_scheme=url_scheme,
77+
api_audience=None
78+
)
79+
80+
@property
81+
def kind(self) -> str:
82+
return "rest_asyncio"

tests/integration/goldens/asset/tests/unit/gapic/asset_v1/test_asset_service.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16405,26 +16405,33 @@ def test_transport_adc(transport_class):
1640516405
transport_class()
1640616406
adc.assert_called_once()
1640716407

16408-
@pytest.mark.parametrize("transport_name", [
16409-
"grpc",
16410-
"rest",
16411-
])
16412-
def test_transport_kind(transport_name):
16413-
transport = AssetServiceClient.get_transport_class(transport_name)(
16414-
credentials=ga_credentials.AnonymousCredentials(),
16408+
16409+
def test_transport_kind_grpc():
16410+
transport = AssetServiceClient.get_transport_class("grpc")(
16411+
credentials=ga_credentials.AnonymousCredentials()
1641516412
)
16416-
assert transport.kind == transport_name
16413+
assert transport.kind == "grpc"
1641716414

1641816415

16419-
@pytest.mark.parametrize("transport_name", [
16420-
"grpc_asyncio",
16421-
])
16422-
@pytest.mark.asyncio
16423-
async def test_transport_kind_async(transport_name):
16424-
transport = AssetServiceAsyncClient.get_transport_class(transport_name)(
16425-
credentials=async_anonymous_credentials(),
16416+
def test_transport_kind_grpc_asyncio():
16417+
transport = AssetServiceAsyncClient.get_transport_class("grpc_asyncio")(
16418+
credentials=async_anonymous_credentials()
16419+
)
16420+
assert transport.kind == "grpc_asyncio"
16421+
16422+
16423+
def test_transport_kind_rest():
16424+
transport = AssetServiceClient.get_transport_class("rest")(
16425+
credentials=ga_credentials.AnonymousCredentials()
16426+
)
16427+
assert transport.kind == "rest"
16428+
16429+
16430+
def test_transport_kind_rest_asyncio():
16431+
transport = AssetServiceAsyncClient.get_transport_class("rest_asyncio")(
16432+
credentials=async_anonymous_credentials()
1642616433
)
16427-
assert transport.kind == transport_name
16434+
assert transport.kind == "rest_asyncio"
1642816435

1642916436

1643016437
def test_transport_grpc_default():

tests/integration/goldens/credentials/tests/unit/gapic/credentials_v1/test_iam_credentials.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3490,26 +3490,26 @@ def test_transport_adc(transport_class):
34903490
transport_class()
34913491
adc.assert_called_once()
34923492

3493-
@pytest.mark.parametrize("transport_name", [
3494-
"grpc",
3495-
"rest",
3496-
])
3497-
def test_transport_kind(transport_name):
3498-
transport = IAMCredentialsClient.get_transport_class(transport_name)(
3499-
credentials=ga_credentials.AnonymousCredentials(),
3493+
3494+
def test_transport_kind_grpc():
3495+
transport = IAMCredentialsClient.get_transport_class("grpc")(
3496+
credentials=ga_credentials.AnonymousCredentials()
35003497
)
3501-
assert transport.kind == transport_name
3498+
assert transport.kind == "grpc"
35023499

35033500

3504-
@pytest.mark.parametrize("transport_name", [
3505-
"grpc_asyncio",
3506-
])
3507-
@pytest.mark.asyncio
3508-
async def test_transport_kind_async(transport_name):
3509-
transport = IAMCredentialsAsyncClient.get_transport_class(transport_name)(
3510-
credentials=async_anonymous_credentials(),
3501+
def test_transport_kind_grpc_asyncio():
3502+
transport = IAMCredentialsAsyncClient.get_transport_class("grpc_asyncio")(
3503+
credentials=async_anonymous_credentials()
3504+
)
3505+
assert transport.kind == "grpc_asyncio"
3506+
3507+
3508+
def test_transport_kind_rest():
3509+
transport = IAMCredentialsClient.get_transport_class("rest")(
3510+
credentials=ga_credentials.AnonymousCredentials()
35113511
)
3512-
assert transport.kind == transport_name
3512+
assert transport.kind == "rest"
35133513

35143514

35153515
def test_transport_grpc_default():

0 commit comments

Comments
 (0)