[Twisted-Python] inlineCallbacks yield tuple support
This example shows what i want: @defer.inlineCallbacks def create_audio_link(tel, addr1, addr2): try: connection1, connection2 = yield (tel.connect(addr1), tel.connect(addr2)) except ConnectionError, exc: ... some error work ... else: return tel.create_audiolink(connection1, connection2) At now we can do this with DeferredList but it is complex (compare with first example): @defer.inlineCallbacks def create_audio_link(tel, addr1, addr2): try: try: r = yield DeferredList([tel.connect(addr1), tel.connect(addr2)], fireOnOneErrback=1, consumeErrors=1) except FirstError, exc: raise exc.subFailure.value else: connection1, connection2 = tuple(_r for _s, _r in r) except ConnectionError, exc: ... some error work ... else: return tel.create_audiolink(connection1, connection2) Approximate solution (idea) is patch in defer.py: def _inlineCallbacks(result, g, deferred): ... skipped ... if isinstance(result, Deferred): # a deferred was yielded, get the result. ... skipped ... waiting[0] = True waiting[1] = None if isinstance(result, tuple): # a tuple was yielded, get the result. result = DeferredList(result, fireOnOneErrback=1, consumeErrors=1) def gotResult(r): if isinstance(r, failure.Failure): r = r.value.subFailure else: r = tuple(_r for _s, _r in r) if waiting[0]: waiting[0] = False waiting[1] = r else: _inlineCallbacks(r, g, deferred) result.addBoth(gotResult) if waiting[0]: # Haven't called back yet, set flag so that we get reinvoked # and return from the loop waiting[0] = False return deferred result = waiting[1] # Reset waiting to initial values for next loop. gotResult uses # waiting, but this isn't a problem because gotResult is only # executed once, and if it hasn't been executed yet, the return # branch above would have been taken. waiting[0] = True waiting[1] = None return deferred I post this as ticket but was redirected to mailing-list http://twistedmatrix.com/trac/ticket/4627
participants (1)
-
Сергей Магафуров