aboutsummaryrefslogtreecommitdiffstats
path: root/backend/route_manager.py
diff options
context:
space:
mode:
Diffstat (limited to 'backend/route_manager.py')
-rw-r--r--backend/route_manager.py60
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())