2023-04-03 23:21:01 +00:00
|
|
|
import ast
|
|
|
|
import inspect
|
|
|
|
from textwrap import dedent
|
2023-04-03 16:50:34 +00:00
|
|
|
from types import FunctionType
|
2023-04-03 23:21:01 +00:00
|
|
|
from typing import Any, Callable
|
|
|
|
|
|
|
|
|
|
|
|
def ast_dump(sobject) -> None:
|
|
|
|
print(ast.dump(ast.parse(
|
|
|
|
source=dedent(inspect.getsource(sobject)),
|
|
|
|
), indent=4))
|
|
|
|
|
|
|
|
|
|
|
|
def func_info(f: Callable) -> None:
|
|
|
|
print(f"{f.__name__ } = {f}, {f.__code__.co_varnames = }")
|
|
|
|
f("bar")
|
|
|
|
f("baz")
|
2023-04-03 16:50:34 +00:00
|
|
|
|
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
def func1(pstr: str) -> None:
|
2023-04-03 16:50:34 +00:00
|
|
|
def foo() -> None:
|
|
|
|
print(f"{pstr = }")
|
|
|
|
|
|
|
|
foo()
|
|
|
|
|
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
def shoehorn(f: Callable) -> Callable:
|
2023-04-03 23:21:01 +00:00
|
|
|
ast_dump(f)
|
|
|
|
f_ast = ast.parse(source=dedent(inspect.getsource(f)))
|
|
|
|
|
|
|
|
def foo() -> None:
|
|
|
|
print(f"{pstr = }") # type:ignore # noqa: F821
|
|
|
|
|
|
|
|
ast_dump(foo)
|
|
|
|
# foo_ast = ast.parse(source=dedent(inspect.getsource(foo)))
|
|
|
|
|
|
|
|
class Shoehorn(ast.NodeTransformer):
|
|
|
|
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
|
|
|
print(ast.dump(node, indent=4))
|
|
|
|
return node
|
|
|
|
|
|
|
|
new_f_ast = ast.fix_missing_locations(Shoehorn().visit(f_ast))
|
|
|
|
print(ast.dump(new_f_ast, indent=4))
|
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
code = f.__code__.replace(
|
|
|
|
co_nlocals=2,
|
|
|
|
co_varnames=("pstr", "foo"),
|
|
|
|
)
|
2023-04-03 16:50:34 +00:00
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
return FunctionType(
|
|
|
|
name=f.__name__,
|
|
|
|
code=code,
|
|
|
|
globals=func1.__globals__,
|
|
|
|
)
|
2023-04-03 16:50:34 +00:00
|
|
|
|
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
@shoehorn
|
|
|
|
def func2(pstr: str) -> None:
|
2023-04-03 23:21:01 +00:00
|
|
|
foo() # type:ignore # noqa: F821
|
2023-04-03 16:50:34 +00:00
|
|
|
|
|
|
|
|
2023-04-03 22:23:23 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
func_info(func1)
|
2023-04-03 23:21:01 +00:00
|
|
|
# ast_dump(func1)
|
2023-04-03 22:23:23 +00:00
|
|
|
func_info(func2)
|
2023-04-03 16:50:34 +00:00
|
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
print(json.dumps({
|
2023-04-03 22:23:23 +00:00
|
|
|
name: repr(getattr(func2.__code__, name))
|
|
|
|
for name in dir(func2.__code__)
|
2023-04-03 16:50:34 +00:00
|
|
|
}, indent=2))
|