2022-06-27 11:19:26 +03:00

39 lines
1023 B
Python

from abc import ABC, abstractmethod
from ast import NodeTransformer, parse
from inspect import getsource
from textwrap import dedent
from typing import Any, Dict, List, Set, Type
class BaseScheme(ABC):
ident: str
_registry: Set[Type] = set()
def __init__(self, app) -> None:
self.app = app
@abstractmethod
def visitors(self) -> List[NodeTransformer]:
...
def __init_subclass__(cls):
BaseScheme._registry.add(cls)
def __call__(self):
return self.visitors()
@classmethod
def build(cls, method, module_globals, app):
raw_source = getsource(method)
src = dedent(raw_source)
node = parse(src)
for scheme in cls._registry:
for visitor in scheme(app)():
node = visitor.visit(node)
compiled_src = compile(node, method.__name__, "exec")
exec_locals: Dict[str, Any] = {}
exec(compiled_src, module_globals, exec_locals) # nosec
return exec_locals[method.__name__]