aboutsummaryrefslogtreecommitdiffstats
path: root/backend/route_manager.py
diff options
context:
space:
mode:
authorGravatar Joe Banks <[email protected]>2020-10-25 19:50:36 +0000
committerGravatar Joe Banks <[email protected]>2020-10-25 19:50:36 +0000
commita68686f9d77147fb034d6dea646b3fb9336faf2e (patch)
treebf4f04868840a54c1c853bf961e5eae9db428f23 /backend/route_manager.py
parentAdd database middleware (diff)
Add route class and route manager for dynamic route loading
Diffstat (limited to 'backend/route_manager.py')
-rw-r--r--backend/route_manager.py57
1 files changed, 57 insertions, 0 deletions
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