11# Size of a single page in a paginated query.
22from abc import ABC , abstractmethod
3- from typing import Any , Callable , Dict , List , Optional
3+ from typing import Any , Callable , Dict , List , Optional , Tuple , Type
44
55from typing import TYPE_CHECKING
66if TYPE_CHECKING :
@@ -24,9 +24,9 @@ def __init__(self,
2424 query : str ,
2525 params : Dict [str , str ],
2626 dereferencing : Dict [str , Any ],
27- obj_class : "DbObject" ,
27+ obj_class : Type [ "DbObject" ] ,
2828 cursor_path : Optional [Dict [str , Any ]] = None ,
29- beta : bool = False ):
29+ experimental : bool = False ):
3030 """ Creates a PaginatedCollection.
3131
3232 Args:
@@ -43,98 +43,117 @@ def __init__(self,
4343 cursor_path: If not None, this is used to find the cursor
4444 experimental: Used to call experimental endpoints
4545 """
46- self .client = client
47- self .query = query
48- self .params = params
49- self .dereferencing = dereferencing
50- self .obj_class = obj_class
51- self .cursor_path = cursor_path
52- self .beta = beta
53-
5446 self ._fetched_all = False
5547 self ._data : List [Dict [str , Any ]] = []
5648 self ._data_ind = 0
5749
50+ pagination_kwargs = {
51+ 'client' : client ,
52+ 'obj_class' : obj_class ,
53+ 'dereferencing' : dereferencing ,
54+ 'experimental' : experimental ,
55+ 'query' : query ,
56+ 'params' : params
57+ }
58+
5859 self .paginator = _CursorPagination (
59- client , cursor_path ) if cursor_path else _OffsetPagination (client )
60+ cursor_path , **
61+ pagination_kwargs ) if cursor_path else _OffsetPagination (
62+ ** pagination_kwargs )
6063
6164 def __iter__ (self ):
6265 self ._data_ind = 0
6366 return self
6467
65- def get_page_data (self , results ):
66- for deref in self .dereferencing :
67- results = results [deref ]
68- return [self .obj_class (self .client , result ) for result in results ]
69-
7068 def __next__ (self ):
7169 if len (self ._data ) <= self ._data_ind :
7270 if self ._fetched_all :
7371 raise StopIteration ()
7472
75- results = self .paginator .fetch_results (self .query , self .params ,
76- self .beta )
77- page_data = self .get_page_data (results )
73+ page_data , self ._fetched_all = self .paginator .get_next_page ()
7874 self ._data .extend (page_data )
79- n_items = len (page_data )
80-
81- if n_items == 0 :
75+ if len (page_data ) == 0 :
8276 raise StopIteration ()
8377
84- self ._fetched_all = self .paginator .fetched_all (n_items , results )
85-
8678 rval = self ._data [self ._data_ind ]
8779 self ._data_ind += 1
8880 return rval
8981
9082
9183class _Pagination (ABC ):
9284
93- @abstractmethod
94- def fetched_all (self , n_items : int , results : List [Dict [str , Any ]]) -> bool :
95- ...
85+ def __init__ (self , client : "Client" , obj_class : Type ["DbObject" ],
86+ dereferencing : Dict [str , Any ], query : str ,
87+ params : Dict [str , Any ], experimental : bool ):
88+ self .client = client
89+ self .obj_class = obj_class
90+ self .dereferencing = dereferencing
91+ self .experimental = experimental
92+ self .query = query
93+ self .params = params
94+
95+ def get_page_data (self , results : Dict [str , Any ]) -> List ["DbObject" ]:
96+ for deref in self .dereferencing :
97+ results = results [deref ]
98+ return [self .obj_class (self .client , result ) for result in results ]
9699
97100 @abstractmethod
98- def fetch_results (self , query : str , params : Dict [str , Any ],
99- beta : bool ) -> Dict [str , Any ]:
101+ def get_next_page (self ) -> Tuple [Dict [str , Any ], bool ]:
100102 ...
101103
102104
103105class _CursorPagination (_Pagination ):
104106
105- def __init__ (self , client : "Client" , cursor_path : Dict [str , Any ]):
106- self . client = client
107+ def __init__ (self , cursor_path : Dict [str , Any ], * args , ** kwargs ):
108+ super (). __init__ ( * args , ** kwargs )
107109 self .cursor_path = cursor_path
108- self .next_cursor : Optional [str ] = None
110+ self .next_cursor : Optional [Any ] = None
109111
110- def get_next_cursor (self , results ) -> Optional [str ] :
112+ def increment_page (self , results : Dict [str , Any ]) :
111113 for path in self .cursor_path :
112114 results = results [path ]
113- return results
115+ self . next_cursor = results
114116
115- def fetched_all (self , n_items : int , results : List [Dict [str , Any ]]) -> bool :
116- self .next_cursor = self .get_next_cursor (results )
117- return bool (self .next_cursor is None )
117+ def fetched_all (self ) -> bool :
118+ return bool (self .next_cursor )
118119
119- def fetch_results (self , query : str , params : Dict [str , Any ],
120- beta : bool ) -> Dict [str , Any ]:
121- params .update ({'from' : self .next_cursor , 'first' : _PAGE_SIZE })
122- return self .client .execute (query , params , beta = beta )
120+ def fetch_results (self ) -> Dict [str , Any ]:
121+ self .params .update ({'from' : self .next_cursor , 'first' : _PAGE_SIZE })
122+ return self .client .execute (self .query ,
123+ self .params ,
124+ experimental = self .experimental )
125+
126+ def get_next_page (self ):
127+ results = self .fetch_results ()
128+ page_data = self .get_page_data (results )
129+ self .increment_page (results )
130+ done = self .fetched_all ()
131+ return page_data , done
123132
124133
125134class _OffsetPagination (_Pagination ):
126135
127- def __init__ (self , client : "Client" ):
128- self . client = client
136+ def __init__ (self , * args , ** kwargs ):
137+ super (). __init__ ( * args , ** kwargs )
129138 self ._fetched_pages = 0
130139
131- def fetched_all (self , n_items : int , results : List [ Dict [ str , Any ]]) -> bool :
140+ def increment_page (self ) :
132141 self ._fetched_pages += 1
142+
143+ def fetched_all (self , n_items : int ) -> bool :
133144 if n_items < _PAGE_SIZE :
134145 return True
135146 return False
136147
137- def fetch_results (self , query : str , params : Dict [str , Any ],
138- beta : bool ) -> Dict [str , Any ]:
139- query = query % (self ._fetched_pages * _PAGE_SIZE , _PAGE_SIZE )
140- return self .client .execute (query , params , beta = beta )
148+ def fetch_results (self ) -> Dict [str , Any ]:
149+ query = self .query % (self ._fetched_pages * _PAGE_SIZE , _PAGE_SIZE )
150+ return self .client .execute (query ,
151+ self .params ,
152+ experimental = self .experimental )
153+
154+ def get_next_page (self ):
155+ results = self .fetch_results ()
156+ page_data = self .get_page_data (results )
157+ self .increment_page ()
158+ done = self .fetched_all (len (page_data ))
159+ return page_data , done
0 commit comments