Skip to content

Commit

Permalink
Fix routes when using uvicorn workers or reload functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Declow committed Jan 15, 2025
1 parent d4d9f4b commit cc001e7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 9 deletions.
25 changes: 20 additions & 5 deletions tests/test_page_router.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from uiwiz.app import UiwizApp
from uiwiz.page_route import PageRouter
from uiwiz.shared import page_map
from uiwiz.shared import fetch_route


def test_page_go_to_get_request():
Expand All @@ -16,9 +16,7 @@ def func():

apis = {item.path: item for item in app.routes}

print(page_map)

assert route == page_map[func]
assert route == fetch_route(func)
assert route == apis.get(route).path
assert "func" == apis.get(route).name
assert {"GET"} == apis.get(route).methods
Expand All @@ -38,7 +36,24 @@ def func():

apis = {item.path: item for item in app.routes}

assert route == page_map[func]
assert route == fetch_route(func)
assert route == apis.get(route).path
assert "func" == apis.get(route).name
assert {"POST"} == apis.get(route).methods


def test_app_ui_go_to_post_request():
app = UiwizApp()

route = "/path"

@app.ui(route)
def func():
... # pragma: no cover

apis = {item.path: item for item in app.routes}

assert route == fetch_route(func)
assert route == apis.get(route).path
assert "func" == apis.get(route).name
assert {"POST"} == apis.get(route).methods
4 changes: 2 additions & 2 deletions uiwiz/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from uiwiz.element_types import ELEMENT_SIZE, ELEMENT_TYPES, VOID_ELEMENTS
from uiwiz.event import FUNC_TYPE, TARGET_TYPE, Event
from uiwiz.frame import Frame
from uiwiz.shared import page_map, register_resource, route_exists
from uiwiz.shared import fetch_route, register_resource, route_exists


class Element:
Expand Down Expand Up @@ -220,7 +220,7 @@ def __get_endpoint__(self, func: FUNC_TYPE) -> str:
if isinstance(func, str):
return func

endpoint: Optional[str] = page_map.get(func)
endpoint: Optional[str] = fetch_route(func)
if endpoint:
if params := self.event.get("params"):
return endpoint.format(**params)
Expand Down
25 changes: 23 additions & 2 deletions uiwiz/shared.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
import hashlib
import inspect
from functools import lru_cache
from pathlib import Path
from typing import Callable, Dict
from typing import Callable, Dict, Optional

resources: Dict[str, Path] = {}
page_map: Dict[Callable, str] = {}


@lru_cache(maxsize=None)
def hash_function_extended(func):
"""
This was an interesting problem. I needed to hash the function
to be able to store the route in a dictionary. Nothing special
but the reason for using the source code has to do with
uvicorn and multiple workers. The function object is not the
same in different workers, so I had to use the source code
to generate a hash that would be the same in all workers.
"""
source = inspect.getsource(func)
return hashlib.sha256(source.encode("utf-8")).hexdigest()


def register_resource(key: str, resource: Path):
resources[key] = resource


def register_path(key: str, func: Callable):
page_map[func] = key
page_map[hash_function_extended(func)] = key


def fetch_route(func: Callable) -> Optional[str]:
return page_map.get(hash_function_extended(func))


def reset_resources():
Expand Down

0 comments on commit cc001e7

Please sign in to comment.