@@ -345,23 +345,31 @@ def _getTargetClass(self):
345345 def _makeOne (self , * args , ** kw ):
346346 return self ._getTargetClass ()(* args , ** kw )
347347
348- def _addQueryResults (self , connection , cursor = _END , more = False ):
348+ def _addQueryResults (self , connection , cursor = _END , more = False ,
349+ skipped_results = None , no_entity = False ):
349350 from gcloud .datastore ._generated import entity_pb2
350351 from gcloud .datastore ._generated import query_pb2
351352 from gcloud .datastore .helpers import _new_value_pb
352353
353- MORE = query_pb2 .QueryResultBatch .NOT_FINISHED
354- NO_MORE = query_pb2 .QueryResultBatch .MORE_RESULTS_AFTER_LIMIT
354+ if more :
355+ more_enum = query_pb2 .QueryResultBatch .NOT_FINISHED
356+ else :
357+ more_enum = query_pb2 .QueryResultBatch .MORE_RESULTS_AFTER_LIMIT
355358 _ID = 123
356- entity_pb = entity_pb2 .Entity ()
357- entity_pb .key .partition_id .project_id = self ._PROJECT
358- path_element = entity_pb .key .path .add ()
359- path_element .kind = self ._KIND
360- path_element .id = _ID
361- value_pb = _new_value_pb (entity_pb , 'foo' )
362- value_pb .string_value = u'Foo'
359+ if no_entity :
360+ entities = []
361+ else :
362+ entity_pb = entity_pb2 .Entity ()
363+ entity_pb .key .partition_id .project_id = self ._PROJECT
364+ path_element = entity_pb .key .path .add ()
365+ path_element .kind = self ._KIND
366+ path_element .id = _ID
367+ value_pb = _new_value_pb (entity_pb , 'foo' )
368+ value_pb .string_value = u'Foo'
369+ entities = [entity_pb ]
370+
363371 connection ._results .append (
364- ([ entity_pb ] , cursor , MORE if more else NO_MORE ))
372+ (entities , cursor , more_enum , skipped_results ))
365373
366374 def _makeClient (self , connection = None ):
367375 if connection is None :
@@ -374,7 +382,8 @@ def test_ctor_defaults(self):
374382 iterator = self ._makeOne (query , connection )
375383 self .assertTrue (iterator ._query is query )
376384 self .assertEqual (iterator ._limit , None )
377- self .assertEqual (iterator ._offset , 0 )
385+ self .assertEqual (iterator ._offset , None )
386+ self .assertEqual (iterator ._skipped_results , None )
378387
379388 def test_ctor_explicit (self ):
380389 client = self ._makeClient ()
@@ -392,6 +401,7 @@ def test_next_page_no_cursors_no_more(self):
392401 self ._addQueryResults (connection , cursor = b'' )
393402 iterator = self ._makeOne (query , client )
394403 entities , more_results , cursor = iterator .next_page ()
404+ self .assertEqual (iterator ._skipped_results , None )
395405
396406 self .assertEqual (cursor , None )
397407 self .assertFalse (more_results )
@@ -415,13 +425,16 @@ def test_next_page_no_cursors_no_more_w_offset_and_limit(self):
415425 connection = _Connection ()
416426 client = self ._makeClient (connection )
417427 query = _Query (client , self ._KIND , self ._PROJECT , self ._NAMESPACE )
418- self ._addQueryResults (connection , cursor = b'' )
428+ skipped_results = object ()
429+ self ._addQueryResults (connection , cursor = b'' ,
430+ skipped_results = skipped_results )
419431 iterator = self ._makeOne (query , client , 13 , 29 )
420432 entities , more_results , cursor = iterator .next_page ()
421433
422434 self .assertEqual (cursor , None )
423435 self .assertFalse (more_results )
424436 self .assertFalse (iterator ._more_results )
437+ self .assertEqual (iterator ._skipped_results , skipped_results )
425438 self .assertEqual (len (entities ), 1 )
426439 self .assertEqual (entities [0 ].key .path ,
427440 [{'kind' : self ._KIND , 'id' : self ._ID }])
@@ -453,6 +466,7 @@ def test_next_page_w_cursors_w_more(self):
453466 self .assertEqual (cursor , urlsafe_b64encode (self ._END ))
454467 self .assertTrue (more_results )
455468 self .assertTrue (iterator ._more_results )
469+ self .assertEqual (iterator ._skipped_results , None )
456470 self .assertEqual (iterator ._end_cursor , None )
457471 self .assertEqual (urlsafe_b64decode (iterator ._start_cursor ), self ._END )
458472 self .assertEqual (len (entities ), 1 )
@@ -476,8 +490,8 @@ def test_next_page_w_cursors_w_bogus_more(self):
476490 client = self ._makeClient (connection )
477491 query = _Query (client , self ._KIND , self ._PROJECT , self ._NAMESPACE )
478492 self ._addQueryResults (connection , cursor = self ._END , more = True )
479- epb , cursor , _ = connection ._results .pop ()
480- connection ._results .append ((epb , cursor , 4 )) # invalid enum
493+ epb , cursor , _ , _ = connection ._results .pop ()
494+ connection ._results .append ((epb , cursor , 5 , None )) # invalid enum
481495 iterator = self ._makeOne (query , client )
482496 self .assertRaises (ValueError , iterator .next_page )
483497
@@ -523,9 +537,7 @@ def test___iter___w_more(self):
523537 [{'kind' : self ._KIND , 'id' : self ._ID }])
524538 self .assertEqual (entities [1 ]['foo' ], u'Foo' )
525539 qpb1 = _pb_from_query (query )
526- qpb1 .offset = 0
527540 qpb2 = _pb_from_query (query )
528- qpb2 .offset = 0
529541 qpb2 .start_cursor = self ._END
530542 EXPECTED1 = {
531543 'project' : self ._PROJECT ,
@@ -543,6 +555,61 @@ def test___iter___w_more(self):
543555 self .assertEqual (connection ._called_with [0 ], EXPECTED1 )
544556 self .assertEqual (connection ._called_with [1 ], EXPECTED2 )
545557
558+ def test___iter___w_limit (self ):
559+ from gcloud .datastore .query import _pb_from_query
560+
561+ connection = _Connection ()
562+ client = self ._makeClient (connection )
563+ query = _Query (client , self ._KIND , self ._PROJECT , self ._NAMESPACE )
564+ skip1 = 4
565+ skip2 = 9
566+ self ._addQueryResults (connection , more = True , skipped_results = skip1 ,
567+ no_entity = True )
568+ self ._addQueryResults (connection , more = True , skipped_results = skip2 )
569+ self ._addQueryResults (connection )
570+ offset = skip1 + skip2
571+ iterator = self ._makeOne (query , client , limit = 2 , offset = offset )
572+ entities = list (iterator )
573+
574+ self .assertFalse (iterator ._more_results )
575+ self .assertEqual (len (entities ), 2 )
576+ for entity in entities :
577+ self .assertEqual (
578+ entity .key .path ,
579+ [{'kind' : self ._KIND , 'id' : self ._ID }])
580+ qpb1 = _pb_from_query (query )
581+ qpb1 .limit .value = 2
582+ qpb1 .offset = offset
583+ qpb2 = _pb_from_query (query )
584+ qpb2 .start_cursor = self ._END
585+ qpb2 .limit .value = 2
586+ qpb2 .offset = offset - skip1
587+ qpb3 = _pb_from_query (query )
588+ qpb3 .start_cursor = self ._END
589+ qpb3 .limit .value = 1
590+ EXPECTED1 = {
591+ 'project' : self ._PROJECT ,
592+ 'query_pb' : qpb1 ,
593+ 'namespace' : self ._NAMESPACE ,
594+ 'transaction_id' : None ,
595+ }
596+ EXPECTED2 = {
597+ 'project' : self ._PROJECT ,
598+ 'query_pb' : qpb2 ,
599+ 'namespace' : self ._NAMESPACE ,
600+ 'transaction_id' : None ,
601+ }
602+ EXPECTED3 = {
603+ 'project' : self ._PROJECT ,
604+ 'query_pb' : qpb3 ,
605+ 'namespace' : self ._NAMESPACE ,
606+ 'transaction_id' : None ,
607+ }
608+ self .assertEqual (len (connection ._called_with ), 3 )
609+ self .assertEqual (connection ._called_with [0 ], EXPECTED1 )
610+ self .assertEqual (connection ._called_with [1 ], EXPECTED2 )
611+ self .assertEqual (connection ._called_with [2 ], EXPECTED3 )
612+
546613
547614class Test__pb_from_query (unittest2 .TestCase ):
548615
0 commit comments