diff --git a/gcloud/datastore/key.py b/gcloud/datastore/key.py index 23de61356402..ea970dba3cd4 100644 --- a/gcloud/datastore/key.py +++ b/gcloud/datastore/key.py @@ -47,6 +47,7 @@ def __init__(self, path=None, namespace=None, dataset_id=None): **must** treat any value set by the back-end as opaque. """ self._path = path or [{'kind': ''}] + self._parent = None self._namespace = namespace self._dataset_id = dataset_id @@ -166,21 +167,35 @@ def dataset_id(self): """ return self._dataset_id + def _make_parent(self): + """Creates a parent key for the current path. + + Extracts all but the last element in the key path and creates a new + key, while still matching the namespace and the dataset ID. + + :rtype: :class:`gcloud.datastore.key.Key` or `NoneType` + :returns: a new `Key` instance, whose path consists of all but the last + element of self's path. If self has only one path element, + returns None. + """ + parent_path = self.path[:-1] + if parent_path: + return Key(path=parent_path, dataset_id=self.dataset_id, + namespace=self.namespace) + @property def parent(self): """Getter: return a new key for the next highest element in path. - :rtype: :class:`gcloud.datastore.key.Key` + :rtype: :class:`gcloud.datastore.key.Key` or `NoneType` :returns: a new `Key` instance, whose path consists of all but the last element of self's path. If self has only one path element, returns None. """ - if len(self._path) <= 1: - return None - # This is temporary. Will be addressed throughout #451. - clone = self._clone() - clone._path = self.path[:-1] - return clone + if self._parent is None: + self._parent = self._make_parent() + + return self._parent def __repr__(self): return '' % self.path diff --git a/gcloud/datastore/test_key.py b/gcloud/datastore/test_key.py index c5922241065f..46e01f397511 100644 --- a/gcloud/datastore/test_key.py +++ b/gcloud/datastore/test_key.py @@ -186,3 +186,14 @@ def test_parent_explicit_nested(self): {'kind': 'ghi', 'id': 123}, ]) self.assertEqual(key.parent.path, [parent_part]) + + def test_parent_multiple_calls(self): + _PARENT_KIND = 'KIND1' + _PARENT_ID = 1234 + _PARENT_PATH = {'kind': _PARENT_KIND, 'id': _PARENT_ID} + _PATH = [_PARENT_PATH, {'kind': 'KIND2'}] + key = self._makeOne(path=_PATH) + parent = key.parent + self.assertEqual(parent.path, [_PARENT_PATH]) + new_parent = key.parent + self.assertTrue(parent is new_parent)