def _help_tasklet_along(self, gen, val=None, exc=None, tb=None): # XXX Docstring info = utils.gen_info(gen) __ndb_debug__ = info try: save_context = get_context() try: set_context(self._context) if exc is not None: logging.debug('Throwing %s(%s) into %s', exc.__class__.__name__, exc, info) value = gen.throw(exc.__class__, exc, tb) else: logging.debug('Sending %r to %s', val, info) value = gen.send(val) self._context = get_context() finally: set_context(save_context) except StopIteration, err: result = get_return_value(err) logging.debug('%s returned %r', info, result) self.set_result(result) return
if isinstance(value, datastore_rpc.MultiRpc): # TODO: Tail recursion if the RPC is already complete. if len(value.rpcs) == 1: value = value.rpcs[0] # Fall through to next isinstance test. else: assert False # TODO: Support MultiRpc using MultiFuture. if isinstance(value, UserRPC): # TODO: Tail recursion if the RPC is already complete. eventloop.queue_rpc(value, self._on_rpc_completion, value, gen) return if isinstance(value, Future): # TODO: Tail recursion if the Future is already done. assert not self._next, self._next self._next = value self._geninfo = utils.gen_info(gen) logging.debug('%s is now blocked waiting for %s', self, value) value.add_callback(self._on_future_completion, value, gen) return if isinstance(value, (tuple, list)): # Arrange for yield to return a list of results (not Futures). info = 'multi-yield from ' + utils.gen_info(gen) mfut = MultiFuture(info) for subfuture in value: mfut.add_dependent(subfuture) mfut.complete() mfut.add_callback(self._on_future_completion, mfut, gen) return if is_generator(value): assert False # TODO: emulate PEP 380 here? assert False # A tasklet shouldn't yield plain values.