5 __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 # pylint: disable=unused-argument
19 @functools.wraps(caller
)
20 def _decorator(func
, *dummy_args
, **dummy_opts
):
21 @functools.wraps(func
)
22 def _caller(*args
, **opts
):
23 return caller(func
, *args
, **opts
)
27 _decorator
.func
= caller
30 # return a decorated function
31 @functools.wraps(func
)
32 def _decorated(*args
, **opts
):
33 return caller(func
, *args
, **opts
)
35 _decorated
.func
= func
41 A decorator for memoizing function calls
43 http://en.wikipedia.org/wiki/Memoization
47 return decorator(_memoize
, func
)
50 def _memoize(func
, *args
, **opts
):
51 """Implements memoized cache lookups"""
52 if opts
: # frozenset is used to ensure hashability
53 key
= (args
, frozenset(list(opts
.items())))
56 cache
= func
.cache
# attribute added by memoize
60 result
= cache
[key
] = func(*args
, **opts
)
65 def interruptable(func
, *args
, **opts
):
66 """Handle interruptible system calls
68 OSX and others are known to interrupt system calls
70 http://en.wikipedia.org/wiki/PCLSRing
71 http://en.wikipedia.org/wiki/Unix_philosophy#Worse_is_better
73 The @interruptable decorator handles this situation
78 result
= func(*args
, **opts
)
80 if e
.errno
in (errno
.EINTR
, errno
.EINVAL
):