Skip to content

Commit 68fa5dd

Browse files
Implement file size warning
Closes #44, Regenerate tests
1 parent a22f02c commit 68fa5dd

10 files changed

Lines changed: 985 additions & 511 deletions

File tree

mediux_posters/__main__.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from collections.abc import Generator
33
from enum import Enum
44
from platform import python_version
5-
from typing import Annotated, Protocol, TypeVar
5+
from typing import Annotated, Final, Protocol, TypeVar
66

77
from typer import Abort, Argument, Context, Exit, Option, Typer
88

@@ -27,7 +27,10 @@
2727
LOGGER = logging.getLogger(__project__)
2828
app = Typer(no_args_is_help=True)
2929
app.add_typer(settings_app, name="settings")
30-
HIGH_VALUE = 1_000_000
30+
31+
# Constants
32+
DEFAULT_CREATOR_RANK: Final[int] = 1_000_000
33+
MAX_IMAGE_SIZE: Final[int] = 10_000_000 # 10 MB
3134

3235

3336
class ServiceOption(str, Enum):
@@ -108,7 +111,7 @@ def process_set_data(
108111
def get_creator_rank(creator: str | None) -> int:
109112
if creator and creator in priority_usernames:
110113
return priority_usernames.index(creator)
111-
return HIGH_VALUE
114+
return DEFAULT_CREATOR_RANK
112115

113116
def find_matching_file(file_type: FileType, id_value: int) -> File | None:
114117
for f in set_data.files:
@@ -166,6 +169,14 @@ def process_image(
166169
LOGGER.error("[Mediux] %s", err)
167170
return
168171

172+
if image_file.stat().st_size >= MAX_IMAGE_SIZE:
173+
LOGGER.warning(
174+
"[%s] Image file '%s' is larger than %d MB, skipping upload",
175+
type(service).__name__,
176+
image_file,
177+
MAX_IMAGE_SIZE,
178+
)
179+
return
169180
try:
170181
success = service.upload_image(
171182
object_id=obj.id, image_file=image_file, kometa_integration=kometa_integration

tests/application_test.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from unittest.mock import MagicMock, patch
2+
3+
import pytest
4+
5+
from mediux_posters.__main__ import MAX_IMAGE_SIZE, process_set_data
6+
from mediux_posters.mediux import Mediux
7+
from mediux_posters.mediux.schemas import MovieSet as SetData
8+
from mediux_posters.services._base.schemas import BaseMovie as Media
9+
from mediux_posters.services._base.service import BaseService
10+
from mediux_posters.services.service_cache import ServiceCache
11+
12+
13+
@pytest.fixture
14+
def mock_services() -> tuple[Mediux, BaseService]:
15+
mediux: Mediux = MagicMock(spec=Mediux)
16+
service: BaseService = MagicMock(spec=BaseService)
17+
service_cache: ServiceCache = MagicMock(spec=ServiceCache)
18+
service_cache.select.return_value = None
19+
service.cache = service_cache
20+
return mediux, service
21+
22+
23+
@pytest.mark.parametrize(
24+
("max_size", "should_warn"),
25+
[(MAX_IMAGE_SIZE + 1, True), (MAX_IMAGE_SIZE, True), (MAX_IMAGE_SIZE - 1, False)],
26+
)
27+
def test_image_size_warning_threshold(
28+
media_obj: Media,
29+
set_data: SetData,
30+
mock_services: tuple[Mediux, BaseService],
31+
max_size: int,
32+
should_warn: bool,
33+
) -> None:
34+
mediux, service = mock_services
35+
36+
image_file = MagicMock()
37+
image_file.stat.return_value.st_size = max_size
38+
39+
with (
40+
patch("mediux_posters.__main__.get_cached_image", return_value=image_file),
41+
patch("mediux_posters.__main__.LOGGER") as mock_logger,
42+
):
43+
process_set_data(
44+
entry=media_obj,
45+
set_data=set_data,
46+
mediux=mediux,
47+
service=service,
48+
priority_usernames=[],
49+
)
50+
if should_warn:
51+
mock_logger.warning.assert_called_once()
52+
else:
53+
mock_logger.warning.assert_not_called()

tests/conftest.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import os
2+
from datetime import date, datetime
23

34
import pytest
45

5-
from mediux_posters.mediux import Mediux
6+
from mediux_posters.mediux import FileType, Mediux
7+
from mediux_posters.mediux.schemas import File, Movie as MediuxMedia, MovieSet as SetData
8+
from mediux_posters.services._base.schemas import BaseMovie as Media
69
from mediux_posters.services.jellyfin import Jellyfin
710
from mediux_posters.services.plex import Plex
811

@@ -60,3 +63,27 @@ def plex_session(plex_base_url: str | None, plex_token: str | None) -> Plex | No
6063
assert plex.validate() is True
6164
return plex
6265
return None
66+
67+
68+
@pytest.fixture
69+
def media_obj() -> Media:
70+
return Media(id=1, name="Test Movie", tmdb_id=1, year=2025)
71+
72+
73+
@pytest.fixture
74+
def set_data() -> SetData:
75+
return SetData(
76+
date_updated=datetime.now(), # noqa: DTZ005
77+
files=[
78+
File(
79+
id="file-poster-id",
80+
file_type=FileType.POSTER,
81+
modified_on=datetime.now(), # noqa: DTZ005
82+
movie_id=1,
83+
)
84+
],
85+
id=1,
86+
movie_id=MediuxMedia(id=1, release_date=date.today(), title="Test Movie"), # noqa: DTZ011
87+
set_title="Test Set",
88+
username="Test User",
89+
)

tests/jellyfin_test.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ def test_get_series(jellyfin_session: Jellyfin | None, httpx_mock: HTTPXMock) ->
6161
result = jellyfin_session.get_show(tmdb_id=33907)
6262
assert result is not None
6363

64-
assert result.id == "375ad80948bb3e9bd78684d915430bfa"
64+
assert result.id == "7df9cc7bbd2d497ec18b448731d3c1ec"
6565
assert result.imdb_id == "tt1606375"
6666
assert result.name == "Downton Abbey"
6767
assert result.premiere_date == date(2010, 9, 26)
6868
assert result.tmdb_id == 33907
69-
assert result.tv_maze_id == 251
69+
assert result.tv_maze_id is None
7070
assert result.tv_rage_id == 26615
7171
assert result.tvdb_id == 193131
7272
assert result.year == 2010
@@ -87,10 +87,10 @@ def test_list_seasons(jellyfin_session: Jellyfin | None, httpx_mock: HTTPXMock)
8787
is_reusable=True,
8888
)
8989

90-
results = jellyfin_session.list_seasons(show_id="375ad80948bb3e9bd78684d915430bfa")
90+
results = jellyfin_session.list_seasons(show_id="7df9cc7bbd2d497ec18b448731d3c1ec")
9191
assert len(results) != 0
9292

93-
assert results[1].id == "759a122515cb24b264e906bb80f3f06a"
93+
assert results[1].id == "a32f5e92104998e8991c370feccb83e6"
9494
assert results[1].imdb_id is None
9595
assert results[1].name == "Season 1"
9696
assert results[1].number == 1
@@ -117,11 +117,11 @@ def test_list_episodes(jellyfin_session: Jellyfin | None, httpx_mock: HTTPXMock)
117117
)
118118

119119
results = jellyfin_session.list_episodes(
120-
show_id="375ad80948bb3e9bd78684d915430bfa", season_id="759a122515cb24b264e906bb80f3f06a"
120+
show_id="7df9cc7bbd2d497ec18b448731d3c1ec", season_id="a32f5e92104998e8991c370feccb83e6"
121121
)
122122
assert len(results) != 0
123123

124-
assert results[0].id == "d26bb397376eb1e63b2621eaa3ff9add"
124+
assert results[0].id == "54cdfd0a76e33e9aa61d0946856b963f"
125125
assert results[0].imdb_id == "tt1608844"
126126
assert results[0].name == "Episode 1"
127127
assert results[0].number == 1

tests/plex_test.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ def test_list_movies(plex_session: Plex | None, httpx_mock: HTTPXMock) -> None:
243243
results = plex_session.list_movies()
244244
assert len(results) != 0
245245

246-
result = next(iter(x for x in results if x.tmdb_id == 431580), None)
246+
result = next(iter(x for x in results if x.tmdb_id == 302946), None)
247247
assert result is not None
248248

249249

@@ -267,13 +267,13 @@ def test_get_movie(plex_session: Plex | None, httpx_mock: HTTPXMock) -> None:
267267
is_reusable=True,
268268
)
269269

