def eval_function_def_as_closure(function_def, closure_names, globals_=None, flags=None):
"""
Evaluates an AST of a function definition inside a closure with the variables
from ``closure_names`` set to ``None``, and an optional dictionary of globals.
Returns a callable function (a ``types.FunctionType`` object).
.. warning::
Before the returned function can be actually called, the "fake" closure cells
(filled with ``None``) must be substituted by actual closure cells
that will be used during the call.
"""
assert type(function_def) == ast.FunctionDef
none = ast.NameConstant(value=None)
# We can't possibly recreate ASTs of existing closure variables
# (because all we have are their values).
# So we create fake closure variables for the function to attach to,
# and then substitute the closure cells with the ones obtained from
# the "prototype" of this function (a ``types.FunctionType`` object
# from which this tree was extracted).
fake_closure_vars = [
ast.Assign(
targets=[ast.Name(id=name, ctx=ast.Store())],
value=none)
for name in closure_names]
empty_args = ast.arguments(
args=[],
vararg=None,
kwonlyargs=[],
kwarg=None,
defaults=[],
kw_defaults=[])
wrapper_def = ast.FunctionDef(
name='__peval_wrapper',
args=empty_args,
decorator_list=[],
body=(
fake_closure_vars +
[function_def] +
[ast.Return(value=ast.Name(id=function_def.name, ctx=ast.Load()))]))
wrapper = eval_function_def(wrapper_def, globals_=globals_, flags=flags)
return wrapper()
评论列表
文章目录