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

Commit a518cc1

Browse files
committed
feat: allow user-provided client info
1 parent 7c2bab7 commit a518cc1

10 files changed

Lines changed: 109 additions & 35 deletions

File tree

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ from google.oauth2 import service_account # type: ignore
2323
{% endfor -%}
2424
{% endfor -%}
2525
{% endfilter %}
26-
from .transports.base import {{ service.name }}Transport
26+
from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO
2727
from .transports.grpc import {{ service.name }}GrpcTransport
2828

2929

@@ -135,6 +135,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
135135
credentials: credentials.Credentials = None,
136136
transport: Union[str, {{ service.name }}Transport] = None,
137137
client_options: ClientOptions = None,
138+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
138139
) -> None:
139140
"""Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}.
140141

@@ -209,6 +210,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
209210
host=client_options.api_endpoint,
210211
api_mtls_endpoint=client_options.api_endpoint,
211212
client_cert_source=client_options.client_cert_source,
213+
client_info=client_info,
212214
)
213215

214216

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/base.py.j2

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ from google.auth import credentials # type: ignore
2121
{% endfilter %}
2222

2323
try:
24-
_client_info = gapic_v1.client_info.ClientInfo(
24+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
2525
gapic_version=pkg_resources.get_distribution(
2626
'{{ api.naming.warehouse_package_name }}',
2727
).version,
2828
)
2929
except pkg_resources.DistributionNotFound:
30-
_client_info = gapic_v1.client_info.ClientInfo()
30+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
3131

3232

3333
class {{ service.name }}Transport(metaclass=abc.ABCMeta):
@@ -43,6 +43,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
4343
self, *,
4444
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
4545
credentials: credentials.Credentials = None,
46+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
4647
) -> None:
4748
"""Instantiate the transport.
4849

@@ -69,9 +70,9 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
6970
self._credentials = credentials
7071

7172
# Lifted into its own function so it can be stubbed out during tests.
72-
self._prep_wrapped_messages()
73+
self._prep_wrapped_messages(client_info)
7374

74-
def _prep_wrapped_messages(self):
75+
def _prep_wrapped_messages(self, client_info):
7576
# Precomputed wrapped methods
7677
self._wrapped_methods = {
7778
{% for method in service.methods.values() -%}
@@ -92,7 +93,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
9293
),
9394
{%- endif %}
9495
default_timeout={{ method.timeout }},
95-
client_info=_client_info,
96+
client_info=client_info,
9697
),
9798
{% endfor %} {# precomputed wrappers loop #}
9899
}

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ from google.api_core import grpc_helpers # type: ignore
77
{%- if service.has_lro %}
88
from google.api_core import operations_v1 # type: ignore
99
{%- endif %}
10+
from google.api_core import gapic_v1 # type: ignore
1011
from google import auth # type: ignore
1112
from google.auth import credentials # type: ignore
1213
from google.auth.transport.grpc import SslCredentials # type: ignore
@@ -20,7 +21,7 @@ import grpc # type: ignore
2021
{{ method.output.ident.python_import }}
2122
{% endfor -%}
2223
{% endfilter %}
23-
from .base import {{ service.name }}Transport
24+
from .base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO
2425

2526

