GvRs App Engine ndb Library as well as monocle and - to my understanding - modern Javascript use Generators to make async code look like blocking code.
Things are decorated with @ndb.tasklet. They yield when they want to give back execution to the runloop and when they have their result ready they raise StopIteration(value) (or the alias ndb.Return):
@ndb.tasklet
def get_google_async():
context = ndb.get_context()
result = yield context.urlfetch("http://www.google.com/")
if result.status_code == 200:
raise ndb.Return(result.content)
raise RuntimeError
To use such a Function you get a ndb.Future object back and call the get get_result() Function on that to wait for the result and get it. E.g.:
def get_google():
future = get_google_async()
# do something else in real code here
return future.get_result()
This all works very nice. but how to add type Annotations? The correct types are:
- get_google_async() -> ndb.Future (via yield)
- ndb.tasklet(get_google_async) -> ndb.Future
- ndb.tasklet(get_google_async).get_result() -> str
So far, I came only up with casting the async function.
def get_google():
# type: () -> str
future = get_google_async()
# do something else in real code here
return cast('str', future.get_result())
Unfortunately this is not only about urlfetch but about hundreds of Methods- mainly of ndb.Model.