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

Commit a51bcd3

Browse files
committed
Create a base class for clients
1 parent e8ff641 commit a51bcd3

5 files changed

Lines changed: 234 additions & 310 deletions

File tree

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

Lines changed: 7 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ from google.oauth2 import service_account # type: ignore
2222
{% endfilter %}
2323
from .transports.base import {{ service.name }}Transport
2424
from .transports.grpc_asyncio import {{ service.name }}GrpcAsyncIOTransport
25+
from .base_client import {{ service.name }}BaseClient, {{ service.name }}BaseClientMeta
2526

26-
27-
class {{ service.async_client_name }}Meta(type):
27+
class {{ service.async_client_name }}Meta({{ service.name }}BaseClientMeta):
2828
"""Metaclass for the {{ service.name }} client.
2929

3030
This provides class-level methods for building and retrieving
@@ -55,149 +55,13 @@ class {{ service.async_client_name }}Meta(type):
5555
return next(iter(cls._transport_registry.values()))
5656

5757

58-
class {{ service.async_client_name }}(metaclass={{ service.async_client_name }}Meta):
58+
class {{ service.async_client_name }}({{ service.name }}BaseClient, metaclass={{ service.async_client_name }}Meta):
5959
"""{{ service.meta.doc|rst(width=72, indent=4) }}"""
6060

61-
@staticmethod
62-
def _get_default_mtls_endpoint(api_endpoint):
63-
"""Convert api endpoint to mTLS endpoint.
64-
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
65-
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
66-
Args:
67-
api_endpoint (Optional[str]): the api endpoint to convert.
68-
Returns:
69-
str: converted mTLS api endpoint.
70-
"""
71-
if not api_endpoint:
72-
return api_endpoint
73-
74-
mtls_endpoint_re = re.compile(
75-
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
76-
)
77-
78-
m = mtls_endpoint_re.match(api_endpoint)
79-
name, mtls, sandbox, googledomain = m.groups()
80-
if mtls or not googledomain:
81-
return api_endpoint
82-
83-
if sandbox:
84-
return api_endpoint.replace(
85-
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
86-
)
87-
88-
return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
89-
90-
DEFAULT_ENDPOINT = {% if service.host %}'{{ service.host }}'{% else %}None{% endif %}
91-
DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
92-
DEFAULT_ENDPOINT
93-
)
94-
DEFAULT_MTLS_TRANSPORT = {{ service.grpc_asyncio_transport_name }}
95-
9661
@classmethod
97-
def from_service_account_file(cls, filename: str, *args, **kwargs):
98-
"""Creates an instance of this client using the provided credentials
99-
file.
100-
101-
Args:
102-
filename (str): The path to the service account private key json
103-
file.
104-
args: Additional arguments to pass to the constructor.
105-
kwargs: Additional arguments to pass to the constructor.
106-
107-
Returns:
108-
{@api.name}: The constructed client.
109-
"""
110-
credentials = service_account.Credentials.from_service_account_file(
111-
filename)
112-
kwargs['credentials'] = credentials
113-
return cls(*args, **kwargs)
114-
115-
from_service_account_json = from_service_account_file
116-
117-
118-
{% for message in service.resource_messages -%}
119-
@staticmethod
120-
def {{ message.resource_type|snake_case }}_path({% for arg in message.resource_path_args %}{{ arg }}: str,{% endfor %}) -> str:
121-
"""Return a fully-qualified {{ message.resource_type|snake_case }} string."""
122-
return "{{ message.resource_path }}".format({% for arg in message.resource_path_args %}{{ arg }}={{ arg }}, {% endfor %})
123-
124-
{% endfor %}
125-
126-
def __init__(self, *,
127-
credentials: credentials.Credentials = None,
128-
transport: Union[str, {{ service.name }}Transport] = None,
129-
client_options: ClientOptions = None,
130-
) -> None:
131-
"""Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}.
132-
133-
Args:
134-
credentials (Optional[google.auth.credentials.Credentials]): The
135-
authorization credentials to attach to requests. These
136-
credentials identify the application to the service; if none
137-
are specified, the client will attempt to ascertain the
138-
credentials from the environment.
139-
transport (Union[str, ~.{{ service.name }}Transport]): The
140-
transport to use. If set to None, a transport is chosen
141-
automatically.
142-
client_options (ClientOptions): Custom options for the client.
143-
(1) The ``api_endpoint`` property can be used to override the
144-
default endpoint provided by the client.
145-
(2) If ``transport`` argument is None, ``client_options`` can be
146-
used to create a mutual TLS transport. If ``client_cert_source``
147-
is provided, mutual TLS transport will be created with the given
148-
``api_endpoint`` or the default mTLS endpoint, and the client
149-
SSL credentials obtained from ``client_cert_source``.
150-
151-
Raises:
152-
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
153-
creation failed for any reason.
154-
"""
155-
if isinstance(client_options, dict):
156-
client_options = ClientOptions.from_dict(client_options)
157-
158-
# Save or instantiate the transport.
159-
# Ordinarily, we provide the transport, but allowing a custom transport
160-
# instance provides an extensibility point for unusual situations.
161-
if isinstance(transport, {{ service.name }}Transport):
162-
# transport is a {{ service.name }}Transport instance.
163-
if credentials:
164-
raise ValueError('When providing a transport instance, '
165-
'provide its credentials directly.')
166-
self._transport = transport
167-
elif client_options is None or (
168-
client_options.api_endpoint == None
169-
and client_options.client_cert_source is None
170-
):
171-
# Don't trigger mTLS if we get an empty ClientOptions.
172-
Transport = type(self).get_transport_class(transport)
173-
self._transport = Transport(
174-
credentials=credentials, host=self.DEFAULT_ENDPOINT
175-
)
176-
else:
177-
# We have a non-empty ClientOptions. If client_cert_source is
178-
# provided, trigger mTLS with user provided endpoint or the default
179-
# mTLS endpoint.
180-
if client_options.client_cert_source:
181-
api_mtls_endpoint = (
182-
client_options.api_endpoint
183-
if client_options.api_endpoint
184-
else self.DEFAULT_MTLS_ENDPOINT
185-
)
186-
else:
187-
api_mtls_endpoint = None
188-
189-
api_endpoint = (
190-
client_options.api_endpoint
191-
if client_options.api_endpoint
192-
else self.DEFAULT_ENDPOINT
193-
)
194-
195-
self._transport = self.DEFAULT_MTLS_TRANSPORT(
196-
credentials=credentials,
197-
host=api_endpoint,
198-
api_mtls_endpoint=api_mtls_endpoint,
199-
client_cert_source=client_options.client_cert_source,
200-
)
62+
def _default_mtls_transport(cls) -> str:
63+
"""Returns the default MTLS transport name."""
64+
return "grpc_asyncio"
20165

20266
{% for method in service.methods.values() -%}
20367
{% if not method.server_streaming %}async {% endif -%}def {{ method.name|snake_case }}(self,
@@ -312,7 +176,7 @@ class {{ service.async_client_name }}(metaclass={{ service.async_client_name }}M
312176
),
313177
{%- endif %}
314178
default_timeout={{ method.timeout }},
315-
client_info=_client_info,
179+
client_info=self._client_info,
316180
)
317181
{%- if method.field_headers %}
318182

@@ -367,16 +231,6 @@ class {{ service.async_client_name }}(metaclass={{ service.async_client_name }}M
367231
{% endfor %}
368232

369233

370-
try:
371-
_client_info = gapic_v1.client_info.ClientInfo(
372-
gapic_version=pkg_resources.get_distribution(
373-
'{{ api.naming.warehouse_package_name }}',
374-
).version,
375-
)
376-
except pkg_resources.DistributionNotFound:
377-
_client_info = gapic_v1.client_info.ClientInfo()
378-
379-
380234
__all__ = (
381235
'{{ service.async_client_name }}',
382236
)

0 commit comments

Comments
 (0)