def lookup(self, project_id, read_options, keys, options=None): """ Looks up entities by key. Example: >>> from google.cloud.gapic.datastore.v1 import datastore_client >>> from google.cloud.proto.datastore.v1 import datastore_pb2 >>> from google.cloud.proto.datastore.v1 import entity_pb2 >>> api = datastore_client.DatastoreClient() >>> project_id = '' >>> read_options = datastore_pb2.ReadOptions() >>> keys = [] >>> response = api.lookup(project_id, read_options, keys) Args: project_id (string): The ID of the project against which to make the request. read_options (:class:`google.cloud.proto.datastore.v1.datastore_pb2.ReadOptions`): The options for this lookup request. keys (list[:class:`google.cloud.proto.datastore.v1.entity_pb2.Key`]): Keys of entities to look up. options (:class:`google.gax.CallOptions`): Overrides the default settings for this call, e.g, timeout, retries etc. Returns: A :class:`google.cloud.proto.datastore.v1.datastore_pb2.LookupResponse` instance. Raises: :exc:`google.gax.errors.GaxError` if the RPC is aborted. :exc:`ValueError` if the parameters are invalid. """ # Create the request object. request = datastore_pb2.LookupRequest(project_id=project_id, read_options=read_options, keys=keys) return self._lookup(request, options)
def test_lookup_multiple_keys_empty_response(self): from google.cloud.proto.datastore.v1 import datastore_pb2 project = 'PROJECT' key_pb1 = self._make_key_pb(project) key_pb2 = self._make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, spec=['_http']) # Make request. conn = self._make_one(client) response = conn.lookup(project, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = '/'.join([ conn.api_base_url, conn.API_VERSION, 'projects', project + ':lookup', ]) self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(len(response.deferred), 0) cw = http._called_with self._verify_protobuf_call(cw, uri, conn) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) keys = list(request.keys) self.assertEqual(len(keys), 2) self.assertEqual(key_pb1, keys[0]) self.assertEqual(key_pb2, keys[1])
def test_lookup_multiple_keys_w_deferred(self): from google.cloud.proto.datastore.v1 import datastore_pb2 project = 'PROJECT' key_pb1 = _make_key_pb(project) key_pb2 = _make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() rsp_pb.deferred.add().CopyFrom(key_pb1) rsp_pb.deferred.add().CopyFrom(key_pb2) read_options = datastore_pb2.ReadOptions() # Create mock HTTP and client with response. http = _make_requests_session( [_make_response(content=rsp_pb.SerializeToString())]) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. ds_api = self._make_one(client) response = ds_api.lookup(project, read_options, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(client._base_url, project, 'lookup') self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(list(response.deferred), [key_pb1, key_pb2]) request = _verify_protobuf_call(http, uri, datastore_pb2.LookupRequest()) self.assertEqual(list(request.keys), [key_pb1, key_pb2]) self.assertEqual(request.read_options, read_options)
def lookup(self, project, read_options, key_pbs): """Perform a ``lookup`` request. :type project: str :param project: The project to connect to. This is usually your project name in the cloud console. :type read_options: :class:`.datastore_pb2.ReadOptions` :param read_options: The options for this lookup. Contains a either the transaction for the read or ``STRONG`` or ``EVENTUAL`` read consistency. :type key_pbs: list of :class:`.entity_pb2.Key` :param key_pbs: The keys to retrieve from the datastore. :rtype: :class:`.datastore_pb2.LookupResponse` :returns: The returned protobuf response object. """ request_pb = _datastore_pb2.LookupRequest( project_id=project, read_options=read_options, keys=key_pbs, ) return _rpc(self.client._http, project, 'lookup', self.client._base_url, request_pb, _datastore_pb2.LookupResponse)
def test_lookup(self, mock_create_stub): # Mock gRPC layer grpc_stub = mock.Mock() mock_create_stub.return_value = grpc_stub client = datastore_client.DatastoreClient() # Mock request project_id = 'projectId-1969970175' keys = [] # Mock response expected_response = datastore_pb2.LookupResponse() grpc_stub.Lookup.return_value = expected_response response = client.lookup(project_id, keys) self.assertEqual(expected_response, response) grpc_stub.Lookup.assert_called_once() args, kwargs = grpc_stub.Lookup.call_args self.assertEqual(len(args), 2) self.assertEqual(len(kwargs), 1) self.assertIn('metadata', kwargs) actual_request = args[0] expected_request = datastore_pb2.LookupRequest(project_id=project_id, keys=keys) self.assertEqual(expected_request, actual_request)
def test_lookup_single_key_empty_response_w_transaction(self): from google.cloud.proto.datastore.v1 import datastore_pb2 project = 'PROJECT' transaction = b'TRANSACTION' key_pb = _make_key_pb(project) rsp_pb = datastore_pb2.LookupResponse() # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. conn = self._make_one(client) response = conn.lookup(project, [key_pb], transaction_id=transaction) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(conn.api_base_url, project, 'lookup') self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(len(response.deferred), 0) cw = http._called_with _verify_protobuf_call(self, cw, uri) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) keys = list(request.keys) self.assertEqual(len(keys), 1) self.assertEqual(key_pb, keys[0]) self.assertEqual(request.read_options.transaction, transaction)
def test_lookup_multiple_keys_empty_response(self): from google.cloud.proto.datastore.v1 import datastore_pb2 project = 'PROJECT' key_pb1 = _make_key_pb(project) key_pb2 = _make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() read_options = datastore_pb2.ReadOptions() # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. ds_api = self._make_one(client) response = ds_api.lookup(project, read_options, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(client._base_url, project, 'lookup') self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(len(response.deferred), 0) cw = http._called_with _verify_protobuf_call(self, cw, uri) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) self.assertEqual(list(request.keys), [key_pb1, key_pb2]) self.assertEqual(request.read_options, read_options)
def lookup(self, project, key_pbs, eventual=False, transaction_id=None): """Lookup keys from a project in the Cloud Datastore. Maps the ``DatastoreService.Lookup`` protobuf RPC. This uses mostly protobufs (:class:`.entity_pb2.Key` as input and :class:`.entity_pb2.Entity` as output). It is used under the hood in :meth:`Client.get() <.datastore.client.Client.get>`: .. code-block:: python >>> from google.cloud import datastore >>> client = datastore.Client(project='project') >>> key = client.key('MyKind', 1234) >>> client.get(key) [<Entity object>] Using a :class:`Connection` directly: .. code-block:: python >>> connection.lookup('project', [key.to_protobuf()]) [<Entity protobuf>] :type project: str :param project: The project to look up the keys in. :type key_pbs: list of :class:`.entity_pb2.Key` :param key_pbs: The keys to retrieve from the datastore. :type eventual: bool :param eventual: If False (the default), request ``STRONG`` read consistency. If True, request ``EVENTUAL`` read consistency. :type transaction_id: str :param transaction_id: If passed, make the request in the scope of the given transaction. Incompatible with ``eventual==True``. :rtype: tuple :returns: A triple of (``results``, ``missing``, ``deferred``) where both ``results`` and ``missing`` are lists of :class:`.entity_pb2.Entity` and ``deferred`` is a list of :class:`.entity_pb2.Key`. """ lookup_request = _datastore_pb2.LookupRequest() _set_read_options(lookup_request, eventual, transaction_id) _add_keys_to_request(lookup_request.keys, key_pbs) lookup_response = self._datastore_api.lookup(project, lookup_request) results = [result.entity for result in lookup_response.found] missing = [result.entity for result in lookup_response.missing] return results, missing, list(lookup_response.deferred)
def test_connect(self): # when zipped grpc needs to load a resource that it tries to get from disk # that resource must be unzipped along with the native code library credentials = grpc.ssl_channel_credentials() channel = grpc.secure_channel('datastore.googleapis.com', credentials) datastore_stub = datastore_pb2_grpc.DatastoreStub(channel) request = datastore_pb2.LookupRequest() with self.assertRaisesRegexp( grpc.RpcError, 'missing required authentication') as context: datastore_stub.Lookup(request) self.assertEqual(context.exception.code(), grpc.StatusCode.UNAUTHENTICATED)
def test_lookup_multiple_keys_w_deferred(self): from google.cloud.proto.datastore.v1 import datastore_pb2 from google.cloud import _http as connection_module from google.cloud.datastore._http import _CLIENT_INFO project = 'PROJECT' key_pb1 = self._make_key_pb(project) key_pb2 = self._make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() rsp_pb.deferred.add().CopyFrom(key_pb1) rsp_pb.deferred.add().CopyFrom(key_pb2) # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, spec=['_http']) # Make request. conn = self._make_one(client) response = conn.lookup(project, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = '/'.join([ conn.api_base_url, conn.API_VERSION, 'projects', project + ':lookup', ]) self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(list(response.deferred), [key_pb1, key_pb2]) cw = http._called_with self._verify_protobuf_call(cw, uri, conn) self.assertEqual(cw['uri'], uri) self.assertEqual(cw['method'], 'POST') expected_headers = { 'Content-Type': 'application/x-protobuf', 'User-Agent': conn.USER_AGENT, 'Content-Length': '48', connection_module.CLIENT_INFO_HEADER: _CLIENT_INFO, } self.assertEqual(cw['headers'], expected_headers) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) keys = list(request.keys) self.assertEqual(len(keys), 2) self.assertEqual(key_pb1, keys[0]) self.assertEqual(key_pb2, keys[1])
def test_lookup_multiple_keys_w_deferred(self): from google.cloud.proto.datastore.v1 import datastore_pb2 from google.cloud import _http as connection_module from google.cloud.datastore._http import _CLIENT_INFO project = 'PROJECT' key_pb1 = _make_key_pb(project) key_pb2 = _make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() rsp_pb.deferred.add().CopyFrom(key_pb1) rsp_pb.deferred.add().CopyFrom(key_pb2) read_options = datastore_pb2.ReadOptions() # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. ds_api = self._make_one(client) response = ds_api.lookup(project, read_options, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(client._base_url, project, 'lookup') self.assertEqual(len(response.found), 0) self.assertEqual(len(response.missing), 0) self.assertEqual(list(response.deferred), [key_pb1, key_pb2]) cw = http._called_with _verify_protobuf_call(self, cw, uri) self.assertEqual(cw['uri'], uri) self.assertEqual(cw['method'], 'POST') expected_headers = { 'Content-Type': 'application/x-protobuf', 'User-Agent': connection_module.DEFAULT_USER_AGENT, 'Content-Length': str(len(cw['body'])), connection_module.CLIENT_INFO_HEADER: _CLIENT_INFO, } self.assertEqual(cw['headers'], expected_headers) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) self.assertEqual(list(request.keys), [key_pb1, key_pb2]) self.assertEqual(request.read_options, read_options)
def test_lookup_single_key_nonempty_response(self): from google.cloud.proto.datastore.v1 import datastore_pb2 from google.cloud.proto.datastore.v1 import entity_pb2 project = 'PROJECT' key_pb = self._make_key_pb(project) rsp_pb = datastore_pb2.LookupResponse() entity = entity_pb2.Entity() entity.key.CopyFrom(key_pb) rsp_pb.found.add(entity=entity) # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, spec=['_http']) # Make request. conn = self._make_one(client) response = conn.lookup(project, [key_pb]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = '/'.join([ conn.api_base_url, conn.API_VERSION, 'projects', project + ':lookup', ]) self.assertEqual(len(response.found), 1) self.assertEqual(len(response.missing), 0) self.assertEqual(len(response.deferred), 0) found = response.found[0].entity self.assertEqual(found.key.path[0].kind, 'Kind') self.assertEqual(found.key.path[0].id, 1234) cw = http._called_with self._verify_protobuf_call(cw, uri, conn) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) keys = list(request.keys) self.assertEqual(len(keys), 1) self.assertEqual(key_pb, keys[0])
def test_lookup_single_key_nonempty_response(self): from google.cloud.proto.datastore.v1 import datastore_pb2 from google.cloud.proto.datastore.v1 import entity_pb2 project = 'PROJECT' key_pb = _make_key_pb(project) rsp_pb = datastore_pb2.LookupResponse() entity = entity_pb2.Entity() entity.key.CopyFrom(key_pb) rsp_pb.found.add(entity=entity) read_options = datastore_pb2.ReadOptions() # Create mock HTTP and client with response. http = _make_requests_session( [_make_response(content=rsp_pb.SerializeToString())]) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. ds_api = self._make_one(client) response = ds_api.lookup(project, read_options, [key_pb]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(client._base_url, project, 'lookup') self.assertEqual(len(response.found), 1) self.assertEqual(len(response.missing), 0) self.assertEqual(len(response.deferred), 0) found = response.found[0].entity self.assertEqual(found.key.path[0].kind, 'Kind') self.assertEqual(found.key.path[0].id, 1234) request = _verify_protobuf_call(http, uri, datastore_pb2.LookupRequest()) self.assertEqual(list(request.keys), [key_pb]) self.assertEqual(request.read_options, read_options)
def test_lookup_multiple_keys_w_missing(self): from google.cloud.proto.datastore.v1 import datastore_pb2 project = 'PROJECT' key_pb1 = _make_key_pb(project) key_pb2 = _make_key_pb(project, id_=2345) rsp_pb = datastore_pb2.LookupResponse() er_1 = rsp_pb.missing.add() er_1.entity.key.CopyFrom(key_pb1) er_2 = rsp_pb.missing.add() er_2.entity.key.CopyFrom(key_pb2) # Create mock HTTP and client with response. http = Http({'status': '200'}, rsp_pb.SerializeToString()) client = mock.Mock(_http=http, _base_url='test.invalid', spec=['_http', '_base_url']) # Make request. conn = self._make_one(client) response = conn.lookup(project, [key_pb1, key_pb2]) # Check the result and verify the callers. self.assertEqual(response, rsp_pb) uri = _build_expected_url(conn.api_base_url, project, 'lookup') self.assertEqual(len(response.found), 0) self.assertEqual(len(response.deferred), 0) missing_keys = [result.entity.key for result in response.missing] self.assertEqual(missing_keys, [key_pb1, key_pb2]) cw = http._called_with _verify_protobuf_call(self, cw, uri) request = datastore_pb2.LookupRequest() request.ParseFromString(cw['body']) keys = list(request.keys) self.assertEqual(len(keys), 2) self.assertEqual(key_pb1, keys[0]) self.assertEqual(key_pb2, keys[1])