Skip to content

Commit 8b9d76c

Browse files
committed
add unit test and more coverage
1 parent 87c2aec commit 8b9d76c

File tree

9 files changed

+421
-175
lines changed

9 files changed

+421
-175
lines changed

poetry.lock

Lines changed: 66 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ packages = [{include = "bss_web_file_server", from = "src"}]
88

99
[tool.poetry.dependencies]
1010
python = "^3.12"
11-
fastapi = {extras=["all"], version="0.110.0"}
12-
uvicorn = {extras = ["standard"], version = "0.28.0"}
11+
fastapi = {version="0.110.0", extras=["all"]}
12+
uvicorn = {version = "0.28.0", extras = ["standard"]}
1313
pillow = "10.2.0"
1414
pillow-avif-plugin = "1.4.3"
1515
python-multipart = "0.0.9"
@@ -20,6 +20,7 @@ pylint = "3.1.0"
2020
black = "24.3.0"
2121
isort = "5.13.2"
2222
types-Pillow = "10.1.0.2"
23+
coverage = {version = "^7.4.4", extras = ["test"]}
2324

2425
[tool.poetry.group.test.dependencies]
2526
httpx = "^0.23.0"
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
""" A module for storing the video model. """
22

3+
from typing import Annotated
34
from uuid import UUID
45

6+
from annotated_types import Len
57
from pydantic import BaseModel
68

79

810
class Video(BaseModel):
911
"""A class for storing video data."""
1012

1113
id: UUID
12-
urls: list[str]
14+
urls: Annotated[list[str], Len(min_length=1)]

src/bss_web_file_server/services/member.py

Lines changed: 83 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,85 +7,87 @@
77
from ..settings import settings
88
from .image import ImgFormat, create_images
99

10-
id_paths_base = Path(settings.server_base_path, "m")
11-
url_paths_base = Path(settings.server_base_path, "member")
1210

