From 947a30f7406b7d025cf2e5754b59389af4213718 Mon Sep 17 00:00:00 2001 From: decorator-factory <42166884+decorator-factory@users.noreply.github.com> Date: Tue, 15 Dec 2020 08:13:37 +0300 Subject: fix various type annotation issues --- backend/route_manager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backend/route_manager.py') diff --git a/backend/route_manager.py b/backend/route_manager.py index 25529eb..7427298 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -6,13 +6,13 @@ import importlib import inspect 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,7 +26,7 @@ def construct_route_map_from_dict(route_dict: dict) -> list: return route_map -def create_route_map() -> list: +def create_route_map() -> list[BaseRoute]: routes_directory = Path("backend") / "routes" route_dict = nested_dict() -- cgit v1.2.3 From 7e98943c9d15b2f81f83fc6bfc75e9b3a57eb31c Mon Sep 17 00:00:00 2001 From: decorator-factory <42166884+decorator-factory@users.noreply.github.com> Date: Tue, 15 Dec 2020 08:28:22 +0300 Subject: minor refactorings --- backend/authentication/backend.py | 7 +++---- backend/authentication/user.py | 3 +-- backend/models/form.py | 4 ++-- backend/route_manager.py | 35 +++++++++++++++++++---------------- 4 files changed, 25 insertions(+), 24 deletions(-) (limited to 'backend/route_manager.py') diff --git a/backend/authentication/backend.py b/backend/authentication/backend.py index e4699bd..f1d2ece 100644 --- a/backend/authentication/backend.py +++ b/backend/authentication/backend.py @@ -1,6 +1,5 @@ import jwt import typing as t -from abc import ABC from starlette import authentication from starlette.requests import Request @@ -10,7 +9,7 @@ from backend import constants from .user import User -class JWTAuthenticationBackend(authentication.AuthenticationBackend, ABC): +class JWTAuthenticationBackend(authentication.AuthenticationBackend): """Custom Starlette authentication backend for JWT.""" @staticmethod @@ -35,7 +34,7 @@ class JWTAuthenticationBackend(authentication.AuthenticationBackend, ABC): ) -> t.Optional[tuple[authentication.AuthCredentials, authentication.BaseUser]]: """Handles JWT authentication process.""" if "Authorization" not in request.headers: - return + return None auth = request.headers["Authorization"] token = self.get_token_from_header(auth) @@ -47,7 +46,7 @@ class JWTAuthenticationBackend(authentication.AuthenticationBackend, ABC): scopes = ["authenticated"] - if payload.get("admin", False) is True: + if payload.get("admin") is True: scopes.append("admin") return authentication.AuthCredentials(scopes), User(token, payload) diff --git a/backend/authentication/user.py b/backend/authentication/user.py index 3bed0a1..722c348 100644 --- a/backend/authentication/user.py +++ b/backend/authentication/user.py @@ -1,10 +1,9 @@ import typing as t -from abc import ABC from starlette.authentication import BaseUser -class User(BaseUser, ABC): +class User(BaseUser): """Starlette BaseUser implementation for JWT authentication.""" def __init__(self, token: str, payload: dict[str, t.Any]) -> None: diff --git a/backend/models/form.py b/backend/models/form.py index 21cc549..cb58065 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -25,8 +25,8 @@ class Form(BaseModel): """Validates is all features in allowed list.""" # Uppercase everything to avoid mixed case in DB value = [v.upper() for v in value] - allowed_values = list(v.value for v in FormFeatures.__members__.values()) - if not all(v in allowed_values for v in value): + allowed_values = [v.value for v in FormFeatures.__members__.values()] + if any(v not in allowed_values for v in value): raise ValueError("Form features list contains one or more invalid values.") if FormFeatures.COLLECT_EMAIL in value and FormFeatures.REQUIRES_LOGIN not in value: # noqa diff --git a/backend/route_manager.py b/backend/route_manager.py index 7427298..437cbf6 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -4,6 +4,8 @@ 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, BaseRoute, Mount @@ -26,6 +28,10 @@ def construct_route_map_from_dict(route_dict: dict) -> list[BaseRoute]: return route_map +def is_route_class(member: t.Any) -> bool: + return inspect.isclass(member) and issubclass(member, Route) and member != Route + + def create_route_map() -> list[BaseRoute]: routes_directory = Path("backend") / "routes" @@ -37,24 +43,21 @@ def create_route_map() -> list[BaseRoute]: 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() + if is_route_class(member): + member.check_parameters() - levels = str(file.parent).split("/")[2:] + 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 + current_level = None + for level in levels: + if current_level is None: + current_level = route_dict[f"/{level}"] else: - route_dict[member.path] = member + current_level = current_level[f"/{level}"] - route_map = construct_route_map_from_dict(route_dict.to_dict()) + 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()) -- cgit v1.2.3 From 55d51f87438fe0402b34f653807e596a3d2082c0 Mon Sep 17 00:00:00 2001 From: decorator-factory <42166884+decorator-factory@users.noreply.github.com> Date: Tue, 15 Dec 2020 09:03:00 +0300 Subject: refactor route discovery --- backend/route_manager.py | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'backend/route_manager.py') diff --git a/backend/route_manager.py b/backend/route_manager.py index 437cbf6..7866404 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -17,6 +17,7 @@ from backend.route import Route def construct_route_map_from_dict(route_dict: dict) -> list[BaseRoute]: route_map = [] for mount, item in route_dict.items(): + print(mount, item) if inspect.isclass(item): route_map.append(StarletteRoute(mount, item)) else: @@ -32,32 +33,35 @@ def is_route_class(member: t.Any) -> bool: return inspect.isclass(member) and issubclass(member, Route) and member != Route -def create_route_map() -> list[BaseRoute]: +def route_classes() -> t.Iterator[tuple[Path, type[Route]]]: 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): + for module_path in routes_directory.rglob("*.py"): + import_name = f"{str(module_path.parent).replace('/', '.')}.{module_path.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) - 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}"] +def create_route_map() -> list[BaseRoute]: + route_dict = nested_dict() - if current_level is not None: - current_level[member.path] = member - else: - route_dict[member.path] = member + for module_path, member in route_classes(): + # module_path == Path("backend/routes/foo/bar/baz/bin.py") + # => levels == ["foo", "bar", "baz"] + levels = str(module_path.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 return construct_route_map_from_dict(route_dict.to_dict()) -- cgit v1.2.3 From 9c7af9c463672a24657153245d8f1b0c59e69589 Mon Sep 17 00:00:00 2001 From: decorator-factory <42166884+decorator-factory@users.noreply.github.com> Date: Tue, 15 Dec 2020 09:21:34 +0300 Subject: remove stray print --- backend/route_manager.py | 1 - 1 file changed, 1 deletion(-) (limited to 'backend/route_manager.py') diff --git a/backend/route_manager.py b/backend/route_manager.py index 7866404..d9e5700 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -17,7 +17,6 @@ from backend.route import Route def construct_route_map_from_dict(route_dict: dict) -> list[BaseRoute]: route_map = [] for mount, item in route_dict.items(): - print(mount, item) if inspect.isclass(item): route_map.append(StarletteRoute(mount, item)) else: -- cgit v1.2.3 From fc04997fa483464d5daee52a9d70745df555f5b1 Mon Sep 17 00:00:00 2001 From: decorator-factory <42166884+decorator-factory@users.noreply.github.com> Date: Tue, 15 Dec 2020 09:30:53 +0300 Subject: Fix f-string referencing the wrong name Fix missing type annotation Lint fix --- backend/route.py | 2 +- backend/route_manager.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'backend/route_manager.py') diff --git a/backend/route.py b/backend/route.py index d8c38fc..d778bf0 100644 --- a/backend/route.py +++ b/backend/route.py @@ -9,7 +9,7 @@ class Route(HTTPEndpoint): path: str @classmethod - def check_parameters(cls): + def check_parameters(cls) -> None: if not hasattr(cls, "name"): raise ValueError(f"Route {cls.__name__} has not defined a name") diff --git a/backend/route_manager.py b/backend/route_manager.py index c48ea8e..031c9b3 100644 --- a/backend/route_manager.py +++ b/backend/route_manager.py @@ -36,7 +36,7 @@ def route_classes() -> t.Iterator[tuple[Path, type[Route]]]: routes_directory = Path("backend") / "routes" for module_path in routes_directory.rglob("*.py"): - import_name = f"{'.'.join(file.parent.parts)}.{file.stem}" + import_name = f"{'.'.join(module_path.parent.parts)}.{module_path.stem}" route_module = importlib.import_module(import_name) for _member_name, member in inspect.getmembers(route_module): if is_route_class(member): @@ -50,7 +50,7 @@ def create_route_map() -> list[BaseRoute]: 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:] + levels = module_path.parent.parts[2:] current_level = None for level in levels: if current_level is None: -- cgit v1.2.3