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

43 statements  

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

1"""Application configuration loaded from environment variables.""" 

2 

3import os 

4from collections.abc import Mapping 

5from dataclasses import dataclass 

6from pathlib import Path 

7from typing import Self 

8 

9from ph.targets import DARKOS, LinuxTarget, resolve_target 

10from ph.updater import DEFAULT_UPDATE_API_URL 

11 

12DEFAULT_VIMM_BASE_URL = "https://vimm.net" 

13DEFAULT_MINERVA_BASE_URL = "https://minerva-archive.org" 

14DEFAULT_MINERVA_TORRENT_BASE_URL = "https://cdn.minerva-archive.org/torrents" 

15 

16 

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

18class Config: 

19 """Runtime settings shared by every supported Linux target.""" 

20 

21 vimm_base_url: str 

22 download_directory: Path 

23 roms_directories: tuple[Path, ...] 

24 timeout_seconds: float = 30.0 

25 minerva_base_url: str = DEFAULT_MINERVA_BASE_URL 

26 minerva_torrent_base_url: str = DEFAULT_MINERVA_TORRENT_BASE_URL 

27 enabled_stores: tuple[str, ...] = ("vimm", "minerva") 

28 install_directory: Path | None = None 

29 update_api_url: str = DEFAULT_UPDATE_API_URL 

30 log_file: Path | None = None 

31 log_level: str = "INFO" 

32 target: LinuxTarget = DARKOS 

33 

34 @classmethod 

35 def from_environment(cls, environment: Mapping[str, str] | None = None) -> Self: 

36 """Build settings with DarkOS as the currently tested default target.""" 

37 

38 values = os.environ if environment is None else environment 

39 vimm_base_url = values.get("PH_VIMM_BASE_URL", DEFAULT_VIMM_BASE_URL).rstrip("/") 

40 directory = Path(values.get("PH_DOWNLOAD_DIR", ".")).expanduser() 

41 roms_values = values.get("PH_ROMS_DIRS") 

42 if roms_values is not None: 

43 roms_directories = tuple( 

44 dict.fromkeys( 

45 Path(value).expanduser() 

46 for value in roms_values.split(os.pathsep) 

47 if value.strip() 

48 ) 

49 ) 

50 else: 

51 roms_value = values.get("PH_ROMS_DIR") 

52 roms_directories = (Path(roms_value).expanduser(),) if roms_value else () 

53 timeout = float(values.get("PH_TIMEOUT", "30")) 

54 minerva_base_url = values.get("PH_MINERVA_BASE_URL", DEFAULT_MINERVA_BASE_URL).rstrip("/") 

55 minerva_torrent_base_url = values.get( 

56 "PH_MINERVA_TORRENT_BASE_URL", DEFAULT_MINERVA_TORRENT_BASE_URL 

57 ).rstrip("/") 

58 enabled_stores = tuple( 

59 dict.fromkeys( 

60 store.strip().casefold() 

61 for store in values.get("PH_STORES", "vimm,minerva").split(",") 

62 if store.strip() 

63 ) 

64 ) 

65 install_value = values.get("PH_INSTALL_DIR") 

66 install_directory = Path(install_value).expanduser() if install_value else None 

67 update_api_url = values.get("PH_UPDATE_API_URL", DEFAULT_UPDATE_API_URL) 

68 log_value = values.get("PH_LOG_FILE") 

69 log_file = Path(log_value).expanduser() if log_value else None 

70 log_level = values.get("PH_LOG_LEVEL", "INFO") 

71 target = resolve_target(values.get("PH_TARGET_OS", DARKOS.target_id)) 

72 return cls( 

73 vimm_base_url=vimm_base_url, 

74 download_directory=directory, 

75 roms_directories=roms_directories, 

76 timeout_seconds=timeout, 

77 minerva_base_url=minerva_base_url, 

78 minerva_torrent_base_url=minerva_torrent_base_url, 

79 enabled_stores=enabled_stores, 

80 install_directory=install_directory, 

81 update_api_url=update_api_url, 

82 log_file=log_file, 

83 log_level=log_level, 

84 target=target, 

85 )