I had an idea to transform all given functions that are tagged using a decorator similar to the below,
@transform_ast
def foo(x):
return x
In transform_ast, I get the source, extract the ast, transform it, and then create a code object and function type from it again. It looks something like the below,
import ast
import inspect
import types
class Rewrite(ast.NodeTransformer):
pass
def transform_ast(f):
source = inspect.getsource(f)
source = '\n'.join(source.splitlines()[1:]) # remove the decorator first line.
print(source)
old_code_obj = f.__code__
old_ast = ast.parse(source)
new_ast = Rewrite().visit(old_ast)
new_code_obj = compile(new_ast, old_code_obj.co_filename, 'exec')
new_f = types.FunctionType(new_code_obj, {})
return new_f
@transform_ast
def foo(x):
return x
However, it doesn't seem to work properly when I subsequently call foo(x).
For all practical purposes, we can assume my transform is just re-writing return x to return x+1. Ideally I would like everything to work as per-normal, including being able to step into the function with a debugger...
Calling foo(10), would give the following error,
TypeError: module() takes no arguments (1 given)
Is there anything that I'm doing wrong?