diff --git a/gcloud/datastore/__init__.py b/gcloud/datastore/__init__.py index dcc72276a1b0..3e4e0ad0a164 100644 --- a/gcloud/datastore/__init__.py +++ b/gcloud/datastore/__init__.py @@ -49,6 +49,8 @@ from gcloud import credentials from gcloud.datastore import _implicit_environ from gcloud.datastore.connection import Connection +from gcloud.datastore.dataset import Dataset +from gcloud.datastore import helpers SCOPE = ('https://www.googleapis.com/auth/datastore ', @@ -158,16 +160,57 @@ def _require_connection(): return _implicit_environ.CONNECTION -def get_entities(keys): +def get_entities(keys, missing=None, deferred=None, + connection=None, dataset_id=None): """Retrieves entities from implied dataset, along with their attributes. :type keys: list of :class:`gcloud.datastore.key.Key` :param keys: The name of the item to retrieve. + :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. + + :type dataset_id: :class:`str`. + :param dataset_id: Optional. The ID of the dataset. + :rtype: list of :class:`gcloud.datastore.entity.Entity` :returns: The requested entities. """ - return _require_dataset().get_entities(keys) + connection = connection or _require_connection() + dataset_id = dataset_id or _require_dataset().id() + + entity_pbs = connection.lookup( + dataset_id=dataset_id, + key_pbs=[k.to_protobuf() for k in keys], + missing=missing, deferred=deferred, + ) + + new_dataset = Dataset(dataset_id, connection=connection) + if missing is not None: + missing[:] = [ + helpers.entity_from_protobuf(missed_pb, dataset=new_dataset) + 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=new_dataset)) + return entities def allocate_ids(incomplete_key, num_ids, connection=None, dataset_id=None): @@ -180,10 +223,10 @@ def allocate_ids(incomplete_key, num_ids, connection=None, dataset_id=None): :param num_ids: The number of IDs to allocate. :type connection: :class:`gcloud.datastore.connection.Connection` - :param connection: Optional. The connection used to allocate IDs. + :param connection: Optional. The connection used to connect to datastore. :type dataset_id: :class:`str`. - :param dataset_id: Optional. The ID of the dataset used to allocate. + :param dataset_id: Optional. The ID of the dataset. :rtype: list of :class:`gcloud.datastore.key.Key` :returns: The (complete) keys allocated with `incomplete_key` as root. diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index e00170eac70f..13e676d7481f 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -14,13 +14,13 @@ """Connections to gcloud datastore API servers.""" -from gcloud import connection as base_connection +from gcloud import connection from gcloud.datastore import datastore_v1_pb2 as datastore_pb from gcloud.datastore import helpers from gcloud.datastore.dataset import Dataset -class Connection(base_connection.Connection): +class Connection(connection.Connection): """A connection to the Google Cloud Datastore via the Protobuf API. This class should understand only the basic types (and protobufs) @@ -125,7 +125,7 @@ def build_api_url(cls, dataset_id, method, base_url=None, api_version=(api_version or cls.API_VERSION), dataset_id=dataset_id, method=method) - def transaction(self, transaction=base_connection.Connection._EMPTY): + def transaction(self, transaction=connection.Connection._EMPTY): """Getter/setter for the connection's transaction object. :type transaction: :class:`gcloud.datastore.transaction.Transaction`, diff --git a/gcloud/datastore/dataset.py b/gcloud/datastore/dataset.py index 659c2b90d07e..d51df64b11cb 100644 --- a/gcloud/datastore/dataset.py +++ b/gcloud/datastore/dataset.py @@ -14,8 +14,6 @@ """Create / interact with gcloud datastore datasets.""" -from gcloud.datastore import helpers - class Dataset(object): """A dataset in the Cloud Datastore. @@ -71,44 +69,3 @@ def id(self): """ return self._id - - 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` - :returns: 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 diff --git a/gcloud/datastore/key.py b/gcloud/datastore/key.py index b573a64ff6fa..732718355ce6 100644 --- a/gcloud/datastore/key.py +++ b/gcloud/datastore/key.py @@ -238,12 +238,12 @@ def get(self, connection=None): match found. """ # Temporary import hack until Dataset is removed in #477. - from gcloud.datastore.dataset import Dataset + from gcloud import datastore # We allow partial keys to attempt a get, the backend will fail. connection = connection or _implicit_environ.CONNECTION - dataset = Dataset(self.dataset_id, connection=connection) - entities = dataset.get_entities([self]) + entities = datastore.get_entities( + [self], connection=connection, dataset_id=self.dataset_id) if entities: result = entities[0] diff --git a/gcloud/datastore/test___init__.py b/gcloud/datastore/test___init__.py index 7ed7717cf824..e3717384aa41 100644 --- a/gcloud/datastore/test___init__.py +++ b/gcloud/datastore/test___init__.py @@ -189,21 +189,152 @@ def test__require_connection_value_set(self): stored_connection = gcloud.datastore._require_connection() self.assertTrue(stored_connection is FAKE_CONNECTION) - def test_get_entities(self): - import gcloud.datastore + +class Test_get_entities_function(unittest2.TestCase): + + def _callFUT(self, keys, missing=None, deferred=None, + connection=None, dataset_id=None): + from gcloud.datastore import get_entities + return get_entities(keys, missing=missing, deferred=deferred, + connection=connection, dataset_id=dataset_id) + + def test_get_entities_miss(self): + from gcloud.datastore.key import Key + from gcloud.datastore.test_connection import _Connection + + DATASET_ID = 'DATASET' + connection = _Connection() + key = Key('Kind', 1234, dataset_id=DATASET_ID) + results = self._callFUT([key], connection=connection, + dataset_id=DATASET_ID) + self.assertEqual(results, []) + + def test_get_entities_miss_w_missing(self): + from gcloud.datastore import datastore_v1_pb2 as datastore_pb + from gcloud.datastore.key import Key + from gcloud.datastore.test_connection import _Connection + + DATASET_ID = 'DATASET' + KIND = 'Kind' + ID = 1234 + + # Make a missing entity pb to be returned from mock backend. + missed = datastore_pb.Entity() + missed.key.partition_id.dataset_id = DATASET_ID + path_element = missed.key.path_element.add() + path_element.kind = KIND + path_element.id = ID + + # Set missing entity on mock connection. + connection = _Connection() + connection._missing = [missed] + + key = Key(KIND, ID, dataset_id=DATASET_ID) + missing = [] + entities = self._callFUT([key], connection=connection, + dataset_id=DATASET_ID, missing=missing) + self.assertEqual(entities, []) + self.assertEqual([missed.key().to_protobuf() for missed in missing], + [key.to_protobuf()]) + + def test_get_entities_miss_w_deferred(self): + from gcloud.datastore.key import Key + from gcloud.datastore.test_connection import _Connection + + DATASET_ID = 'DATASET' + key = Key('Kind', 1234, dataset_id=DATASET_ID) + + # Set deferred entity on mock connection. + connection = _Connection() + connection._deferred = [key.to_protobuf()] + + deferred = [] + entities = self._callFUT([key], connection=connection, + dataset_id=DATASET_ID, deferred=deferred) + self.assertEqual(entities, []) + self.assertEqual([def_key.to_protobuf() for def_key in deferred], + [key.to_protobuf()]) + + def _make_entity_pb(self, dataset_id, kind, integer_id, name, str_val): + from gcloud.datastore import datastore_v1_pb2 as datastore_pb + + entity_pb = datastore_pb.Entity() + entity_pb.key.partition_id.dataset_id = dataset_id + path_element = entity_pb.key.path_element.add() + path_element.kind = kind + path_element.id = integer_id + prop = entity_pb.property.add() + prop.name = name + prop.value.string_value = str_val + + return entity_pb + + def test_get_entities_hit(self): + from gcloud.datastore.key import Key + from gcloud.datastore.test_connection import _Connection + + DATASET_ID = 'DATASET' + KIND = 'Kind' + ID = 1234 + PATH = [{'kind': KIND, 'id': ID}] + + # Make a found entity pb to be returned from mock backend. + entity_pb = self._make_entity_pb(DATASET_ID, KIND, ID, + 'foo', 'Foo') + + # Make a connection to return the entity pb. + connection = _Connection(entity_pb) + + key = Key(KIND, ID, dataset_id=DATASET_ID) + result, = self._callFUT([key], connection=connection, + dataset_id=DATASET_ID) + new_key = result.key() + + # Check the returned value is as expected. + self.assertFalse(new_key is key) + self.assertEqual(new_key.dataset_id, DATASET_ID) + self.assertEqual(new_key.path, PATH) + self.assertEqual(list(result), ['foo']) + self.assertEqual(result['foo'], 'Foo') + + def test_get_entities_implicit(self): from gcloud.datastore import _implicit_environ + from gcloud.datastore.key import Key + from gcloud.datastore.test_connection import _Connection from gcloud.datastore.test_entity import _Dataset from gcloud._testing import _Monkey + DATASET_ID = 'DATASET' + KIND = 'Kind' + ID = 1234 + PATH = [{'kind': KIND, 'id': ID}] + + # Make a found entity pb to be returned from mock backend. + entity_pb = self._make_entity_pb(DATASET_ID, KIND, ID, + 'foo', 'Foo') + + # Make a connection to return the entity pb. + CUSTOM_CONNECTION = _Connection(entity_pb) CUSTOM_DATASET = _Dataset() - DUMMY_KEYS = [object(), object()] - DUMMY_VALS = [object(), object()] - for key, val in zip(DUMMY_KEYS, DUMMY_VALS): - CUSTOM_DATASET[key] = val - with _Monkey(_implicit_environ, DATASET=CUSTOM_DATASET): - result = gcloud.datastore.get_entities(DUMMY_KEYS) - self.assertTrue(result == DUMMY_VALS) + key = Key(KIND, ID, dataset_id=DATASET_ID) + with _Monkey(_implicit_environ, DATASET=CUSTOM_DATASET, + CONNECTION=CUSTOM_CONNECTION): + result, = self._callFUT([key]) + + expected_called_with = { + 'dataset_id': DATASET_ID, + 'key_pbs': [key.to_protobuf()], + } + self.assertEqual(CUSTOM_CONNECTION._called_with, expected_called_with) + + new_key = result.key() + # Check the returned value is as expected. + self.assertFalse(new_key is key) + self.assertEqual(new_key.dataset_id, DATASET_ID) + self.assertEqual(new_key.path, PATH) + self.assertEqual(list(result), ['foo']) + self.assertEqual(result['foo'], 'Foo') class Test_allocate_ids_function(unittest2.TestCase): @@ -216,7 +347,7 @@ def _callFUT(self, incomplete_key, num_ids, def test_allocate_ids(self): from gcloud.datastore.key import Key - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection DATASET_ID = 'DATASET' INCOMPLETE_KEY = Key('KIND', dataset_id=DATASET_ID) @@ -235,7 +366,7 @@ def test_allocate_ids(self): def test_allocate_ids_implicit(self): from gcloud.datastore import _implicit_environ from gcloud.datastore.key import Key - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection from gcloud.datastore.test_entity import _Dataset from gcloud._testing import _Monkey @@ -253,7 +384,7 @@ def test_allocate_ids_implicit(self): def test_allocate_ids_with_complete(self): from gcloud.datastore import _implicit_environ from gcloud.datastore.key import Key - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection from gcloud.datastore.test_entity import _Dataset from gcloud._testing import _Monkey diff --git a/gcloud/datastore/test_connection.py b/gcloud/datastore/test_connection.py index a61b29ddbb8f..3373cf131f78 100644 --- a/gcloud/datastore/test_connection.py +++ b/gcloud/datastore/test_connection.py @@ -188,7 +188,7 @@ def test_transaction_setter(self): def test_mutation_wo_transaction(self): from gcloud._testing import _Monkey - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb class Mutation(object): pass @@ -218,7 +218,7 @@ def test_dataset(self): self.assertEqual(dataset.id(), DATASET_ID) def test_lookup_single_key_empty_response(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -244,7 +244,7 @@ def test_lookup_single_key_empty_response(self): _compare_key_pb_after_request(self, key_pb, keys[0]) def test_lookup_single_key_empty_response_w_eventual(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -282,7 +282,7 @@ def test_lookup_single_key_empty_response_w_eventual_and_transaction(self): ValueError, conn.lookup, DATASET_ID, key_pb, eventual=True) def test_lookup_single_key_empty_response_w_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' TRANSACTION = 'TRANSACTION' @@ -311,7 +311,7 @@ def test_lookup_single_key_empty_response_w_transaction(self): self.assertEqual(request.read_options.transaction, TRANSACTION) def test_lookup_single_key_nonempty_response(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -342,7 +342,7 @@ def test_lookup_single_key_nonempty_response(self): _compare_key_pb_after_request(self, key_pb, keys[0]) def test_lookup_multiple_keys_empty_response(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb1 = self._make_key_pb(DATASET_ID) @@ -370,7 +370,7 @@ def test_lookup_multiple_keys_empty_response(self): _compare_key_pb_after_request(self, key_pb2, keys[1]) def test_lookup_multiple_keys_w_missing(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb1 = self._make_key_pb(DATASET_ID) @@ -416,7 +416,7 @@ def test_lookup_multiple_keys_w_missing_non_empty(self): conn.lookup, DATASET_ID, [key_pb1, key_pb2], missing=missing) def test_lookup_multiple_keys_w_deferred(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb1 = self._make_key_pb(DATASET_ID) @@ -464,7 +464,7 @@ def test_lookup_multiple_keys_w_deferred_non_empty(self): conn.lookup, DATASET_ID, [key_pb1, key_pb2], deferred=deferred) def test_lookup_multiple_keys_w_deferred_from_backend_but_not_passed(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb1 = self._make_key_pb(DATASET_ID) @@ -516,7 +516,7 @@ def test_lookup_multiple_keys_w_deferred_from_backend_but_not_passed(self): self.assertEqual(keys[0], key_pb2) def test_run_query_w_eventual_no_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' KIND = 'Nonesuch' @@ -555,7 +555,7 @@ def test_run_query_w_eventual_no_transaction(self): self.assertEqual(request.read_options.transaction, '') def test_run_query_wo_eventual_w_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' KIND = 'Nonesuch' @@ -595,7 +595,7 @@ def test_run_query_wo_eventual_w_transaction(self): self.assertEqual(request.read_options.transaction, TRANSACTION) def test_run_query_w_eventual_and_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' KIND = 'Nonesuch' @@ -613,7 +613,7 @@ def test_run_query_w_eventual_and_transaction(self): ValueError, conn.run_query, DATASET_ID, q_pb, eventual=True) def test_run_query_wo_namespace_empty_result(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' KIND = 'Nonesuch' @@ -648,7 +648,7 @@ def test_run_query_wo_namespace_empty_result(self): self.assertEqual(request.query, q_pb) def test_run_query_w_namespace_nonempty_result(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' KIND = 'Kind' @@ -685,7 +685,7 @@ def test_begin_transaction_w_existing_transaction(self): self.assertRaises(ValueError, conn.begin_transaction, DATASET_ID) def test_begin_transaction_default_serialize(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' TRANSACTION = 'TRANSACTION' @@ -710,7 +710,7 @@ def test_begin_transaction_default_serialize(self): self.assertEqual(request.isolation_level, rq_class.SNAPSHOT) def test_begin_transaction_explicit_serialize(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' TRANSACTION = 'TRANSACTION' @@ -735,7 +735,7 @@ def test_begin_transaction_explicit_serialize(self): self.assertEqual(request.isolation_level, rq_class.SERIALIZABLE) def test_commit_wo_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -769,7 +769,7 @@ def test_commit_wo_transaction(self): self.assertEqual(request.mode, rq_class.NON_TRANSACTIONAL) def test_commit_w_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb class Xact(object): def id(self): @@ -825,7 +825,7 @@ def id(self): conn.rollback, DATASET_ID) def test_rollback_ok(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' TRANSACTION = 'xact' @@ -854,7 +854,7 @@ def id(self): self.assertEqual(request.transaction, TRANSACTION) def test_allocate_ids_empty(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' rsp_pb = datastore_pb.AllocateIdsResponse() @@ -877,7 +877,7 @@ def test_allocate_ids_empty(self): self.assertEqual(list(request.key), []) def test_allocate_ids_non_empty(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' before_key_pbs = [ @@ -913,7 +913,7 @@ def test_allocate_ids_non_empty(self): _compare_key_pb_after_request(self, key_before, key_after) def test_save_entity_wo_transaction_w_upsert(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -951,7 +951,7 @@ def test_save_entity_wo_transaction_w_upsert(self): self.assertEqual(request.mode, rq_class.NON_TRANSACTIONAL) def test_save_entity_w_exclude_from_indexes(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb import operator DATASET_ID = 'DATASET' @@ -1000,7 +1000,7 @@ def test_save_entity_w_exclude_from_indexes(self): self.assertEqual(request.mode, rq_class.NON_TRANSACTIONAL) def test_save_entity_wo_transaction_w_auto_id(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID, id=None) @@ -1043,7 +1043,7 @@ def test_save_entity_wo_transaction_w_auto_id(self): self.assertEqual(request.mode, rq_class.NON_TRANSACTIONAL) def test_save_entity_w_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb mutation = datastore_pb.Mutation() @@ -1063,7 +1063,7 @@ def mutation(self): self.assertEqual(len(mutation.upsert), 1) def test_save_entity_w_transaction_nested_entity(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb from gcloud.datastore.entity import Entity mutation = datastore_pb.Mutation() @@ -1086,7 +1086,7 @@ def mutation(self): self.assertEqual(len(mutation.upsert), 1) def test_delete_entities_wo_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb DATASET_ID = 'DATASET' key_pb = self._make_key_pb(DATASET_ID) @@ -1119,7 +1119,7 @@ def test_delete_entities_wo_transaction(self): self.assertEqual(request.mode, rq_class.NON_TRANSACTIONAL) def test_delete_entities_w_transaction(self): - from gcloud.datastore.connection import datastore_pb + from gcloud.datastore import datastore_v1_pb2 as datastore_pb mutation = datastore_pb.Mutation() @@ -1181,3 +1181,44 @@ def _compare_key_pb_after_request(test, key_before, key_after): len(key_after.path_element)) for elt1, elt2 in zip(key_before.path_element, key_after.path_element): test.assertEqual(elt1, elt2) + + +class _Connection(object): + _called_with = None + _missing = _deferred = () + + def __init__(self, *result): + self._result = list(result) + + def lookup(self, **kw): + self._called_with = kw + missing = kw.pop('missing', None) + if missing is not None: + missing.extend(self._missing) + deferred = kw.pop('deferred', None) + if deferred is not None: + deferred.extend(self._deferred) + return self._result + + def allocate_ids(self, dataset_id, key_pbs): + self._called_dataset_id = dataset_id + self._called_key_pbs = key_pbs + num_pbs = len(key_pbs) + return [_KeyProto(i) for i in range(num_pbs)] + + def delete_entities(self, dataset_id, key_pbs): + self._called_dataset_id = dataset_id + self._called_key_pbs = key_pbs + return True + + +class _PathElementProto(object): + + def __init__(self, _id): + self.id = _id + + +class _KeyProto(object): + + def __init__(self, id_): + self.path_element = [_PathElementProto(id_)] diff --git a/gcloud/datastore/test_dataset.py b/gcloud/datastore/test_dataset.py index d335905e27e3..6c0a2a3fa0d2 100644 --- a/gcloud/datastore/test_dataset.py +++ b/gcloud/datastore/test_dataset.py @@ -39,112 +39,3 @@ def test_ctor_explicit(self): dataset = self._makeOne(DATASET_ID, CONNECTION) self.assertEqual(dataset.id(), DATASET_ID) self.assertTrue(dataset.connection() is CONNECTION) - - def test_get_entities_miss(self): - from gcloud.datastore.key import Key - DATASET_ID = 'DATASET' - connection = _Connection() - dataset = self._makeOne(DATASET_ID, connection) - key = Key('Kind', 1234, dataset_id=DATASET_ID) - self.assertEqual(dataset.get_entities([key]), []) - - def test_get_entities_miss_w_missing(self): - from gcloud.datastore.connection import datastore_pb - from gcloud.datastore.key import Key - DATASET_ID = 'DATASET' - KIND = 'Kind' - ID = 1234 - missed = datastore_pb.Entity() - missed.key.partition_id.dataset_id = DATASET_ID - path_element = missed.key.path_element.add() - path_element.kind = KIND - path_element.id = ID - connection = _Connection() - connection._missing = [missed] - dataset = self._makeOne(DATASET_ID, connection) - key = Key(KIND, ID, dataset_id=DATASET_ID) - missing = [] - entities = dataset.get_entities([key], missing=missing) - self.assertEqual(entities, []) - self.assertEqual([missed.key().to_protobuf() for missed in missing], - [key.to_protobuf()]) - - def test_get_entities_miss_w_deferred(self): - from gcloud.datastore.key import Key - DATASET_ID = 'DATASET' - connection = _Connection() - dataset = self._makeOne(DATASET_ID, connection) - key = Key('Kind', 1234, dataset_id=DATASET_ID) - connection._deferred = [key.to_protobuf()] - deferred = [] - entities = dataset.get_entities([key], deferred=deferred) - self.assertEqual(entities, []) - self.assertEqual([def_key.to_protobuf() for def_key in deferred], - [key.to_protobuf()]) - - def test_get_entities_hit(self): - from gcloud.datastore.connection import datastore_pb - from gcloud.datastore.key import Key - DATASET_ID = 'DATASET' - KIND = 'Kind' - ID = 1234 - PATH = [{'kind': KIND, 'id': ID}] - entity_pb = datastore_pb.Entity() - entity_pb.key.partition_id.dataset_id = DATASET_ID - path_element = entity_pb.key.path_element.add() - path_element.kind = KIND - path_element.id = ID - prop = entity_pb.property.add() - prop.name = 'foo' - prop.value.string_value = 'Foo' - connection = _Connection(entity_pb) - dataset = self._makeOne(DATASET_ID, connection) - key = Key(KIND, ID, dataset_id=DATASET_ID) - result, = dataset.get_entities([key]) - new_key = result.key() - self.assertFalse(new_key is key) - self.assertEqual(new_key.dataset_id, DATASET_ID) - self.assertEqual(new_key.path, PATH) - self.assertEqual(list(result), ['foo']) - self.assertEqual(result['foo'], 'Foo') - - -class _Connection(object): - _called_with = None - _missing = _deferred = () - - def __init__(self, *result): - self._result = list(result) - - def lookup(self, **kw): - self._called_with = kw - missing = kw.pop('missing', None) - if missing is not None: - missing.extend(self._missing) - deferred = kw.pop('deferred', None) - if deferred is not None: - deferred.extend(self._deferred) - return self._result - - def allocate_ids(self, dataset_id, key_pbs): - self._called_dataset_id = dataset_id - self._called_key_pbs = key_pbs - num_pbs = len(key_pbs) - return [_KeyProto(i) for i in range(num_pbs)] - - def delete_entities(self, dataset_id, key_pbs): - self._called_dataset_id = dataset_id - self._called_key_pbs = key_pbs - return True - - -class _PathElementProto(object): - - def __init__(self, _id): - self.id = _id - - -class _KeyProto(object): - - def __init__(self, id_): - self.path_element = [_PathElementProto(id_)] diff --git a/gcloud/datastore/test_entity.py b/gcloud/datastore/test_entity.py index 60e02e9efd29..f77fe5ef7261 100644 --- a/gcloud/datastore/test_entity.py +++ b/gcloud/datastore/test_entity.py @@ -271,9 +271,6 @@ def id(self): def connection(self): return self._connection - def get_entities(self, keys): - return [self.get(key) for key in keys] - class _Connection(object): _transaction = _saved = _deleted = None diff --git a/gcloud/datastore/test_key.py b/gcloud/datastore/test_key.py index 22603def4e01..cfb5d1c0fa99 100644 --- a/gcloud/datastore/test_key.py +++ b/gcloud/datastore/test_key.py @@ -196,7 +196,7 @@ def test_to_protobuf_w_no_kind(self): self.assertFalse(pb.path_element[0].HasField('kind')) def test_get_explicit_connection_miss(self): - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection cnxn_lookup_result = [] cnxn = _Connection(*cnxn_lookup_result) @@ -207,7 +207,7 @@ def test_get_explicit_connection_miss(self): def test_get_implicit_connection_miss(self): from gcloud._testing import _Monkey from gcloud.datastore import _implicit_environ - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection cnxn_lookup_result = [] cnxn = _Connection(*cnxn_lookup_result) @@ -218,7 +218,7 @@ def test_get_implicit_connection_miss(self): def test_get_explicit_connection_hit(self): from gcloud.datastore import datastore_v1_pb2 - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection KIND = 'KIND' ID = 1234 @@ -248,11 +248,11 @@ def test_get_no_connection(self): self.assertEqual(_implicit_environ.CONNECTION, None) key = self._makeOne('KIND', 1234) - with self.assertRaises(AttributeError): + with self.assertRaises(EnvironmentError): key.get() def test_delete_explicit_connection(self): - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection cnxn = _Connection() key = self._makeOne('KIND', 1234) @@ -264,7 +264,7 @@ def test_delete_explicit_connection(self): def test_delete_implicit_connection(self): from gcloud._testing import _Monkey from gcloud.datastore import _implicit_environ - from gcloud.datastore.test_dataset import _Connection + from gcloud.datastore.test_connection import _Connection cnxn = _Connection() key = self._makeOne('KIND', 1234)