diff --git a/datastore/google/cloud/datastore/_gax.py b/datastore/google/cloud/datastore/_gax.py index b29ce874f298..58500301c950 100644 --- a/datastore/google/cloud/datastore/_gax.py +++ b/datastore/google/cloud/datastore/_gax.py @@ -17,15 +17,24 @@ import contextlib +from google.cloud.proto.datastore.v1 import datastore_pb2_grpc +from google.gax.utils import metrics from grpc import StatusCode from google.cloud._helpers import make_insecure_stub from google.cloud._helpers import make_secure_stub from google.cloud import exceptions -from google.cloud.proto.datastore.v1 import datastore_pb2_grpc +from google.cloud.datastore import __version__ +_METRICS_HEADERS = ( + ('gccl', __version__), +) +_HEADER_STR = metrics.stringify(metrics.fill(_METRICS_HEADERS)) +_GRPC_EXTRA_OPTIONS = ( + ('x-goog-api-client', _HEADER_STR), +) _GRPC_ERROR_MAPPING = { StatusCode.UNKNOWN: exceptions.InternalServerError, StatusCode.INVALID_ARGUMENT: exceptions.BadRequest, @@ -85,10 +94,10 @@ class _DatastoreAPIOverGRPC(object): def __init__(self, connection, secure): if secure: - self._stub = make_secure_stub(connection.credentials, - connection.USER_AGENT, - datastore_pb2_grpc.DatastoreStub, - connection.host) + self._stub = make_secure_stub( + connection.credentials, connection.USER_AGENT, + datastore_pb2_grpc.DatastoreStub, connection.host, + extra_options=_GRPC_EXTRA_OPTIONS) else: self._stub = make_insecure_stub(datastore_pb2_grpc.DatastoreStub, connection.host) diff --git a/datastore/setup.py b/datastore/setup.py index 170692218b4f..625415c65ddb 100644 --- a/datastore/setup.py +++ b/datastore/setup.py @@ -51,7 +51,7 @@ REQUIREMENTS = [ 'google-cloud-core >= 0.23.1, < 0.24dev', - 'grpcio >= 1.0.2, < 2.0dev', + 'google-gax>=0.15.7, <0.16dev', 'gapic-google-cloud-datastore-v1 >= 0.15.0, < 0.16dev', ] diff --git a/datastore/unit_tests/test__gax.py b/datastore/unit_tests/test__gax.py index e0fc912e0081..419c85cc9fdc 100644 --- a/datastore/unit_tests/test__gax.py +++ b/datastore/unit_tests/test__gax.py @@ -97,7 +97,7 @@ def _get_target_class(): return _DatastoreAPIOverGRPC - def _make_one(self, stub, connection=None, secure=True, mock_args=None): + def _make_one(self, stub, connection=None, secure=True): if connection is None: connection = mock.Mock( credentials=object(), @@ -106,27 +106,21 @@ def _make_one(self, stub, connection=None, secure=True, mock_args=None): spec=['credentials', 'host', 'USER_AGENT'], ) - if mock_args is None: - mock_args = [] - - def mock_make_stub(*args): - mock_args.append(args) - return stub - if secure: patch = mock.patch( 'google.cloud.datastore._gax.make_secure_stub', - new=mock_make_stub) + return_value=stub) else: patch = mock.patch( 'google.cloud.datastore._gax.make_insecure_stub', - new=mock_make_stub) + return_value=stub) - with patch: - return self._get_target_class()(connection, secure) + with patch as make_stub_mock: + api_obj = self._get_target_class()(connection, secure) + return api_obj, make_stub_mock def test_constructor(self): - from google.cloud.proto.datastore.v1 import datastore_pb2_grpc + import google.cloud.datastore._gax as MUT conn = mock.Mock( credentials=object(), @@ -136,17 +130,17 @@ def test_constructor(self): ) stub = _GRPCStub() - mock_args = [] - datastore_api = self._make_one(stub, connection=conn, - mock_args=mock_args) - self.assertIs(datastore_api._stub, stub) + datastore_api, make_stub_mock = self._make_one( + stub, connection=conn) - self.assertEqual(mock_args, [( + self.assertIs(datastore_api._stub, stub) + make_stub_mock.assert_called_once_with( conn.credentials, conn.USER_AGENT, - datastore_pb2_grpc.DatastoreStub, + MUT.datastore_pb2_grpc.DatastoreStub, conn.host, - )]) + extra_options=MUT._GRPC_EXTRA_OPTIONS, + ) def test_constructor_insecure(self): from google.cloud.proto.datastore.v1 import datastore_pb2_grpc @@ -158,21 +152,19 @@ def test_constructor_insecure(self): ) stub = _GRPCStub() - mock_args = [] - datastore_api = self._make_one(stub, connection=conn, - secure=False, - mock_args=mock_args) - self.assertIs(datastore_api._stub, stub) + datastore_api, make_stub_mock = self._make_one( + stub, connection=conn, secure=False) - self.assertEqual(mock_args, [( + self.assertIs(datastore_api._stub, stub) + make_stub_mock.assert_called_once_with( datastore_pb2_grpc.DatastoreStub, conn.host, - )]) + ) def test_lookup(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -185,7 +177,7 @@ def test_lookup(self): def test_run_query(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -197,7 +189,7 @@ def test_run_query(self): def _run_query_failure_helper(self, exc, err_class): stub = _GRPCStub(side_effect=exc) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -225,7 +217,7 @@ def test_run_query_invalid_argument(self): def test_begin_transaction(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -239,7 +231,7 @@ def test_begin_transaction(self): def test_commit_success(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -252,7 +244,7 @@ def test_commit_success(self): def test_rollback(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT' @@ -265,7 +257,7 @@ def test_rollback(self): def test_allocate_ids(self): return_val = object() stub = _GRPCStub(return_val) - datastore_api = self._make_one(stub=stub) + datastore_api, _ = self._make_one(stub=stub) request_pb = mock.Mock(project_id=None, spec=['project_id']) project = 'PROJECT'