1 from __future__
import division
, absolute_import
, unicode_literals
3 __all__
= ('decorator', 'memoize', 'interruptable')
8 def decorator(caller
, func
=None):
10 Create a new decorator
12 decorator(caller) converts a caller function into a decorator;
13 decorator(caller, func) decorates a function using a caller.
18 def _decorator(f
, *args
, **opts
):
19 def _caller(*args
, **opts
):
20 return caller(f
, *args
, **opts
)
22 _decorator
.func
= func
25 # return a decorated function
26 def _decorated(*args
, **opts
):
27 return caller(func
, *args
, **opts
)
28 _decorated
.func
= func
34 A decorator for memoizing function calls
36 http://en.wikipedia.org/wiki/Memoization
40 return decorator(_memoize
, func
)
43 def _memoize(func
, *args
, **opts
):
44 """Implements memoized cache lookups"""
45 if opts
: # frozenset is used to ensure hashability
46 key
= args
, frozenset(opts
.items())
49 cache
= func
.cache
# attribute added by memoize
53 result
= cache
[key
] = func(*args
, **opts
)
58 def interruptable(func
, *args
, **opts
):
59 """Handle interruptable system calls
61 OSX and others are known to interrupt system calls
63 http://en.wikipedia.org/wiki/PCLSRing
64 http://en.wikipedia.org/wiki/Unix_philosophy#Worse_is_better
66 The @interruptable decorator handles this situation
71 result
= func(*args
, **opts
)
73 if e
.errno
== errno
.EINTR
:
77 if e
.errno
in (errno
.EINTR
, errno
.EINVAL
):