270-
result = plex_session.get_movie(tmdb_id=431580)
270+
result = plex_session.get_movie(tmdb_id=302946)
271271
assert result is not None
272272

273-
assert result.id == 102210
274-
assert result.imdb_id == "tt6324278"
275-
assert result.name == "Abominable"
276-
assert result.premiere_date == date(2019, 9, 19)
277-
assert result.tmdb_id == 431580
278-
assert result.tvdb_id == 12176
279-
assert result.year == 2019
273+
assert result.id == 120683
274+
assert result.imdb_id == "tt2140479"
275+
assert result.name == "The Accountant"
276+
assert result.premiere_date == date(2016, 10, 13)
277+
assert result.tmdb_id == 302946
278+
assert result.tvdb_id == 940
279+
assert result.year == 2016

tests/resources/jellyfin/get-show.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{
44
"Name": "Downton Abbey",
55
"ServerId": "dc3a12fa42114b4b9e119db7af393829",
6-
"Id": "375ad80948bb3e9bd78684d915430bfa",
6+
"Id": "7df9cc7bbd2d497ec18b448731d3c1ec",
77
"PremiereDate": "2010-09-26T00:00:00.0000000Z",
88
"OfficialRating": "TV-14",
99
"ChannelId": null,
@@ -14,8 +14,7 @@
1414
"Imdb": "tt1606375",
1515
"Tmdb": "33907",
1616
"TvRage": "26615",
17-
"Tvdb": "193131",
18-
"TvMaze": "251"
17+
"Tvdb": "193131"
1918
},
2019
"IsFolder": true,
2120
"Type": "Series",

