Skip to content

Commit fe7e7bf

Browse files
committed
Merge pull request #456 from dhermes/fix-451-part1
Address first part of 451: Remove Key.from_path
2 parents 563a19f + bd71dc6 commit fe7e7bf

File tree

9 files changed

+36
-167
lines changed

9 files changed

+36
-167
lines changed

gcloud/datastore/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def get_entity(key):
145145
:param key: The name of the item to retrieve.
146146
147147
:rtype: :class:`gcloud.datastore.entity.Entity` or ``None``
148-
:return: The requested entity, or ``None`` if there was no match found.
148+
:returns: The requested entity, or ``None`` if there was no match found.
149149
"""
150150
return _require_dataset().get_entity(key)
151151

@@ -157,7 +157,7 @@ def get_entities(keys):
157157
:param keys: The name of the item to retrieve.
158158
159159
:rtype: list of :class:`gcloud.datastore.entity.Entity`
160-
:return: The requested entities.
160+
:returns: The requested entities.
161161
"""
162162
return _require_dataset().get_entities(keys)
163163

@@ -172,6 +172,6 @@ def allocate_ids(incomplete_key, num_ids):
172172
:param num_ids: The number of IDs to allocate.
173173
174174
:rtype: list of :class:`gcloud.datastore.key.Key`
175-
:return: The (complete) keys allocated with `incomplete_key` as root.
175+
:returns: The (complete) keys allocated with `incomplete_key` as root.
176176
"""
177177
return _require_dataset().allocate_ids(incomplete_key, num_ids)

gcloud/datastore/dataset.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from gcloud.datastore.entity import Entity
1919
from gcloud.datastore.query import Query
2020
from gcloud.datastore.transaction import Transaction
21-
from gcloud.datastore.key import Key
2221

2322

2423
class Dataset(object):
@@ -118,26 +117,17 @@ def transaction(self, *args, **kwargs):
118117
kwargs['dataset'] = self
119118
return Transaction(*args, **kwargs)
120119

121-
def get_entity(self, key_or_path):
120+
def get_entity(self, key):
122121
"""Retrieves entity from the dataset, along with its attributes.
123122
124-
:type key_or_path: :class:`gcloud.datastore.key.Key` or path
125-
:param key_or_path: The name of the item to retrieve or sequence
126-
of even length, where the first of each pair
127-
is a string representing the 'kind' of the
128-
path element, and the second of the pair is
129-
either a string (for the path element's name)
130-
or an integer (for its id).
123+
:type key: :class:`gcloud.datastore.key.Key` or path
124+
:param key: The key of the entity to be retrieved.
131125
132-
:rtype: :class:`gcloud.datastore.entity.Entity` or ``None``
133-
:return: The requested entity, or ``None`` if there was no match found.
126+
:rtype: :class:`gcloud.datastore.entity.Entity` or `NoneType`
127+
:returns: The requested entity, or ``None`` if there was no
128+
match found.
134129
"""
135-
136-
if isinstance(key_or_path, Key):
137-
entities = self.get_entities([key_or_path])
138-
else:
139-
key = Key.from_path(*key_or_path)
140-
entities = self.get_entities([key])
130+
entities = self.get_entities([key])
141131

142132
if entities:
143133
return entities[0]
@@ -159,7 +149,7 @@ def get_entities(self, keys, missing=None, deferred=None):
159149
Use only as a keyword param.
160150
161151
:rtype: list of :class:`gcloud.datastore.entity.Entity`
162-
:return: The requested entities.
152+
:returns: The requested entities.
163153
"""
164154
entity_pbs = self.connection().lookup(
165155
dataset_id=self.id(),
@@ -193,7 +183,7 @@ def allocate_ids(self, incomplete_key, num_ids):
193183
:param num_ids: The number of IDs to allocate.
194184
195185
:rtype: list of :class:`gcloud.datastore.key.Key`
196-
:return: The (complete) keys allocated with `incomplete_key` as root.
186+
:returns: The (complete) keys allocated with `incomplete_key` as root.
197187
:raises: `ValueError` if `incomplete_key` is not a partial key.
198188
"""
199189
if not incomplete_key.is_partial():

gcloud/datastore/key.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
"""Create / interact with gcloud datastore keys."""
1616

1717
import copy
18-
from itertools import izip
19-
20-
import six
2118

2219
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
2320

@@ -90,40 +87,6 @@ def to_protobuf(self):
9087

9188
return key
9289

93-
@classmethod
94-
def from_path(cls, *args, **kwargs):
95-
"""Factory method for creating a key based on a path.
96-
97-
:type args: :class:`tuple`
98-
:param args: sequence of even length, where the first of each pair is a
99-
string representing the 'kind' of the path element, and
100-
the second of the pair is either a string (for the path
101-
element's name) or an integer (for its id).
102-
103-
:type kwargs: :class:`dict`
104-
:param kwargs: Other named parameters which can be passed to
105-
:func:`Key.__init__`.
106-
107-
:rtype: :class:`gcloud.datastore.key.Key`
108-
:returns: a new :class:`Key` instance
109-
"""
110-
if len(args) % 2:
111-
raise ValueError('Must pass an even number of args.')
112-
113-
path = []
114-
items = iter(args)
115-
116-
for kind, id_or_name in izip(items, items):
117-
entry = {'kind': kind}
118-
if isinstance(id_or_name, six.string_types):
119-
entry['name'] = id_or_name
120-
else:
121-
entry['id'] = id_or_name
122-
path.append(entry)
123-
124-
kwargs['path'] = path
125-
return cls(**kwargs)
126-
12790
def is_partial(self):
12891
"""Boolean test: is the key fully mapped onto a backend entity?
12992

gcloud/datastore/query.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -172,22 +172,15 @@ def ancestor(self, ancestor):
172172
This will return a clone of the current :class:`Query` filtered
173173
by the ancestor provided. For example::
174174
175-
>>> parent_key = Key.from_path('Person', '1')
175+
>>> parent_key = Key(path=[{'kind': 'Person', 'name': '1'}])
176176
>>> query = dataset.query('Person')
177177
>>> filtered_query = query.ancestor(parent_key)
178178
179-
If you don't have a :class:`gcloud.datastore.key.Key` but just
180-
know the path, you can provide that as well::
181-
182-
>>> query = dataset.query('Person')
183-
>>> filtered_query = query.ancestor(['Person', '1'])
184-
185179
Each call to ``.ancestor()`` returns a cloned :class:`Query`,
186180
however a query may only have one ancestor at a time.
187181
188-
:type ancestor: :class:`gcloud.datastore.key.Key` or list
189-
:param ancestor: Either a Key or a path of the form
190-
``['Kind', 'id or name', 'Kind', 'id or name', ...]``.
182+
:type ancestor: :class:`gcloud.datastore.key.Key`
183+
:param ancestor: A Key to an entity
191184
192185
:rtype: :class:`Query`
193186
:returns: A Query filtered by the ancestor provided.
@@ -211,13 +204,9 @@ def ancestor(self, ancestor):
211204
if not ancestor:
212205
return clone
213206

214-
# If a list was provided, turn it into a Key.
215-
if isinstance(ancestor, list):
216-
ancestor = Key.from_path(*ancestor)
217-
218207
# If we don't have a Key value by now, something is wrong.
219208
if not isinstance(ancestor, Key):
220-
raise TypeError('Expected list or Key, got %s.' % type(ancestor))
209+
raise TypeError('Expected Key, got %s.' % type(ancestor))
221210

222211
# Get the composite filter and add a new property filter.
223212
composite_filter = clone._pb.filter.composite_filter

gcloud/datastore/test_dataset.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -109,39 +109,6 @@ def test_get_entity_hit(self):
109109
self.assertEqual(list(result), ['foo'])
110110
self.assertEqual(result['foo'], 'Foo')
111111

112-
def test_get_entity_path(self):
113-
from gcloud.datastore.connection import datastore_pb
114-
DATASET_ID = 'DATASET'
115-
KIND = 'Kind'
116-
ID = 1234
117-
PATH = [{'kind': KIND, 'id': ID}]
118-
entity_pb = datastore_pb.Entity()
119-
entity_pb.key.partition_id.dataset_id = DATASET_ID
120-
path_element = entity_pb.key.path_element.add()
121-
path_element.kind = KIND
122-
path_element.id = ID
123-
prop = entity_pb.property.add()
124-
prop.name = 'foo'
125-
prop.value.string_value = 'Foo'
126-
connection = _Connection(entity_pb)
127-
dataset = self._makeOne(DATASET_ID, connection)
128-
result = dataset.get_entity([KIND, ID])
129-
key = result.key()
130-
self.assertEqual(key._dataset_id, DATASET_ID)
131-
self.assertEqual(key.path(), PATH)
132-
self.assertEqual(list(result), ['foo'])
133-
self.assertEqual(result['foo'], 'Foo')
134-
135-
def test_get_entity_odd_nonetype(self):
136-
DATASET_ID = 'DATASET'
137-
KIND = 'Kind'
138-
connection = _Connection()
139-
dataset = self._makeOne(DATASET_ID, connection)
140-
with self.assertRaises(ValueError):
141-
dataset.get_entity([KIND])
142-
with self.assertRaises(TypeError):
143-
dataset.get_entity(None)
144-
145112
def test_get_entities_miss(self):
146113
from gcloud.datastore.key import Key
147114
DATASET_ID = 'DATASET'

gcloud/datastore/test_key.py

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -102,39 +102,6 @@ def test_to_protobuf_w_explicit_path(self):
102102
self.assertEqual(elems[2].name, '')
103103
self.assertEqual(elems[2].id, 0)
104104

105-
def test_from_path_empty(self):
106-
key = self._getTargetClass().from_path()
107-
self.assertEqual(key._dataset_id, None)
108-
self.assertEqual(key.namespace(), None)
109-
self.assertEqual(key.kind(), '')
110-
self.assertEqual(key.path(), [{'kind': ''}])
111-
112-
def test_from_path_single_element(self):
113-
self.assertRaises(ValueError, self._getTargetClass().from_path, 'abc')
114-
115-
def test_from_path_three_elements(self):
116-
self.assertRaises(ValueError, self._getTargetClass().from_path,
117-
'abc', 'def', 'ghi')
118-
119-
def test_from_path_two_elements_second_string(self):
120-
key = self._getTargetClass().from_path('abc', 'def')
121-
self.assertEqual(key.kind(), 'abc')
122-
self.assertEqual(key.path(), [{'kind': 'abc', 'name': 'def'}])
123-
124-
def test_from_path_two_elements_second_int(self):
125-
key = self._getTargetClass().from_path('abc', 123)
126-
self.assertEqual(key.kind(), 'abc')
127-
self.assertEqual(key.path(), [{'kind': 'abc', 'id': 123}])
128-
129-
def test_from_path_nested(self):
130-
key = self._getTargetClass().from_path('abc', 'def', 'ghi', 123)
131-
self.assertEqual(key.kind(), 'ghi')
132-
expected_path = [
133-
{'kind': 'abc', 'name': 'def'},
134-
{'kind': 'ghi', 'id': 123},
135-
]
136-
self.assertEqual(key.path(), expected_path)
137-
138105
def test_is_partial_no_name_or_id(self):
139106
key = self._makeOne()
140107
self.assertTrue(key.is_partial())
@@ -282,9 +249,13 @@ def test_parent_default(self):
282249
self.assertEqual(key.parent(), None)
283250

284251
def test_parent_explicit_top_level(self):
285-
key = self._getTargetClass().from_path('abc', 'def')
252+
key = self._makeOne(path=[{'kind': 'abc', 'name': 'def'}])
286253
self.assertEqual(key.parent(), None)
287254

288255
def test_parent_explicit_nested(self):
289-
key = self._getTargetClass().from_path('abc', 'def', 'ghi', 123)
290-
self.assertEqual(key.parent().path(), [{'kind': 'abc', 'name': 'def'}])
256+
parent_part = {'kind': 'abc', 'name': 'def'}
257+
key = self._makeOne(path=[
258+
parent_part,
259+
{'kind': 'ghi', 'id': 123},
260+
])
261+
self.assertEqual(key.parent().path(), [parent_part])

gcloud/datastore/test_query.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ def test_filter_w_whitespace_property_name(self):
168168
self.assertEqual(p_pb.value.string_value, u'John')
169169
self.assertEqual(p_pb.operator, datastore_pb.PropertyFilter.EQUAL)
170170

171-
def test_ancestor_w_non_key_non_list(self):
171+
def test_ancestor_w_non_key(self):
172172
query = self._makeOne()
173173
self.assertRaises(TypeError, query.ancestor, object())
174+
self.assertRaises(TypeError, query.ancestor, ['KIND', 'NAME'])
174175

175176
def test_ancestor_wo_existing_ancestor_query_w_key_and_propfilter(self):
176177
from gcloud.datastore.key import Key
@@ -208,39 +209,27 @@ def test_ancestor_wo_existing_ancestor_query_w_key(self):
208209
self.assertEqual(p_pb.property.name, '__key__')
209210
self.assertEqual(p_pb.value.key_value, key.to_protobuf())
210211

211-
def test_ancestor_wo_existing_ancestor_query_w_list(self):
212+
def test_ancestor_clears_existing_ancestor_query_w_only(self):
212213
from gcloud.datastore.key import Key
213214
_KIND = 'KIND'
214215
_ID = 123
215216
key = Key(path=[{'kind': _KIND, 'id': _ID}])
216217
query = self._makeOne()
217-
after = query.ancestor([_KIND, _ID])
218-
self.assertFalse(after is query)
219-
self.assertTrue(isinstance(after, self._getTargetClass()))
220-
q_pb = after.to_protobuf()
221-
self.assertEqual(q_pb.filter.composite_filter.operator, 1) # AND
222-
f_pb, = list(q_pb.filter.composite_filter.filter)
223-
p_pb = f_pb.property_filter
224-
self.assertEqual(p_pb.property.name, '__key__')
225-
self.assertEqual(p_pb.value.key_value, key.to_protobuf())
226-
227-
def test_ancestor_clears_existing_ancestor_query_w_only(self):
228-
_KIND = 'KIND'
229-
_ID = 123
230-
query = self._makeOne()
231-
between = query.ancestor([_KIND, _ID])
218+
between = query.ancestor(key)
232219
after = between.ancestor(None)
233220
self.assertFalse(after is query)
234221
self.assertTrue(isinstance(after, self._getTargetClass()))
235222
q_pb = after.to_protobuf()
236223
self.assertEqual(list(q_pb.filter.composite_filter.filter), [])
237224

238225
def test_ancestor_clears_existing_ancestor_query_w_others(self):
226+
from gcloud.datastore.key import Key
239227
_KIND = 'KIND'
240228
_ID = 123
241229
_NAME = u'NAME'
230+
key = Key(path=[{'kind': _KIND, 'id': _ID}])
242231
query = self._makeOne().filter('name', '=', _NAME)
243-
between = query.ancestor([_KIND, _ID])
232+
between = query.ancestor(key)
244233
after = between.ancestor(None)
245234
self.assertFalse(after is query)
246235
self.assertTrue(isinstance(after, self._getTargetClass()))

pylintrc_default

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PyLint config for 'gcloud' *library* code.
1+
# PyLint config for 'gcloud' *library* code.
22
#
33
# NOTES:
44
#
@@ -65,14 +65,14 @@ ignore =
6565
# DEFAULT: disable=
6666
# RATIONALE:
6767
# - maybe-no-member: bi-modal functions confuse pylint type inference.
68-
# - no-member: indirections in protobuf-generated code
68+
# - no-member: indirections in protobuf-generated code
6969
# - protected-access: helpers use '_foo' of classes from generated code.
7070
# - redefined-builtin: use of 'id', 'type', 'filter' args in API-bound funcs;
7171
# use of 'NotImplemented' to map HTTP response code.
7272
# - similarities: 'Bucket' and 'Key' define 'metageneration' and 'owner' with
7373
# identical implementation but different docstrings.
7474
# - star-args: standard Python idioms for varargs:
75-
# ancestor = Key.from_path(*ancestor)
75+
# ancestor = Query().filter(*order_props)
7676
disable =
7777
maybe-no-member,
7878
no-member,
@@ -201,7 +201,7 @@ max-module-lines=1500
201201

202202
# Good variable names which should always be accepted, separated by a comma
203203
# DEFAULT: good-names=i,j,k,ex,Run,_
204-
# RATIONALE: 'pb' and 'id' have well-understood meainings in the code.
204+
# RATIONALE: 'pb' and 'id' have well-understood meainings in the code.
205205
good-names = i, j, k, ex, Run, _,
206206
pb,
207207
id,

regression/datastore.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def test_empty_kind(self):
146146
class TestDatastoreSaveKeys(TestDatastore):
147147

148148
def test_save_key_self_reference(self):
149-
key = datastore.key.Key.from_path('Person', 'name')
149+
key = datastore.key.Key(path=[{'kind': 'Person', 'name': 'name'}])
150150
entity = datastore.entity.Entity(kind=None).key(key)
151151
entity['fullName'] = u'Full name'
152152
entity['linkedTo'] = key # Self reference.
@@ -337,7 +337,7 @@ def test_query_group_by(self):
337337
class TestDatastoreTransaction(TestDatastore):
338338

339339
def test_transaction(self):
340-
key = datastore.key.Key.from_path('Company', 'Google')
340+
key = datastore.key.Key(path=[{'kind': 'Company', 'name': 'Google'}])
341341
entity = datastore.entity.Entity(kind=None).key(key)
342342
entity['url'] = u'www.google.com'
343343

0 commit comments

Comments
 (0)