18
18
__all__ = ['needs_read_lock',
19
19
'needs_write_lock',
20
'use_fast_decorators',
21
'use_pretty_decorators',
22
def needs_read_lock(unbound):
28
def _get_parameters(func):
29
"""Recreate the parameters for a function using introspection.
31
:return: (function_params, calling_params)
32
function_params: is a string representing the parameters of the
33
function. (such as "a, b, c=None, d=1")
34
This is used in the function declaration.
35
calling_params: is another string representing how you would call the
36
function with the correct parameters. (such as "a, b, c=c, d=d")
37
Assuming you sued function_params in the function declaration, this
38
is the parameters to put in the function call.
42
def wrapper(%(function_params)s):
43
return original(%(calling_params)s)
45
# "import inspect" should stay in local scope. 'inspect' takes a long time
46
# to import the first time. And since we don't always need it, don't import
49
args, varargs, varkw, defaults = inspect.getargspec(func)
50
formatted = inspect.formatargspec(args, varargs=varargs,
56
first_default = len(args) - len(defaults)
57
args_passed = args[:first_default]
58
for arg in args[first_default:]:
59
args_passed.append("%s=%s" % (arg, arg))
60
if varargs is not None:
61
args_passed.append('*' + varargs)
63
args_passed.append('**' + varkw)
64
args_passed = ', '.join(args_passed)
66
return formatted[1:-1], args_passed
69
def _pretty_needs_read_lock(unbound):
70
"""Decorate unbound to take out and release a read lock.
72
This decorator can be applied to methods of any class with lock_read() and
79
def branch_method(self, ...):
82
# This compiles a function with a similar name, but wrapped with
83
# lock_read/unlock calls. We use dynamic creation, because we need the
84
# internal name of the function to be modified so that --lsprof will see
86
# TODO: jam 20070111 Modify this template so that the generated function
87
# has the same argument signature as the original function, which
88
# will help commands like epydoc.
89
# This seems possible by introspecting foo.func_defaults, and
90
# foo.func_code.co_argcount and foo.func_code.co_varnames
92
def %(name)s_read_locked(%(params)s):
95
result = unbound(%(passed_params)s)
98
exc_info = sys.exc_info()
102
raise exc_info[0], exc_info[1], exc_info[2]
106
read_locked = %(name)s_read_locked
108
params, passed_params = _get_parameters(unbound)
109
variables = {'name':unbound.__name__,
111
'passed_params':passed_params,
113
func_def = template % variables
115
exec func_def in locals()
117
read_locked.__doc__ = unbound.__doc__
118
read_locked.__name__ = unbound.__name__
122
def _fast_needs_read_lock(unbound):
23
123
"""Decorate unbound to take out and release a read lock.
25
125
This decorator can be applied to methods of any class with lock_read() and
35
135
def read_locked(self, *args, **kwargs):
38
return unbound(self, *args, **kwargs)
138
result = unbound(self, *args, **kwargs)
141
exc_info = sys.exc_info()
145
raise exc_info[0], exc_info[1], exc_info[2]
41
149
read_locked.__doc__ = unbound.__doc__
42
150
read_locked.__name__ = unbound.__name__
43
151
return read_locked
46
def needs_write_lock(unbound):
154
def _pretty_needs_write_lock(unbound):
155
"""Decorate unbound to take out and release a write lock."""
157
def %(name)s_write_locked(%(params)s):
160
result = unbound(%(passed_params)s)
163
exc_info = sys.exc_info()
167
raise exc_info[0], exc_info[1], exc_info[2]
171
write_locked = %(name)s_write_locked
173
params, passed_params = _get_parameters(unbound)
174
variables = {'name':unbound.__name__,
176
'passed_params':passed_params,
178
func_def = template % variables
180
exec func_def in locals()
182
write_locked.__doc__ = unbound.__doc__
183
write_locked.__name__ = unbound.__name__
187
def _fast_needs_write_lock(unbound):
47
188
"""Decorate unbound to take out and release a write lock."""
48
189
def write_locked(self, *args, **kwargs):
51
return unbound(self, *args, **kwargs)
192
result = unbound(self, *args, **kwargs)
194
exc_info = sys.exc_info()
198
raise exc_info[0], exc_info[1], exc_info[2]
54
202
write_locked.__doc__ = unbound.__doc__
55
203
write_locked.__name__ = unbound.__name__
56
204
return write_locked
207
# Default is more functionality, 'bzr' the commandline will request fast
209
needs_read_lock = _pretty_needs_read_lock
210
needs_write_lock = _pretty_needs_write_lock
213
def use_fast_decorators():
214
"""Change the default decorators to be fast loading ones.
216
The alternative is to have decorators that do more work to produce
217
nice-looking decorated functions, but this slows startup time.
219
global needs_read_lock, needs_write_lock
220
needs_read_lock = _fast_needs_read_lock
221
needs_write_lock = _fast_needs_write_lock
224
def use_pretty_decorators():
225
"""Change the default decorators to be pretty ones."""
226
global needs_read_lock, needs_write_lock
227
needs_read_lock = _pretty_needs_read_lock
228
needs_write_lock = _pretty_needs_write_lock