Files
pristontale-eu-linux/ptdiag/process.py
2026-08-27 17:50:36 +02:00

106 lines
3.1 KiB
Python

"""Read-only host and configured environment inspection."""
from __future__ import annotations
from dataclasses import asdict, dataclass
from datetime import datetime
import os
from pathlib import Path
import platform
import shutil
import sys
from typing import Any
from .config import AppConfig
from .prefix import proton_wineserver_candidates
@dataclass(frozen=True)
class EnvironmentCheck:
name: str
ok: bool
value: str
required: bool = True
def to_dict(self) -> dict[str, str | bool]:
return asdict(self)
def collect_environment(config: AppConfig) -> dict[str, Any]:
checks = environment_checks(config)
return {
"collected_at": datetime.now().astimezone().isoformat(),
"host": {
"platform": platform.platform(),
"machine": platform.machine(),
"python": sys.version,
"executable": sys.executable,
"cwd": os.getcwd(),
},
"config": config.to_dict(),
"checks": [check.to_dict() for check in checks],
"ok": all(check.ok for check in checks if check.required),
}
def environment_checks(config: AppConfig) -> list[EnvironmentCheck]:
checks = [
_path_check("app_root", config.paths.app_root, "directory"),
_path_check("live_prefix", config.paths.live_prefix, "directory"),
_path_check("live_game", config.paths.live_game, "directory"),
_path_check("logs", config.paths.logs, "directory"),
_path_check("native_logs", config.paths.native_logs, "directory"),
_path_check("proton7", config.proton7.proton, "file"),
_any_path_check("proton7_wineserver", proton_wineserver_candidates(config)),
_path_check("steam_root", config.proton7.steam_root, "directory"),
_path_check("compat", config.proton7.compat, "directory"),
_path_check("dedicated_prefix", config.proton7.prefix, "directory"),
_path_check("game_exe", config.paths.live_game / config.game.exe, "file"),
EnvironmentCheck(
"game_argument",
config.game.args == ("PTEU_REBORN",),
" ".join(config.game.args),
),
EnvironmentCheck(
"virtual_desktop",
config.game.virtual_desktop == "1600x900",
config.game.virtual_desktop,
),
_tool_check("strace", required=False),
_tool_check("gdb", required=False),
_i386_vulkan_check(),
]
return checks
def _path_check(name: str, path: Path, kind: str) -> EnvironmentCheck:
ok = path.is_file() if kind == "file" else path.is_dir()
return EnvironmentCheck(name, ok, str(path))
def _tool_check(name: str, required: bool) -> EnvironmentCheck:
path = shutil.which(name)
return EnvironmentCheck(name, path is not None, path or "not found", required)
def _any_path_check(name: str, candidates: tuple[Path, ...]) -> EnvironmentCheck:
found = next((path for path in candidates if path.is_file()), None)
return EnvironmentCheck(
name,
found is not None,
str(found) if found is not None else "not found: " + ", ".join(map(str, candidates)),
)
def _i386_vulkan_check() -> EnvironmentCheck:
candidates = (
Path("/usr/lib/i386-linux-gnu/libvulkan.so.1"),
Path("/usr/lib/i386-linux-gnu/libvulkan.so"),
)
found = next((path for path in candidates if path.exists()), None)
return EnvironmentCheck(
"i386_vulkan_loader",
found is not None,
str(found) if found is not None else "not found",
)