Skip to content

Instantly share code, notes, and snippets.

@a-recknagel
Last active January 17, 2023 23:16
Show Gist options
  • Save a-recknagel/ca4fdb69bdeb1702b131653a3b4f14b8 to your computer and use it in GitHub Desktop.
Save a-recknagel/ca4fdb69bdeb1702b131653a3b4f14b8 to your computer and use it in GitHub Desktop.
fetch annotations defined in __init__
import ast
import inspect
class InitAnnotations(ast.NodeVisitor):
def __init__(self, locals_, globals_):
self.globals = globals_
self.locals = locals_
self.annotations = {}
def visit_AnnAssign(self, node: ast.AnnAssign):
if not node.simple:
if isinstance(node.annotation, ast.Constant):
annotation = node.annotation.value
else:
annotation = node.annotation.id
self.annotations[f"self.{node.target.attr}"] = eval(
annotation,
self.globals,
self.locals
)
def get_init_annotations(cls: type) -> dict[str, type]:
try:
src = inspect.getsource(cls)
except OSError:
print("cheeky, huh? 😒")
return {}
anno = InitAnnotations(vars(cls), vars(inspect.getmodule(cls)))
anno.visit(ast.parse(src))
return anno.annotations
class Foo:
class Bar:
pass
def __init__(self):
i: int = 1
self.x: int = 3
if False:
self.y: str = "still a valid annotation"
self.z: Bar = Bar()
self.a: "Foo" = self
print(get_init_annotations(Foo))
# {'self.x': <class 'int'>, 'self.y': <class 'str'>, 'self.z': <class '__main__.Foo.Bar'>, 'self.a': <class '__main__.Foo'>}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment