Hi!
As part of our Python library, we have a decorator for parsing user functions into an AST and transpiling the code into another language.
This works well when user modules are evaluated the standard way, but we can’t figure out how to get that to work when the code is stored as a string in memory and users evaluate it with exec()
.
See the following snippet as an example.
# Library Code
# ------------
import ast
import inspect
def lib_decorator(func):
source = inspect.getsource(func)
tree = ast.parse(source)
print(tree.body[0])
# User Code
# ---------
# This works.
@lib_decorator
def user_function():
pass
# This doesn't work.
exec("""
@lib_decorator
def user_function():
pass
""")
The issue being that inspect.getsource(func)
fails to retrieve the source code since it relies on it being stored in a file on disk, and it looks like exec()
doesn’t store the string being evaluated anywhere.
I couldn’t find any official helper to build an AST from a function’s bytecode, which I’m assuming is expected since it doesn’t seem trivial.
Am I missing any trick to retrieve the AST of the func
argument passed to lib_decorator
regardless of how the user code is evaluated?
Thank you!