Skip to content

Commit 1c1333e

Browse files
committed
Made kind take and return a single string and change more_results.
Incorporates feedback from @pcostell. In particular, treats `NOT_FINISHED` as the only enum that needs `more_results=True` and both `NO_MORE_RESULTS` and `MORE_RESULTS_AFTER_LIMIT` as responses which don't need paging.
1 parent 78d0dde commit 1c1333e

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

gcloud/datastore/query.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ class Query(object):
5656
:param dataset: The namespace to which to restrict results.
5757
"""
5858

59-
_MORE_RESULTS = datastore_pb.QueryResultBatch.MORE_RESULTS_AFTER_LIMIT
60-
_NO_MORE_RESULTS = datastore_pb.QueryResultBatch.NO_MORE_RESULTS
59+
_NOT_FINISHED = datastore_pb.QueryResultBatch.NOT_FINISHED
60+
_FINISHED = (
61+
datastore_pb.QueryResultBatch.NO_MORE_RESULTS,
62+
datastore_pb.QueryResultBatch.MORE_RESULTS_AFTER_LIMIT,
63+
)
6164
OPERATORS = {
6265
'<=': datastore_pb.PropertyFilter.LESS_THAN_OR_EQUAL,
6366
'>=': datastore_pb.PropertyFilter.GREATER_THAN_OR_EQUAL,
@@ -227,26 +230,24 @@ def ancestor(self, ancestor):
227230

228231
return clone
229232

230-
def kind(self, *kinds):
233+
def kind(self, kind=None):
231234
"""Get or set the Kind of the Query.
232235
233-
.. note::
234-
This is an **additive** operation. That is, if the Query is
235-
set for kinds A and B, and you call ``.kind('C')``, it will
236-
query for kinds A, B, *and*, C.
236+
:type kind: string
237+
:param kind: Optional. The entity kinds for which to query.
237238
238-
:type kinds: string
239-
:param kinds: The entity kinds for which to query.
240-
241-
:rtype: string, list of strings, or :class:`Query`
242-
:returns: If no arguments, returns the kind or list of kinds.
243-
If a kind is provided, returns a clone of the :class:`Query`
244-
with those kinds set.
239+
:rtype: string or :class:`Query`
240+
:returns: If `kind` is None, returns the kind. If a kind is provided,
241+
returns a clone of the :class:`Query` with that kind set.
242+
:raises: `ValueError` from the getter if multiple kinds are set on
243+
the query.
245244
"""
246-
if kinds:
245+
if kind is not None:
246+
kinds = [kind]
247247
clone = self._clone()
248-
for kind in kinds:
249-
clone._pb.kind.add().name = kind
248+
clone._pb.ClearField('kind')
249+
for new_kind in kinds:
250+
clone._pb.kind.add().name = new_kind
250251
return clone
251252
else:
252253
# In the proto definition for Query, `kind` is repeated.
@@ -255,7 +256,7 @@ def kind(self, *kinds):
255256
if num_kinds == 1:
256257
return kind_names[0]
257258
elif num_kinds > 1:
258-
return kind_names
259+
raise ValueError('Only a single kind can be set.')
259260

260261
def limit(self, limit=None):
261262
"""Get or set the limit of the Query.
@@ -343,7 +344,7 @@ def fetch_page(self, limit=None):
343344
encoded cursor for paging and the third is a boolean
344345
indicating if there are more results.
345346
:raises: `ValueError` if more_results is not one of the enums
346-
MORE_RESULTS_AFTER_LIMIT or NO_MORE_RESULTS.
347+
NOT_FINISHED, MORE_RESULTS_AFTER_LIMIT, NO_MORE_RESULTS.
347348
"""
348349
clone = self
349350

@@ -372,13 +373,11 @@ def fetch_page(self, limit=None):
372373

373374
cursor = base64.b64encode(cursor_as_bytes)
374375

375-
if more_results_enum == self._MORE_RESULTS:
376+
if more_results_enum == self._NOT_FINISHED:
376377
more_results = True
377-
elif more_results_enum == self._NO_MORE_RESULTS:
378+
elif more_results_enum in self._FINISHED:
378379
more_results = False
379380
else:
380-
# Note this covers the value NOT_FINISHED since this fetch does
381-
# not occur within a batch, we don't expect to see NOT_FINISHED.
382381
raise ValueError('Unexpected value returned for `more_results`.')
383382

384383
return entities, cursor, more_results

gcloud/datastore/test_query.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,22 @@ def test_kind_setter_w_existing(self):
261261
_KIND_AFTER = 'KIND_AFTER'
262262
dataset = Dataset(_DATASET)
263263
query = self._makeOne(_KIND_BEFORE, dataset)
264+
self.assertEqual(query.kind(), _KIND_BEFORE)
264265
after = query.kind(_KIND_AFTER)
265266
self.assertFalse(after is query)
266267
self.assertTrue(isinstance(after, self._getTargetClass()))
267268
self.assertTrue(after.dataset() is dataset)
268-
self.assertEqual(after.kind(), [_KIND_BEFORE, _KIND_AFTER])
269+
self.assertEqual(after.kind(), _KIND_AFTER)
270+
271+
def test_kind_getter_unset(self):
272+
query = self._makeOne()
273+
self.assertEqual(query.kind(), None)
274+
275+
def test_kind_getter_bad_pb(self):
276+
query = self._makeOne()
277+
query._pb.kind.add().name = 'foo'
278+
query._pb.kind.add().name = 'bar'
279+
self.assertRaises(ValueError, query.kind)
269280

270281
def test_limit_setter_wo_existing(self):
271282
from gcloud.datastore.dataset import Dataset
@@ -293,8 +304,9 @@ def test_dataset_setter(self):
293304
self.assertTrue(after.dataset() is dataset)
294305
self.assertEqual(query.kind(), _KIND)
295306

296-
def _fetch_page_helper(self, cursor=b'\x00', limit=None, more_results=True,
297-
_more_pb=None, use_fetch=False):
307+
def _fetch_page_helper(self, cursor=b'\x00', limit=None,
308+
more_results=False, _more_pb=None,
309+
use_fetch=False):
298310
import base64
299311
from gcloud.datastore.datastore_v1_pb2 import Entity
300312
_CURSOR_FOR_USER = (None if cursor is None
@@ -351,16 +363,14 @@ def test_fetch_page_explicit_limit(self):
351363
def test_fetch_page_no_more_results(self):
352364
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
353365
no_more = datastore_pb.QueryResultBatch.NO_MORE_RESULTS
354-
self._fetch_page_helper(cursor='CURSOR', limit=13, more_results=False,
355-
_more_pb=no_more)
366+
self._fetch_page_helper(cursor='CURSOR', limit=13, _more_pb=no_more)
356367

357-
def test_fetch_page_more_results_ill_formed(self):
368+
def test_fetch_page_not_finished(self):
358369
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
359370
not_finished = datastore_pb.QueryResultBatch.NOT_FINISHED
360-
# Try a valid enum but not allowed.
361-
self.assertRaises(ValueError, self._fetch_page_helper,
362-
_more_pb=not_finished)
363-
# Try an invalid enum but not allowed.
371+
self._fetch_page_helper(_more_pb=not_finished, more_results=True)
372+
373+
def test_fetch_page_more_results_invalid(self):
364374
self.assertRaises(ValueError, self._fetch_page_helper,
365375
_more_pb=object())
366376

0 commit comments

Comments
 (0)