Coverage for src/ph/models.py: 100.0%

27 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-28 08:17 +0000

1"""Typed domain models shared by the client and user interfaces.""" 

2 

3from dataclasses import dataclass 

4from pathlib import Path 

5 

6 

7@dataclass(frozen=True, slots=True) 

8class Platform: 

9 """A searchable platform and its accepted user-facing names.""" 

10 

11 name: str 

12 slug: str 

13 code: str 

14 alias: str 

15 rom_folder: str | None = None 

16 alternate_folders: tuple[str, ...] = () 

17 

18 @property 

19 def rom_folders(self) -> tuple[str, ...]: 

20 """Return every accepted folder, with the preferred destination first.""" 

21 

22 if self.rom_folder is None: 

23 return () 

24 return (self.rom_folder, *self.alternate_folders) 

25 

26 

27@dataclass(frozen=True, slots=True) 

28class SearchResult: 

29 """One row returned by a library search.""" 

30 

31 title: str 

32 link: str 

33 system: str = "" 

34 region: str = "" 

35 version: str = "" 

36 languages: str = "-" 

37 rating: str = "-" 

38 

39 

40@dataclass(frozen=True, slots=True) 

41class DownloadResult: 

42 """A completed download.""" 

43 

44 url: str 

45 path: Path 

46 

47 

48@dataclass(frozen=True, slots=True) 

49class MediaDownload: 

50 """A resolved media download, optionally selecting one file from a torrent.""" 

51 

52 url: str 

53 torrent_file_index: int | None = None 

54 expected_filename: str | None = None 

55 torrent_file_path: tuple[str, ...] | None = None 

56 

57 

58@dataclass(frozen=True, slots=True) 

59class InstalledGame: 

60 """One installed title, optionally composed of several referenced files.""" 

61 

62 title: str 

63 platform: Platform 

64 roms_directory: Path 

65 primary_file: Path 

66 files: tuple[Path, ...]