Skip to content

Commit 7c15085

Browse files
authored
Add client_info support to client. (#8013)
1 parent 01a10ce commit 7c15085

File tree

6 files changed

+213
-74
lines changed

6 files changed

+213
-74
lines changed

datastore/google/cloud/datastore/_gapic.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,12 @@
1414

1515
"""Helpers for making API requests via gapic / gRPC."""
1616

17-
from google.api_core.gapic_v1 import client_info
18-
from google.cloud.datastore_v1.gapic import datastore_client
1917
from grpc import insecure_channel
2018
import six
2119

2220
from google.cloud._helpers import make_secure_channel
2321
from google.cloud._http import DEFAULT_USER_AGENT
24-
25-
from google.cloud.datastore import __version__
22+
from google.cloud.datastore_v1.gapic import datastore_client
2623

2724

2825
def make_datastore_api(client):
@@ -42,8 +39,5 @@ def make_datastore_api(client):
4239
channel = insecure_channel(host)
4340

4441
return datastore_client.DatastoreClient(
45-
channel=channel,
46-
client_info=client_info.ClientInfo(
47-
client_library_version=__version__, gapic_version=__version__
48-
),
42+
channel=channel, client_info=client._client_info
4943
)

datastore/google/cloud/datastore/_http.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
from google.cloud import exceptions
2121
from google.cloud.datastore_v1.proto import datastore_pb2 as _datastore_pb2
2222

23-
from google.cloud.datastore import __version__
24-
2523

2624
DATASTORE_API_HOST = "datastore.googleapis.com"
2725
"""Datastore API request host."""
@@ -32,10 +30,8 @@
3230
API_URL_TEMPLATE = "{api_base}/{api_version}/projects" "/{project}:{method}"
3331
"""A template for the URL of a particular API call."""
3432

35-
_CLIENT_INFO = connection_module.CLIENT_INFO_TEMPLATE.format(__version__)
36-
3733

38-
def _request(http, project, method, data, base_url):
34+
def _request(http, project, method, data, base_url, client_info):
3935
"""Make a request over the Http transport to the Cloud Datastore API.
4036
4137
:type http: :class:`requests.Session`
@@ -55,15 +51,19 @@ def _request(http, project, method, data, base_url):
5551
:type base_url: str
5652
:param base_url: The base URL where the API lives.
5753
54+
:type client_info: :class:`google.api_core.client_info.ClientInfo`
55+
:param client_info: used to generate user agent.
56+
5857
:rtype: str
5958
:returns: The string response content from the API call.
6059
:raises: :class:`google.cloud.exceptions.GoogleCloudError` if the
6160
response code is not 200 OK.
6261
"""
62+
user_agent = client_info.to_user_agent()
6363
headers = {
6464
"Content-Type": "application/x-protobuf",
65-
"User-Agent": connection_module.DEFAULT_USER_AGENT,
66-
connection_module.CLIENT_INFO_HEADER: _CLIENT_INFO,
65+
"User-Agent": user_agent,
66+
connection_module.CLIENT_INFO_HEADER: user_agent,
6767
}
6868
api_url = build_api_url(project, method, base_url)
6969

@@ -78,7 +78,7 @@ def _request(http, project, method, data, base_url):
7878
return response.content
7979

8080

81-
def _rpc(http, project, method, base_url, request_pb, response_pb_cls):
81+
def _rpc(http, project, method, base_url, client_info, request_pb, response_pb_cls):
8282
"""Make a protobuf RPC request.
8383
8484
:type http: :class:`requests.Session`
@@ -94,6 +94,9 @@ def _rpc(http, project, method, base_url, request_pb, response_pb_cls):
9494
:type base_url: str
9595
:param base_url: The base URL where the API lives.
9696
97+
:type client_info: :class:`google.api_core.client_info.ClientInfo`
98+
:param client_info: used to generate user agent.
99+
97100
:type request_pb: :class:`google.protobuf.message.Message` instance
98101
:param request_pb: the protobuf instance representing the request.
99102
@@ -106,7 +109,7 @@ def _rpc(http, project, method, base_url, request_pb, response_pb_cls):
106109
:returns: The RPC message parsed from the response.
107110
"""
108111
req_data = request_pb.SerializeToString()
109-
response = _request(http, project, method, req_data, base_url)
112+
response = _request(http, project, method, req_data, base_url, client_info)
110113
return response_pb_cls.FromString(response)
111114

112115

@@ -172,6 +175,7 @@ def lookup(self, project_id, keys, read_options=None):
172175
project_id,
173176
"lookup",
174177
self.client._base_url,
178+
self.client._client_info,
175179
request_pb,
176180
_datastore_pb2.LookupResponse,
177181
)
@@ -217,6 +221,7 @@ def run_query(
217221
project_id,
218222
"runQuery",
219223
self.client._base_url,
224+
self.client._client_info,
220225
request_pb,
221226
_datastore_pb2.RunQueryResponse,
222227
)
@@ -240,6 +245,7 @@ def begin_transaction(self, project_id, transaction_options=None):
240245
project_id,
241246
"beginTransaction",
242247
self.client._base_url,
248+
self.client._client_info,
243249
request_pb,
244250
_datastore_pb2.BeginTransactionResponse,
245251
)
@@ -278,6 +284,7 @@ def commit(self, project_id, mode, mutations, transaction=None):
278284
project_id,
279285
"commit",
280286
self.client._base_url,
287+
self.client._client_info,
281288
request_pb,
282289
_datastore_pb2.CommitResponse,
283290
)
@@ -304,6 +311,7 @@ def rollback(self, project_id, transaction):
304311
project_id,
305312
"rollback",
306313
self.client._base_url,
314+
self.client._client_info,
307315
request_pb,
308316
_datastore_pb2.RollbackResponse,
309317
)
@@ -327,6 +335,7 @@ def allocate_ids(self, project_id, keys):
327335
project_id,
328336
"allocateIds",
329337
self.client._base_url,
338+
self.client._client_info,
330339
request_pb,
331340
_datastore_pb2.AllocateIdsResponse,
332341
)

