@@ -197,6 +197,7 @@ def initiate_device_flow(self, scope=None, timeout=None, **kwargs):
197197 ** kwargs ).json ()
198198 flow ["interval" ] = int (flow .get ("interval" , 5 )) # Some IdP returns string
199199 flow ["expires_in" ] = int (flow .get ("expires_in" , 1800 ))
200+ flow ["expires_at" ] = time .time () + flow ["expires_in" ] # We invent this
200201 return flow
201202
202203 def _obtain_token_by_device_flow (self , flow , ** kwargs ):
@@ -219,25 +220,41 @@ def _obtain_token_by_device_flow(self, flow, **kwargs):
219220 flow ["latest_attempt_at" ] = now
220221 return result
221222
222- def obtain_token_by_device_flow (self , flow , exit_condition = lambda : True , ** kwargs ):
223+ def obtain_token_by_device_flow (self ,
224+ flow ,
225+ exit_condition = lambda flow : flow .get ("expires_at" , 0 ) < time .time (),
226+ ** kwargs ):
223227 # type: (dict, Callable) -> dict
224- """Obtain token by a device flow object, with optional polling effect.
228+ """Obtain token by a device flow object, with customizable polling effect.
225229
226230 Args:
227231 flow (dict):
228232 An object previously generated by initiate_device_flow(...).
233+ Its content WILL BE CHANGED by this method during each run.
234+ We share this object with you, so that you could implement
235+ your own loop, should you choose to do so.
236+
229237 exit_condition (Callable):
230238 This method implements a loop to provide polling effect.
231239 The loop's exit condition is calculated by this callback.
232- The default callback makes the loop run only once, i.e. no polling.
240+
241+ The default callback makes the loop run until the flow expires.
242+ Therefore, one of the ways to exit the polling early,
243+ is to change the flow["expires_at"] to a small number such as 0.
244+
245+ In case you are doing async programming, you may want to
246+ completely turn off the loop. You can do so by using a callback as:
247+
248+ exit_condition = lambda flow: True
249+
250+ to make the loop run only once, i.e. no polling, hence non-block.
233251 """
234- _flow = flow .copy ()
235252 while True :
236- result = self ._obtain_token_by_device_flow (_flow , ** kwargs )
253+ result = self ._obtain_token_by_device_flow (flow , ** kwargs )
237254 if result .get ("error" ) not in self .DEVICE_FLOW_RETRIABLE_ERRORS :
238255 return result
239- for i in range (_flow .get ("interval" , 5 )): # Wait interval seconds
240- if exit_condition ():
256+ for i in range (flow .get ("interval" , 5 )): # Wait interval seconds
257+ if exit_condition (flow ):
241258 return result
242259 time .sleep (1 ) # Shorten each round, to make exit more responsive
243260
0 commit comments