Skip to content

Commit fbc10b8

Browse files
authored
feat(spanner): add client_options to constructor (#9151)
1 parent 9872fb0 commit fbc10b8

4 files changed

Lines changed: 45 additions & 9 deletions

File tree

spanner/google/cloud/spanner_v1/client.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ class Client(ClientWithProject):
111111
:param user_agent:
112112
(Deprecated) The user agent to be used with API request.
113113
Not used.
114+
:type client_options: :class:`~google.api_core.client_options.ClientOptions`
115+
or :class:`dict`
116+
:param client_options: (Optional) Client options used to set user options
117+
on the client. API Endpoint should be set through client_options.
114118
115119
:raises: :class:`ValueError <exceptions.ValueError>` if both ``read_only``
116120
and ``admin`` are :data:`True`
@@ -125,7 +129,12 @@ class Client(ClientWithProject):
125129
"""The scopes required for Google Cloud Spanner."""
126130

127131
def __init__(
128-
self, project=None, credentials=None, client_info=_CLIENT_INFO, user_agent=None
132+
self,
133+
project=None,
134+
credentials=None,
135+
client_info=_CLIENT_INFO,
136+
user_agent=None,
137+
client_options=None,
129138
):
130139
# NOTE: This API has no use for the _http argument, but sending it
131140
# will have no impact since the _http() @property only lazily
@@ -134,6 +143,7 @@ def __init__(
134143
project=project, credentials=credentials, _http=None
135144
)
136145
self._client_info = client_info
146+
self._client_options = client_options
137147

138148
if user_agent is not None:
139149
warnings.warn(_USER_AGENT_DEPRECATED, DeprecationWarning, stacklevel=2)
@@ -173,7 +183,9 @@ def instance_admin_api(self):
173183
"""Helper for session-related API calls."""
174184
if self._instance_admin_api is None:
175185
self._instance_admin_api = InstanceAdminClient(
176-
credentials=self.credentials, client_info=self._client_info
186+
credentials=self.credentials,
187+
client_info=self._client_info,
188+
client_options=self._client_options,
177189
)
178190
return self._instance_admin_api
179191

@@ -182,7 +194,9 @@ def database_admin_api(self):
182194
"""Helper for session-related API calls."""
183195
if self._database_admin_api is None:
184196
self._database_admin_api = DatabaseAdminClient(
185-
credentials=self.credentials, client_info=self._client_info
197+
credentials=self.credentials,
198+
client_info=self._client_info,
199+
client_options=self._client_options,
186200
)
187201
return self._database_admin_api
188202

spanner/google/cloud/spanner_v1/database.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,11 @@ def spanner_api(self):
177177
if isinstance(credentials, google.auth.credentials.Scoped):
178178
credentials = credentials.with_scopes((SPANNER_DATA_SCOPE,))
179179
client_info = self._instance._client._client_info
180+
client_options = self._instance._client._client_options
180181
self._spanner_api = SpannerClient(
181-
credentials=credentials, client_info=client_info
182+
credentials=credentials,
183+
client_info=client_info,
184+
client_options=client_options,
182185
)
183186
return self._spanner_api
184187

spanner/tests/unit/test_client.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def _constructor_test_helper(
5555
expected_creds=None,
5656
client_info=None,
5757
user_agent=None,
58+
client_options=None,
5859
):
5960
from google.cloud.spanner_v1 import client as MUT
6061

@@ -79,6 +80,7 @@ def _constructor_test_helper(
7980
self.assertEqual(client.project, self.PROJECT)
8081
self.assertIs(client._client_info, expected_client_info)
8182
self.assertEqual(client.user_agent, user_agent)
83+
self.assertEqual(client._client_options, client_options)
8284

8385
def test_constructor_default_scopes(self):
8486
from google.cloud.spanner_v1 import client as MUT
@@ -130,8 +132,12 @@ def test_instance_admin_api(self):
130132

131133
credentials = _make_credentials()
132134
client_info = mock.Mock()
135+
client_options = mock.Mock()
133136
client = self._make_one(
134-
project=self.PROJECT, credentials=credentials, client_info=client_info
137+
project=self.PROJECT,
138+
credentials=credentials,
139+
client_info=client_info,
140+
client_options=client_options,
135141
)
136142
expected_scopes = (SPANNER_ADMIN_SCOPE,)
137143

@@ -146,7 +152,9 @@ def test_instance_admin_api(self):
146152
self.assertIs(again, api)
147153

148154
instance_admin_client.assert_called_once_with(
149-
credentials=credentials.with_scopes.return_value, client_info=client_info
155+
credentials=credentials.with_scopes.return_value,
156+
client_info=client_info,
157+
client_options=client_options,
150158
)
151159

152160
credentials.with_scopes.assert_called_once_with(expected_scopes)
@@ -156,8 +164,12 @@ def test_database_admin_api(self):
156164

157165
credentials = _make_credentials()
158166
client_info = mock.Mock()
167+
client_options = mock.Mock()
159168
client = self._make_one(
160-
project=self.PROJECT, credentials=credentials, client_info=client_info
169+
project=self.PROJECT,
170+
credentials=credentials,
171+
client_info=client_info,
172+
client_options=client_options,
161173
)
162174
expected_scopes = (SPANNER_ADMIN_SCOPE,)
163175

@@ -172,7 +184,9 @@ def test_database_admin_api(self):
172184
self.assertIs(again, api)
173185

174186
database_admin_client.assert_called_once_with(
175-
credentials=credentials.with_scopes.return_value, client_info=client_info
187+
credentials=credentials.with_scopes.return_value,
188+
client_info=client_info,
189+
client_options=client_options,
176190
)
177191

178192
credentials.with_scopes.assert_called_once_with(expected_scopes)

spanner/tests/unit/test_database.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ def test_name_property(self):
233233
def test_spanner_api_property_w_scopeless_creds(self):
234234
client = _Client()
235235
client_info = client._client_info = mock.Mock()
236+
client_options = client._client_options = mock.Mock()
236237
credentials = client.credentials = object()
237238
instance = _Instance(self.INSTANCE_NAME, client=client)
238239
pool = _Pool()
@@ -250,7 +251,9 @@ def test_spanner_api_property_w_scopeless_creds(self):
250251
self.assertIs(again, api)
251252

252253
spanner_client.assert_called_once_with(
253-
credentials=credentials, client_info=client_info
254+
credentials=credentials,
255+
client_info=client_info,
256+
client_options=client_options,
254257
)
255258

256259
def test_spanner_api_w_scoped_creds(self):
@@ -271,6 +274,7 @@ def with_scopes(self, scopes):
271274
expected_scopes = (SPANNER_DATA_SCOPE,)
272275
client = _Client()
273276
client_info = client._client_info = mock.Mock()
277+
client_options = client._client_options = mock.Mock()
274278
credentials = client.credentials = _CredentialsWithScopes()
275279
instance = _Instance(self.INSTANCE_NAME, client=client)
276280
pool = _Pool()
@@ -291,6 +295,7 @@ def with_scopes(self, scopes):
291295
called_args, called_kw = spanner_client.call_args
292296
self.assertEqual(called_args, ())
293297
self.assertEqual(called_kw["client_info"], client_info)
298+
self.assertEqual(called_kw["client_options"], client_options)
294299
scoped = called_kw["credentials"]
295300
self.assertEqual(scoped._scopes, expected_scopes)
296301
self.assertIs(scoped._source, credentials)

0 commit comments

Comments
 (0)