datastore/google/cloud/datastore/client.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from google.cloud._helpers import _LocalStack
1919
from google.cloud._helpers import _determine_default_project as _base_default_project
2020
from google.cloud.client import ClientWithProject
21+
from google.cloud.datastore import __version__
2122
from google.cloud.datastore import helpers
2223
from google.cloud.datastore._http import HTTPDatastoreAPI
2324
from google.cloud.datastore.batch import Batch
@@ -32,17 +33,27 @@
3233
try:
3334
from google.cloud.datastore._gapic import make_datastore_api
3435

35-
_HAVE_GRPC = True
3636
except ImportError: # pragma: NO COVER
37+
from google.api_core import client_info
38+
3739
make_datastore_api = None
3840
_HAVE_GRPC = False
41+
_CLIENT_INFO = client_info.ClientInfo(client_library_version=__version__)
42+
else:
43+
from google.api_core.gapic_v1 import client_info
44+
45+
_HAVE_GRPC = True
46+
_CLIENT_INFO = client_info.ClientInfo(
47+
client_library_version=__version__, gapic_version=__version__
48+
)
3949

4050

4151
_MAX_LOOPS = 128
4252
"""Maximum number of iterations to wait for deferred keys."""
4353
_DATASTORE_BASE_URL = "https://datastore.googleapis.com"
4454
"""Datastore API request URL base."""
4555

56+
4657
_USE_GRPC = _HAVE_GRPC and not os.getenv(DISABLE_GRPC, False)
4758

4859

@@ -182,6 +193,14 @@ class Client(ClientWithProject):
182193
passed), falls back to the default inferred from the
183194
environment.
184195
196+
:type client_info: :class:`google.api_core.gapic_v1.client_info.ClientInfo`
197+
or :class:`google.api_core.client_info.ClientInfo`
198+
:param client_info: (Optional) The client info used to send a user-agent
199+
string along with API requests. If ``None``, then
200+
default info will be used. Generally,
201+
you only need to set this if you're developing your
202+
own library or partner tool.
203+
185204
:type _http: :class:`~requests.Session`
186205
:param _http: (Optional) HTTP object to make requests. Can be any object
187206
that defines ``request()`` with the same interface as
@@ -204,12 +223,19 @@ class Client(ClientWithProject):
204223
"""The scopes required for authenticating as a Cloud Datastore consumer."""
205224

206225
def __init__(
207-
self, project=None, namespace=None, credentials=None, _http=None, _use_grpc=None
226+
self,
227+
project=None,
228+
namespace=None,
229+
credentials=None,
230+
client_info=_CLIENT_INFO,
231+
_http=None,
232+
_use_grpc=None,
208233
):
209234
super(Client, self).__init__(
210235
project=project, credentials=credentials, _http=_http
211236
)
212237
self.namespace = namespace
238+
self._client_info = client_info
213239
self._batch_stack = _LocalStack()
214240
self._datastore_api_internal = None
215241
if _use_grpc is None:

datastore/tests/unit/test__gapic.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def test_live_api(self, make_chan, mock_klass):
4141
client = mock.Mock(
4242
_base_url=base_url,
4343
_credentials=mock.sentinel.credentials,
44-
spec=["_base_url", "_credentials"],
44+
_client_info=mock.sentinel.client_info,
45+
spec=["_base_url", "_credentials", "_client_info"],
4546
)
4647
ds_api = self._call_fut(client)
4748
self.assertIs(ds_api, mock.sentinel.ds_client)
@@ -52,7 +53,7 @@ def test_live_api(self, make_chan, mock_klass):
5253
"datastore.googleapis.com:443",
5354
)
5455
mock_klass.assert_called_once_with(
55-
channel=mock.sentinel.channel, client_info=mock.ANY
56+
channel=mock.sentinel.channel, client_info=mock.sentinel.client_info
5657
)
5758

5859
@mock.patch(
@@ -70,12 +71,13 @@ def test_emulator(self, make_chan, mock_klass):
7071
client = mock.Mock(
7172
_base_url=base_url,
7273
_credentials=mock.sentinel.credentials,
73-
spec=["_base_url", "_credentials"],
74+
_client_info=mock.sentinel.client_info,
75+
spec=["_base_url", "_credentials", "_client_info"],
7476
)
7577
ds_api = self._call_fut(client)
7678
self.assertIs(ds_api, mock.sentinel.ds_client)
7779

7880
make_chan.assert_called_once_with(host)
7981
mock_klass.assert_called_once_with(
80-
channel=mock.sentinel.channel, client_info=mock.ANY
82+
channel=mock.sentinel.channel, client_info=mock.sentinel.client_info
8183
)

0 commit comments

Comments
 (0)