1
0
Fork 0
cursed-snakes/namespace-inject.py

72 lines
1.5 KiB
Python

import ast
import inspect
from textwrap import dedent
from types import FunctionType
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")
def func1(pstr: str) -> None:
def foo() -> None:
print(f"{pstr = }")
foo()
def shoehorn(f: Callable) -> Callable:
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))
code = f.__code__.replace(
co_nlocals=2,
co_varnames=("pstr", "foo"),
)
return FunctionType(
name=f.__name__,
code=code,
globals=func1.__globals__,
)
@shoehorn
def func2(pstr: str) -> None:
foo() # type:ignore # noqa: F821
if __name__ == "__main__":
func_info(func1)
# ast_dump(func1)
func_info(func2)
import json
print(json.dumps({
name: repr(getattr(func2.__code__, name))
for name in dir(func2.__code__)
}, indent=2))