Skip to content

Commit 2beaa95

Browse files
authored
feat(bigtable): add 'client_options' / 'admin_client_options' to Client (#9517)
Toward #8475.
1 parent 7e175c6 commit 2beaa95

File tree

2 files changed

+121
-16
lines changed

2 files changed

+121
-16
lines changed

bigtable/google/cloud/bigtable/client.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@
6060
"""Scope for reading table data."""
6161

6262

63-
def _create_gapic_client(client_class):
63+
def _create_gapic_client(client_class, client_options=None):
6464
def inner(self):
6565
if self._emulator_host is None:
6666
return client_class(
67-
credentials=self._credentials, client_info=self._client_info
67+
credentials=self._credentials,
68+
client_info=self._client_info,
69+
client_options=client_options,
6870
)
6971
else:
7072
return client_class(
@@ -109,6 +111,17 @@ class Client(ClientWithProject):
109111
you only need to set this if you're developing your own library
110112
or partner tool.
111113
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.
118+
119+
:type admin_client_options:
120+
:class:`~google.api_core.client_options.ClientOptions` or :class:`dict`
121+
:param admin_client_options: (Optional) Client options used to set user
122+
options on the client. API Endpoint for admin operations should be set
123+
through admin_client_options.
124+
112125
:type channel: :instance: grpc.Channel
113126
:param channel (grpc.Channel): (Optional) DEPRECATED:
114127
A ``Channel`` instance through which to make calls.
@@ -130,6 +143,8 @@ def __init__(
130143
read_only=False,
131144
admin=False,
132145
client_info=_CLIENT_INFO,
146+
client_options=None,
147+
admin_client_options=None,
133148
channel=None,
134149
):
135150
if read_only and admin:
@@ -155,6 +170,8 @@ def __init__(
155170
stacklevel=2,
156171
)
157172

173+
self._client_options = client_options
174+
self._admin_client_options = admin_client_options
158175
self._channel = channel
159176
self.SCOPE = self._get_scopes()
160177
super(Client, self).__init__(project=project, credentials=credentials)
@@ -213,9 +230,10 @@ def table_data_client(self):
213230
:returns: A BigtableClient object.
214231
"""
215232
if self._table_data_client is None:
216-
self._table_data_client = _create_gapic_client(bigtable_v2.BigtableClient)(
217-
self
233+
klass = _create_gapic_client(
234+
bigtable_v2.BigtableClient, client_options=self._client_options
218235
)
236+
self._table_data_client = klass(self)
219237
return self._table_data_client
220238

221239
@property
@@ -237,9 +255,11 @@ def table_admin_client(self):
237255
if self._table_admin_client is None:
238256
if not self._admin:
239257
raise ValueError("Client is not an admin client.")
240-
self._table_admin_client = _create_gapic_client(
241-
bigtable_admin_v2.BigtableTableAdminClient
242-
)(self)
258+
klass = _create_gapic_client(
259+
bigtable_admin_v2.BigtableTableAdminClient,
260+
client_options=self._admin_client_options,
261+
)
262+
self._table_admin_client = klass(self)
243263
return self._table_admin_client
244264

245265
@property
@@ -261,9 +281,11 @@ def instance_admin_client(self):
261281
if self._instance_admin_client is None:
262282
if not self._admin:
263283
raise ValueError("Client is not an admin client.")
264-
self._instance_admin_client = _create_gapic_client(
265-
bigtable_admin_v2.BigtableInstanceAdminClient
266-
)(self)
284+
klass = _create_gapic_client(
285+
bigtable_admin_v2.BigtableInstanceAdminClient,
286+
client_options=self._admin_client_options,
287+
)
288+
self._instance_admin_client = klass(self)
267289
return self._instance_admin_client
268290

269291
def instance(self, instance_id, display_name=None, instance_type=None, labels=None):

bigtable/tests/unit/test_client.py

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121

2222

2323
class Test__create_gapic_client(unittest.TestCase):
24-
def _invoke_client_factory(self, client_class):
24+
def _invoke_client_factory(self, client_class, **kw):
2525
from google.cloud.bigtable.client import _create_gapic_client
2626

27-
return _create_gapic_client(client_class)
27+
return _create_gapic_client(client_class, **kw)
2828

29-
def test_without_emulator(self):
29+
def test_wo_emulator(self):
3030
client_class = mock.Mock()
3131
credentials = _make_credentials()
3232
client = _Client(credentials)
@@ -36,10 +36,30 @@ def test_without_emulator(self):
3636

3737
self.assertIs(result, client_class.return_value)
3838
client_class.assert_called_once_with(
39-
credentials=client._credentials, client_info=client_info
39+
credentials=client._credentials,
40+
client_info=client_info,
41+
client_options=None,
4042
)
4143

42-
def test_with_emulator(self):
44+
def test_wo_emulator_w_client_options(self):
45+
client_class = mock.Mock()
46+
credentials = _make_credentials()
47+
client = _Client(credentials)
48+
client_info = client._client_info = mock.Mock()
49+
client_options = mock.Mock()
50+
51+
result = self._invoke_client_factory(
52+
client_class, client_options=client_options
53+
)(client)
54+
55+
self.assertIs(result, client_class.return_value)
56+
client_class.assert_called_once_with(
57+
credentials=client._credentials,
58+
client_info=client_info,
59+
client_options=client_options,
60+
)
61+
62+
def test_w_emulator(self):
4363
client_class = mock.Mock()
4464
emulator_host = emulator_channel = object()
4565
credentials = _make_credentials()
@@ -210,6 +230,25 @@ def test_table_data_client_not_initialized_w_client_info(self):
210230
self.assertIs(table_data_client._client_info, client_info)
211231
self.assertIs(client._table_data_client, table_data_client)
212232

233+
def test_table_data_client_not_initialized_w_client_options(self):
234+
credentials = _make_credentials()
235+
client_options = mock.Mock()
236+
client = self._make_one(
237+
project=self.PROJECT, credentials=credentials, client_options=client_options
238+
)
239+
240+
patch = mock.patch("google.cloud.bigtable_v2.BigtableClient")
241+
with patch as mocked:
242+
table_data_client = client.table_data_client
243+
244+
self.assertIs(table_data_client, mocked.return_value)
245+
self.assertIs(client._table_data_client, table_data_client)
246+
mocked.assert_called_once_with(
247+
client_info=client._client_info,
248+
credentials=mock.ANY, # added scopes
249+
client_options=client_options,
250+
)
251+
213252
def test_table_data_client_initialized(self):
214253
credentials = _make_credentials()
215254
client = self._make_one(
@@ -257,6 +296,28 @@ def test_table_admin_client_not_initialized_w_client_info(self):
257296
self.assertIs(table_admin_client._client_info, client_info)
258297
self.assertIs(client._table_admin_client, table_admin_client)
259298

299+
def test_table_admin_client_not_initialized_w_client_options(self):
300+
credentials = _make_credentials()
301+
admin_client_options = mock.Mock()
302+
client = self._make_one(
303+
project=self.PROJECT,
304+
credentials=credentials,
305+
admin=True,
306+
admin_client_options=admin_client_options,
307+
)
308+
309+
patch = mock.patch("google.cloud.bigtable_admin_v2.BigtableTableAdminClient")
310+
with patch as mocked:
311+
table_admin_client = client.table_admin_client
312+
313+
self.assertIs(table_admin_client, mocked.return_value)
314+
self.assertIs(client._table_admin_client, table_admin_client)
315+
mocked.assert_called_once_with(
316+
client_info=client._client_info,
317+
credentials=mock.ANY, # added scopes
318+
client_options=admin_client_options,
319+
)
320+
260321
def test_table_admin_client_initialized(self):
261322
credentials = _make_credentials()
262323
client = self._make_one(
@@ -287,7 +348,7 @@ def test_instance_admin_client_not_initialized_w_admin_flag(self):
287348
self.assertIs(instance_admin_client._client_info, _CLIENT_INFO)
288349
self.assertIs(client._instance_admin_client, instance_admin_client)
289350

290-
def test_instance_admin_client_not_initialized_w_admin_and_client_info(self):
351+
def test_instance_admin_client_not_initialized_w_client_info(self):
291352
from google.cloud.bigtable_admin_v2 import BigtableInstanceAdminClient
292353

293354
credentials = _make_credentials()
@@ -304,6 +365,28 @@ def test_instance_admin_client_not_initialized_w_admin_and_client_info(self):
304365
self.assertIs(instance_admin_client._client_info, client_info)
305366
self.assertIs(client._instance_admin_client, instance_admin_client)
306367

368+
def test_instance_admin_client_not_initialized_w_client_options(self):
369+
credentials = _make_credentials()
370+
admin_client_options = mock.Mock()
371+
client = self._make_one(
372+
project=self.PROJECT,
373+
credentials=credentials,
374+
admin=True,
375+
admin_client_options=admin_client_options,
376+
)
377+
378+
patch = mock.patch("google.cloud.bigtable_admin_v2.BigtableInstanceAdminClient")
379+
with patch as mocked:
380+
instance_admin_client = client.instance_admin_client
381+
382+
self.assertIs(instance_admin_client, mocked.return_value)
383+
self.assertIs(client._instance_admin_client, instance_admin_client)
384+
mocked.assert_called_once_with(
385+
client_info=client._client_info,
386+
credentials=mock.ANY, # added scopes
387+
client_options=admin_client_options,
388+
)
389+
307390
def test_instance_admin_client_initialized(self):
308391
credentials = _make_credentials()
309392
client = self._make_one(

0 commit comments

Comments
 (0)