Skip to content

Commit 1bd09e7

Browse files
authored
Merge pull request #2486 from rommapp/rom-multi-file-rework
Split `rom.multi` into more specific fields
2 parents 54e2bcf + 35bfe9e commit 1bd09e7

File tree

13 files changed

+83
-33
lines changed

13 files changed

+83
-33
lines changed

backend/endpoints/responses/rom.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import re
44
from datetime import datetime, timezone
5-
from typing import NotRequired, TypedDict, get_type_hints
5+
from typing import Annotated, NotRequired, TypedDict, get_type_hints
66

77
from fastapi import Request
8-
from pydantic import computed_field, field_validator
8+
from pydantic import Field, computed_field, field_validator
99

1010
from endpoints.responses.assets import SaveSchema, ScreenshotSchema, StateSchema
1111
from handler.metadata.flashpoint_handler import FlashpointMetadata
@@ -255,7 +255,11 @@ class RomSchema(BaseModel):
255255
md5_hash: str | None
256256
sha1_hash: str | None
257257

258-
multi: bool
258+
# TODO: Remove this after 4.3 release
259+
multi: Annotated[bool, Field(deprecated="Replaced by has_multiple_files")]
260+
has_simple_single_file: bool
261+
has_nested_single_file: bool
262+
has_multiple_files: bool
259263
files: list[RomFileSchema]
260264
full_path: str
261265
created_at: datetime

