diff options
Diffstat (limited to 'backend/route_manager.py')
-rw-r--r-- | backend/route_manager.py | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/backend/route_manager.py b/backend/route_manager.py index bac275a..c48ea8e 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -4,15 +4,17 @@ Module to dynamically generate a Starlette routing map based on a directory tree import importlib import inspect +import typing as t + from pathlib import Path -from starlette.routing import Route as StarletteRoute, Mount +from starlette.routing import Route as StarletteRoute, BaseRoute, Mount from nested_dict import nested_dict from backend.route import Route -def construct_route_map_from_dict(route_dict: dict) -> list: +def construct_route_map_from_dict(route_dict: dict) -> list[BaseRoute]: route_map = [] for mount, item in route_dict.items(): if inspect.isclass(item): @@ -26,35 +28,39 @@ def construct_route_map_from_dict(route_dict: dict) -> list: return route_map -def create_route_map() -> list: - routes_directory = Path("backend") / "routes" - - route_dict = nested_dict() - - for file in routes_directory.rglob("*.py"): - import_name = f"{'.'.join(file.parent.parts)}.{file.stem}" +def is_route_class(member: t.Any) -> bool: + return inspect.isclass(member) and issubclass(member, Route) and member != Route - route = importlib.import_module(import_name) - for _member_name, member in inspect.getmembers(route): - if inspect.isclass(member): - if issubclass(member, Route) and member != Route: - member.check_parameters() +def route_classes() -> t.Iterator[tuple[Path, type[Route]]]: + routes_directory = Path("backend") / "routes" - levels = file.parent.parts[2:] + for module_path in routes_directory.rglob("*.py"): + import_name = f"{'.'.join(file.parent.parts)}.{file.stem}" + route_module = importlib.import_module(import_name) + for _member_name, member in inspect.getmembers(route_module): + if is_route_class(member): + member.check_parameters() + yield (module_path, member) - current_level = None - for level in levels: - if current_level is None: - current_level = route_dict[f"/{level}"] - else: - current_level = current_level[f"/{level}"] - if current_level is not None: - current_level[member.path] = member - else: - route_dict[member.path] = member +def create_route_map() -> list[BaseRoute]: + route_dict = nested_dict() - route_map = construct_route_map_from_dict(route_dict.to_dict()) + for module_path, member in route_classes(): + # module_path == Path("backend/routes/foo/bar/baz/bin.py") + # => levels == ["foo", "bar", "baz"] + levels = file.parent.parts[2:] + current_level = None + for level in levels: + if current_level is None: + current_level = route_dict[f"/{level}"] + else: + current_level = current_level[f"/{level}"] + + if current_level is not None: + current_level[member.path] = member + else: + route_dict[member.path] = member - return route_map + return construct_route_map_from_dict(route_dict.to_dict()) |