2627
class {{ service.name }}GrpcTransport({{ service.name }}Transport):
@@ -40,7 +41,9 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
4041
credentials: credentials.Credentials = None,
4142
channel: grpc.Channel = None,
4243
api_mtls_endpoint: str = None,
43-
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None) -> None:
44+
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
45+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
46+
) -> None:
4447
"""Instantiate the transport.
4548

4649
Args:
@@ -101,7 +104,11 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
101104
self._stubs = {} # type: Dict[str, Callable]
102105

103106
# Run the base constructor.
104-
super().__init__(host=host, credentials=credentials)
107+
super().__init__(
108+
host=host,
109+
credentials=credentials,
110+
client_info=client_info,
111+
)
105112

106113

107114
@classmethod

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ from google.api_core import future
2424
from google.api_core import operations_v1
2525
from google.longrunning import operations_pb2
2626
{% endif -%}
27-
{% if service.has_pagers -%}
2827
from google.api_core import gapic_v1
29-
{% endif -%}
3028
{% for method in service.methods.values() -%}
3129
{% for ref_type in method.ref_types
3230
if not ((ref_type.ident.python_import.package == ('google', 'api_core') and ref_type.ident.python_import.module == 'operation')
@@ -109,6 +107,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
109107
client_cert_source=None,
110108
credentials=None,
111109
host="squid.clam.whelk",
110+
client_info=transports.base.DEFAULT_CLIENT_INFO,
112111
)
113112

114113
# Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is
@@ -122,6 +121,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
122121
client_cert_source=None,
123122
credentials=None,
124123
host=client.DEFAULT_ENDPOINT,
124+
client_info=transports.base.DEFAULT_CLIENT_INFO,
125125
)
126126

127127
# Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is
@@ -135,6 +135,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
135135
client_cert_source=None,
136136
credentials=None,
137137
host=client.DEFAULT_MTLS_ENDPOINT,
138+
client_info=transports.base.DEFAULT_CLIENT_INFO,
138139
)
139140

140141
# Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is
@@ -149,6 +150,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
149150
client_cert_source=client_cert_source_callback,
150151
credentials=None,
151152
host=client.DEFAULT_MTLS_ENDPOINT,
153+
client_info=transports.base.DEFAULT_CLIENT_INFO,
152154
)
153155

154156
# Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is
@@ -163,6 +165,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
163165
client_cert_source=None,
164166
credentials=None,
165167
host=client.DEFAULT_MTLS_ENDPOINT,
168+
client_info=transports.base.DEFAULT_CLIENT_INFO,
166169
)
167170

168171
# Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is
@@ -177,6 +180,7 @@ def test_{{ service.client_name|snake_case }}_client_options():
177180
client_cert_source=None,
178181
credentials=None,
179182
host=client.DEFAULT_ENDPOINT,
183+
client_info=transports.base.DEFAULT_CLIENT_INFO,
180184
)
181185

182186
# Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has
@@ -197,6 +201,7 @@ def test_{{ service.client_name|snake_case }}_client_options_from_dict():
197201
client_cert_source=None,
198202
credentials=None,
199203
host="squid.clam.whelk",
204+
client_info=transports.base.DEFAULT_CLIENT_INFO,
200205
)
201206

202207

@@ -769,4 +774,23 @@ def test_parse_{{ message.resource_type|snake_case }}_path():
769774
{% endwith -%}
770775
{% endfor -%}
771776

777+
def test_client_withDEFAULT_CLIENT_INFO():
778+
client_info = gapic_v1.client_info.ClientInfo()
779+
780+
with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep:
781+
client = {{ service.client_name }}(
782+
credentials=credentials.AnonymousCredentials(),
783+
client_info=client_info,
784+
)
785+
prep.assert_called_once_with(client_info)
786+
787+
with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep:
788+
transport_class = {{ service.client_name }}.get_transport_class()
789+
transport = transport_class(
790+
credentials=credentials.AnonymousCredentials(),
791+
client_info=client_info,
792+
)
793+
prep.assert_called_once_with(client_info)
794+
795+
772796
{% endblock %}

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
2525
from google.iam.v1 import policy_pb2 as policy # type: ignore
2626
{% endif %}
2727
{% endfilter %}
28-
from .transports.base import {{ service.name }}Transport
28+
from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO
2929
from .transports.grpc_asyncio import {{ service.grpc_asyncio_transport_name }}
3030
from .client import {{ service.client_name }}
3131

@@ -52,6 +52,7 @@ class {{ service.async_client_name }}:
5252
credentials: credentials.Credentials = None,
5353
transport: Union[str, {{ service.name }}Transport] = 'grpc_asyncio',
5454
client_options: ClientOptions = None,
55+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
5556
) -> None:
5657
"""Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}.
5758

@@ -87,6 +88,8 @@ class {{ service.async_client_name }}:
8788
credentials=credentials,
8889
transport=transport,
8990
client_options=client_options,
91+
client_info=client_info,
92+
9093
)
9194

9295
{% for method in service.methods.values() -%}
@@ -202,7 +205,7 @@ class {{ service.async_client_name }}:
202205
),
203206
{%- endif %}
204207
default_timeout={{ method.timeout }},
205-
client_info=_client_info,
208+
client_info=DEFAULT_CLIENT_INFO,
206209
)
207210
{%- if method.field_headers %}
208211

@@ -352,7 +355,7 @@ class {{ service.async_client_name }}:
352355
rpc = gapic_v1.method_async.wrap_method(
353356
self._client._transport.set_iam_policy,
354357
default_timeout=None,
355-
client_info=_client_info,
358+
client_info=DEFAULT_CLIENT_INFO,
356359
)
357360

358361
# Certain fields should be provided within the metadata header;
@@ -459,7 +462,7 @@ class {{ service.async_client_name }}:
459462
rpc = gapic_v1.method_async.wrap_method(
460463
self._client._transport.get_iam_policy,
461464
default_timeout=None,
462-
client_info=_client_info,
465+
client_info=DEFAULT_CLIENT_INFO,
463466
)
464467

465468
# Certain fields should be provided within the metadata header;
@@ -510,7 +513,7 @@ class {{ service.async_client_name }}:
510513
rpc = gapic_v1.method_async.wrap_method(
511514
self._client._transport.test_iam_permissions,
512515
default_timeout=None,
513-
client_info=_client_info,
516+
client_info=DEFAULT_CLIENT_INFO,
514517
)
515518

