Merge pull request #2264 from rommapp/fs-size-column-props

Use column properties to calculate fs_size_bytes
This commit is contained in:
Georges-Antoine Assi
2025-08-15 10:52:53 -05:00
committed by GitHub
2 changed files with 46 additions and 46 deletions

View File

@@ -4,7 +4,7 @@ from functools import cached_property
from typing import TYPE_CHECKING
from models.base import BaseModel
from models.rom import Rom
from models.rom import Rom, RomFile
from sqlalchemy import String, func, select
from sqlalchemy.orm import Mapped, column_property, mapped_column, relationship
@@ -55,6 +55,14 @@ class Platform(BaseModel):
select(func.count(Rom.id)).where(Rom.platform_id == id).scalar_subquery()
)
fs_size_bytes: Mapped[int] = column_property(
select(func.coalesce(func.sum(RomFile.file_size_bytes), 0))
.select_from(RomFile.__table__.join(Rom.__table__, RomFile.rom_id == Rom.id))
.where(Rom.platform_id == id)
.correlate_except(RomFile, Rom)
.scalar_subquery()
)
missing_from_fs: Mapped[bool] = mapped_column(default=False, nullable=False)
@property
@@ -72,12 +80,6 @@ class Platform(BaseModel):
def is_identified(self) -> bool:
return not self.is_unidentified
@cached_property
def fs_size_bytes(self) -> int:
from handler.database import db_stats_handler
return db_stats_handler.get_platform_filesize(self.id)
@cached_property
def igdb_slug(self) -> str | None:
from handler.metadata import meta_igdb_handler

View File

@@ -22,8 +22,10 @@ from sqlalchemy import (
String,
Text,
UniqueConstraint,
func,
select,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.orm import Mapped, column_property, mapped_column, relationship
from utils.database import CustomJSON
if TYPE_CHECKING:
@@ -193,6 +195,8 @@ class Rom(BaseModel):
sha1_hash: Mapped[str | None] = mapped_column(String(length=100))
ra_hash: Mapped[str | None] = mapped_column(String(length=100))
missing_from_fs: Mapped[bool] = mapped_column(default=False, nullable=False)
platform_id: Mapped[int] = mapped_column(
ForeignKey("platforms.id", ondelete="CASCADE")
)
@@ -222,7 +226,12 @@ class Rom(BaseModel):
back_populates="roms",
)
missing_from_fs: Mapped[bool] = mapped_column(default=False, nullable=False)
fs_size_bytes: Mapped[int] = column_property(
select(func.coalesce(func.sum(RomFile.file_size_bytes), 0))
.where(RomFile.rom_id == id)
.correlate_except(RomFile)
.scalar_subquery()
)
@property
def platform_slug(self) -> str:
@@ -261,20 +270,9 @@ class Rom(BaseModel):
@cached_property
def multi(self) -> bool:
# TODO: Improve multi game detection as this is a very basic check
if len(self.files) > 1:
return True
if (
self.files
and len(self.files) > 0
and len(self.files[0].full_path.split("/")) > 3
):
return True
return False
@cached_property
def fs_size_bytes(self) -> int:
return sum(f.file_size_bytes for f in self.files)
return len(self.files) > 1 or (
len(self.files) > 0 and len(self.files[0].full_path.split("/")) > 3
)
@property
def fs_resources_path(self) -> str:
@@ -296,7 +294,29 @@ class Rom(BaseModel):
else ""
)
# # Metadata fields
@property
def is_unidentified(self) -> bool:
return (
not self.igdb_id
and not self.moby_id
and not self.ss_id
and not self.ra_id
and not self.launchbox_id
and not self.hasheous_id
)
@property
def is_identified(self) -> bool:
return not self.is_unidentified
def has_m3u_file(self) -> bool:
"""
Check if the ROM has an M3U file associated with it.
This is used for multi-disc games.
"""
return any(file.file_extension.lower() == "m3u" for file in self.files)
# Metadata fields
@property
def youtube_video_id(self) -> str | None:
igdb_video_id = (
@@ -333,28 +353,6 @@ class Rom(BaseModel):
)
return self.ra_metadata
@property
def is_unidentified(self) -> bool:
return (
not self.igdb_id
and not self.moby_id
and not self.ss_id
and not self.ra_id
and not self.launchbox_id
and not self.hasheous_id
)
@property
def is_identified(self) -> bool:
return not self.is_unidentified
def has_m3u_file(self) -> bool:
"""
Check if the ROM has an M3U file associated with it.
This is used for multi-disc games.
"""
return any(file.file_extension.lower() == "m3u" for file in self.files)
def __repr__(self) -> str:
return self.fs_name