Skip to content

from reactivity.hmr.exec_hack import *

fix_class_name_resolution

fix_class_name_resolution[T: ast.AST](
    mod: T,
    lineno_offset=0,
    col_offset=0,
    skip_annotations=ABOVE_3_14,
) -> T
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/__init__.py
def fix_class_name_resolution[T: ast.AST](mod: T, lineno_offset=0, col_offset=0, skip_annotations=ABOVE_3_14) -> T:
    new_mod = ClassTransformer(skip_annotations).visit(mod)
    if lineno_offset:
        ast.increment_lineno(new_mod, lineno_offset)
    if col_offset:
        _increment_col_offset(new_mod, col_offset)
    return new_mod

_increment_col_offset

_increment_col_offset[T: ast.AST](tree: T, n: int) -> T
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/__init__.py
def _increment_col_offset[T: ast.AST](tree: T, n: int) -> T:
    for node in ast.walk(tree):
        if isinstance(node, (ast.stmt, ast.expr)):
            node.col_offset += n
            if isinstance(node.end_col_offset, int):
                node.end_col_offset += n
    return tree

dedent

dedent(source: str)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/__init__.py
def dedent(source: str):
    lines = source.splitlines(keepends=True)
    level = len(lines[0]) - len(lines[0].lstrip())
    return "".join(line[level:] for line in lines), level

is_future_annotations_enabled

is_future_annotations_enabled(flags: int)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/__init__.py
def is_future_annotations_enabled(flags: int):
    import __future__

    return flags & __future__.annotations.compiler_flag != 0

transform

ABOVE_3_14 module-attribute

ABOVE_3_14 = version_info >= (3, 14)

name_lookup_source module-attribute

name_lookup_source = "\n\ndef __name_lookup():\n    from builtins import KeyError, NameError\n    from collections import ChainMap\n    from inspect import currentframe\n    f = currentframe().f_back\n    c = ChainMap(f.f_locals, f.f_globals, f.f_builtins)\n    if freevars := f.f_code.co_freevars:\n        c.maps.insert(1, e := {})\n        freevars = {*f.f_code.co_freevars}\n        while freevars:\n            f = f.f_back\n            for name in f.f_code.co_cellvars:\n                if name in freevars.intersection(f.f_code.co_cellvars):\n                    freevars.remove(name)\n                    e[name] = f.f_locals[name]\n    def lookup(name):\n        try:\n            return c[name]\n        except KeyError as e:\n            raise NameError(*e.args) from None\n    return lookup\n\n__name_lookup = __name_lookup()\n\n"

ClassTransformer

Bases: NodeTransformer

Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
class ClassTransformer(ast.NodeTransformer):
    def __init__(self, skip_annotations=ABOVE_3_14):
        self.skip_annotations = skip_annotations

    @override
    def visit_ClassDef(self, node: ast.ClassDef):
        traverser = ClassBodyTransformer(self.skip_annotations)
        has_docstring = node.body and isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Constant) and isinstance(node.body[0].value.value, str)
        node.body[has_docstring:] = [
            *def_name_lookup().body,
            *map(traverser.visit, node.body[has_docstring:]),
            ast.Delete(targets=[ast.Name(id="__name_lookup", ctx=ast.Del())]),
            ast.parse(f"False and ( {','.join(traverser.names)} )").body[0],
        ]
        return ast.fix_missing_locations(node)
skip_annotations instance-attribute
skip_annotations = skip_annotations
__init__
__init__(skip_annotations=ABOVE_3_14)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
def __init__(self, skip_annotations=ABOVE_3_14):
    self.skip_annotations = skip_annotations
visit_ClassDef
visit_ClassDef(node: ClassDef)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
@override
def visit_ClassDef(self, node: ast.ClassDef):
    traverser = ClassBodyTransformer(self.skip_annotations)
    has_docstring = node.body and isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Constant) and isinstance(node.body[0].value.value, str)
    node.body[has_docstring:] = [
        *def_name_lookup().body,
        *map(traverser.visit, node.body[has_docstring:]),
        ast.Delete(targets=[ast.Name(id="__name_lookup", ctx=ast.Del())]),
        ast.parse(f"False and ( {','.join(traverser.names)} )").body[0],
    ]
    return ast.fix_missing_locations(node)

ClassBodyTransformer

Bases: NodeTransformer

Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
class ClassBodyTransformer(ast.NodeTransformer):
    def __init__(self, skip_annotations: bool):
        self.skip_annotations = skip_annotations
        self.names: dict[str, None] = {}  # to keep order for better readability

    @override
    def visit_Name(self, node: ast.Name):
        if isinstance(node.ctx, ast.Load) and node.id != "__name_lookup":
            self.names[node.id] = None
            return build_name_lookup(node.id)
        return node

    @override
    def visit_arg(self, node: ast.arg):
        if not self.skip_annotations and node.annotation:
            node.annotation = self.visit(node.annotation)
        return node

    @override
    def visit_FunctionDef(self, node: ast.FunctionDef):
        node.decorator_list = [self.visit(d) for d in node.decorator_list]
        self.visit(node.args)
        if not self.skip_annotations and node.returns:
            node.returns = self.visit(node.returns)
        return node

    visit_AsyncFunctionDef = visit_FunctionDef  # type: ignore

    @override
    def visit_Lambda(self, node: ast.Lambda):
        self.visit(node.args)
        return node
skip_annotations instance-attribute
skip_annotations = skip_annotations
names instance-attribute
names: dict[str, None] = {}
visit_AsyncFunctionDef class-attribute instance-attribute
visit_AsyncFunctionDef = visit_FunctionDef
__init__
__init__(skip_annotations: bool)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
def __init__(self, skip_annotations: bool):
    self.skip_annotations = skip_annotations
    self.names: dict[str, None] = {}  # to keep order for better readability
visit_Name
visit_Name(node: Name)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
@override
def visit_Name(self, node: ast.Name):
    if isinstance(node.ctx, ast.Load) and node.id != "__name_lookup":
        self.names[node.id] = None
        return build_name_lookup(node.id)
    return node
visit_arg
visit_arg(node: arg)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
@override
def visit_arg(self, node: ast.arg):
    if not self.skip_annotations and node.annotation:
        node.annotation = self.visit(node.annotation)
    return node
visit_FunctionDef
visit_FunctionDef(node: FunctionDef)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
@override
def visit_FunctionDef(self, node: ast.FunctionDef):
    node.decorator_list = [self.visit(d) for d in node.decorator_list]
    self.visit(node.args)
    if not self.skip_annotations and node.returns:
        node.returns = self.visit(node.returns)
    return node
visit_Lambda
visit_Lambda(node: Lambda)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
@override
def visit_Lambda(self, node: ast.Lambda):
    self.visit(node.args)
    return node

build_name_lookup

build_name_lookup(name: str) -> ast.Call
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
def build_name_lookup(name: str) -> ast.Call:
    return ast.Call(func=ast.Name(id="__name_lookup", ctx=ast.Load()), args=[ast.Constant(value=name)], keywords=[])

def_name_lookup

def_name_lookup()
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/exec_hack/transform.py
def def_name_lookup():
    tree = ast.parse(name_lookup_source)

    for node in ast.walk(tree):
        for attr in ("lineno", "end_lineno", "col_offset", "end_col_offset"):
            if hasattr(node, attr):
                delattr(node, attr)

    return tree