def _callFUT(self, val, dataset=_MARKER): from gcloud.datastore.helpers import entity_from_protobuf if dataset is self._MARKER: return entity_from_protobuf(val) return entity_from_protobuf(val, dataset)
def get_multi(self, keys, missing=None, deferred=None, transaction=None): """Retrieve entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: list :param missing: (Optional) If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. If the list is not empty, an error will occur. :type deferred: list :param deferred: (Optional) If a list is passed, the keys returned by the backend as "deferred" will be copied into it. If the list is not empty, an error will occur. :type transaction: :class:`gcloud.datastore.transaction.Transaction` :param transaction: (Optional) Transaction to use for read consistency. If not passed, uses current transaction, if set. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: :class:`ValueError` if one or more of ``keys`` has a project which does not match our project. """ if not keys: return [] ids = set(key.project for key in keys) for current_id in ids: if current_id != self.project: raise ValueError('Keys do not match project') if transaction is None: transaction = self.current_transaction entity_pbs = _extended_lookup( connection=self.connection, project=self.project, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing ] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred ] return [ helpers.entity_from_protobuf(entity_pb) for entity_pb in entity_pbs ]
def get_multi(self, keys, missing=None, deferred=None, transaction=None): """Retrieve entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: list :param missing: (Optional) If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. If the list is not empty, an error will occur. :type deferred: list :param deferred: (Optional) If a list is passed, the keys returned by the backend as "deferred" will be copied into it. If the list is not empty, an error will occur. :type transaction: :class:`gcloud.datastore.transaction.Transaction` :param transaction: (Optional) Transaction to use for read consistency. If not passed, uses current transaction, if set. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: :class:`ValueError` if one or more of ``keys`` has a project which does not match our project. """ if not keys: return [] ids = set(key.project for key in keys) for current_id in ids: if current_id != self.project: raise ValueError('Keys do not match project') if transaction is None: transaction = self.current_transaction entity_pbs = _extended_lookup( connection=self.connection, project=self.project, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] return [helpers.entity_from_protobuf(entity_pb) for entity_pb in entity_pbs]
def get_multi(self, keys, missing=None, deferred=None): """Retrieve entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: ValueError if one or more of ``keys`` has a dataset ID which does not match our dataset ID. """ if not keys: return [] ids = list(set([key.dataset_id for key in keys])) if ids != [self.dataset_id]: raise ValueError('Keys do not match dataset ID') transaction = self.current_transaction entity_pbs = _extended_lookup( connection=self.connection, dataset_id=self.dataset_id, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing ] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred ] return [ helpers.entity_from_protobuf(entity_pb) for entity_pb in entity_pbs ]
def get_multi(self, keys, missing=None, deferred=None): """Retrieve entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: ValueError if one or more of ``keys`` has a dataset ID which does not match our dataset ID. """ if not keys: return [] ids = set(key.dataset_id for key in keys) for current_id in ids: if not _dataset_ids_equal(current_id, self.dataset_id): raise ValueError('Keys do not match dataset ID') transaction = self.current_transaction entity_pbs = _extended_lookup( connection=self.connection, dataset_id=self.dataset_id, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] return [helpers.entity_from_protobuf(entity_pb) for entity_pb in entity_pbs]
def get(keys, missing=None, deferred=None, connection=None): """Retrieves entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :type connection: :class:`gcloud.datastore.connection.Connection` :param connection: Optional. The connection used to connect to datastore. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. """ if not keys: return [] connection = _require_connection(connection) dataset_id = _get_dataset_id_from_keys(keys) transaction = Transaction.current() entity_pbs = connection.lookup( dataset_id=dataset_id, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] entities = [] for entity_pb in entity_pbs: entities.append(helpers.entity_from_protobuf(entity_pb)) return entities
def next_page(self): """Fetch a single "page" of query results. Low-level API for fine control: the more convenient API is to iterate on the current Iterator. :rtype: tuple, (entities, more_results, cursor) """ pb = _pb_from_query(self._query) start_cursor = self._start_cursor if start_cursor is not None: pb.start_cursor = base64.urlsafe_b64decode(start_cursor) end_cursor = self._end_cursor if end_cursor is not None: pb.end_cursor = base64.urlsafe_b64decode(end_cursor) if self._limit is not None: pb.limit.value = self._limit pb.offset = self._offset transaction = self._client.current_transaction query_results = self._client.connection.run_query( query_pb=pb, project=self._query.project, namespace=self._query.namespace, transaction_id=transaction and transaction.id, ) # NOTE: `query_results` contains an extra value that we don't use, # namely `skipped_results`. # # NOTE: The value of `more_results` is not currently useful because # the back-end always returns an enum # value of MORE_RESULTS_AFTER_LIMIT even if there are no more # results. See # https://github.com/GoogleCloudPlatform/gcloud-python/issues/280 # for discussion. entity_pbs, cursor_as_bytes, more_results_enum = query_results[:3] if cursor_as_bytes == b'': self._start_cursor = None else: self._start_cursor = base64.urlsafe_b64encode(cursor_as_bytes) self._end_cursor = None if more_results_enum == self._NOT_FINISHED: self._more_results = True elif more_results_enum in self._FINISHED: self._more_results = False else: raise ValueError('Unexpected value returned for `more_results`.') self._page = [ helpers.entity_from_protobuf(entity) for entity in entity_pbs] return self._page, self._more_results, self._start_cursor
def next_page(self): """Fetch a single "page" of query results. Low-level API for fine control: the more convenient API is to iterate on the current Iterator. :rtype: tuple, (entities, more_results, cursor) """ pb = _pb_from_query(self._query) start_cursor = self._start_cursor if start_cursor is not None: pb.start_cursor = base64.urlsafe_b64decode(start_cursor) end_cursor = self._end_cursor if end_cursor is not None: pb.end_cursor = base64.urlsafe_b64decode(end_cursor) if self._limit is not None: pb.limit = self._limit pb.offset = self._offset transaction = self._client.current_transaction query_results = self._client.connection.run_query( query_pb=pb, project=self._query.project, namespace=self._query.namespace, transaction_id=transaction and transaction.id, ) # NOTE: `query_results` contains an extra value that we don't use, # namely `skipped_results`. # # NOTE: The value of `more_results` is not currently useful because # the back-end always returns an enum # value of MORE_RESULTS_AFTER_LIMIT even if there are no more # results. See # https://github.com/GoogleCloudPlatform/gcloud-python/issues/280 # for discussion. entity_pbs, cursor_as_bytes, more_results_enum = query_results[:3] if cursor_as_bytes == b'': self._start_cursor = None else: self._start_cursor = base64.urlsafe_b64encode(cursor_as_bytes) self._end_cursor = None if more_results_enum == self._NOT_FINISHED: self._more_results = True elif more_results_enum in self._FINISHED: self._more_results = False else: raise ValueError('Unexpected value returned for `more_results`.') self._page = [ helpers.entity_from_protobuf(entity) for entity in entity_pbs] return self._page, self._more_results, self._start_cursor
def get_entities(self, keys, missing=None, deferred=None): """Retrieves entities from the dataset, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: List of keys to be retrieved. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :rtype: list of :class:`gcloud.datastore.entity.Entity` :return: The requested entities. """ entity_pbs = self.connection().lookup( dataset_id=self.id(), key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb, dataset=self) for missed_pb in missing ] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred ] entities = [] for entity_pb in entity_pbs: entities.append( helpers.entity_from_protobuf(entity_pb, dataset=self)) return entities
def next_page(self): """Fetch a single "page" of query results. Low-level API for fine control: the more convenient API is to iterate on the current Iterator. :rtype: tuple, (entities, more_results, cursor) :returns: The next page of results. """ pb = _pb_from_query(self._query) start_cursor = self._start_cursor if start_cursor is not None: pb.start_cursor = base64.urlsafe_b64decode(start_cursor) end_cursor = self._end_cursor if end_cursor is not None: pb.end_cursor = base64.urlsafe_b64decode(end_cursor) if self._limit is not None: pb.limit.value = self._limit if self._offset is not None: pb.offset = self._offset transaction = self._client.current_transaction query_results = self._client.connection.run_query( query_pb=pb, project=self._query.project, namespace=self._query.namespace, transaction_id=transaction and transaction.id, ) (entity_pbs, cursor_as_bytes, more_results_enum, self._skipped_results) = query_results if cursor_as_bytes == b'': self._start_cursor = None else: self._start_cursor = base64.urlsafe_b64encode(cursor_as_bytes) self._end_cursor = None if more_results_enum == self._NOT_FINISHED: self._more_results = True elif more_results_enum in self._FINISHED: self._more_results = False else: raise ValueError('Unexpected value returned for `more_results`.') self._page = [ helpers.entity_from_protobuf(entity) for entity in entity_pbs ] return self._page, self._more_results, self._start_cursor
def next_page(self): """Fetch a single "page" of query results. Low-level API for fine control: the more convenient API is to iterate on the current Iterator. :rtype: tuple, (entities, more_results, cursor) :returns: The next page of results. """ pb = _pb_from_query(self._query) start_cursor = self._start_cursor if start_cursor is not None: pb.start_cursor = base64.urlsafe_b64decode(start_cursor) end_cursor = self._end_cursor if end_cursor is not None: pb.end_cursor = base64.urlsafe_b64decode(end_cursor) if self._limit is not None: pb.limit.value = self._limit if self._offset is not None: pb.offset = self._offset transaction = self._client.current_transaction query_results = self._client.connection.run_query( query_pb=pb, project=self._query.project, namespace=self._query.namespace, transaction_id=transaction and transaction.id, ) (entity_pbs, cursor_as_bytes, more_results_enum, self._skipped_results) = query_results if cursor_as_bytes == b'': self._start_cursor = None else: self._start_cursor = base64.urlsafe_b64encode(cursor_as_bytes) self._end_cursor = None if more_results_enum == self._NOT_FINISHED: self._more_results = True elif more_results_enum in self._FINISHED: self._more_results = False else: raise ValueError('Unexpected value returned for `more_results`.') self._page = [ helpers.entity_from_protobuf(entity) for entity in entity_pbs] return self._page, self._more_results, self._start_cursor
def get_entities(self, keys, missing=None, deferred=None): """Retrieves entities from the dataset, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: List of keys to be retrieved. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :rtype: list of :class:`gcloud.datastore.entity.Entity` :return: The requested entities. """ entity_pbs = self.connection().lookup( dataset_id=self.id(), key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb, dataset=self) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] entities = [] for entity_pb in entity_pbs: entities.append(helpers.entity_from_protobuf( entity_pb, dataset=self)) return entities
def fetch(self, limit=None): """Executes the Query and returns all matching entities. This makes an API call to the Cloud Datastore, sends the Query as a protobuf, parses the responses to Entity protobufs, and then converts them to :class:`gcloud.datastore.entity.Entity` objects. For example:: >>> from gcloud import datastore >>> dataset = datastore.get_dataset('dataset-id', email, key_path) >>> query = dataset.query('Person').filter('name =', 'Sally') >>> query.fetch() [<Entity object>, <Entity object>, ...] >>> query.fetch(1) [<Entity object>] >>> query.limit() None :type limit: integer :param limit: An optional limit to apply temporarily to this query. That is, the Query itself won't be altered, but the limit will be applied to the query before it is executed. :rtype: list of :class:`gcloud.datastore.entity.Entity`'s :returns: The list of entities matching this query's criteria. """ clone = self if limit: clone = self.limit(limit) query_results = self.dataset().connection().run_query( query_pb=clone.to_protobuf(), dataset_id=self.dataset().id(), namespace=self._namespace, ) # NOTE: `query_results` contains two extra values that we don't use, # namely `more_results` and `skipped_results`. The value of # `more_results` is unusable because it always returns an enum # value of MORE_RESULTS_AFTER_LIMIT even if there are no more # results. See # https://github.com/GoogleCloudPlatform/gcloud-python/issues/280 # for discussion. entity_pbs, end_cursor = query_results[:2] self._cursor = end_cursor return [ helpers.entity_from_protobuf(entity, dataset=self.dataset()) for entity in entity_pbs ]
def test_inverts_to_protobuf(self): from gcloud.datastore._generated import entity_pb2 from gcloud.datastore.helpers import _new_value_pb from gcloud.datastore.helpers import entity_from_protobuf original_pb = entity_pb2.Entity() # Add a key. original_pb.key.partition_id.dataset_id = project = 'PROJECT' elem1 = original_pb.key.path_element.add() elem1.kind = 'Family' elem1.id = 1234 elem2 = original_pb.key.path_element.add() elem2.kind = 'King' elem2.name = 'Spades' # Add an integer property. val_pb1 = _new_value_pb(original_pb, 'foo') val_pb1.integer_value = 1337 val_pb1.indexed = False # Add a string property. val_pb2 = _new_value_pb(original_pb, 'bar') val_pb2.string_value = u'hello' # Add a nested (entity) property. val_pb3 = _new_value_pb(original_pb, 'entity-baz') sub_pb = entity_pb2.Entity() sub_val_pb1 = _new_value_pb(sub_pb, 'x') sub_val_pb1.double_value = 3.14 sub_val_pb2 = _new_value_pb(sub_pb, 'y') sub_val_pb2.double_value = 2.718281828 val_pb3.meaning = 9 val_pb3.entity_value.CopyFrom(sub_pb) # Add a list property. val_pb4 = _new_value_pb(original_pb, 'list-quux') list_val1 = val_pb4.list_value.add() list_val1.indexed = False list_val1.meaning = meaning = 22 list_val1.blob_value = b'\xe2\x98\x83' list_val2 = val_pb4.list_value.add() list_val2.indexed = False list_val2.meaning = meaning list_val2.blob_value = b'\xe2\x98\x85' # Convert to the user-space Entity. entity = entity_from_protobuf(original_pb) # Convert the user-space Entity back to a protobuf. new_pb = self._callFUT(entity) # NOTE: entity_to_protobuf() strips the project so we "cheat". new_pb.key.partition_id.dataset_id = project self._compareEntityProto(original_pb, new_pb)
def test_inverts_to_protobuf(self): from gcloud.datastore._generated import entity_pb2 from gcloud.datastore.helpers import _new_value_pb from gcloud.datastore.helpers import entity_from_protobuf original_pb = entity_pb2.Entity() # Add a key. original_pb.key.partition_id.project_id = project = 'PROJECT' elem1 = original_pb.key.path.add() elem1.kind = 'Family' elem1.id = 1234 elem2 = original_pb.key.path.add() elem2.kind = 'King' elem2.name = 'Spades' # Add an integer property. val_pb1 = _new_value_pb(original_pb, 'foo') val_pb1.integer_value = 1337 val_pb1.exclude_from_indexes = True # Add a string property. val_pb2 = _new_value_pb(original_pb, 'bar') val_pb2.string_value = u'hello' # Add a nested (entity) property. val_pb3 = _new_value_pb(original_pb, 'entity-baz') sub_pb = entity_pb2.Entity() sub_val_pb1 = _new_value_pb(sub_pb, 'x') sub_val_pb1.double_value = 3.14 sub_val_pb2 = _new_value_pb(sub_pb, 'y') sub_val_pb2.double_value = 2.718281828 val_pb3.meaning = 9 val_pb3.entity_value.CopyFrom(sub_pb) # Add a list property. val_pb4 = _new_value_pb(original_pb, 'list-quux') array_val1 = val_pb4.array_value.values.add() array_val1.exclude_from_indexes = False array_val1.meaning = meaning = 22 array_val1.blob_value = b'\xe2\x98\x83' array_val2 = val_pb4.array_value.values.add() array_val2.exclude_from_indexes = False array_val2.meaning = meaning array_val2.blob_value = b'\xe2\x98\x85' # Convert to the user-space Entity. entity = entity_from_protobuf(original_pb) # Convert the user-space Entity back to a protobuf. new_pb = self._callFUT(entity) # NOTE: entity_to_protobuf() strips the project so we "cheat". new_pb.key.partition_id.project_id = project self._compareEntityProto(original_pb, new_pb)
def fetch(self, limit=None): """Executes the Query and returns all matching entities. This makes an API call to the Cloud Datastore, sends the Query as a protobuf, parses the responses to Entity protobufs, and then converts them to :class:`gcloud.datastore.entity.Entity` objects. For example:: >>> from gcloud import datastore >>> dataset = datastore.get_dataset('dataset-id', email, key_path) >>> query = dataset.query('Person').filter('name =', 'Sally') >>> query.fetch() [<Entity object>, <Entity object>, ...] >>> query.fetch(1) [<Entity object>] >>> query.limit() None :type limit: integer :param limit: An optional limit to apply temporarily to this query. That is, the Query itself won't be altered, but the limit will be applied to the query before it is executed. :rtype: list of :class:`gcloud.datastore.entity.Entity`'s :returns: The list of entities matching this query's criteria. """ clone = self if limit: clone = self.limit(limit) query_results = self.dataset().connection().run_query( query_pb=clone.to_protobuf(), dataset_id=self.dataset().id(), namespace=self._namespace, ) # NOTE: `query_results` contains two extra values that we don't use, # namely `more_results` and `skipped_results`. The value of # `more_results` is unusable because it always returns an enum # value of MORE_RESULTS_AFTER_LIMIT even if there are no more # results. See # https://github.com/GoogleCloudPlatform/gcloud-python/issues/280 # for discussion. entity_pbs, end_cursor = query_results[:2] self._cursor = end_cursor return [helpers.entity_from_protobuf(entity, dataset=self.dataset()) for entity in entity_pbs]
def get_entities(self, keys): """Retrieves entities from the dataset, along with their attributes. :type key: list of :class:`gcloud.datastore.key.Key` :param item_name: The name of the item to retrieve. :rtype: list of :class:`gcloud.datastore.entity.Entity` :return: The requested entities. """ entity_pbs = self.connection().lookup( dataset_id=self.id(), key_pbs=[k.to_protobuf() for k in keys]) entities = [] for entity_pb in entity_pbs: entities.append( helpers.entity_from_protobuf(entity_pb, dataset=self)) return entities
def get_entities(self, keys): """Retrieves entities from the dataset, along with their attributes. :type key: list of :class:`gcloud.datastore.key.Key` :param item_name: The name of the item to retrieve. :rtype: list of :class:`gcloud.datastore.entity.Entity` :return: The requested entities. """ entity_pbs = self.connection().lookup( dataset_id=self.id(), key_pbs=[k.to_protobuf() for k in keys] ) entities = [] for entity_pb in entity_pbs: entities.append(helpers.entity_from_protobuf( entity_pb, dataset=self)) return entities
def get(keys, missing=None, deferred=None, connection=None, dataset_id=None): """Retrieves entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :type connection: :class:`gcloud.datastore.connection.Connection` :param connection: Optional. The connection used to connect to datastore. If not passed, inferred from the environment. :type dataset_id: :class:`gcloud.datastore.connection.Connection` :param dataset_id: Optional. The dataset ID used to connect to datastore. If not passed, inferred from the environment. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: EnvironmentError if ``connection`` or ``dataset_id`` not passed, and cannot be inferred from the environment. ValueError if one or more of ``keys`` has a dataset ID which does not match the passed / inferred dataset ID. """ if not keys: return [] connection = _require_connection(connection) dataset_id = _require_dataset_id(dataset_id, keys[0]) if list(set([key.dataset_id for key in keys])) != [dataset_id]: raise ValueError('Keys do not match dataset ID') transaction = Transaction.current() entity_pbs = _extended_lookup( connection, dataset_id=dataset_id, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] entities = [] for entity_pb in entity_pbs: entities.append(helpers.entity_from_protobuf(entity_pb)) return entities
def _callFUT(self, val): from gcloud.datastore.helpers import entity_from_protobuf return entity_from_protobuf(val)
def fetch_page(self, limit=None): """Executes the Query and returns matching entities, and paging info. In addition to the fetched entities, it also returns a cursor to allow paging through a results set and a boolean `more_results` indicating if there are any more. This makes an API call to the Cloud Datastore, sends the Query as a protobuf, parses the responses to Entity protobufs, and then converts them to :class:`gcloud.datastore.entity.Entity` objects. For example:: >>> from gcloud import datastore >>> dataset = datastore.get_dataset('dataset-id') >>> query = dataset.query('Person').filter('name', '=', 'Sally') >>> query.fetch_page() [<Entity object>, <Entity object>, ...], 'cursorbase64', True >>> query.fetch_page(1) [<Entity object>], 'cursorbase64', True >>> query.limit() None :type limit: integer :param limit: An optional limit to apply temporarily to this query. That is, the Query itself won't be altered, but the limit will be applied to the query before it is executed. :rtype: tuple of mixed types :returns: The first entry is a :class:`gcloud.datastore.entity.Entity` list matching this query's criteria. The second is a base64 encoded cursor for paging and the third is a boolean indicating if there are more results. :raises: `ValueError` if more_results is not one of the enums NOT_FINISHED, MORE_RESULTS_AFTER_LIMIT, NO_MORE_RESULTS. """ clone = self if limit: clone = self.limit(limit) query_results = self.dataset().connection().run_query( query_pb=clone.to_protobuf(), dataset_id=self.dataset().id(), namespace=self._namespace, ) # NOTE: `query_results` contains an extra value that we don't use, # namely `skipped_results`. # # NOTE: The value of `more_results` is not currently useful because # the back-end always returns an enum # value of MORE_RESULTS_AFTER_LIMIT even if there are no more # results. See # https://github.com/GoogleCloudPlatform/gcloud-python/issues/280 # for discussion. entity_pbs, cursor_as_bytes, more_results_enum = query_results[:3] entities = [helpers.entity_from_protobuf(entity, dataset=self.dataset()) for entity in entity_pbs] cursor = base64.b64encode(cursor_as_bytes) if more_results_enum == self._NOT_FINISHED: more_results = True elif more_results_enum in self._FINISHED: more_results = False else: raise ValueError('Unexpected value returned for `more_results`.') return entities, cursor, more_results
def get_multi(keys, missing=None, deferred=None, connection=None, dataset_id=None): """Retrieves entities, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The keys to be retrieved from the datastore. :type missing: an empty list or None. :param missing: If a list is passed, the key-only entities returned by the backend as "missing" will be copied into it. Use only as a keyword param. :type deferred: an empty list or None. :param deferred: If a list is passed, the keys returned by the backend as "deferred" will be copied into it. Use only as a keyword param. :type connection: :class:`gcloud.datastore.connection.Connection` :param connection: Optional. The connection used to connect to datastore. If not passed, inferred from the environment. :type dataset_id: :class:`gcloud.datastore.connection.Connection` :param dataset_id: Optional. The dataset ID used to connect to datastore. If not passed, inferred from the environment. :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. :raises: EnvironmentError if ``connection`` or ``dataset_id`` not passed, and cannot be inferred from the environment. ValueError if one or more of ``keys`` has a dataset ID which does not match the passed / inferred dataset ID. """ if not keys: return [] connection = _require_connection(connection) dataset_id = _require_dataset_id(dataset_id, keys[0]) if list(set([key.dataset_id for key in keys])) != [dataset_id]: raise ValueError('Keys do not match dataset ID') transaction = Transaction.current() entity_pbs = _extended_lookup( connection, dataset_id=dataset_id, key_pbs=[k.to_protobuf() for k in keys], missing=missing, deferred=deferred, transaction_id=transaction and transaction.id, ) if missing is not None: missing[:] = [ helpers.entity_from_protobuf(missed_pb) for missed_pb in missing] if deferred is not None: deferred[:] = [ helpers.key_from_protobuf(deferred_pb) for deferred_pb in deferred] entities = [] for entity_pb in entity_pbs: entities.append(helpers.entity_from_protobuf(entity_pb)) return entities