tests/resources/jellyfin/list-episodes.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{
44
"Name": "Episode 1",
55
"ServerId": "dc3a12fa42114b4b9e119db7af393829",
6-
"Id": "d26bb397376eb1e63b2621eaa3ff9add",
6+
"Id": "54cdfd0a76e33e9aa61d0946856b963f",
77
"HasSubtitles": true,
88
"Container": "mkv",
99
"PremiereDate": "2010-09-26T00:00:00.0000000Z",
@@ -46,7 +46,7 @@
4646
"ae93cc1aa5891be2b76a99eb735eaefb"
4747
],
4848
"SeriesName": "Downton Abbey",
49-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
49+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
5050
"SeasonId": "759a122515cb24b264e906bb80f3f06a",
5151
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
5252
"SeasonName": "Season 1",
@@ -143,7 +143,7 @@
143143
"ae93cc1aa5891be2b76a99eb735eaefb"
144144
],
145145
"SeriesName": "Downton Abbey",
146-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
146+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
147147
"SeasonId": "759a122515cb24b264e906bb80f3f06a",
148148
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
149149
"SeasonName": "Season 1",
@@ -240,7 +240,7 @@
240240
"ae93cc1aa5891be2b76a99eb735eaefb"
241241
],
242242
"SeriesName": "Downton Abbey",
243-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
243+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
244244
"SeasonId": "759a122515cb24b264e906bb80f3f06a",
245245
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
246246
"SeasonName": "Season 1",

tests/resources/jellyfin/list-seasons.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"ae93cc1aa5891be2b76a99eb735eaefb"
4141
],
4242
"SeriesName": "Downton Abbey",
43-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
43+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
4444
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
4545
"ImageTags": {
4646
"Primary": "64b4c4c21e0cbbc341622540882ca38c"
@@ -91,7 +91,7 @@
9191
{
9292
"Name": "Season 1",
9393
"ServerId": "dc3a12fa42114b4b9e119db7af393829",
94-
"Id": "759a122515cb24b264e906bb80f3f06a",
94+
"Id": "a32f5e92104998e8991c370feccb83e6",
9595
"PremiereDate": "2010-09-26T00:00:00.0000000Z",
9696
"ChannelId": null,
9797
"ProductionYear": 2010,
@@ -128,7 +128,7 @@
128128
"ae93cc1aa5891be2b76a99eb735eaefb"
129129
],
130130
"SeriesName": "Downton Abbey",
131-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
131+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
132132
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
133133
"ImageTags": {
134134
"Primary": "99328cc41550afff23f9e8bd58ea9728"
@@ -216,7 +216,7 @@
216216
"ae93cc1aa5891be2b76a99eb735eaefb"
217217
],
218218
"SeriesName": "Downton Abbey",
219-
"SeriesId": "375ad80948bb3e9bd78684d915430bfa",
219+
"SeriesId": "7df9cc7bbd2d497ec18b448731d3c1ec",
220220
"SeriesPrimaryImageTag": "6cdccd5e1d7bb45616000a1fd1fe2933",
221221
"ImageTags": {
222222
"Primary": "85603468b2c3d256febdf2f57d42d657"

tests/resources/jellyfin/list-shows.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
{
8686
"Name": "Downton Abbey",
8787
"ServerId": "dc3a12fa42114b4b9e119db7af393829",
88-
"Id": "375ad80948bb3e9bd78684d915430bfa",
88+
"Id": "7df9cc7bbd2d497ec18b448731d3c1ec",
8989
"PremiereDate": "2010-09-26T00:00:00.0000000Z",
9090
"OfficialRating": "TV-14",
9191
"ChannelId": null,
@@ -96,8 +96,7 @@
9696
"Imdb": "tt1606375",
9797
"Tmdb": "33907",
9898
"TvRage": "26615",
99-
"Tvdb": "193131",
100-
"TvMaze": "251"
99+
"Tvdb": "193131"
101100
},
102101
"IsFolder": true,
103102
"Type": "Series",

0 commit comments

Comments
 (0)