diff --git a/gcloud/datastore/key.py b/gcloud/datastore/key.py index 1c189c1dbaac6..4632de0c1461d 100644 --- a/gcloud/datastore/key.py +++ b/gcloud/datastore/key.py @@ -155,15 +155,18 @@ def _clone(self): """Duplicates the Key. Most attributes are simple types, so don't require copying. Other - attributes like ``parent`` are long-lived and so we re-use them rather - than creating copies. + attributes like ``parent`` are long-lived and so we re-use them. :rtype: :class:`gcloud.datastore.key.Key` :returns: A new ``Key`` instance with the same data as the current one. """ - return self.__class__(*self.flat_path, parent=self.parent, - dataset_id=self.dataset_id, - namespace=self.namespace) + cloned_self = self.__class__(*self.flat_path, + dataset_id=self.dataset_id, + namespace=self.namespace) + # If the current parent has already been set, we re-use + # the same instance + cloned_self._parent = self._parent + return cloned_self def completed_key(self, id_or_name): """Creates new key from existing partial key by adding final ID/name. diff --git a/gcloud/datastore/test_key.py b/gcloud/datastore/test_key.py index 8c83f9c7a47f6..dd96685ea66e9 100644 --- a/gcloud/datastore/test_key.py +++ b/gcloud/datastore/test_key.py @@ -152,6 +152,25 @@ def test__clone(self): self.assertEqual(clone.kind, _KIND) self.assertEqual(clone.path, _PATH) + def test__clone_with_parent(self): + _DATASET = 'DATASET-ALT' + _NAMESPACE = 'NAMESPACE' + _KIND1 = 'PARENT' + _KIND2 = 'KIND' + _ID1 = 1234 + _ID2 = 2345 + _PATH = [{'kind': _KIND1, 'id': _ID1}, {'kind': _KIND2, 'id': _ID2}] + + parent = self._makeOne(_KIND1, _ID1, namespace=_NAMESPACE, + dataset_id=_DATASET) + key = self._makeOne(_KIND2, _ID2, parent=parent) + self.assertTrue(key.parent is parent) + clone = key._clone() + self.assertTrue(clone.parent is key.parent) + self.assertEqual(clone.dataset_id, _DATASET) + self.assertEqual(clone.namespace, _NAMESPACE) + self.assertEqual(clone.path, _PATH) + def test_completed_key_on_partial_w_id(self): key = self._makeOne('KIND', dataset_id=self._DEFAULT_DATASET) _ID = 1234 diff --git a/regression/datastore.py b/regression/datastore.py index 6cdef1f78e9cf..52a2739a43d1a 100644 --- a/regression/datastore.py +++ b/regression/datastore.py @@ -55,6 +55,8 @@ def test_allocate_ids(self): class TestDatastoreSave(TestDatastore): + PARENT = datastore.Key('Blog', 'PizzaMan') + def _get_post(self, id_or_name=None, post_content=None): post_content = post_content or { 'title': u'How to make the perfect pizza in your grill', @@ -66,7 +68,10 @@ def _get_post(self, id_or_name=None, post_content=None): 'rating': 5.0, } # Create an entity with the given content. - entity = datastore.Entity(key=datastore.Key('Post')) + # NOTE: Using a parent to ensure consistency for query + # in `test_empty_kind`. + key = datastore.Key('Post', parent=self.PARENT) + entity = datastore.Entity(key=key) entity.update(post_content) # Update the entity key. @@ -77,8 +82,7 @@ def _get_post(self, id_or_name=None, post_content=None): def _generic_test_post(self, name=None, key_id=None): entity = self._get_post(id_or_name=(name or key_id)) - with datastore.Transaction(): - datastore.put([entity]) + datastore.put([entity]) # Register entity to be deleted. self.case_entities_to_delete.append(entity) @@ -135,6 +139,7 @@ def test_save_multiple(self): def test_empty_kind(self): query = datastore.Query(kind='Post') + query.ancestor = self.PARENT posts = list(query.fetch(limit=2)) self.assertEqual(posts, []) @@ -142,16 +147,18 @@ def test_empty_kind(self): class TestDatastoreSaveKeys(TestDatastore): def test_save_key_self_reference(self): - key = datastore.Key('Person', 'name') + parent_key = datastore.Key('Residence', 'NewYork') + key = datastore.Key('Person', 'name', parent=parent_key) entity = datastore.Entity(key=key) entity['fullName'] = u'Full name' entity['linkedTo'] = key # Self reference. - with datastore.Transaction(): - datastore.put([entity]) + datastore.put([entity]) self.case_entities_to_delete.append(entity) query = datastore.Query(kind='Person') + # Adding ancestor to ensure consistency. + query.ancestor = parent_key query.add_filter('linkedTo', '=', key) stored_persons = list(query.fetch(limit=2))