### Setup Development Environment Source: https://hmr.promplate.dev/contributing Clone the repository, create a virtual environment, and install development dependencies. ```bash git clone https://github.com/YOUR_USERNAME/hmr.git cd hmr python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -e ".[dev]" ``` -------------------------------- ### Run the HMR Demo Source: https://hmr.promplate.dev/integrations/demo Navigate to the demo directory and execute the entry point script using the hmr command to start the example. ```bash cd examples/demo hmr entry.py ``` -------------------------------- ### Install and Run FastAPI/ASGI Apps with HMR Source: https://hmr.promplate.dev/getting-started/quick-start Install the `uvicorn-hmr` package and run your FastAPI/ASGI application using `uvicorn-hmr`. ```bash pip install uvicorn-hmr uvicorn-hmr main:app ``` -------------------------------- ### Install and run Uvicorn with HMR Source: https://hmr.promplate.dev/getting-started/what-is-hmr Integrate HMR with ASGI frameworks like FastAPI by installing `uvicorn-hmr` and running your application through it. ```bash pip install uvicorn-hmr uvicorn-hmr main:app ``` -------------------------------- ### Install and Run MCP Servers with HMR Source: https://hmr.promplate.dev/getting-started/quick-start Install the `mcp-hmr` package and run your MCP server using `mcp-hmr`. ```bash pip install mcp-hmr mcp-hmr main:app ``` -------------------------------- ### Verify HMR Installation Source: https://hmr.promplate.dev/getting-started/installation Check if the HMR CLI is installed correctly by running the help command. ```bash hmr --help ``` -------------------------------- ### Install uvicorn-hmr Source: https://hmr.promplate.dev/integrations/uvicorn Install the uvicorn-hmr package. For optional browser auto-refresh functionality, install with the 'all' extra. ```bash pip install uvicorn-hmr # optional browser auto-refresh pip install uvicorn-hmr[all] ``` -------------------------------- ### Dependency Graph Example Source: https://hmr.promplate.dev/reactive This example demonstrates how Signals, Derived computations, and Effects form a dependency graph. Effects only rerun if the computed value changes. ```python from reactivity import signal, derived, effect s = signal(0) @derived def f(): return s.get() // 2 @effect def _(): print(f()) # output: 0 s.set(1) # no output because f() = 0, unchanged, no need to rerun effect s.set(2) # output: 1 s.set(3) # no output ``` -------------------------------- ### Install mcp-hmr Source: https://hmr.promplate.dev/integrations/mcp Install the mcp-hmr package using pip. ```bash pip install mcp-hmr ``` -------------------------------- ### Run Application with HMR Source: https://hmr.promplate.dev/getting-started/quick-start Execute the `main.py` script using the HMR command to start the development server. ```bash hmr main.py ``` -------------------------------- ### Simple MCP Server Structure Source: https://hmr.promplate.dev/integrations/mcp Example of a basic MCP server structure using FastMCP, including a tool and a resource. This structure is suitable for demonstrating hot reloading. ```python # main.py from fastmcp import FastMCP app = FastMCP() @app.tool() def echo(message: str): return message @app.resource("example://greet") def greet(): return "hello world" if __name__ == "__main__": app.run("stdio") ``` -------------------------------- ### Install HMR CLI Source: https://hmr.promplate.dev/getting-started/installation Install the HMR command-line interface into your active virtual environment using pip. ```bash pip install hmr ``` -------------------------------- ### Run uvicorn-hmr Source: https://hmr.promplate.dev/integrations/uvicorn Start your ASGI application using the uvicorn-hmr command. Common uvicorn options are supported. ```bash uvicorn-hmr main:app # supports common uvicorn options; see `uvicorn-hmr --help` ``` -------------------------------- ### hmr_daemon.windows.main Source: https://hmr.promplate.dev/references/hmr-daemon Main function to start the HMR daemon on Windows, setting up a reloader. ```APIDOC ## `hmr_daemon.windows.main` ### Description Main function to start the HMR daemon on Windows, setting up a reloader. ### Function `main()` ``` -------------------------------- ### FastAPI Application Example Source: https://hmr.promplate.dev/integrations/uvicorn A basic FastAPI application to be run with uvicorn-hmr. ```python # main.py from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"message": "Hello, World!"} ``` -------------------------------- ### Install and run MCP with HMR Source: https://hmr.promplate.dev/getting-started/what-is-hmr Integrate HMR with MCP server development by installing `mcp-hmr` and running your application through it. ```bash pip install mcp-hmr mcp-hmr main:app ``` -------------------------------- ### Setup File System Audit Hook Source: https://hmr.promplate.dev/references/hmr/fs Sets up a system audit hook to track file open events. It filters based on _filters and tracks modified paths. ```python @cache def setup_fs_audithook(): @sys.addaudithook def _(event: str, args: tuple): if event == "open": file, _, flags = args if (flags % 2 == 0) and _filters and isinstance(file, str) and HMR_CONTEXT.leaf.current_computations: p = Path(file).resolve() if any(f(p) for f in _filters): track(p) ``` -------------------------------- ### Run Python Module with HMR Source: https://hmr.promplate.dev/references/hmr/run Executes a Python module by name using HMR. It finds the module's entry point, potentially handling packages and their `__main__.py`, and then starts the `SyncReloader`. This is useful for running installed modules or packages as scripts. ```python def run_module(module_name: str, args: list[str]): if (cwd := str(Path.cwd())) not in sys.path: sys.path.insert(0, cwd) from importlib.util import find_spec from .core import ReactiveModule, SyncReloader, _loader, patch_meta_path patch_meta_path() spec = find_spec(module_name) if spec is None: raise ModuleNotFoundError(f"No module named '{module_name}'") if spec.submodule_search_locations is not None: # It's a package, look for __main__.py spec = find_spec(f"{module_name}.__main__") if spec and spec.origin: entry = spec.origin else: raise ModuleNotFoundError(f"No module named '{module_name}.__main__'; '{module_name}' is a package and cannot be directly executed") elif spec.origin is None: raise ModuleNotFoundError(f"Cannot find entry point for module '{module_name}'") else: entry = spec.origin args[0] = entry # Replace the first argument with the full path _argv = sys.argv[:] sys.argv[:] = args _main = sys.modules["__main__"] try: reloader = SyncReloader(entry) if spec.loader is not _loader: spec.loader = _loader # make it reactive namespace = {"__file__": entry, "__name__": "__main__", "__spec__": spec, "__loader__": _loader, "__package__": spec.parent, "__cached__": None, "__builtins__": builtins} sys.modules["__main__"] = reloader.entry_module = ReactiveModule(Path(entry), namespace, "__main__") reloader.keep_watching_until_interrupt() finally: sys.argv[:] = _argv sys.modules["__main__"] = _main ``` -------------------------------- ### Run HMR without Installation Source: https://hmr.promplate.dev/getting-started/installation Execute the HMR CLI without a formal installation using uvx or pipx. ```bash uvx hmr path/to/entry.py # or pipx run hmr path/to/entry.py ``` -------------------------------- ### __enter__ Source: https://hmr.promplate.dev/references/hmr/api Enters the runtime context related to this object. It starts the hot module reloading process in a separate thread and waits for it to be ready. ```APIDOC ## __enter__ ### Description Enters the runtime context related to this object. It starts the hot module reloading process in a separate thread and waits for it to be ready. ### Method `__enter__` ### Parameters None ### Request Example ```python with AsyncReloaderAPI() as reloader: # Use reloader pass ``` ### Response #### Success Response Returns the reloader object itself. #### Response Example ```python ``` ``` -------------------------------- ### Async Reloader Start Watching Source: https://hmr.promplate.dev/references/hmr/core Initiates asynchronous file watching using `watchfiles.awatch`. It asynchronously iterates over file system events. ```python async def start_watching(self): from watchfiles import awatch async for events in awatch(self.entry, *self.includes, stop_event=self._stop_event): # type: ignore self.on_events(events) del self._stop_event ``` -------------------------------- ### Event for Main Loop Start Source: https://hmr.promplate.dev/references/uvicorn-hmr An event used to signal when the main loop of the Uvicorn server has started. This is crucial for coordinating tasks that depend on the server's readiness. ```python main_loop_started = Event() ``` -------------------------------- ### PipeReloader start_watching Method Source: https://hmr.promplate.dev/references/hmr-daemon Starts the watching process by continuously iterating over pipe events and calling the on_events handler. ```python def start_watching(self): for events in self.iterate_pipe_events(): if shutdown_event.is_set(): return self.on_events(events) ``` -------------------------------- ### Create a New Reactivity Context Source: https://hmr.promplate.dev/references/reactivity/context Initializes and returns a completely new reactivity context. This context starts with empty lists for computations and batches, and a new ContextVar for tracking the current context. ```python def new_context(): return Context([], [], async_execution_context=ContextVar("current context", default=None)) ``` -------------------------------- ### __enter__ Method for SyncReloaderAPI Source: https://hmr.promplate.dev/references/hmr/api Enters the synchronous reloader context. It starts the HMR process with hooks and begins watching for changes in a separate thread. ```python def __enter__(self): from threading import Thread self.run_with_hooks() self.thread = Thread(target=self.start_watching) self.thread.start() return super() ``` -------------------------------- ### Synchronous Context Manager Entry Source: https://hmr.promplate.dev/references/hmr/api Implements the __enter__ method for synchronous context management. It starts a watcher thread and waits for it to be ready. ```python def __enter__(self): from asyncio import run from threading import Event, Thread self.run_with_hooks() e = Event() async def task(): e.set() await self.start_watching() self.thread = Thread(target=lambda: run(task())) self.thread.start() e.wait() return super() ``` -------------------------------- ### Get Code Function Source: https://hmr.promplate.dev/references/hmr-daemon Retrieves and compiles the Abstract Syntax Tree (AST) for a given module name. ```python def get_code(_: ReactiveModuleLoader, fullname: str): from ast import parse from importlib.util import find_spec if (spec := find_spec(fullname)) is not None and (file := spec.origin) is not None: return compile(parse(Path(file).read_text(), str(file)), str(file), "exec", dont_inherit=True) ``` -------------------------------- ### Flask App with Reactivity Signal Source: https://hmr.promplate.dev/integrations/flask A basic Flask application example demonstrating the use of reactivity signals for managing state that can be hot-reloaded. Ensure route registration is idempotent and minimize module-level state for best results. ```python # app.py from flask import Flask, jsonify from reactivity import signal counter = signal(0) # counter can be a reactivity signal app = Flask(__name__) @app.get("/count") def get_count(): return jsonify({"count": counter.get()}) ``` -------------------------------- ### Sync Reloader Start Watching Source: https://hmr.promplate.dev/references/hmr/core Initiates synchronous file watching using `watchfiles.watch`. It iterates over file system events and processes them. ```python def start_watching(self): from watchfiles import watch for events in watch(self.entry, *self.includes, stop_event=self._stop_event): self.on_events(events) del self._stop_event ``` -------------------------------- ### Synchronous Call Entry Point Source: https://hmr.promplate.dev/references/reactivity/async_primitives The synchronous entry point for triggering an asynchronous computation. It tracks the current context and then starts the `_call_async` method, returning the awaitable task. ```python def __call__(self): self.track() return self.start(self._call_async) ``` -------------------------------- ### Signal Initialization Source: https://hmr.promplate.dev/references/reactivity/primitives Initializes a Signal instance with an optional initial value and equality check setting. It ensures proper setup of the reactive state. ```python def __init__(self, initial_value: T = None, check_equality=True, *, context: Context | None = None): super().__init__(context=context) self._value: T = initial_value self._check_equality = check_equality ``` -------------------------------- ### Run FastAPI App with uvicorn-hmr Source: https://hmr.promplate.dev/integrations/uvicorn Run the example FastAPI application using uvicorn-hmr. The --refresh option enables browser auto-refresh. ```bash uvicorn-hmr main:app # with browser auto-refresh (requires `fastapi-reloader` to be installed): uvicorn-hmr main:app --refresh ``` -------------------------------- ### Asynchronous Context Manager Entry Source: https://hmr.promplate.dev/references/hmr/api Implements the __aenter__ method for asynchronous context management. It starts watching for changes asynchronously. ```python async def __aenter__(self): from asyncio import ensure_future, sleep, to_thread await to_thread(self.run_with_hooks) self.future = ensure_future(self.start_watching()) await sleep(0) return super() ``` -------------------------------- ### Main Function for Windows Daemon Source: https://hmr.promplate.dev/references/hmr-daemon Initializes and starts the HMR daemon's watcher for Windows. It configures includes, excludes, and error filters. ```python def main(): state.disabled = True class Reloader(SyncReloader): def __init__(self): self.includes = (".",) self.excludes = excludes self.error_filter = ErrorFilter(*map(str, Path(hmr_file, "..").resolve().glob("**/*.py")), __file__) def start_watching(self): if shutdown_event.is_set(): return from watchfiles import PythonFilter, watch if shutdown_event.is_set(): return for events in watch(".", watch_filter=PythonFilter(), stop_event=shutdown_event): self.on_events(events) if not shutdown_event.is_set(): Reloader().start_watching() ``` -------------------------------- ### __aenter__ Method for SyncReloaderAPI (async) Source: https://hmr.promplate.dev/references/hmr/api Enters the asynchronous reloader context. It runs HMR hooks and starts watching for changes using asyncio. ```python async def __aenter__(self): from asyncio import ensure_future, sleep, to_thread await to_thread(self.run_with_hooks) self.future = ensure_future(to_thread(self.start_watching)) await sleep(0) return super() ``` -------------------------------- ### Synchronize Dirty Dependencies (Sync Wrapper) Source: https://hmr.promplate.dev/references/reactivity/async_primitives Provides a synchronous wrapper to initiate the asynchronous dependency synchronization process. If the sync task is already running, it returns the existing task. Otherwise, it starts a new task for `__sync_dirty_deps`. ```python def _sync_dirty_deps(self): if self._sync_dirty_deps_task is not None: return self._sync_dirty_deps_task task = self._sync_dirty_deps_task = self.start(self.__sync_dirty_deps) return task ``` -------------------------------- ### Async Derived and Effect Example Source: https://hmr.promplate.dev/references/reactivity/async_primitives Demonstrates the usage of async_derived for cached asynchronous computations and async_effect for asynchronous side effects. Requires an active async runtime (like asyncio or trio) and uses 'anyio.sleep' for demonstration. The effect runs initially and reruns when the signal changes. ```python from anyio import sleep from reactivity import signal, async_derived, async_effect count = signal(1) async def main(): @async_derived async def doubled(): await sleep(0.01) return count.get() * 2 @async_effect async def printer(): print(await doubled()) await sleep(0.03) count.set(2) await sleep(0.03) ``` -------------------------------- ### Create Main Application File Source: https://hmr.promplate.dev/getting-started/quick-start Create the `main.py` file that imports and uses the function from `greet.py`. ```python from greet import message print(message()) ``` -------------------------------- ### Build Documentation Preview Source: https://hmr.promplate.dev/contributing Build the project documentation locally to preview changes before deployment. ```bash zensical build # outputs to site/ ``` -------------------------------- ### Create Dependency File Source: https://hmr.promplate.dev/getting-started/quick-start Create the `greet.py` file containing a simple function. ```python def message(): return "Hello, World!" ``` -------------------------------- ### Batch __init__ method Source: https://hmr.promplate.dev/references/reactivity/primitives Initializes a Batch, setting up callbacks and flush behavior. ```python def __init__(self, force_flush=True, *, context: Context | None = None): self.callbacks = set[BaseComputation]() self.force_flush = force_flush self.context = context or default_context ``` -------------------------------- ### Create and Manage a Signal Source: https://hmr.promplate.dev/reactive/signals Demonstrates creating a signal with an initial value, retrieving its value using `.get()`, and updating it using `.set()` or `.update()`. ```python from reactivity import signal s = signal(0) # initial value is 0 print(s.get()) # use .get() to get the value of a signal s.set(1) # set its value to 1 print(s.get()) s.update(lambda x: x + 1) # update using a function ``` -------------------------------- ### UniversalMiddleware __init__ Method Source: https://hmr.promplate.dev/references/fastapi-reloader Initializes the UniversalMiddleware with an ASGI middleware callable. This method is part of the class definition for adapting middleware. ```python def __init__(self, asgi_middleware: Callable[[ASGIApp], T]): self.fn = asgi_middleware super().__init__(self) ``` -------------------------------- ### Observe Initial Output Source: https://hmr.promplate.dev/getting-started/quick-start The initial output when running `main.py` with HMR. ```text Hello, World! ``` -------------------------------- ### run_with_hooks Method Source: https://hmr.promplate.dev/references/hmr/api Executes pre-reload hooks, sets the entry module as the main module, creates an effect for running the entry file, and executes post-reload hooks. ```python def run_with_hooks(self): self._original_main_module = sys.modules["__main__"] sys.modules["__main__"] = self.entry_module call_pre_reload_hooks() self.effect = HMR_CONTEXT.effect(self.run_entry_file) call_post_reload_hooks() ``` -------------------------------- ### Initialize ReactiveSetProxy Source: https://hmr.promplate.dev/references/reactivity/collections Initializes a ReactiveSetProxy with an initial set, equality check preference, and an optional context. ```python def __init__(self, initial: MutableSet[T], check_equality=True, *, context: Context | None = None): self.context = context or default_context self._check_equality = check_equality self._data = initial self._items = defaultdict(self._signal, {k: self._signal(True) for k in tuple(initial)}) self._iter = Subscribable() ``` -------------------------------- ### Name Class get Method Source: https://hmr.promplate.dev/references/hmr/core The get method of the Name class. It ensures that any dirty dependencies are synchronized before retrieving the value. ```python def get(self, track=True): self._sync_dirty_deps() return super().get(track) ``` -------------------------------- ### BaseComputation Initialization Source: https://hmr.promplate.dev/references/reactivity/primitives Initializes a BaseComputation instance. It sets up the context and initializes the dependencies set. Use when creating a new computation that needs to track reactive dependencies. ```python def __init__(self, *, context: Context | None = None): super().__init__() self.dependencies = WeakSet[Subscribable]() self.context = context or default_context ``` -------------------------------- ### Initialize ReactiveMappingProxy Source: https://hmr.promplate.dev/references/reactivity/collections Initializes a ReactiveMappingProxy with an optional initial mapping, equality check, and context. The `_keys` attribute is populated to track the presence of keys. ```python def __init__(self, initial: MutableMapping[K, V], check_equality=True, *, context: Context | None = None): self.context = context or default_context self._check_equality = check_equality self._data = initial self._keys = defaultdict(self._signal, {k: self._signal(True) for k in tuple(initial)}) # in subclasses, self._signal() may mutate `initial` self._iter = Subscribable() ``` -------------------------------- ### Subscribable __init__ Method Source: https://hmr.promplate.dev/references/reactivity/primitives Initializes a Subscribable object, setting up its subscribers set and context. It accepts an optional context argument. ```python __init__(*, context: Context | None = None) ``` ```python def __init__(self, *, context: Context | None = None): super().__init__() self.subscribers = set[BaseComputation]() self.context = context or default_context ``` -------------------------------- ### Get string representation of reactive collection Source: https://hmr.promplate.dev/references/reactivity/collections Returns a string representation of the collection, typically as a list. ```python def __repr__(self): return repr([*self]) ``` -------------------------------- ### Keys Initialization Source: https://hmr.promplate.dev/references/reactivity/collections Initializes a defaultdict to store signals for keys, used for tracking index access. ```python _keys = defaultdict(_signal) ``` -------------------------------- ### Get the length of a collection Source: https://hmr.promplate.dev/references/reactivity/collections Returns the current number of elements in the collection. Tracks iterator access. ```Python def __len__(self): self._iter.track() return self._length ``` -------------------------------- ### Get Length of ReactiveMappingProxy Source: https://hmr.promplate.dev/references/reactivity/collections Returns the number of items in the proxy. It tracks iteration to ensure reactivity. ```python def __len__(self): self._iter.track() return len(self._data) ``` -------------------------------- ### Initialize HMR Core Source: https://hmr.promplate.dev/references/hmr/core Initializes the HMR core with include and exclude paths. Use this to set up the module watching environment. ```python def __init__(self, includes: Iterable[str] = ".", excludes: Iterable[str] = ()): super().__init__() builtins = map(get_paths().__getitem__, ("stdlib", "platstdlib", "platlib", "purelib")) self.includes = _deduplicate(includes) self.excludes = _deduplicate((getenv("VIRTUAL_ENV"), *getsitepackages(), getusersitepackages(), *builtins, *excludes)) setup_fs_audithook() add_filter(lambda path: not is_relative_to_any(path, self.excludes) and is_relative_to_any(path, self.includes)) self._last_sys_path: list[str] = [] self._last_cwd: Path = Path() self._cached_search_paths: list[Path] = [] ``` -------------------------------- ### BaseReloader __init__ Method Source: https://hmr.promplate.dev/references/hmr/core Initializes the BaseReloader with an entry file, include paths, and exclude paths. It also sets up the error filter for module loading. ```python def __init__(self, entry_file: str, includes: Iterable[str] = (".",), excludes: Iterable[str] = ()): self.entry = entry_file self.includes = includes self.excludes = excludes patch_meta_path(includes, excludes) self.error_filter = ErrorFilter(*map(str, Path(__file__, "../..").resolve().glob("**/*.py")), "") ``` -------------------------------- ### Send Reload Signal Source: https://hmr.promplate.dev/references/uvicorn-hmr Attempts to send a reload signal using `fastapi_reloader`. Raises an ImportError if the library is not installed. ```python def _try_refresh(): try: from fastapi_reloader import send_reload_signal send_reload_signal() except ImportError: secho(NOTE, fg="red") raise ``` -------------------------------- ### setup_fs_audithook Source: https://hmr.promplate.dev/references/hmr/fs Sets up a system audit hook to monitor file open events. It filters events based on configured path filters and tracks relevant file changes. ```APIDOC ## setup_fs_audithook ### Description Configures a system-level hook to intercept file open operations. It checks if the opened file matches any registered filters and triggers tracking if it does. ### Method N/A (Function call) ### Endpoint N/A ### Parameters None ### Request Example ```python setup_fs_audithook() ``` ### Response None. This function sets up a side effect (the audit hook). ``` -------------------------------- ### Patch Application for Auto-Reloading Source: https://hmr.promplate.dev/references/uvicorn-hmr Attempts to patch the application for auto-reloading using `fastapi_reloader`. Raises an ImportError if the library is not installed. ```python def _try_patch(app): try: from fastapi_reloader import patch_for_auto_reloading return patch_for_auto_reloading(app) except ImportError: secho(NOTE, fg="red") raise ``` -------------------------------- ### ReactiveModuleFinder Initialization Source: https://hmr.promplate.dev/references/hmr/core Initializes the ReactiveModuleFinder with include and exclude path patterns. It sets up filesystem auditing and adds filters to manage module loading. ```python class ReactiveModuleFinder(MetaPathFinder): def __init__(self, includes: Iterable[str] = ".", excludes: Iterable[str] = ()): super().__init__() builtins = map(get_paths().__getitem__, ("stdlib", "platstdlib", "platlib", "purelib")) self.includes = _deduplicate(includes) self.excludes = _deduplicate((getenv("VIRTUAL_ENV"), *getsitepackages(), getusersitepackages(), *builtins, *excludes)) setup_fs_audithook() add_filter(lambda path: not is_relative_to_any(path, self.excludes) and is_relative_to_any(path, self.includes)) ``` -------------------------------- ### Data Initialization Source: https://hmr.promplate.dev/references/reactivity/collections Sets the initial data for the collection. ```python _data = initial ``` -------------------------------- ### Get Directory Iterator for ReactiveModule Source: https://hmr.promplate.dev/references/hmr/core Provides an iterator for the module's namespace proxy, used for directory listing operations. ```python def __dir__(self): return iter(self.__namespace_proxy) ``` -------------------------------- ### enter Source: https://hmr.promplate.dev/references/reactivity/context Enters a computation context, managing dependencies and ensuring proper cleanup. This context manager is used to wrap computations that should be tracked within the current reactivity system. ```APIDOC ## enter ### Description Enters a computation context. This is a context manager that tracks dependencies and handles potential exceptions or reactivity loss strategies. ### Method `enter(computation: BaseComputation)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python with context_manager.enter(my_computation): # Code that uses my_computation ``` ### Response #### Success Response (yields control back to the `with` block) None #### Response Example None ### Error Handling Handles exceptions by attempting to restore old dependencies if they were lost. Issues a `RuntimeWarning` if a computation loses all its dependencies or has no dependencies and the strategy is not 'ignore'. ``` -------------------------------- ### Import Signal and State Source: https://hmr.promplate.dev/reactive/signals Import the necessary primitives for creating signals and state descriptors. ```python from reactivity import signal, state ``` -------------------------------- ### Initialize Default Reactivity Context Source: https://hmr.promplate.dev/references/reactivity/context This snippet shows the initialization of the default reactivity context using `new_context()`. This is typically used implicitly in simple programs. ```python default_context = new_context() ``` -------------------------------- ### Get descriptor or memoized method Source: https://hmr.promplate.dev/references/reactivity/helpers Handles attribute access for the descriptor. Returns the descriptor itself if accessed on the class, or the memoized method if accessed on an instance. ```python def __get__(self, instance: I | None, owner): if instance is None: return self return self.find(instance) ``` -------------------------------- ### Enter Reactivity Context for Computation Source: https://hmr.promplate.dev/references/reactivity/context Use this context manager to enter a reactivity context for a given computation. It manages dependencies and handles exceptions by potentially restoring old dependencies. It also warns if a computation loses all its dependencies. ```python @contextmanager def enter(self, computation: BaseComputation): old_dependencies = {*computation.dependencies} computation.dispose() self.current_computations.append(computation) try: yield except BaseException: # For backward compatibility, we restore old dependencies only if some dependencies are lost after an exception. # This behavior may be configurable in the future. if computation.dependencies.issubset(old_dependencies): for dep in old_dependencies: dep.subscribers.add(computation) computation.dependencies.update(old_dependencies) raise else: if not computation.dependencies and (strategy := computation.reactivity_loss_strategy) != "ignore": if strategy == "restore" and old_dependencies: for dep in old_dependencies: dep.subscribers.add(computation) computation.dependencies.update(old_dependencies) return from pathlib import Path from sysconfig import get_path from warnings import warn msg = "lost all its dependencies" if old_dependencies else "has no dependencies" warn(f"{computation} {msg} and will never be auto-triggered.", RuntimeWarning, skip_file_prefixes=(str(Path(__file__).parent), str(Path(get_path("stdlib")).resolve()))) finally: last = self.current_computations.pop() assert last is computation # sanity check ``` -------------------------------- ### Get descriptor or memoized value Source: https://hmr.promplate.dev/references/reactivity/helpers Handles attribute access for the descriptor. Returns the descriptor itself if accessed on the class, or the memoized value if accessed on an instance. ```python def __get__(self, instance: I | None, owner): if instance is None: return self return self.find(instance)() ``` -------------------------------- ### Context Isolation Source: https://hmr.promplate.dev/reactive/advanced Shows how to create isolated reactivity environments using `new_context()`. Signals and effects defined within a context are independent of others. ```python ctx = new_context() s = signal(0, context=ctx) @effect(context=ctx) def _(): print(s.get()) ``` -------------------------------- ### Importing Reactivity Utilities Source: https://hmr.promplate.dev/reactive/derived Imports necessary components from the reactivity library for signal and derived value creation. ```python from reactivity import signal, derived, memoized, effect ``` -------------------------------- ### Edit Dependency File Source: https://hmr.promplate.dev/getting-started/quick-start Modify the `greet.py` file to change the return message. Save the file to trigger a reload. ```python def message(): return "HMR is working!" ``` -------------------------------- ### Get Path Module Map Source: https://hmr.promplate.dev/references/hmr/core Retrieves a dictionary mapping module paths to their corresponding `ReactiveModule` instances. This is useful for inspecting the state of HMR-managed modules. ```python def get_path_module_map(): return {**ReactiveModule.instances} ``` -------------------------------- ### Get Item from ReactiveMappingProxy Source: https://hmr.promplate.dev/references/reactivity/collections Retrieves an item from the proxy. It checks if the key is marked as present before accessing the underlying data. Raises KeyError if the key is not present. ```python def __getitem__(self, key: K): if self._keys[key].get(): return self._data[key] raise KeyError(key) ``` -------------------------------- ### Signal Get Method Source: https://hmr.promplate.dev/references/reactivity/primitives Retrieves the current value of the Signal. Optionally tracks the access if `track` is True, which is useful for dependency tracking in reactive systems. ```python def get(self, track=True): if track: self.track() return self._value ``` -------------------------------- ### Initialize ReactiveModule Source: https://hmr.promplate.dev/references/hmr/core Initializes a ReactiveModule instance with file path, namespace, name, and an optional docstring. It updates the instance's dictionary with the provided namespace and sets up internal proxies and hooks. ```python def __init__(self, file: Path, namespace: dict, name: str, doc: str | None = None): super().__init__(name, doc) self.__is_initialized = False self.__dict__.update(namespace) self.__is_initialized = True self.__namespace = namespace self.__namespace_proxy = NamespaceProxy(namespace, self, context=HMR_CONTEXT) self.__hooks: list[Callable[[], Any]] = [] self.__file = file __class__.instances[file.resolve()] = self ``` -------------------------------- ### Signal Class Definition Source: https://hmr.promplate.dev/references/reactivity/primitives Defines the Signal class, which inherits from Subscribable and manages a reactive value. It includes initialization, get, set, and update methods. ```python class Signal[T](Subscribable): def __init__(self, initial_value: T = None, check_equality=True, *, context: Context | None = None): super().__init__(context=context) self._value: T = initial_value self._check_equality = check_equality def get(self, track=True): if track: self.track() return self._value def set(self, value: T): if not self._check_equality or not _equal(self._value, value): self._value = value self.notify() return True return False def update(self, updater: Callable[[T], T]): return self.set(updater(self._value)) ``` -------------------------------- ### Create ReactiveModule using ReactiveModuleLoader Source: https://hmr.promplate.dev/references/hmr/core Creates a new ReactiveModule instance. It sets up the initial namespace with standard module attributes and returns a ReactiveModule initialized with the module's origin path and namespace. ```python def create_module(self, spec: ModuleSpec): assert spec.origin is not None, "This loader can only load file-backed modules" path = Path(spec.origin) namespace = {"__file__": spec.origin, "__spec__": spec, "__loader__": self, "__name__": spec.name, "__package__": spec.parent, "__cached__": None, "__builtins__": __builtins__} if spec.submodule_search_locations is not None: namespace["__path__"] = spec.submodule_search_locations[:] = [str(path.parent)] return ReactiveModule(path, namespace, spec.name) ``` -------------------------------- ### Run HMR with Flask App Source: https://hmr.promplate.dev/integrations/flask Execute HMR to watch and reload your Flask application. This command starts the HMR server, which monitors your Python files for changes. ```bash hmr app.py # or for package entry hmr -m mypackage ``` -------------------------------- ### Create Signal Source: https://hmr.promplate.dev/references/reactivity Creates a signal with an initial value, optional equality checking, and context. ```python def signal[T](initial_value: T = None, /, check_equality=True, *, context: Context | None = None) -> Signal[T]: return Signal(initial_value, check_equality, context=context) ``` -------------------------------- ### Updating a signal to trigger an effect Source: https://hmr.promplate.dev/reactive/effects Demonstrates how changing a signal's value triggers the associated effect to rerun. This example shows the effect printing the new value. ```python s.set(1) ``` -------------------------------- ### State initialization Source: https://hmr.promplate.dev/references/reactivity/primitives Initializes the State object with an optional initial value, a flag to check for equality, and an optional context. ```Python def __init__(self, initial_value: T = None, check_equality=True, *, context: Context | None = None): super().__init__(initial_value, check_equality, context=context) self._value = initial_value self._check_equality = check_equality ``` -------------------------------- ### NamespaceProxy __init__ Method Source: https://hmr.promplate.dev/references/hmr/core The constructor for NamespaceProxy. It initializes the proxy with an initial mapping, associates it with a module, and sets up equality checking and context. ```python def __init__(self, initial: MutableMapping, module: "ReactiveModule", check_equality=True, *, context: Context | None = None): self.module = module super().__init__(initial, check_equality, context=context) ``` -------------------------------- ### Get Item by Integer Index Source: https://hmr.promplate.dev/references/reactivity/collections Retrieves a single item by its integer index. Tracks the access to the specific key signal. Handles both positive and negative indices within the valid range. ```python else: # Handle integer indices self._keys[key].track() if -self._length <= key < self._length: return self._data[key] raise IndexError(key) ``` -------------------------------- ### `cli` Source: https://hmr.promplate.dev/references/hmr Command-line interface for running Python modules with HMR. ```APIDOC ## `cli` ### Description Provides a command-line interface for running Python scripts or modules with Hot Module Replacement (HMR) enabled. It mimics the behavior of the `python` and `python -m` commands. ### Signature ```python cli(args: list[str] | None = None) ``` ### Parameters * **args** (list[str] | None, optional) - A list of command-line arguments. If None, `sys.argv[1:]` is used. Defaults to None. ### Usage Examples * Run a script: `hmr ` * Run a module: `hmr -m ` ### Return Value Returns an integer representing the exit code (0 for success, 1 for error). ``` -------------------------------- ### Run HMR Reloader with Patching Source: https://hmr.promplate.dev/references/hmr-daemon Executes the HMR reloader, managing the patching of the BaseReloader and starting a watch thread. It handles the order of operations for patching and watching based on the `patch_first` flag. ```python def run_reloader(process: Popen): state.disabled = True # disable self-shutdown wrapper until first reloader init def watch(): try: _watch(process) finally: shutdown_event.set() if patch_first: patch() Thread(target=watch, daemon=True, name="hmr-daemon").start() else: Thread(target=lambda: [patch(), watch()], daemon=True, name="hmr-daemon").start() ``` -------------------------------- ### Get Attribute from ReactiveModule Source: https://hmr.promplate.dev/references/hmr/core Handles attribute retrieval for a ReactiveModule. It returns the module's namespace for '__dict__' if initialized, and raises an AttributeError for 'instances' to prevent access to class-level attributes. Otherwise, it delegates to the superclass. ```python def __getattribute__(self, name: str): if name == "__dict__" and self.__is_initialized: return self.__namespace if name == "instances": # class-level attribute raise AttributeError(name) return super().__getattribute__(name) ``` -------------------------------- ### _SimpleEvent __init__ Method Source: https://hmr.promplate.dev/references/hmr/core Initializes the _SimpleEvent, setting its initial state to not set. ```python def __init__(self): self._set = False ``` -------------------------------- ### Name Class Definition Source: https://hmr.promplate.dev/references/hmr/core Defines the Name class, inheriting from Signal and BaseDerived, used for tracking dependencies within the HMR system. It overrides the get method to synchronize dirty dependencies before returning the value. ```python class Name(Signal, BaseDerived): def get(self, track=True): self._sync_dirty_deps() return super().get(track) ``` -------------------------------- ### BaseComputation Enter Context Manager Source: https://hmr.promplate.dev/references/reactivity/primitives Enables the BaseComputation to be used as a context manager. Use with 'with' statements to ensure proper entry and exit, including disposal. ```python def __enter__(self): return self ``` -------------------------------- ### _injection_http_middleware for Hot Reloading Source: https://hmr.promplate.dev/references/fastapi-reloader An asynchronous HTTP middleware that injects a hot-reloading script into HTML responses for GET requests. It conditionally injects the script only if the response is an HTML page, not compressed, and not already flagged for injection. ```python async def _injection_http_middleware(request: Request, call_next: Callable[[Request], Awaitable[Response]]): res = await call_next(request) if request.scope.get(FLAG) or request.method != "GET" or "html" not in (res.headers.get("content-type", "")) or res.headers.get("content-encoding", "identity") != "identity": return res request.scope[FLAG] = True async def response(): if is_streaming_response(res): async for chunk in res.body_iterator: yield chunk else: yield res.body yield INJECTION headers = {k: v for k, v in res.headers.items() if k.lower() not in {"content-length", "transfer-encoding"}} return StreamingResponse(response(), res.status_code, headers, res.media_type) ``` -------------------------------- ### Call Async Computation Source: https://hmr.promplate.dev/references/reactivity/async_primitives Manages the asynchronous execution of a computation. It first synchronizes dirty dependencies, then awaits any ongoing recomputation task, or starts a new one if the state is dirty. Returns the computed value. ```python async def _call_async(self): await self._sync_dirty_deps() try: if self.dirty: if self._call_task is not None: await self._call_task else: task = self._call_task = self.start(self.recompute) await task return self._value finally: self._call_task = None ``` -------------------------------- ### Get Attribute Fallback for ReactiveModule Source: https://hmr.promplate.dev/references/hmr/core Handles missing attributes by attempting to retrieve them from the namespace proxy or the module's namespace. If a fallback '__getattr__' is defined in the namespace proxy, it's used. Otherwise, an AttributeError is raised. ```python def __getattr__(self, name: str): try: return self.__namespace_proxy[name] if name not in STATIC_ATTRS else self.__namespace[name] except KeyError as e: if name not in STATIC_ATTRS and (getattr := self.__namespace_proxy.get("__getattr__")): return getattr(name) raise AttributeError(*e.args) from None ``` -------------------------------- ### Collection Initialization Source: https://hmr.promplate.dev/references/reactivity/collections Initializes a reactive collection with initial data, equality check flag, and context. It sets up internal signals for keys and tracks the initial length. ```python def __init__(self, initial: MutableSequence[T], check_equality=True, *, context: Context | None = None): self.context = context or default_context self._check_equality = check_equality self._data = initial self._keys = keys = defaultdict(self._signal) # positive and negative index signals self._iter = Subscribable() self._length = len(initial) for index in range(-len(initial), len(initial)): keys[index] = self._signal() ``` -------------------------------- ### Command-Line Interface for MCP HMR Source: https://hmr.promplate.dev/references/mcp-hmr Provides a command-line interface for running MCP servers with hot module replacement. It parses arguments for target, transport, log level, and other server configurations. Use this to start an HMR-enabled server from your terminal. ```python def cli(argv: list[str] = sys.argv[1:]): from argparse import SUPPRESS, ArgumentParser parser = ArgumentParser("mcp-hmr", description="Hot Reloading for MCP Servers • Automatically reload on code changes") if sys.version_info >= (3, 14): parser.suggest_on_error = True parser.add_argument("target", help="The import path of the FastMCP instance. Supports module:attr and path:attr") parser.add_argument("-t", "--transport", choices=["stdio", "http", "sse", "streamable-http"], default="stdio", help="Transport protocol to use (default: stdio)") parser.add_argument("-l", "--log-level", choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], type=str.upper, default=None) parser.add_argument("--host", default="localhost", help="Host to bind to for http/sse transports (default: localhost)") parser.add_argument("--port", type=int, default=None, help="Port to bind to for http/sse transports (default: 8000)") parser.add_argument("--path", default=None, help="Route path for the server (default: /mcp for http, /sse for sse)") parser.add_argument("--stateless", action="store_true", help="Shortcut for `stateless_http=True` and `json_response=True`") parser.add_argument("--no-cors", action="store_true", help="Disable CORS (the default is to enable CORS for all origins)") parser.add_argument("--version", action="version", version=f"mcp-hmr {__version__}", help=SUPPRESS) if not argv: parser.print_help() return args = parser.parse_args(argv) target: str = args.target if ":" not in target[1:-1]: parser.exit(1, f"The target argument must be in the format 'module:attr' (e.g. 'main:app') or 'path:attr' (e.g. './path/to/main.py:app'). Got: '{target}'") kwargs = args.__dict__ if kwargs.pop("stateless"): if args.transport != "http": parser.exit(1, "--stateless can only be used with the http transport.") args.json_response = True args.stateless_http = True if kwargs.pop("no_cors"): if args.transport != "http": parser.exit(1, "--no-cors can only be used with the http transport.") elif args.transport == "http": from starlette.middleware import Middleware, cors args.middleware = [Middleware(cors.CORSMiddleware, allow_origins="*", allow_methods="*", allow_headers="*", expose_headers="*")] if args.transport != "stdio": args.uvicorn_config = {"timeout_graceful_shutdown": 1e-100} # align with upstream behavior but prevent error messages when no clients are connected from asyncio import run from contextlib import suppress if (cwd := str(Path.cwd())) not in sys.path: sys.path.append(cwd) if (file := Path(module_or_path := target[: target.rindex(":")])).is_file(): sys.path.insert(0, str(file.parent)) else: if "." in module_or_path: # find_spec may cause implicit imports of parent packages from reactivity.hmr.core import patch_meta_path patch_meta_path() if find_spec(module_or_path) is None: parser.exit(1, f"The target '{module_or_path}' not found. Please provide a valid module name or a file path.") with suppress(KeyboardInterrupt): run(run_with_hmr(**kwargs)) ``` -------------------------------- ### _wrap_asgi_app for Lifespan Management Source: https://hmr.promplate.dev/references/fastapi-reloader Wraps an existing ASGI application to include a lifespan context manager and a reload router. This is used to create a new FastAPI application instance that correctly handles startup and shutdown events for auto-reloading. ```python def _wrap_asgi_app(app: ASGIApp): @asynccontextmanager async def lifespan(_): async with LifespanManager(app, inf, inf): yield new_app = FastAPI(openapi_url=None, lifespan=lifespan) new_app.include_router(reload_router) new_app.mount("/", app) return new_app ``` -------------------------------- ### Run Python File with HMR Source: https://hmr.promplate.dev/references/hmr/run Executes a Python file or a directory containing an `__main__.py` file using HMR. It resolves the entry point, modifies `sys.path` and `sys.argv`, and starts the `SyncReloader`. Use this to run a specific script or package entry point. ```python def run_path(entry: str, args: list[str]): path = Path(entry).resolve() if path.is_dir(): if (__main__ := path / "__main__.py").is_file(): parent = "" path = __main__ else: raise FileNotFoundError(f"No __main__.py file in {path}") elif path.is_file(): parent = None else: raise FileNotFoundError(f"No such file named {path}") entry = str(path) sys.path.insert(0, str(path.parent)) from .core import SyncReloader _argv = sys.argv[:] sys.argv[:] = args _main = sys.modules["__main__"] try: reloader = SyncReloader(entry) sys.modules["__main__"] = mod = reloader.entry_module ns: dict = mod._ReactiveModule__namespace ns.update({"__package__": parent, "__spec__": None if parent is None else mod.__spec__}) reloader.keep_watching_until_interrupt() finally: sys.argv[:] = _argv sys.modules["__main__"] = _main ``` -------------------------------- ### Initialize ReactiveMapping Source: https://hmr.promplate.dev/references/reactivity/collections Initializes a ReactiveMapping with optional initial data and equality checking. ```python class ReactiveMapping[K, V](ReactiveMappingProxy[K, V]): def __init__(self, initial: Mapping[K, V] | None = None, check_equality=True, *, context: Context | None = None): super().__init__({**initial} if initial is not None else {}, check_equality, context=context) ```