From a68686f9d77147fb034d6dea646b3fb9336faf2e Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sun, 25 Oct 2020 19:50:36 +0000 Subject: Add route class and route manager for dynamic route loading --- backend/route_manager.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 backend/route_manager.py (limited to 'backend/route_manager.py') diff --git a/backend/route_manager.py b/backend/route_manager.py new file mode 100644 index 0000000..ef5d835 --- /dev/null +++ b/backend/route_manager.py @@ -0,0 +1,57 @@ +""" +Module to dynamically generate a Starlette routing map based on a directory tree. +""" + +import importlib +import inspect +from pathlib import Path + +from starlette.routing import Route as StarletteRoute, Mount +from nested_dict import nested_dict + +from backend.route import Route + + +def construct_route_map_from_dict(route_dict: dict): + route_map = [] + for mount, item in route_dict.items(): + if inspect.isclass(item): + route_map.append(StarletteRoute(mount, item)) + else: + route_map.append(Mount(mount, routes=construct_route_map_from_dict(item))) + + return route_map + + +def create_route_map(): + routes_directory = Path("backend") / "routes" + + route_dict = nested_dict() + + for file in routes_directory.rglob("*.py"): + import_name = f"{str(file.parent).replace('/', '.')}.{file.stem}" + + 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() + + levels = str(file.parent).split("/")[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 + + route_map = construct_route_map_from_dict(route_dict.to_dict()) + + return route_map -- cgit v1.2.3