"""inject_closure module"""
INJECTEDKEY = "injected_{}"
OUTERLINE = " outer_{0} = injected_{0}"
INNERLINE = " inner_{0} = outer_{0}"
SOURCE= ("def not_important():",
" def also_not_important():",
" return also_not_important")
def inject_closure(f, *args):
"""Return a copy of f, with a new closure.
The new closure will be derived from args, in the same
order. This requires that the caller have knowledge
of the existing closure.
"""
# build the source to exec
injected = {}
source = list(SOURCE)
for i in range(len(args)):
source.insert(1, OUTERLINE.format(i))
source.insert(-1, INNERLINE.format(i))
injected[INJECTEDKEY.format(i)] = args[i]
# exec the source and pull the new closure
exec("\n".join(source), injected, injected)
closure = injected["not_important"]().__closure__
# build the new function object
func = type(f)(f.__code__, f.__globals__, f.__name__,
f.__defaults__, closure)
func.__annotations__ = f.__annotations__
func.__doc__ = f.__doc__
func.__kwdefaults__ = f.__kwdefaults__
func.__module__ = f.__module__
return func
Diff to Previous Revision
--- revision 1 2011-06-17 18:42:38
+++ revision 2 2011-08-12 23:25:55
@@ -1,6 +1,4 @@
"""inject_closure module"""
-
-from types import FunctionType
INJECTEDKEY = "injected_{}"
OUTERLINE = " outer_{0} = injected_{0}"
@@ -31,8 +29,8 @@
closure = injected["not_important"]().__closure__
# build the new function object
- func = FunctionType(f.__code__, f.__globals__, f.__name__,
- f.__defaults__, closure)
+ func = type(f)(f.__code__, f.__globals__, f.__name__,
+ f.__defaults__, closure)
func.__annotations__ = f.__annotations__
func.__doc__ = f.__doc__
func.__kwdefaults__ = f.__kwdefaults__