Added more folders and restructured classes inside them.

This commit is contained in:
2026-09-12 11:10:47 +02:00
parent be7a4782e8
commit 2cbb9315bf
152 changed files with 21734 additions and 914 deletions

View File

@@ -0,0 +1,267 @@
"""Static host, display, filesystem, and process probes for telemetry."""
from __future__ import annotations
from collections.abc import Callable, Mapping
import json
import math
import os
from pathlib import Path
import platform
import re
import resource
import sys
from ..paths import AppPaths
from ..system_identity import (
SystemIdentity,
detect_system_identity,
read_os_release as read_system_os_release,
)
NETWORK_FILESYSTEMS = frozenset(
{"9p", "afs", "ceph", "cifs", "nfs", "nfs4", "smb3", "sshfs"}
)
MOUNT_ESCAPE_PATTERN = re.compile(r"\\([0-7]{3})")
def operating_system_info(
identity: SystemIdentity | None = None,
*,
detect_identity: Callable[[], SystemIdentity] = detect_system_identity,
system_name: Callable[[], str] = platform.system,
kernel_release: Callable[[], str] = platform.release,
machine_name: Callable[[], str] = platform.machine,
libc_version: Callable[[], tuple[str, str]] = platform.libc_ver,
) -> dict[str, object]:
identity = detect_identity() if identity is None else identity
release = identity.operating_system_release
return {
"name": release.get("NAME", system_name() or "unknown"),
"id": release.get("ID", "unknown"),
"version": release.get("PRETTY_NAME", release.get("VERSION", "unknown")),
"version_id": release.get("VERSION_ID", "unknown"),
"kernel": kernel_release(),
"architecture": machine_name() or "unknown",
"machine_architecture": machine_name() or "unknown",
"glibc_version": libc_version()[1] or None,
"identity_source": (
"container_host_os_release"
if identity.host_release is not None
else "execution_os_release"
),
}
def read_os_release(
path: Path = Path("/etc/os-release"),
*,
reader: Callable[[Path], dict[str, str]] = read_system_os_release,
) -> dict[str, str]:
return reader(path)
def execution_environment_info(
identity: SystemIdentity,
*,
libc_version: Callable[[], tuple[str, str]] = platform.libc_ver,
) -> dict[str, object] | None:
if not identity.running_inside_steam_runtime:
return None
release = identity.execution_release
return {
"containerized": True,
"kind": "steam_runtime",
"id": release.get("ID", "steamrt"),
"name": release.get("NAME", "Steam Runtime"),
"version": release.get(
"PRETTY_NAME",
release.get("VERSION", "unknown"),
),
"version_id": release.get("VERSION_ID", "unknown"),
"host_os_release_available": identity.host_release is not None,
"launcher_inside_game_runtime": True,
"glibc_version": libc_version()[1] or None,
}
def display_info(environment: Mapping[str, str]) -> dict[str, object]:
session_type = environment.get("XDG_SESSION_TYPE", "").casefold()
if session_type not in {"wayland", "x11"}:
if environment.get("WAYLAND_DISPLAY"):
session_type = "wayland"
elif environment.get("DISPLAY"):
session_type = "x11"
else:
session_type = "unknown"
desktop = environment.get("XDG_CURRENT_DESKTOP", "")
desktop = desktop.split(":", 1)[0].strip().casefold() or "unknown"
session = environment.get("DESKTOP_SESSION", "").strip().casefold() or "unknown"
return {
"server": session_type,
"desktop": desktop[:64],
"session": session[:64],
}
Mount = tuple[Path, str, set[str]]
def filesystem_info(
target: Path,
*,
read_mounts: Callable[[], list[Mount]] | None = None,
access: Callable[[Path, int], bool] = os.access,
writable_mode: int = os.W_OK,
network_filesystems: frozenset[str] = NETWORK_FILESYSTEMS,
) -> dict[str, object]:
existing = target
while not existing.exists() and existing != existing.parent:
existing = existing.parent
filesystem_type = "unknown"
readonly = False
noexec = False
try:
mounts = read_mountinfo() if read_mounts is None else read_mounts()
resolved = existing.resolve(strict=True)
matches = [
mount
for mount in mounts
if resolved == mount[0] or resolved.is_relative_to(mount[0])
]
if matches:
_mountpoint, filesystem_type, options = max(
matches,
key=lambda item: len(item[0].parts),
)
readonly = "ro" in options
noexec = "noexec" in options
except (OSError, RuntimeError, ValueError):
pass
try:
writable = access(existing, writable_mode) and not readonly
except OSError:
writable = False
return {
"type": filesystem_type,
"writable": writable,
"readonly": readonly,
"noexec": noexec,
"network": filesystem_type.casefold() in network_filesystems,
}
def read_mountinfo(
path: Path = Path("/proc/self/mountinfo"),
*,
unescape: Callable[[str], str] | None = None,
) -> list[Mount]:
decode = unescape_mount_field if unescape is None else unescape
mounts: list[Mount] = []
for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
fields = line.split()
try:
separator = fields.index("-")
except ValueError:
continue
if separator < 6 or len(fields) <= separator + 3:
continue
mountpoint = Path(decode(fields[4]))
filesystem_type = fields[separator + 1]
options = set(fields[5].split(",")) | set(fields[separator + 3].split(","))
mounts.append((mountpoint, filesystem_type, options))
return mounts
def unescape_mount_field(value: str) -> str:
return MOUNT_ESCAPE_PATTERN.sub(
lambda match: chr(int(match.group(1), 8)),
value,
)
def install_is_external(paths: AppPaths, environment: Mapping[str, str]) -> bool:
home_value = environment.get("HOME")
if not home_value:
return False
try:
home = Path(home_value).expanduser().resolve()
data = paths.data.resolve()
return data != home and not data.is_relative_to(home)
except (OSError, RuntimeError):
return False
def current_game_version(
path: Path,
*,
json_loader: Callable[[str], object] = json.loads,
) -> str | None:
try:
value = json_loader(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return None
if not isinstance(value, dict):
return None
version = value.get("version")
return version[:32] if isinstance(version, str) and version else None
def settings_schema_version() -> int:
try:
from ..settings import SETTINGS_SCHEMA
return SETTINGS_SCHEMA
except Exception:
return 1
def resource_usage(
*,
get_usage: Callable[[int], object] = resource.getrusage,
usage_target: int = resource.RUSAGE_SELF,
platform_name: str = sys.platform,
is_finite: Callable[[float], bool] = math.isfinite,
) -> dict[str, object]:
"""Read one bounded process-usage snapshot on the Linux launcher host."""
try:
usage = get_usage(usage_target)
peak_value = float(getattr(usage, "ru_maxrss"))
peak_divisor = 1024 * 1024 if platform_name == "darwin" else 1024
peak_memory_mb = peak_value / peak_divisor
cpu_time_seconds = float(getattr(usage, "ru_utime")) + float(
getattr(usage, "ru_stime")
)
except (OSError, TypeError, ValueError, OverflowError):
return {}
if (
not is_finite(peak_memory_mb)
or not is_finite(cpu_time_seconds)
or peak_memory_mb < 0
or cpu_time_seconds < 0
):
return {}
return {
"peak_memory_mb": round(peak_memory_mb, 2),
"cpu_time_seconds": round(cpu_time_seconds, 3),
}
__all__ = [
"MOUNT_ESCAPE_PATTERN",
"Mount",
"NETWORK_FILESYSTEMS",
"current_game_version",
"display_info",
"execution_environment_info",
"filesystem_info",
"install_is_external",
"operating_system_info",
"read_mountinfo",
"read_os_release",
"resource_usage",
"settings_schema_version",
"unescape_mount_field",
]