On Sat, Jun 6, 2009 at 9:41 PM, Terry Jones<[email protected]> wrote:
> I try to avoid using inlineCallbacks. There are two cases where I will
> happily use it though: when I write a method that would need more than a
> few callback functions, and, more importantly, when the logical flow of a
> method is non-trivial (i.e., it depends on the returned values or errors of
> several deferreds).
>
> One inconvenience with inlineCallbacks is that you might have some kind of
> processing you want done no matter how the function returns, or wherever an
> error occurs. Two solutions here are 1) to put try/except calls around your
> various yields, and/or to perhaps do something else with various callbacks
> that might call defer.returnValue, or 2) expect each caller of your method
> to deal with the result. I don't like the first of those much (depending on
> the code), and don't like the second at all.

How does inlineCallbacks preclude you from adding "processing you want
done no matter how the function returns" or currying callbacks?  From
my understanding of the problem, this is already solved by attaching
callbacks/errbacks in the regular way:

@inlineCallbacks
def foo(a, b, c):
    ...
foo(a, b, c).addBoth(cb, a, b, c)

>
> So I wrote a decorator specifically for inlineCallbacks decorated functions:
>
>    from twisted.internet import defer
>
>    def inlineCallbacksDecorator(callback, errback=defer.passthru):
>        def wrap(f):
>            def wrapper(*args, **kw):
>                d = f(*args, **kw)
>                if isinstance(d, defer.Deferred):
>                    return d.addCallbacks(callback, errback,
>                                          callbackArgs=args, 
> callbackKeywords=kw,
>                                          errbackArgs=args, errbackKeywords=kw)
>                # We were used to decorate a non-inlineCallbacks function.
>                raise Exception(
>                    'Function %r was decorated with inlineCallbacksDecorator 
> but '
>                    'did not return a deferred (did you forget to also 
> decorate '
>                    'with inlineCallbacks?)' % f.__name__)
>            return mergeFunctionMetadata(f, wrapper)
>        return wrap
>
> You can use it like this:
>
>    def _cbok(result, a, b=None):
>        print 'In _cbok: a=%r b=%r' % (a, b)
>        return result
>
>    def _cberr(failure, *args, **kw):
>        pass
>        # Do something....  and maybe also return the failure.
>
>   �...@inlinecallbacksdecorator(_cbok, _cberr)
>   �[email protected]
>    def frog(a, b=None):
>        print 'a = %r, b = %r' % (a, b)
>        result = yield produceDeferred()
>        # yield produceErr()
>        defer.returnValue(a)
>
>
> The nice/interesting thing about this is that the callback and errback
> functions get called with the deferred result of calling frog (as decorated
> by inlineCallbacks) *and* the original arguments passed to frog.  You can
> of course ignore the original args if you're not interested in them.
>
> You can argue that this doesn't really buy you anything. That's of course
> true.  It's only a decorator that makes it neater to do certain things.
> Logging, accounting and error processing come immediately to mind. Just
> keeping code looking simpler/cleaner is enough of a reason for me.
>
> After writing this, I realized it deals with what I was clumsily trying to
> achieve here
> http://twistedmatrix.com/pipermail/twisted-python/2009-April/019492.html
> back in April.
>
> Terry
>
> _______________________________________________
> Twisted-Python mailing list
> [email protected]
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>

_______________________________________________
Twisted-Python mailing list
[email protected]
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to