"""inject_closure module"""
from types import FunctionType
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 = FunctionType(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