@@ -18,6 +18,19 @@ def wrapper(method, instance, args, kwargs):
1818 return instance .request (endpoint_url , * method (* args , ** kwargs ))
1919 return wrapper
2020
21+ def get_default_data (** kwargs ):
22+ """Returns a POST data dict using default values."""
23+ limit = kwargs .get ('limit' , 20 )
24+ offset = kwargs .get ('offset' , 0 )
25+ direction = kwargs .get ('direction' , 'asc' )
26+ if not isinstance (limit , int ):
27+ raise TypeError ("`limit` must be int" )
28+ if not isinstance (offset , int ):
29+ raise TypeError ("`offset` must be int" )
30+ if not direction in ('asc' , 'desc' ):
31+ raise ValueError ("`direction` must be one of 'asc', 'desc'" )
32+ return { 'limit' : limit , 'offset' : offset , 'direction' : direction }
33+
2134class PaginatedMethod :
2235 """Object representing a method that has a POST paginated version (with
2336 args like limit, offset, direction) as well as optionally a GET
@@ -38,12 +51,8 @@ def __call__(self, *args, **kwargs):
3851 )
3952 return self ._method (* args , ** kwargs )
4053
41- def verbose (self , * args , limit = None , offset = None , direction = None ):
42- data = {
43- 'limit' : 20 if limit is None else limit ,
44- 'offset' : 0 if offset is None else offset ,
45- 'direction' : 'asc' if direction is None else direction ,
46- }
54+ def verbose (self , * args , ** kwargs ):
55+ data = get_default_data (** kwargs )
4756 return self .__call__ (* args , data = data , __verbose = True )
4857
4958class Api (BaseApi ):
@@ -64,6 +73,49 @@ def __init__(self, *args):
6473 self .wikidotuser_revisions = PaginatedMethod (self ._wikidotuser_revisions )
6574 self .tags_pages = PaginatedMethod (self ._tags_pages , True )
6675
76+ def verbose (self , method : Callable , * args , ** kwargs ):
77+ """Returns a generator that iterates over a paginated method.
78+
79+ callable `method`: The paginated method to iterate.
80+ Remaining arguments will be passed to this method.
81+
82+
83+ Pass this function int `limit`, an initial int `offset`, and str
84+ `direction`. Each time the returned generator is called, it will
85+ increment `offset` by `limit` and return the method for the resulting
86+ set of parameters. Effectively, applied to a paginated method, this
87+ generator is the same as turning the page.
88+
89+ wiki = scuttle(domain, API_KEY, 1)
90+ generator = wiki.verbose(wiki.thread_posts, thread_id, limit=5)
91+ for posts in generator:
92+ print(len(posts)) # will be 5, except at very end
93+
94+ Note that at the end of the data, the length of the final 'page' will
95+ very likely be less than `limit`.
96+ """
97+ print ("hello!" )
98+ print (method , isinstance (method , PaginatedMethod ))
99+ if not isinstance (method , PaginatedMethod ):
100+ raise TypeError ("Iterated method must be a paginated method" )
101+ data = get_default_data (** kwargs )
102+
103+ def paginated_generator ():
104+ limit : int = data ['limit' ]
105+ length : int = limit
106+ offset : int = data ['offset' ]
107+ direction : str = data ['direction' ]
108+ while True :
109+ result = method .verbose (* args , limit = limit , offset = offset ,
110+ direction = direction )
111+ yield result
112+ if length < data ['limit' ]:
113+ return
114+ length = len (result )
115+ offset += length
116+
117+ return paginated_generator ()
118+
67119 @endpoint ("wikis" )
68120 def wikis (self ):
69121 return None , None
0 commit comments