From 34e2b3317cd1ea919a2d4c4d2d4e7c88e4be6c05 Mon Sep 17 00:00:00 2001 From: Bence Csik <22349790+csikb@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:54:48 +0100 Subject: [PATCH 1/5] Use proper DI --- pyproject.toml | 2 +- src/dependencies.py | 20 ++++++++++++++++++++ src/main.py | 7 +++---- src/routers/member.py | 24 ++++++++++++++++-------- src/routers/video.py | 21 +++++++++++++++------ src/services/member.py | 3 +-- src/services/video.py | 3 +-- 7 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 src/dependencies.py diff --git a/pyproject.toml b/pyproject.toml index 8585da6..f9711fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ testcontainers = "4.3.1" profile = "black" [tool.mypy] -packages= "src" +packages = "src" [build-system] requires = ["poetry-core"] diff --git a/src/dependencies.py b/src/dependencies.py new file mode 100644 index 0000000..2efe43a --- /dev/null +++ b/src/dependencies.py @@ -0,0 +1,20 @@ +from functools import lru_cache + +from .services.member import MemberService +from .services.video import VideoService +from .settings import Settings + + +@lru_cache +def get_settings() -> Settings: + return Settings() + + +def get_member_service(settings=get_settings()) -> MemberService: + """Get the member service.""" + return MemberService(settings.server_base_path) + + +def get_video_service(settings=get_settings()) -> VideoService: + """Get the video service.""" + return VideoService(settings.server_base_path) diff --git a/src/main.py b/src/main.py index dae1d44..7ff6694 100644 --- a/src/main.py +++ b/src/main.py @@ -4,12 +4,11 @@ from fastapi import FastAPI +from .dependencies import get_member_service, get_video_service from .routers import health, member, video -from .services.member import MemberService -from .services.video import VideoService -member_service = MemberService() -video_service = VideoService() +member_service = get_member_service() +video_service = get_video_service() @asynccontextmanager diff --git a/src/routers/member.py b/src/routers/member.py index edb2acc..d7f5982 100644 --- a/src/routers/member.py +++ b/src/routers/member.py @@ -5,18 +5,21 @@ from fastapi import APIRouter, Depends, Response, UploadFile, status +from ..dependencies import get_member_service from ..models.member import Member from ..security import authorize -from ..services.member import MemberService router = APIRouter( tags=["Member"], prefix="/api/v1/member", dependencies=[Depends(authorize)] ) -service: MemberService = MemberService() +service = get_member_service() -@router.post("", response_model=Member) -def create_member_folder(member: Member): + +@router.post("") +def create_member_folder( + member: Member, +): """ Create a folder structure for a member and return the member object. :param member: Member object @@ -26,8 +29,10 @@ def create_member_folder(member: Member): return member -@router.put("", response_model=Member) -def update_member_folder(member: Member): +@router.put("") +def update_member_folder( + member: Member, +): """ Update the folder structure for a member and return the member object. If the member does not exist, return a 404. @@ -40,8 +45,11 @@ def update_member_folder(member: Member): return member -@router.post("/{member_id}/profilePicture", response_model=UUID) -async def upload_member_picture(member_id: UUID, file: UploadFile): +@router.post("/{member_id}/profilePicture") +async def upload_member_picture( + member_id: UUID, + file: UploadFile, +): """ Upload a picture for a member to convert and store the profile picture in different formats diff --git a/src/routers/video.py b/src/routers/video.py index 1a1360f..ff936bd 100644 --- a/src/routers/video.py +++ b/src/routers/video.py @@ -5,6 +5,7 @@ from fastapi import APIRouter, Depends, Response, UploadFile, status +from ..dependencies import get_video_service from ..models.video import Video from ..security import authorize from ..services.video import VideoService @@ -12,11 +13,14 @@ router = APIRouter( tags=["Video"], prefix="/api/v1/video", dependencies=[Depends(authorize)] ) -service: VideoService = VideoService() + +service: VideoService = get_video_service() @router.post("", response_model=Video) -def create_video_folder(video: Video): +def create_video_folder( + video: Video, +): """ Create a folder structure for a video and return the video object. :param video: Video object @@ -26,8 +30,10 @@ def create_video_folder(video: Video): return video -@router.put("", response_model=Video) -def update_video_folder(video: Video): +@router.put("") +def update_video_folder( + video: Video, +): """ Update the folder structure for a video and return the video object. If the video does not exist, return a 404. @@ -40,8 +46,11 @@ def update_video_folder(video: Video): return video -@router.post("/{video_id}/thumbnail", response_model=UUID) -async def upload_video_poster(video_id: UUID, file: UploadFile): +@router.post("/{video_id}/thumbnail") +async def upload_video_poster( + video_id: UUID, + file: UploadFile, +): """ Upload a picture for a video thumbnail to convert and store the thumbnail in different formats diff --git a/src/services/member.py b/src/services/member.py index 61ae718..082926c 100644 --- a/src/services/member.py +++ b/src/services/member.py @@ -4,14 +4,13 @@ from uuid import UUID from ..models.member import Member -from ..settings import settings from .image import ImgFormat, create_images class MemberService: """Member service class.""" - def __init__(self, base_path: str = settings.server_base_path): + def __init__(self, base_path: str): self.id_paths_base = Path(base_path, "m") self.url_paths_base = Path(base_path, "member") diff --git a/src/services/video.py b/src/services/video.py index 5afd6c3..ab5208f 100644 --- a/src/services/video.py +++ b/src/services/video.py @@ -4,14 +4,13 @@ from uuid import UUID from ..models.video import Video -from ..settings import settings from .image import ImgFormat, create_images class VideoService: """Video service class.""" - def __init__(self, base_path: str = settings.server_base_path): + def __init__(self, base_path: str): self.id_paths_base = Path(base_path, "v") self.url_paths_base = Path(base_path, "video") From 4430cd4ad5be12acaf2764490929efc0ab77155d Mon Sep 17 00:00:00 2001 From: Bence Csik <22349790+csikb@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:58:02 +0100 Subject: [PATCH 2/5] wip --- src/routers/member.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/routers/member.py b/src/routers/member.py index d7f5982..993c46b 100644 --- a/src/routers/member.py +++ b/src/routers/member.py @@ -1,6 +1,7 @@ """Member endpoints.""" import re +from typing import Annotated from uuid import UUID from fastapi import APIRouter, Depends, Response, UploadFile, status @@ -8,21 +9,21 @@ from ..dependencies import get_member_service from ..models.member import Member from ..security import authorize +from ..services.member import MemberService router = APIRouter( tags=["Member"], prefix="/api/v1/member", dependencies=[Depends(authorize)] ) -service = get_member_service() - @router.post("") def create_member_folder( - member: Member, + member: Member, service: Annotated[MemberService, Depends(get_member_service)] ): """ Create a folder structure for a member and return the member object. :param member: Member object + :param service: service dependency :return: 200 and the original member object """ service.create_folder_structure(member) @@ -31,12 +32,13 @@ def create_member_folder( @router.put("") def update_member_folder( - member: Member, + member: Member, service: Annotated[MemberService, Depends(get_member_service)] ): """ Update the folder structure for a member and return the member object. If the member does not exist, return a 404. :param member: Member object + :param service: service dependency :return: 200 and the original member object """ if not service.to_id_path(member.id).exists(): @@ -49,6 +51,7 @@ def update_member_folder( async def upload_member_picture( member_id: UUID, file: UploadFile, + service: Annotated[MemberService, Depends(get_member_service)], ): """ Upload a picture for a member to convert @@ -57,6 +60,7 @@ async def upload_member_picture( If the file is not an image, return a 500. :param member_id: the id of the member :param file: the image file + :param service: service dependency :return: 200 and the original member_id """ # pylint: disable=duplicate-code From 5354d54f067098edcb2e152eb6e135941ee85b61 Mon Sep 17 00:00:00 2001 From: Bence Csik <22349790+csikb@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:22:57 +0100 Subject: [PATCH 3/5] WIP --- src/dependencies.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/dependencies.py b/src/dependencies.py index 2efe43a..d5ff76d 100644 --- a/src/dependencies.py +++ b/src/dependencies.py @@ -7,14 +7,19 @@ @lru_cache def get_settings() -> Settings: + print("Loading settings") return Settings() -def get_member_service(settings=get_settings()) -> MemberService: +@lru_cache +def get_member_service() -> MemberService: """Get the member service.""" - return MemberService(settings.server_base_path) + print("Loading member service") + return MemberService(get_settings().server_base_path) -def get_video_service(settings=get_settings()) -> VideoService: +@lru_cache +def get_video_service() -> VideoService: """Get the video service.""" - return VideoService(settings.server_base_path) + print("Loading video service") + return VideoService(get_settings().server_base_path) From 27f4b4e9166b2b4955a993cfa92b48fdd2508324 Mon Sep 17 00:00:00 2001 From: Bence Csik <22349790+csikb@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:27:00 +0100 Subject: [PATCH 4/5] WIP --- src/routers/member.py | 6 ++++-- src/routers/video.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/routers/member.py b/src/routers/member.py index 993c46b..9b1a464 100644 --- a/src/routers/member.py +++ b/src/routers/member.py @@ -18,7 +18,8 @@ @router.post("") def create_member_folder( - member: Member, service: Annotated[MemberService, Depends(get_member_service)] + member: Member, + service: Annotated[MemberService, Depends(get_member_service)], ): """ Create a folder structure for a member and return the member object. @@ -32,7 +33,8 @@ def create_member_folder( @router.put("") def update_member_folder( - member: Member, service: Annotated[MemberService, Depends(get_member_service)] + member: Member, + service: Annotated[MemberService, Depends(get_member_service)], ): """ Update the folder structure for a member and return the member object. diff --git a/src/routers/video.py b/src/routers/video.py index ff936bd..c0c99fb 100644 --- a/src/routers/video.py +++ b/src/routers/video.py @@ -1,6 +1,7 @@ """Video endpoints""" import re +from typing import Annotated from uuid import UUID from fastapi import APIRouter, Depends, Response, UploadFile, status @@ -14,12 +15,11 @@ tags=["Video"], prefix="/api/v1/video", dependencies=[Depends(authorize)] ) -service: VideoService = get_video_service() - @router.post("", response_model=Video) def create_video_folder( video: Video, + service: Annotated[VideoService, Depends(get_video_service)], ): """ Create a folder structure for a video and return the video object. @@ -33,6 +33,7 @@ def create_video_folder( @router.put("") def update_video_folder( video: Video, + service: Annotated[VideoService, Depends(get_video_service)], ): """ Update the folder structure for a video and return the video object. @@ -50,6 +51,7 @@ def update_video_folder( async def upload_video_poster( video_id: UUID, file: UploadFile, + service: Annotated[VideoService, Depends(get_video_service)], ): """ Upload a picture for a video thumbnail to convert From 2a15c39487a52f51c2230df778f1729e0c6d2af2 Mon Sep 17 00:00:00 2001 From: Bence Csik <22349790+csikb@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:54:37 +0100 Subject: [PATCH 5/5] WIP --- src/dependencies.py | 18 ++++++++---------- src/main.py | 10 ++++++---- src/services/member.py | 12 ++++++------ src/services/video.py | 12 ++++++------ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/dependencies.py b/src/dependencies.py index d5ff76d..9ef0a5b 100644 --- a/src/dependencies.py +++ b/src/dependencies.py @@ -1,4 +1,7 @@ from functools import lru_cache +from typing import Annotated + +from fastapi import Depends from .services.member import MemberService from .services.video import VideoService @@ -6,20 +9,15 @@ @lru_cache -def get_settings() -> Settings: - print("Loading settings") +def get_settings(): return Settings() -@lru_cache -def get_member_service() -> MemberService: +def get_member_service(settings: Annotated[Settings, Depends(get_settings)]): """Get the member service.""" - print("Loading member service") - return MemberService(get_settings().server_base_path) + return MemberService(settings.server_base_path) -@lru_cache -def get_video_service() -> VideoService: +def get_video_service(settings: Annotated[Settings, Depends(get_settings)]): """Get the video service.""" - print("Loading video service") - return VideoService(get_settings().server_base_path) + return VideoService(settings.server_base_path) diff --git a/src/main.py b/src/main.py index 7ff6694..fac5702 100644 --- a/src/main.py +++ b/src/main.py @@ -4,16 +4,18 @@ from fastapi import FastAPI -from .dependencies import get_member_service, get_video_service +from .dependencies import get_settings from .routers import health, member, video - -member_service = get_member_service() -video_service = get_video_service() +from .services.member import MemberService +from .services.video import VideoService @asynccontextmanager async def lifespan(api: FastAPI): # pylint: disable=unused-argument """Create the base paths for the video and member folders on startup.""" + settings = get_settings() + member_service = MemberService(settings.server_base_path) + video_service = VideoService(settings.server_base_path) video_service.create_base_path() member_service.create_base_path() yield diff --git a/src/services/member.py b/src/services/member.py index 082926c..645f7ba 100644 --- a/src/services/member.py +++ b/src/services/member.py @@ -13,6 +13,11 @@ class MemberService: def __init__(self, base_path: str): self.id_paths_base = Path(base_path, "m") self.url_paths_base = Path(base_path, "member") + self.profile_picture_sizes = [ + ImgFormat(1920, 1080, "xl"), + ImgFormat(1280, 720, "l"), + ImgFormat(854, 480, "m"), + ] def create_folder_structure(self, member: Member): """ @@ -38,12 +43,7 @@ def create_profile_picture(self, img_file: bytes, member_id: UUID): :return: None """ profile_picture_path = Path(self.to_id_path(member_id), "profile") - profile_picture_sizes = [ - ImgFormat(1920, 1080, "xl"), - ImgFormat(1280, 720, "l"), - ImgFormat(854, 480, "m"), - ] - create_images(img_file, profile_picture_path, profile_picture_sizes) + create_images(img_file, profile_picture_path, self.profile_picture_sizes) def update_symlink(self, member: Member): """ diff --git a/src/services/video.py b/src/services/video.py index ab5208f..3d5bd6f 100644 --- a/src/services/video.py +++ b/src/services/video.py @@ -13,6 +13,11 @@ class VideoService: def __init__(self, base_path: str): self.id_paths_base = Path(base_path, "v") self.url_paths_base = Path(base_path, "video") + self.poster_sizes = [ + ImgFormat(1920, 1080, "fhd"), + ImgFormat(1280, 720, "hd"), + ImgFormat(854, 480, "sd"), + ] def create_folder_structure(self, video: Video): """ @@ -40,12 +45,7 @@ def create_thumbnails(self, img_file: bytes, video_id: UUID): :return: None """ thumbnail_path = Path(self.to_id_path(video_id), "thumbnail") - poster_sizes = [ - ImgFormat(1920, 1080, "fhd"), - ImgFormat(1280, 720, "hd"), - ImgFormat(854, 480, "sd"), - ] - create_images(img_file, thumbnail_path, poster_sizes) + create_images(img_file, thumbnail_path, self.poster_sizes) def update_symlinks(self, video: Video): """