[Twisted-Python] Giving inlineCallbacks-wrapped functions access to the deferred their wrapper will return

This will probably fall into the too-weird or too-infrequent to be worth implementing category, but I think it's worth mentioning. (BTW, none of the following code has been run.) When you write a normal function that returns a deferred, it (of course) has access to the deferred it's going to return: def func(): d = defer.Deferred() d.addCallback(...).addErrback(...) callSomethingElse(d) return d Apart from operating on the deferred itself, func can pass the deferred to some other function that might add more callbacks (as in the call to callSomethingElse). That's all very nice and convenient. But if I write this: @defer.inlineCallbacks def func(): # do some stuff to calculate a result. defer.returnValue(result) func never has its hands on the deferred that will be returned (by _inlineCallbacks) to the caller of its wrapper. I can get around this in ways that are less elegant: @defer.inlineCallbacks def func(): # do some stuff d = defer.Deferred() callSomethingElse(d) d.callback(result) newResult = yield d defer.returnValue(newResult) But I don't really like doing it that way: it's a slightly different coding style, it's much more manual, the above is just one simple example - actual usage could be more involved, and it doesn't feel as natural as the kind of code I can write when I'm not using inlineCallbacks. A way around this (which maybe will generate howls of protest) would be to have _inlineCallbacks do something this: def unwindGenerator(*args, **kwargs): assert '_inlineCallbacksDeferred' not in kwargs d = Deferred() return _inlineCallbacks(None, f(*args, **kwargs, _inlineCallbacksDeferred=d), d) return mergeFunctionMetadata(f, unwindGenerator) While I don't like this implementation much, it does manage to simply put the deferred that _inlineCallbacks will eventually return, into the hands of f (i.e., func above). func can then pass the deferred around, add callbacks to it etc. exactly as a normal (non-inlineCallbacks) function would. Maybe there's a cleaner way to implement this? I ran into this asymmetry today, when I wanted a function to pass its deferred off to another function but realized that because mine was an inlineCallbacks-decorated function I couldn't do it in the same way I would otherwise. Comments? Terry

On 11 Apr, 10:55 pm, terry@jon.es wrote:
I can get around this in ways that are less elegant:
@defer.inlineCallbacks def func(): # do some stuff d = defer.Deferred() callSomethingElse(d) d.callback(result) newResult = yield d defer.returnValue(newResult)
When I write functions that take a Deferred I typically have them return a Deferred as well, to avoid this, and other syntactic nuisances. Would you consider the following more elegant? @inlineCallbacks def func(): # do some stuff returnValue(yield callSomethingElse(succeed(result)))
participants (2)
-
glyph@divmod.com
-
Terry Jones