13-
14-
def create_folder_structure(member: Member):
15-
"""
16-
This method will create the folder structure for a member.
17-
/m/{member.id}/profile
18-
And a symlink to the id folder from the url folder
19-
/member/{member.url} -> /m/{member.id}
20-
:param member: the member object
21-
:return: None
22-
"""
23-
id_path = to_id_path(member.id)
24-
id_path.mkdir(parents=True, exist_ok=True)
25-
# create a folder for the profile pictures
26-
Path(id_path, "profile").mkdir(exist_ok=True)
27-
update_symlink(member)
28-
29-
30-
def create_profile_picture(img_file: bytes, member_id: UUID):
31-
"""
32-
This method will create the profile picture in different formats
33-
/m/{member.id}/profile/{size}.{format}
34-
:param img_file: the image file
35-
:param member_id: the id of the member
36-
:return: None
37-
"""
38-
profile_picture_path = Path(to_id_path(member_id), "profile")
39-
profile_picture_sizes = [
40-
ImgFormat(1920, 1080, "xl"),
41-
ImgFormat(1280, 720, "l"),
42-
ImgFormat(854, 480, "m"),
43-
]
44-
create_images(img_file, profile_picture_path, profile_picture_sizes)
45-
46-
47-
def update_symlink(member: Member):
48-
"""
49-
This method will update the symlink to the id folder from the url folder
50-
First it will remove all references to the id folder
51-
Then it will create a new symlink to the id path
52-
:param member: the member object
53-
:return: None
54-
"""
55-
id_path = to_id_path(member.id)
56-
for url_path in url_paths_base.glob("*/"):
57-
if url_path.is_symlink() and url_path.readlink().samefile(id_path):
58-
url_path.unlink(missing_ok=True)
59-
to_url_path(member.url).symlink_to(
60-
# use the absolute path to the id folder
61-
target=id_path.resolve(),
62-
target_is_directory=True,
63-
)
64-
65-
66-
# pylint: disable=duplicate-code
67-
def create_member_base_path():
68-
"""This method will create the parent folder for all id and url folders."""
69-
if not id_paths_base.exists():
70-
id_paths_base.mkdir(parents=True, exist_ok=True)
71-
if not url_paths_base.exists():
72-
url_paths_base.mkdir(parents=True, exist_ok=True)
73-
74-
75-
def to_id_path(member_id: UUID):
76-
"""
77-
This method will return the base path
78-
where the id folders for members are located.
79-
"""
80-
return Path(id_paths_base, str(member_id))
81-
82-
83-
def to_url_path(member_url: str):
84-
"""
85-
This method will return the base path
86-
where the url folders for members are located.
87-
"""
88-
return Path(url_paths_base, member_url)
89-
90-
91-
# pylint: enable=duplicate-code
11+
class MemberService:
12+
13+
def __init__(self, base_path: str = settings.server_base_path):
14+
self.id_paths_base = Path(base_path, "m")
15+
self.url_paths_base = Path(base_path, "member")
16+
17+
def create_folder_structure(self, member: Member):
18+
"""
19+
This method will create the folder structure for a member.
20+
/m/{member.id}/profile
21+
And a symlink to the id folder from the url folder
22+
/member/{member.url} -> /m/{member.id}
23+
:param member: the member object
24+
:return: None
25+
"""
26+
id_path = self.to_id_path(member.id)
27+
id_path.mkdir(parents=True, exist_ok=True)
28+
# create a folder for the profile pictures
29+
Path(id_path, "profile").mkdir(exist_ok=True)
30+
self.update_symlink(member)
31+
32+
def create_profile_picture(self, img_file: bytes, member_id: UUID):
33+
"""
34+
This method will create the profile picture in different formats
35+
/m/{member.id}/profile/{size}.{format}
36+
:param img_file: the image file
37+
:param member_id: the id of the member
38+
:return: None
39+
"""
40+
profile_picture_path = Path(self.to_id_path(member_id), "profile")
41+
profile_picture_sizes = [
42+
ImgFormat(1920, 1080, "xl"),
43+
ImgFormat(1280, 720, "l"),
44+
ImgFormat(854, 480, "m"),
45+
]
46+
create_images(img_file, profile_picture_path, profile_picture_sizes)
47+
48+
def update_symlink(self, member: Member):
49+
"""
50+
This method will update the symlink to the id folder from the url folder
51+
First it will check if the id folder exists
52+
Then it will remove all references to the id folder
53+
Finally it will create a new symlink to the id path
54+
:param member: the member object
55+
:return: None
56+
"""
57+
id_path = self.to_id_path(member.id)
58+
if not id_path.exists():
59+
raise FileNotFoundError(f"Member folder {id_path.resolve()} does not exist")
60+
for url_path in self.url_paths_base.iterdir():
61+
if url_path.is_symlink() and url_path.readlink().samefile(id_path):
62+
url_path.unlink(missing_ok=True)
63+
self.to_url_path(member.url).symlink_to(
64+
# use the absolute path to the id folder
65+
target=id_path.resolve(),
66+
target_is_directory=True,
67+
)
68+
69+
# pylint: disable=duplicate-code
70+
def create_member_base_path(self):
71+
"""
72+
This method will create the parent folder for all id and url folders.
73+
"""
74+
if not self.id_paths_base.exists():
75+
self.id_paths_base.mkdir(parents=True, exist_ok=True)
76+
if not self.url_paths_base.exists():
77+
self.url_paths_base.mkdir(parents=True, exist_ok=True)
78+
79+
def to_id_path(self, member_id: UUID):
80+
"""
81+
This method will return the base path
82+
where the id folders for members are located.
83+
"""
84+
return Path(self.id_paths_base, str(member_id))
85+
86+
def to_url_path(self, member_url: str):
87+
"""
88+
This method will return the base path
89+
where the url folders for members are located.
90+
"""
91+
return Path(self.url_paths_base, member_url)
92+
93+
# pylint: enable=duplicate-code

0 commit comments

Comments
 (0)