Skip to content

from reactivity.hmr import *

__all__ module-attribute

__all__ = (
    "cache_across_reloads",
    "cli",
    "on_dispose",
    "post_reload",
    "pre_reload",
)

on_dispose

on_dispose(
    func: Callable[[], Any], __file__: str | None = None
)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/hooks.py
def on_dispose(func: Callable[[], Any], __file__: str | None = None):
    path = Path(currentframe().f_back.f_globals["__file__"] if __file__ is None else __file__).resolve()  # type: ignore

    from .core import ReactiveModule

    module = ReactiveModule.instances[path]
    module.register_dispose_callback(func)

post_reload

post_reload[T](func: Callable[[], T]) -> Callable[[], T]
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/hooks.py
def post_reload[T](func: Callable[[], T]) -> Callable[[], T]:
    post_reload_hooks[func.__name__] = func
    return func

pre_reload

pre_reload[T](func: Callable[[], T]) -> Callable[[], T]
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/hooks.py
def pre_reload[T](func: Callable[[], T]) -> Callable[[], T]:
    pre_reload_hooks[func.__name__] = func
    return func

cli

cli(args: list[str] | None = None)
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/run.py
def cli(args: list[str] | None = None):
    if args is None:
        args = sys.argv[1:]

    try:
        if len(args) < 1 or args[0] in ("--help", "-h"):
            print("\n Usage:")
            print("   hmr <entry file>, just like python <entry file>")
            print("   hmr -m <module>, just like python -m <module>\n")
            if len(args) < 1:
                return 1
        elif args[0] == "-m":
            if len(args) < 2:
                print("\n Usage: hmr -m <module>, just like python -m <module>\n")
                return 1
            module_name = args[1]
            args.pop(0)  # remove -m flag
            run_module(module_name, args)
        else:
            run_path(args[0], args)
    except (FileNotFoundError, ModuleNotFoundError) as e:
        print(f"\n Error: {e}\n")
        return 1

    return 0

cache_across_reloads

cache_across_reloads[T](
    func: Callable[[], T],
) -> Callable[[], T]
Source code in .venv/lib/python3.12/site-packages/reactivity/hmr/utils.py
def cache_across_reloads[T](func: Callable[[], T]) -> Callable[[], T]:
    file = getsourcefile(func)
    assert file is not None
    module = ReactiveModule.instances.get(path := Path(file).resolve())

    if module is None:
        from functools import cache

        return cache(func)

    source, col_offset = dedent(getsource(func))

    key = (path, func.__qualname__)

    proxy: NamespaceProxy = module._ReactiveModule__namespace_proxy  # type: ignore
    flags: int = module._ReactiveModule__flags  # type: ignore
    skip_annotations = ABOVE_3_14 or is_future_annotations_enabled(flags)

    global _cache_decorator_phase
    _cache_decorator_phase = not _cache_decorator_phase
    if _cache_decorator_phase:  # this function will be called twice: once transforming ast and once re-executing the patched source
        on_dispose(lambda: functions.pop(key), file)
        try:
            exec(compile(fix_class_name_resolution(parse(source), func.__code__.co_firstlineno - 1, col_offset, skip_annotations), file, "exec", flags, dont_inherit=True), DictProxy(proxy))
        except _Return as e:
            # If this function is used as a decorator, it will raise an `_Return` exception in the second phase.
            return e.value
        else:
            # Otherwise, it is used as a function, and we need to do the second phase ourselves.
            func = proxy[func.__name__]

    func = FunctionType(func.__code__, DictProxy(proxy), func.__name__, func.__defaults__, func.__closure__)

    functions[key] = func

    if result := memos.get(key):
        memo, last_source = result
        if source != last_source:
            Derived.invalidate(memo)  # type: ignore
            memos[key] = memo, source
        return _return(wraps(func)(memo))

    @wraps(func)
    def wrapper() -> T:
        return functions[key]()

    memo = Derived(wrapper, context=HMR_CONTEXT)
    memo.reactivity_loss_strategy = "ignore"  # Manually invalidated on source change, so reactivity loss is safe to ignore
    memos[key] = memo, source

    return _return(wraps(func)(memo))