diff --git a/examples/run.py b/examples/run.py index 35ba35f..368512d 100644 --- a/examples/run.py +++ b/examples/run.py @@ -1,11 +1,10 @@ from datetime import date, datetime, timezone -import uvicorn from fastapi import Request from pydantic import BaseModel -from examples.data import df -from uiwiz import UiwizApp, ui +from data import df +from uiwiz import UiwizApp, ui, server from uiwiz.element import Element as element app = UiwizApp() @@ -94,4 +93,4 @@ def replace(request: Request, input: DataInput): if __name__ == "__main__": - uvicorn.run("run:app", reload=True) + server.run("run:app") diff --git a/src/uiwiz/server/_server.py b/src/uiwiz/server/_server.py index c47231d..452ff62 100644 --- a/src/uiwiz/server/_server.py +++ b/src/uiwiz/server/_server.py @@ -9,6 +9,7 @@ from dataclasses import dataclass from collections import deque from contextlib import suppress +import copy from uvicorn._types import ( ASGI3Application, @@ -19,6 +20,7 @@ from uvicorn.protocols.http.flow_control import HIGH_WATER_LIMIT from uiwiz.app import UiwizApp +from uiwiz import shared import logging formatter = logging.Formatter( @@ -47,10 +49,23 @@ class Config: def import_app_instance(config: Config) -> None: start = perf_counter() if isinstance(config.app, str): + routes = [] + if config.app_instance is not None: + # As the user can register new endpoints with a lambda function and this can happen inside of an endpoint + # i.e not when the application is first loaded but during the exeuction of the endpoint. It is nesscary to + # save the endpoint data and transfer it to the newly created application + routes = copy.copy(config.app_instance.router.routes) + _page_map = copy.copy(shared.page_map) + _resources = copy.copy(shared.resources) + module_name, _, app = config.app.partition(":") module = importlib.import_module(module_name) module = importlib.reload(module) config.app_instance = getattr(module, app) + if routes: + config.app_instance.router.routes = routes + shared.page_map = _page_map + shared.resources = _resources else: config.app_instance = config.app end = perf_counter() @@ -425,6 +440,7 @@ async def run_asgi(self, app: ASGI3Application) -> None: class Server: def __init__(self, config: Config): + logger.warning("Development server. Do not use in production!") self.config = config self.server_state = None import_app_instance(config) diff --git a/src/uiwiz/shared.py b/src/uiwiz/shared.py index 7f3e24b..b6e7d6e 100644 --- a/src/uiwiz/shared.py +++ b/src/uiwiz/shared.py @@ -7,9 +7,8 @@ resources: Dict[str, Path] = {} page_map: Dict[Callable, str] = {} - @lru_cache(maxsize=None) -def hash_function_extended(func): +def _hash_function_extended(func) -> str: """ This was an interesting problem. I needed to hash the function to be able to store the route in a dictionary. Nothing special @@ -26,19 +25,19 @@ def hash_function_extended(func): return hashlib.sha256(source.encode("utf-8")).hexdigest() -def register_resource(key: str, resource: Path): +def register_resource(key: str, resource: Path) -> None: resources[key] = resource -def register_path(key: str, func: Callable): - page_map[hash_function_extended(func)] = key +def register_path(key: str, func: Callable) -> None: + page_map[_hash_function_extended(func)] = key def fetch_route(func: Callable) -> Optional[str]: - return page_map.get(hash_function_extended(func)) + return page_map.get(_hash_function_extended(func)) -def reset_resources(): +def reset_resources() -> None: resources.clear() page_map.clear()