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

Commit 41ba010

Browse files
committed
feat: add credentials_file and scopes support
1 parent a48ff4d commit 41ba010

3 files changed

Lines changed: 48 additions & 8 deletions

File tree

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,21 +194,31 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
194194
# instance provides an extensibility point for unusual situations.
195195
if isinstance(transport, {{ service.name }}Transport):
196196
# transport is a {{ service.name }}Transport instance.
197-
if credentials:
197+
if credentials or client_options.credentials_file:
198198
raise ValueError('When providing a transport instance, '
199199
'provide its credentials directly.')
200+
if client_options.scopes:
201+
raise ValueError(
202+
"When providing a transport instance, "
203+
"provide its scopes directly."
204+
)
200205
self._transport = transport
201206
elif isinstance(transport, str):
202207
Transport = type(self).get_transport_class(transport)
203208
self._transport = Transport(
204-
credentials=credentials, host=self.DEFAULT_ENDPOINT
209+
credentials=credentials,
210+
host=self.DEFAULT_ENDPOINT,
211+
credentials_file=client_options.credentials_file,
212+
scopes=client_options.scopes,
205213
)
206214
else:
207215
self._transport = {{ service.name }}GrpcTransport(
208216
credentials=credentials,
209217
host=client_options.api_endpoint,
210218
api_mtls_endpoint=client_options.api_endpoint,
211219
client_cert_source=client_options.client_cert_source,
220+
credentials_file=client_options.credentials_file,
221+
scopes=client_options.scopes
212222
)
213223

214224
{% for method in service.methods.values() -%}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
3030
self, *,
3131
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
3232
credentials: credentials.Credentials = None,
33+
credentials_file: str = None,
34+
scopes: Sequence[str] = self.AUTH_SCOPES,
3335
) -> None:
3436
"""Instantiate the transport.
3537

@@ -41,6 +43,10 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
4143
credentials identify the application to the service; if none
4244
are specified, the client will attempt to ascertain the
4345
credentials from the environment.
46+
credentials_file (Optional[str]): A file with credentials that can
47+
be loaded with :func:`google.auth.load_credentials_from_file`.
48+
This argument is mutually exclusive with credentials.
49+
scope (Optional[str]): A list of scopes.
4450
"""
4551
# Save the hostname. Default to port 443 (HTTPS) if none is specified.
4652
if ':' not in host:
@@ -49,8 +55,13 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
4955

5056
# If no credentials are provided, then determine the appropriate
5157
# defaults.
52-
if credentials is None:
53-
credentials, _ = auth.default(scopes=self.AUTH_SCOPES)
58+
if credentials and credentials_file:
59+
raise ValueError("'credentials_file' and 'credentials' are mutually exclusive")
60+
61+
if credentials_file is not None:
62+
credentials, _ = auth.load_credentials_from_file(credentials_file, scopes=scopes)
63+
elif credentials is None:
64+
credentials, _ = auth.default(scopes=scopes)
5465

5566
# Save the credentials.
5667
self._credentials = credentials

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% extends '_base.py.j2' %}
22

33
{% block content %}
4-
from typing import Callable, Dict, Tuple
4+
from typing import Callable, Dict, Tuple, Sequence
55

66
from google.api_core import grpc_helpers # type: ignore
77
{%- if service.has_lro %}
@@ -38,6 +38,8 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
3838
def __init__(self, *,
3939
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
4040
credentials: credentials.Credentials = None,
41+
credentials_file: str = None,
42+
scopes: Sequence[str] = None,
4143
channel: grpc.Channel = None,
4244
api_mtls_endpoint: str = None,
4345
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None) -> None:
@@ -52,6 +54,11 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
5254
are specified, the client will attempt to ascertain the
5355
credentials from the environment.
5456
This argument is ignored if ``channel`` is provided.
57+
credentials_file (Optional[str]): A file with credentials that can
58+
be loaded with :func:`google.auth.load_credentials_from_file`.
59+
This argument is ignored if ``channel`` is provided.
60+
scopes (Optional(Sequence[str])): A list of scopes. This argument is
61+
ignored if ``channel`` is provided.
5562
channel (Optional[grpc.Channel]): A ``Channel`` instance through
5663
which to make calls.
5764
api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If
@@ -66,6 +73,7 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
6673
Raises:
6774
google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
6875
creation failed for any reason.
76+
ValueError: If both ``credentials`` and ``credentials_file`` are passed.
6977
"""
7078
if channel:
7179
# Sanity check: Ensure that channel and credentials are not both
@@ -94,19 +102,22 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
94102
self._grpc_channel = grpc_helpers.create_channel(
95103
host,
96104
credentials=credentials,
105+
credentials_file=credentials_file,
97106
ssl_credentials=ssl_credentials,
98-
scopes=self.AUTH_SCOPES,
107+
scopes=scopes or self.AUTH_SCOPES,
99108
)
100109

101110
# Run the base constructor.
102-
super().__init__(host=host, credentials=credentials)
111+
super().__init__(host=host, credentials=credentials, credentials_file=credentials_file, scopes=scopes)
103112
self._stubs = {} # type: Dict[str, Callable]
104113

105114

106115
@classmethod
107116
def create_channel(cls,
108117
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
109118
credentials: credentials.Credentials = None,
119+
credentials_file: str = None,
120+
scopes: Sequence[str] = None,
110121
**kwargs) -> grpc.Channel:
111122
"""Create and return a gRPC channel object.
112123
Args:
@@ -116,15 +127,23 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
116127
credentials identify this application to the service. If
117128
none are specified, the client will attempt to ascertain
118129
the credentials from the environment.
130+
credentials_file (Optional[str]): A file with credentials that can
131+
be loaded with :func:`google.auth.load_credentials_from_file`.
132+
This argument is mutually exclusive with credentials.
133+
scopes (Optional(Sequence[str])): A list of scopes.
119134
kwargs (Optional[dict]): Keyword arguments, which are passed to the
120135
channel creation.
121136
Returns:
122137
grpc.Channel: A gRPC channel object.
138+
139+
Raises:
140+
ValueError: If both ``credentials`` and ``credentials_file`` are passed.
123141
"""
124142
return grpc_helpers.create_channel(
125143
host,
126144
credentials=credentials,
127-
scopes=cls.AUTH_SCOPES,
145+
credentials_file=credentials_file,
146+
scopes=scopes or cls.AUTH_SCOPES,
128147
**kwargs
129148
)
130149

0 commit comments

Comments
 (0)