516519
# Certain fields should be provided within the metadata header;
@@ -527,13 +530,13 @@ class {{ service.async_client_name }}:
527530
{% endif %}
528531

529532
try:
530-
_client_info = gapic_v1.client_info.ClientInfo(
533+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
531534
gapic_version=pkg_resources.get_distribution(
532535
'{{ api.naming.warehouse_package_name }}',
533536
).version,
534537
)
535538
except pkg_resources.DistributionNotFound:
536-
_client_info = gapic_v1.client_info.ClientInfo()
539+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
537540

538541

539542
__all__ = (

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
2727
from google.iam.v1 import policy_pb2 as policy # type: ignore
2828
{% endif %}
2929
{% endfilter %}
30-
from .transports.base import {{ service.name }}Transport
30+
from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO
3131
from .transports.grpc import {{ service.grpc_transport_name }}
3232
from .transports.grpc_asyncio import {{ service.grpc_asyncio_transport_name }}
3333

@@ -141,6 +141,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
141141
credentials: credentials.Credentials = None,
142142
transport: Union[str, {{ service.name }}Transport] = None,
143143
client_options: ClientOptions = None,
144+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
144145
) -> None:
145146
"""Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}.
146147

@@ -219,6 +220,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
219220
api_mtls_endpoint=client_options.api_endpoint,
220221
client_cert_source=client_options.client_cert_source,
221222
quota_project_id=client_options.quota_project_id,
223+
client_info=client_info,
222224
)
223225

224226

@@ -471,7 +473,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
471473
rpc = gapic_v1.method.wrap_method(
472474
self._transport.set_iam_policy,
473475
default_timeout=None,
474-
client_info=_client_info,
476+
client_info=DEFAULT_CLIENT_INFO,
475477
)
476478

477479
# Certain fields should be provided within the metadata header;
@@ -578,7 +580,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
578580
rpc = gapic_v1.method.wrap_method(
579581
self._transport.get_iam_policy,
580582
default_timeout=None,
581-
client_info=_client_info,
583+
client_info=DEFAULT_CLIENT_INFO,
582584
)
583585

584586
# Certain fields should be provided within the metadata header;
@@ -629,7 +631,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
629631
rpc = gapic_v1.method.wrap_method(
630632
self._transport.test_iam_permissions,
631633
default_timeout=None,
632-
client_info=_client_info,
634+
client_info=DEFAULT_CLIENT_INFO,
633635
)
634636

635637
# Certain fields should be provided within the metadata header;
@@ -647,13 +649,13 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
647649

648650

649651
try:
650-
_client_info = gapic_v1.client_info.ClientInfo(
652+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
651653
gapic_version=pkg_resources.get_distribution(
652654
'{{ api.naming.warehouse_package_name }}',
653655
).version,
654656
)
655657
except pkg_resources.DistributionNotFound:
656-
_client_info = gapic_v1.client_info.ClientInfo()
658+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
657659

658660

659661
__all__ = (

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ from google.iam.v1 import policy_pb2 as policy # type: ignore
2626
{% endfilter %}
2727

2828
try:
29-
_client_info = gapic_v1.client_info.ClientInfo(
29+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
3030
gapic_version=pkg_resources.get_distribution(
3131
'{{ api.naming.warehouse_package_name }}',
3232
).version,
3333
)
3434
except pkg_resources.DistributionNotFound:
35-
_client_info = gapic_v1.client_info.ClientInfo()
35+
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
3636

3737
class {{ service.name }}Transport(abc.ABC):
3838
"""Abstract transport class for {{ service.name }}."""
@@ -50,6 +50,7 @@ class {{ service.name }}Transport(abc.ABC):
5050
credentials_file: typing.Optional[str] = None,
5151
scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES,
5252
quota_project_id: typing.Optional[str] = None,
53+
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
5354
**kwargs,
5455
) -> None:
5556
"""Instantiate the transport.
@@ -93,10 +94,10 @@ class {{ service.name }}Transport(abc.ABC):
9394
self._credentials = credentials
9495

9596
# Lifted into its own function so it can be stubbed out during tests.
96-
self._prep_wrapped_messages()
97+
self._prep_wrapped_messages(client_info)
9798

9899

99-
def _prep_wrapped_messages(self):
100+
def _prep_wrapped_messages(self, client_info):
100101
# Precompute the wrapped methods.
101102
self._wrapped_methods = {
102103
{% for method in service.methods.values() -%}
@@ -117,7 +118,7 @@ class {{ service.name }}Transport(abc.ABC):
117118
),
118119
{%- endif %}
119120
default_timeout={{ method.timeout }},
120-
client_info=_client_info,
121+
client_info=client_info,
121122
),
122123
{% endfor %} {# precomputed wrappers loop #}
123124
}

0 commit comments

Comments
 (0)