[Twisted-Python] inlineCallbacksDecorator

2009-06-06 Thread Terry Jones
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.

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)
@defer.inlineCallbacks
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
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


[Twisted-Python] Weekly Bug Summary

2009-06-06 Thread exarkun



Bug summary
__
Summary for 2009-05-31 through 2009-06-07
Bugs opened: 10Bugs closed: 2  Total open bugs: 1121 (+8)

|== Type Changes   |== Priority Changes   |== Component Changes   
|Defect:   +4  |Highest:  +1  |Conch:+3   
|Enhancement:  +3  |Normal:   +5  |Core: +4   
|Regression:   +1  |Low:  +2  |Mail: -1   
  |Web2: +1   
  |Website:  +1   



Total Tickets
Open Tickets



New / Reopened Bugs
__
= Highest =
[#3871] `twistd conch´ always fails due to an unhandled AttributeError; conch server cannot be started. (opened by exarkun)
regression  conch  http://twistedmatrix.com/trac/ticket/3871

= Normal =
[#3862] Chapters in the twisted documentation should have one-line summaries that are included in the table of contents (opened by radix)
enhancement core   http://twistedmatrix.com/trac/ticket/3862

[#3863] twisted.conch.avatar.ConchUser incompletely implements IConchUser (opened by exarkun)
defect  conch  http://twistedmatrix.com/trac/ticket/3863

[#3864] twisted.conch.manhole_ssh.TerminalSessionTransport requires `session` and `write` attributes on an object only documented as being a ProcessProtocol instance (opened by exarkun)
defect  conch  http://twistedmatrix.com/trac/ticket/3864

[#3865] Provide method for debugging twistd plugin scanning (opened by powdahound)
enhancement core   http://twistedmatrix.com/trac/ticket/3865

[#3868] twisted\python\lockfile.py problem on portable Python install (opened by JamesB)
defect  core   http://twistedmatrix.com/trac/ticket/3868

[#3869] API reference not available for download (opened by JamesB)
enhancement websitehttp://twistedmatrix.com/trac/ticket/3869

[#3870] SERVER_SOFTWARE identifier for twisted.web2 is incorrectly formatted (opened by thijs)
defect  web2   http://twistedmatrix.com/trac/ticket/3870

= Low =
[#3866] ClientCreator should not use reactor.callLater to fire its Deferred (opened by exarkun)
defect  core   http://twistedmatrix.com/trac/ticket/3866

[#3867] Document trac-post-commit-hook functionality in svn-dev policy (opened by thijs)
enhancement core   http://twistedmatrix.com/trac/ticket/3867



Closed Bugs
__
= Normal =
[#3846] t.mail.test.test_imap.PreauthIMAP4ClientMixin._result conflicts with Python 2.7 unittest (opened by ivank, closed by exarkun, fixed)
defect  mail   http://twistedmatrix.com/trac/ticket/3846

[#3791] DelayedCall should use unsignedID in str method (opened by therve, closed by exarkun, fixed)
enhancement core   http://twistedmatrix.com/trac/ticket/3791



Ticket Lifetime Stats
__
Oldest open ticket - [#50] conch command-line client doesn't work in win32 (since 2003-07-12 16:41:06).
Newest open ticket - [#3871] `twistd conch´ always fails due to an unhandled AttributeError; conch server cannot be started. (since 2009-06-06 08:51:05).

Mean open ticket age: 792 days, 21:43:50.307043.
Median: 764 days, 20:17:55.238355.
Standard deviation: 553 days, 10:53:17.283842.
Interquartile range: 732 days, 18:46:18.

Mean time between ticket creation and ticket resolution: 201 days, 1:10:33.199041.
Median: 25 days, 18:17:40.
Standard deviation is 342 days, 16:46:19.793774.
The interquartile range is 232 days, 5:56:02.

Mean time spent in review: 72 days, 19:26:24.407228.
Median: 4 days, 0:03:10.
Standard deviation: 238 days, 20:07:26.658173.
Interquartile range: 16 days, 11:11:56.

Mean number of times a ticket is reviewed: 2.02462121212.
Median: 1
Standard deviation: 1.6802551688.
Interquartile range: 1.


Contributor Stats
__
In the last 4 weeks,
20 unique ticket reporters
8 unique ticket reviewers
2 unique ticket resolvers
In the last 24 weeks,
94 unique ticket reporters
18 unique ticket reviewers
14 unique ticket resolvers
In the last 48 weeks,
159 unique ticket reporters
22 unique ticket reviewers
18 unique ticket resolvers





___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] inlineCallbacksDecorator

2009-06-06 Thread Maarten ter Huurne
On Sunday 07 June 2009, Terry Jones wrote:

> 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)
> @defer.inlineCallbacks
> def frog(a, b=None):
> print 'a = %r, b = %r' % (a, b)
> result = yield produceDeferred()
> # yield produceErr()
> defer.returnValue(a)

As far as I can see, this decorator could be applied to any function that 
returns a Deferred, not just to inlineCallbacks.

Bye,
Maarten


___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python