backend/endpoints/sockets/scan.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ async def _identify_rom(
200200
tags=fs_other_tags,
201201
platform_id=platform.id,
202202
name=fs_rom["fs_name"],
203-
multi=fs_rom["multi"],
204203
url_cover="",
205204
url_manual="",
206205
url_screenshots=[],

backend/handler/filesystem/roms_handler.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@
9393

9494

9595
class FSRom(TypedDict):
96-
multi: bool
9796
fs_name: str
97+
flat: bool
98+
nested: bool
9899
files: list[RomFile]
99100
crc_hash: str
100101
md5_hash: str
@@ -247,7 +248,7 @@ def parse_tags(self, fs_name: str) -> tuple:
247248
other_tags.append(tag)
248249
return regs, rev, langs, other_tags
249250

250-
def _exclude_multi_roms(self, roms: list[str]) -> list[str]:
251+
def exclude_multi_roms(self, roms: list[str]) -> list[str]:
251252
excluded_names = cm.get_config().EXCLUDED_MULTI_FILES
252253
filtered_files: list = []
253254

@@ -511,18 +512,19 @@ async def get_roms(self, platform: Platform) -> list[FSRom]:
511512
raise RomsNotFoundException(platform=platform.fs_slug) from e
512513

513514
fs_roms: list[dict] = [
514-
{"multi": False, "fs_name": rom}
515+
{"fs_name": rom, "flat": True, "nested": False}
515516
for rom in self.exclude_single_files(fs_single_roms)
516517
] + [
517-
{"multi": True, "fs_name": rom}
518-
for rom in self._exclude_multi_roms(fs_multi_roms)
518+
{"fs_name": rom, "flat": False, "nested": True}
519+
for rom in self.exclude_multi_roms(fs_multi_roms)
519520
]
520521

521522
return sorted(
522523
[
523524
FSRom(
524-
multi=rom["multi"],
525525
fs_name=rom["fs_name"],
526+
flat=rom["flat"],
527+
nested=rom["nested"],
526528
files=[],
527529
crc_hash="",
528530
md5_hash="",

backend/handler/scan_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ async def scan_rom(
295295
"platform_id": platform.id,
296296
"name": fs_rom["fs_name"],
297297
"fs_name": fs_rom["fs_name"],
298-
"multi": fs_rom["multi"],
299298
"crc_hash": fs_rom["crc_hash"],
300299
"md5_hash": fs_rom["md5_hash"],
301300
"sha1_hash": fs_rom["sha1_hash"],
@@ -741,7 +740,8 @@ async def fetch_sgdb_details() -> SGDBRom:
741740
f"{hl(rom_attrs['fs_name'])} identified as {hl(rom_attrs['name'], color=BLUE)} {emoji.EMOJI_ALIEN_MONSTER}",
742741
extra=LOGGER_MODULE_NAME,
743742
)
744-
if rom.multi:
743+
744+
if rom.has_nested_single_file or rom.has_multiple_files:
745745
for file in fs_rom["files"]:
746746
log.info(
747747
f"\t · {hl(file.file_name, color=LIGHTYELLOW)}",

backend/models/rom.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ def file_extension(self) -> str:
100100

101101
return fs_rom_handler.parse_file_extension(self.file_name)
102102

103+
@cached_property
104+
def is_nested(self) -> bool:
105+
return self.file_path.count("/") > 1
106+
103107
def file_name_for_download(self, rom: Rom, hidden_folder: bool = False) -> str:
104108
# This needs a trailing slash in the path to work!
105109
return self.full_path.replace(
@@ -286,11 +290,22 @@ def merged_screenshots(self) -> list[str]:
286290

287291
return []
288292

293+
# TODO: Remove this after 4.3 release
289294
@cached_property
290295
def multi(self) -> bool:
291-
return len(self.files) > 1 or (
292-
len(self.files) > 0 and len(self.files[0].full_path.split("/")) > 3
293-
)
296+
return self.has_nested_single_file or self.has_multiple_files
297+
298+
@cached_property
299+
def has_simple_single_file(self) -> bool:
300+
return len(self.files) == 1 and not self.files[0].is_nested
301+
302+
@cached_property
303+
def has_nested_single_file(self) -> bool:
304+
return len(self.files) == 1 and self.files[0].is_nested
305+
306+
@cached_property
307+
def has_multiple_files(self) -> bool:
308+
return len(self.files) > 1
294309

295310
@property
296311
def fs_resources_path(self) -> str:

backend/tests/handler/filesystem/test_roms_handler.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,24 @@ def rom_single(self, platform: Platform):
4848

4949
@pytest.fixture
5050
def rom_multi(self, platform: Platform):
51-
rom = Rom(
51+
return Rom(
5252
id=2,
5353
fs_name="Super Mario 64 (J) (Rev A)",
5454
fs_path="n64/roms",
5555
platform=platform,
56+
files=[
57+
RomFile(
58+
id=1,
59+
file_name="Super Mario 64 (J) (Rev A) [Part 1].z64",
60+
file_path="n64/roms",
61+
),
62+
RomFile(
63+
id=2,
64+
file_name="Super Mario 64 (J) (Rev A) [Part 2].z64",
65+
file_path="n64/roms",
66+
),
67+
],
5668
)
57-
rom.multi = True
58-
return rom
5969

6070
def test_init_uses_library_base_path(self, handler: FSRomsHandler):
6171
"""Test that FSRomsHandler initializes with LIBRARY_BASE_PATH"""
@@ -155,19 +165,19 @@ def test_parse_tags_no_tags(self, handler: FSRomsHandler):
155165
assert other_tags == []
156166

157167
def test_exclude_multi_roms_filters_excluded(self, handler: FSRomsHandler, config):
158-
"""Test _exclude_multi_roms filters out excluded multi-file ROMs"""
168+
"""Test exclude_multi_roms filters out excluded multi-file ROMs"""
159169
roms = ["Game1", "excluded_multi", "Game2", "Game3"]
160170

161171
with pytest.MonkeyPatch.context() as m:
162172
m.setattr("handler.filesystem.roms_handler.cm.get_config", lambda: config)
163173

164-
result = handler._exclude_multi_roms(roms)
174+
result = handler.exclude_multi_roms(roms)
165175
expected = ["Game1", "Game2", "Game3"]
166176

167177
assert result == expected
168178

169179
def test_exclude_multi_roms_no_exclusions(self, handler: FSRomsHandler):
170-
"""Test _exclude_multi_roms with no exclusions"""
180+
"""Test exclude_multi_roms with no exclusions"""
171181
roms = ["Game1", "Game2", "Game3"]
172182
config = Config(
173183
EXCLUDED_PLATFORMS=[],
@@ -185,7 +195,7 @@ def test_exclude_multi_roms_no_exclusions(self, handler: FSRomsHandler):
185195
with pytest.MonkeyPatch.context() as m:
186196
m.setattr("handler.filesystem.roms_handler.cm.get_config", lambda: config)
187197

188-
result = handler._exclude_multi_roms(roms)
198+
result = handler.exclude_multi_roms(roms)
189199
assert result == roms
190200

191201
def test_build_rom_file_single_file(self, handler: FSRomsHandler):
@@ -254,8 +264,8 @@ async def test_get_roms(self, handler: FSRomsHandler, platform, config):
254264
assert len(result) > 0
255265

256266
# Check that we have both single and multi ROMs
257-
single_roms = [r for r in result if not r["multi"]]
258-
multi_roms = [r for r in result if r["multi"]]
267+
single_roms = [r for r in result if not r["flat"]]
268+
multi_roms = [r for r in result if r["nested"]]
259269

260270
assert len(single_roms) > 0
261271
assert len(multi_roms) > 0
@@ -477,7 +487,7 @@ async def test_multi_rom_directory_handling(self, handler: FSRomsHandler, config
477487
assert "Test Multi Rom [USA]" in directories
478488

479489
# After exclusion, normal directories should remain
480-
filtered_dirs = handler._exclude_multi_roms(directories)
490+
filtered_dirs = handler.exclude_multi_roms(directories)
481491
assert "Super Mario 64 (J) (Rev A)" in filtered_dirs
482492
assert "Test Multi Rom [USA]" in filtered_dirs
483493

backend/tests/handler/test_fastapi.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ async def test_scan_rom():
4242
igdb_id=3340,
4343
fs_size_bytes=1024,
4444
tags=[],
45-
multi=False,
4645
)
4746

4847
async with initialize_context():
@@ -52,7 +51,8 @@ async def test_scan_rom():
5251
rom=rom,
5352
fs_rom={
5453
"fs_name": "Paper Mario (USA).z64",
55-
"multi": False,
54+
"flat": True,
55+
"nested": False,
5656
"files": [
5757
RomFile(
5858
file_name="Paper Mario (USA).z64",
@@ -73,7 +73,7 @@ async def test_scan_rom():
7373
assert type(rom) is Rom
7474
assert rom.fs_name == "Paper Mario (USA).z64"
7575
assert rom.name == "Paper Mario"
76+
assert rom.fs_path == "n64/Paper Mario (USA)"
7677
assert rom.igdb_id == 3340
7778
assert rom.fs_size_bytes == 1024
7879
assert rom.tags == []
79-
assert not rom.multi

frontend/src/__generated__/models/DetailedRomSchema.ts

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

frontend/src/__generated__/models/SimpleRomSchema.ts

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

frontend/src/components/Details/Info/FileInfo.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ watch(
4646
<template>
4747
<v-row no-gutters>
4848
<v-col>
49-
<v-row v-if="!rom.multi" class="align-center my-3" no-gutters>
49+
<v-row
50+
v-if="rom.has_simple_single_file"
51+
class="align-center my-3"
52+
no-gutters
53+
>
5054
<v-col cols="3" xl="2" class="mr-2">
5155
<span>{{ t("rom.file") }}</span>
5256
</v-col>
@@ -58,7 +62,7 @@ watch(
5862
/><span class="text-body-1">{{ rom.fs_name }}</span>
5963
</v-col>
6064
</v-row>
61-
<v-row v-if="rom.multi" class="align-center my-3" no-gutters>
65+
<v-row v-else class="align-center my-3" no-gutters>
6266
<v-col cols="3" xl="2" class="mr-2">
6367
<span>{{ t("rom.files") }}</span>
6468
</v-col>

0 commit comments

Comments
 (0)