Skip to content

Commit 64ab5ee

Browse files
committed
Implement Key.complete_key for auto_id on partial keys.
Addresses fifth part of #451.
1 parent c17800d commit 64ab5ee

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

gcloud/datastore/dataset.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,17 +196,5 @@ def allocate_ids(self, incomplete_key, num_ids):
196196
self.id(), incomplete_key_pbs)
197197
allocated_ids = [allocated_key_pb.path_element[-1].id
198198
for allocated_key_pb in allocated_key_pbs]
199-
200-
# This method is temporary and will move over to Key in
201-
# part 5 of #451.
202-
def create_new_key(new_id):
203-
"""Temporary method to complete `incomplete_key`.
204-
205-
Uses `incomplete_key` from outside scope.
206-
"""
207-
clone = incomplete_key._clone()
208-
clone._path[-1]['id'] = new_id
209-
return clone
210-
211-
return [create_new_key(allocated_id)
199+
return [incomplete_key.complete_key(allocated_id)
212200
for allocated_id in allocated_ids]

gcloud/datastore/key.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ def _clone(self):
126126
"""
127127
return copy.deepcopy(self)
128128

129+
def complete_key(self, id_or_name):
130+
"""Creates new key from existing partial key by adding final ID/name.
131+
132+
:rtype: :class:`gcloud.datastore.key.Key`
133+
:returns: A new `Key` instance with the same data as the current one
134+
and an extra ID or name added.
135+
:raises: `ValueError` if the current key is not partial or if
136+
`id_or_name` is not a string or integer.
137+
"""
138+
if not self.is_partial:
139+
raise ValueError('Only a partial key can be completed.')
140+
141+
id_or_name_key = None
142+
if isinstance(id_or_name, six.string_types):
143+
id_or_name_key = 'name'
144+
elif isinstance(id_or_name, six.integer_types):
145+
id_or_name_key = 'id'
146+
else:
147+
raise ValueError(id_or_name,
148+
'ID/name was not a string or integer.')
149+
150+
new_key = self._clone()
151+
new_key._path[-1][id_or_name_key] = id_or_name
152+
new_key._flat_path += (id_or_name,)
153+
return new_key
154+
129155
def to_protobuf(self):
130156
"""Return a protobuf corresponding to the key.
131157

gcloud/datastore/test_key.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,30 @@ def test__clone(self):
6060
self.assertEqual(clone.kind, _KIND)
6161
self.assertEqual(clone.path, _PATH)
6262

63+
def test_complete_key_on_partial_w_id(self):
64+
key = self._makeOne('KIND')
65+
_ID = 1234
66+
new_key = key.complete_key(_ID)
67+
self.assertFalse(key is new_key)
68+
self.assertEqual(new_key.id, _ID)
69+
self.assertEqual(new_key.name, None)
70+
71+
def test_complete_key_on_partial_w_name(self):
72+
key = self._makeOne('KIND')
73+
_NAME = 'NAME'
74+
new_key = key.complete_key(_NAME)
75+
self.assertFalse(key is new_key)
76+
self.assertEqual(new_key.id, None)
77+
self.assertEqual(new_key.name, _NAME)
78+
79+
def test_complete_key_on_partial_w_invalid(self):
80+
key = self._makeOne('KIND')
81+
self.assertRaises(ValueError, key.complete_key, object())
82+
83+
def test_complete_key_on_complete(self):
84+
key = self._makeOne('KIND', 1234)
85+
self.assertRaises(ValueError, key.complete_key, 5678)
86+
6387
def test_to_protobuf_defaults(self):
6488
from gcloud.datastore.datastore_v1_pb2 import Key as KeyPB
6589
_KIND = 'KIND'

regression/datastore.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ def _get_post(self, name=None, key_id=None, post_content=None):
7171
# Update the entity key.
7272
key = None
7373
if name is not None:
74-
key = datastore.key.Key('Post', name)
74+
key = entity.key().complete_key(name)
7575
if key_id is not None:
76-
key = datastore.key.Key('Post', key_id)
76+
key = entity.key().complete_key(key_id)
7777
if key is not None:
7878
entity.key(key)
7979

0 commit comments

Comments
 (0)