Skip to content

Commit e86ba09

Browse files
committed
Merge pull request #462 from dhermes/fix-451-part6
Address sixth part of 451: Implement Key.compare_to_proto to check pb keys against existing.
2 parents f0e26b8 + a257a9c commit e86ba09

4 files changed

Lines changed: 25 additions & 36 deletions

File tree

gcloud/datastore/connection.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ def save_entity(self, dataset_id, key_pb, properties,
444444
445445
:type exclude_from_indexes: sequence of str
446446
:param exclude_from_indexes: Names of properties *not* to be indexed.
447+
448+
:rtype: :class:`tuple`
449+
:returns: The pair (`assigned`, `new_id`) where `assigned` is a boolean
450+
indicating if a new ID has been assigned and `new_id` is
451+
either `None` or an integer that has been assigned.
447452
"""
448453
mutation = self.mutation()
449454

@@ -477,14 +482,18 @@ def save_entity(self, dataset_id, key_pb, properties,
477482
# If this is in a transaction, we should just return True. The
478483
# transaction will handle assigning any keys as necessary.
479484
if self.transaction():
480-
return True
485+
return False, None
481486

482487
result = self.commit(dataset_id, mutation)
483-
# If this was an auto-assigned ID, return the new Key.
488+
# If this was an auto-assigned ID, return the new Key. We don't
489+
# verify that this matches the original `key_pb` but trust the
490+
# backend to uphold the values sent (e.g. dataset ID).
484491
if auto_id:
485-
return result.insert_auto_id_key[0]
492+
inserted_key_pb = result.insert_auto_id_key[0]
493+
# Assumes the backend has set `id` without checking HasField('id').
494+
return True, inserted_key_pb.path_element[-1].id
486495

487-
return True
496+
return False, None
488497

489498
def delete_entities(self, dataset_id, key_pbs):
490499
"""Delete keys from a dataset in the Cloud Datastore.

gcloud/datastore/entity.py

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"""Class for representing a single entity in the Cloud Datastore."""
1616

1717
from gcloud.datastore import _implicit_environ
18-
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
1918
from gcloud.datastore.key import Key
2019

2120

@@ -241,7 +240,7 @@ def save(self):
241240
key = self._must_key
242241
dataset = self._must_dataset
243242
connection = dataset.connection()
244-
key_pb = connection.save_entity(
243+
assigned, new_id = connection.save_entity(
245244
dataset_id=dataset.id(),
246245
key_pb=key.to_protobuf(),
247246
properties=dict(self),
@@ -253,23 +252,9 @@ def save(self):
253252
if transaction and key.is_partial:
254253
transaction.add_auto_id_entity(self)
255254

256-
if isinstance(key_pb, datastore_pb.Key):
257-
# Update the path (which may have been altered).
258-
# NOTE: The underlying namespace can't have changed in a save().
259-
# The value of the dataset ID may have changed from implicit
260-
# (i.e. None, with the ID implied from the dataset.Dataset
261-
# object associated with the Entity/Key), but if it was
262-
# implicit before the save() we leave it as implicit.
263-
path = []
264-
for element in key_pb.path_element:
265-
key_part = {}
266-
for descriptor, value in element._fields.items():
267-
key_part[descriptor.name] = value
268-
path.append(key_part)
269-
# This is temporary. Will be addressed throughout #451.
270-
clone = key._clone()
271-
clone._path = path
272-
self._key = clone
255+
if assigned:
256+
# Update the key (which may have been altered).
257+
self.key(self.key().completed_key(new_id))
273258

274259
return self
275260

gcloud/datastore/test_connection.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ def test_save_entity_wo_transaction_w_upsert(self):
926926
])
927927
http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString())
928928
result = conn.save_entity(DATASET_ID, key_pb, {'foo': u'Foo'})
929-
self.assertEqual(result, True)
929+
self.assertEqual(result, (False, None))
930930
cw = http._called_with
931931
self._verifyProtobufCall(cw, URI, conn)
932932
rq_class = datastore_pb.CommitRequest
@@ -967,7 +967,7 @@ def test_save_entity_w_exclude_from_indexes(self):
967967
result = conn.save_entity(DATASET_ID, key_pb,
968968
{'foo': u'Foo', 'bar': [u'bar1', u'bar2']},
969969
exclude_from_indexes=['foo', 'bar'])
970-
self.assertEqual(result, True)
970+
self.assertEqual(result, (False, None))
971971
cw = http._called_with
972972
self._verifyProtobufCall(cw, URI, conn)
973973
rq_class = datastore_pb.CommitRequest
@@ -1018,7 +1018,7 @@ def test_save_entity_wo_transaction_w_auto_id(self):
10181018
])
10191019
http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString())
10201020
result = conn.save_entity(DATASET_ID, key_pb, {'foo': u'Foo'})
1021-
self.assertEqual(result, updated_key_pb)
1021+
self.assertEqual(result, (True, 1234))
10221022
cw = http._called_with
10231023
self._verifyProtobufCall(cw, URI, conn)
10241024
rq_class = datastore_pb.CommitRequest
@@ -1054,7 +1054,7 @@ def mutation(self):
10541054
conn.transaction(Xact())
10551055
http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString())
10561056
result = conn.save_entity(DATASET_ID, key_pb, {'foo': u'Foo'})
1057-
self.assertEqual(result, True)
1057+
self.assertEqual(result, (False, None))
10581058
self.assertEqual(http._called_with, None)
10591059
mutation = conn.mutation()
10601060
self.assertEqual(len(mutation.upsert), 1)
@@ -1077,7 +1077,7 @@ def mutation(self):
10771077
conn.transaction(Xact())
10781078
http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString())
10791079
result = conn.save_entity(DATASET_ID, key_pb, {'foo': nested})
1080-
self.assertEqual(result, True)
1080+
self.assertEqual(result, (False, None))
10811081
self.assertEqual(http._called_with, None)
10821082
mutation = conn.mutation()
10831083
self.assertEqual(len(mutation.upsert), 1)

gcloud/datastore/test_entity.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def test_save_w_returned_key_exclude_from_indexes(self):
194194
key_pb.partition_id.dataset_id = _DATASET_ID
195195
key_pb.path_element.add(kind=_KIND, id=_ID)
196196
connection = _Connection()
197-
connection._save_result = key_pb
197+
connection._save_result = (True, _ID)
198198
dataset = _Dataset(connection)
199199
key = Key('KIND', dataset_id='DATASET')
200200
entity = self._makeOne(dataset, exclude_from_indexes=['foo'])
@@ -287,17 +287,12 @@ def get_entities(self, keys):
287287
return [self.get(key) for key in keys]
288288

289289
def allocate_ids(self, incomplete_key, num_ids):
290-
def clone_with_new_id(key, new_id):
291-
clone = key._clone()
292-
clone._path[-1]['id'] = new_id
293-
return clone
294-
return [clone_with_new_id(incomplete_key, i + 1)
295-
for i in range(num_ids)]
290+
return [incomplete_key.completed_key(i + 1) for i in range(num_ids)]
296291

297292

298293
class _Connection(object):
299294
_transaction = _saved = _deleted = None
300-
_save_result = True
295+
_save_result = (False, None)
301296

302297
def transaction(self):
303298
return self._transaction

0 commit comments

Comments
 (0)