Code cleanup and improvements.
This commit is contained in:
@@ -924,7 +924,7 @@ def _rewrite_wrapped_file(
|
||||
output: Path,
|
||||
patches: list[_BinaryPatch],
|
||||
) -> tuple[str, int]:
|
||||
ordered = sorted(patches, key=lambda patch: patch.offset)
|
||||
ordered = sorted(patches, key=lambda item: item.offset)
|
||||
previous_end = 0
|
||||
for patch in ordered:
|
||||
if patch.offset < previous_end:
|
||||
|
||||
@@ -40,19 +40,11 @@ class GameConfig:
|
||||
virtual_desktop: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SafetyConfig:
|
||||
allow_live_game_modification: bool
|
||||
allow_prefix_modification: bool
|
||||
allow_binary_patch: bool
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AppConfig:
|
||||
paths: PathsConfig
|
||||
proton7: Proton7Config
|
||||
game: GameConfig
|
||||
safety: SafetyConfig
|
||||
source: Path
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
@@ -81,7 +73,6 @@ def load_config(path: str | Path | None = None) -> AppConfig:
|
||||
paths = _section(data, "paths")
|
||||
proton7 = _section(data, "proton7")
|
||||
game = _section(data, "game")
|
||||
safety = _section(data, "safety")
|
||||
virtual_desktop = _required_string(game, "virtual_desktop")
|
||||
if re.fullmatch(r"[1-9][0-9]*x[1-9][0-9]*", virtual_desktop) is None:
|
||||
raise ConfigError("game.virtual_desktop must look like 1600x900")
|
||||
@@ -105,15 +96,6 @@ def load_config(path: str | Path | None = None) -> AppConfig:
|
||||
args=_required_string_tuple(game, "args"),
|
||||
virtual_desktop=virtual_desktop,
|
||||
),
|
||||
safety=SafetyConfig(
|
||||
allow_live_game_modification=_required_bool(
|
||||
safety, "allow_live_game_modification"
|
||||
),
|
||||
allow_prefix_modification=_required_bool(
|
||||
safety, "allow_prefix_modification"
|
||||
),
|
||||
allow_binary_patch=_required_bool(safety, "allow_binary_patch"),
|
||||
),
|
||||
source=config_path,
|
||||
)
|
||||
|
||||
@@ -145,13 +127,6 @@ def _required_string_tuple(section: Mapping[str, Any], key: str) -> tuple[str, .
|
||||
return tuple(value)
|
||||
|
||||
|
||||
def _required_bool(section: Mapping[str, Any], key: str) -> bool:
|
||||
value = section.get(key)
|
||||
if not isinstance(value, bool):
|
||||
raise ConfigError(f"{key} must be true or false")
|
||||
return value
|
||||
|
||||
|
||||
def _paths_to_strings(value: Any) -> Any:
|
||||
if isinstance(value, Path):
|
||||
return str(value)
|
||||
|
||||
@@ -12,7 +12,7 @@ import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from typing import Any, Mapping, Sequence, TextIO
|
||||
from typing import Any, Mapping, Sequence
|
||||
|
||||
from .config import AppConfig, project_root
|
||||
from .filesystem import sha256_file, verify_known_game_hashes
|
||||
@@ -190,7 +190,6 @@ def _run_standard_experiment(
|
||||
_dry_run_commands(
|
||||
config,
|
||||
testcase,
|
||||
result,
|
||||
logger,
|
||||
registry_before,
|
||||
launch_argv,
|
||||
@@ -1025,7 +1024,6 @@ def _preflight(
|
||||
def _dry_run_commands(
|
||||
config: AppConfig,
|
||||
testcase: Testcase,
|
||||
result: ResultDirectory,
|
||||
logger: CommandLogger,
|
||||
registry_before: DesktopRegistrySnapshot,
|
||||
launch_argv: list[str],
|
||||
@@ -1087,8 +1085,6 @@ def _run_and_watch(
|
||||
process: subprocess.Popen[str] | None = None
|
||||
process_identity: dict[str, Any] | None = None
|
||||
failure_state: LogFileState | None = None
|
||||
failure_analysis: dict[str, Any] | None = None
|
||||
failure_text = ""
|
||||
failure_trigger_mtime_ns: int | None = None
|
||||
current_state: LogFileState | None = None
|
||||
current_analysis: dict[str, Any] | None = None
|
||||
@@ -1121,6 +1117,7 @@ def _run_and_watch(
|
||||
error=str(exc),
|
||||
)
|
||||
raise ExperimentError(f"Could not launch experiment: {exc}") from exc
|
||||
assert process is not None
|
||||
logger.record_lifecycle(
|
||||
argv,
|
||||
state="started",
|
||||
@@ -1156,8 +1153,6 @@ def _run_and_watch(
|
||||
current_text = read_current_run_log_text(state, baseline)
|
||||
if analysis.load_texture_to_material_failed:
|
||||
failure_state = state
|
||||
failure_analysis = analysis.to_summary()
|
||||
failure_text = read_current_run_log_text(state, baseline)
|
||||
failure_trigger_mtime_ns = state.mtime_ns
|
||||
detected_at_ns = now_ns
|
||||
post_failure_deadline_ns = now_ns + int(
|
||||
@@ -1235,12 +1230,9 @@ def _run_and_watch(
|
||||
final_states = snapshot_native_logs(config.paths.native_logs)
|
||||
final_state = final_states.get(str(failure_state.path.absolute()))
|
||||
if final_state is not None:
|
||||
failure_state = final_state
|
||||
failure_text = read_current_run_log_text(final_state, baseline)
|
||||
failure_analysis = parse_current_run_log(final_state, baseline).to_summary()
|
||||
current_state = final_state
|
||||
current_text = failure_text
|
||||
current_analysis = failure_analysis
|
||||
current_text = read_current_run_log_text(final_state, baseline)
|
||||
current_analysis = parse_current_run_log(final_state, baseline).to_summary()
|
||||
if current_state is not None:
|
||||
_write_text(result.path / "native.log", current_text)
|
||||
whispering_vale = (
|
||||
@@ -1381,8 +1373,13 @@ def _launch_argv(config: AppConfig, testcase: Testcase, result_directory: Path)
|
||||
|
||||
|
||||
def _proton_command(config: AppConfig, *arguments: str) -> list[str]:
|
||||
shim = Path(__file__).with_name("proton_compat.py")
|
||||
return [sys.executable, str(shim), str(config.proton7.proton), *arguments]
|
||||
shim = project_root() / "ptlinux/proton_compat.py"
|
||||
return [
|
||||
sys.executable,
|
||||
str(shim),
|
||||
str(config.proton7.proton),
|
||||
*arguments,
|
||||
]
|
||||
|
||||
|
||||
def _runtime_environment(
|
||||
@@ -1659,7 +1656,7 @@ def _collect_hashes(config: AppConfig, testcase: Testcase) -> list[dict[str, Any
|
||||
config.proton7.prefix
|
||||
/ "drive_c/windows/syswow64/d3dcompiler_43.dll": "native-d3dcompiler-43",
|
||||
config.proton7.prefix / "drive_c/windows/syswow64/d3d9.dll": "dxvk-d3d9",
|
||||
Path(__file__).with_name("proton_compat.py"): "proton-python314-shim",
|
||||
project_root() / "ptlinux/proton_compat.py": "proton-python314-shim",
|
||||
config.source: "local-config",
|
||||
testcase.source: "testcase",
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ from typing import Iterable, Mapping
|
||||
DEFAULT_NATIVE_LOG_PATTERNS = ("log_*.txt", "*.log")
|
||||
|
||||
_SCENE_RE = re.compile(
|
||||
r"\[S1\]\s+after import\s+(?P<scene>[^:]+):\s*"
|
||||
r"\[S1]\s+after import\s+(?P<scene>[^:]+):\s*"
|
||||
r"materials=(?P<materials>\d+)\s+textures=(?P<textures>\d+)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
@@ -24,14 +24,14 @@ _FAILED_IMPORT_RE = re.compile(
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_MODULE_CODE_SYNC_RE = re.compile(
|
||||
r"Module Code Sync Error\s*\(\[(?P<left>-?\d+)\]\s*!=\s*"
|
||||
r"\[(?P<right>-?\d+)\]\)",
|
||||
r"Module Code Sync Error\s*\(\[(?P<left>-?\d+)]\s*!=\s*"
|
||||
r"\[(?P<right>-?\d+)]\)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_TIMESTAMP_RE = re.compile(
|
||||
r"^\s*(?:\[)?(?P<timestamp>"
|
||||
r"^\s*\[?(?P<timestamp>"
|
||||
r"\d{4}-\d{2}-\d{2}[T ][0-9:.+Z-]+|\d{2}:\d{2}:\d{2}(?:\.\d+)?)"
|
||||
r"(?:\])?"
|
||||
r"]?"
|
||||
)
|
||||
|
||||
|
||||
@@ -90,9 +90,6 @@ class NativeLogAnalysis:
|
||||
return imports[-1]
|
||||
return None
|
||||
|
||||
def first_event(self, kind: str) -> LogEvent | None:
|
||||
return next((event for event in self.events if event.kind == kind), None)
|
||||
|
||||
def to_summary(self) -> dict[str, object]:
|
||||
summary: dict[str, object] = {
|
||||
"scenes": {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
"""Run the retained Proton 7 script safely on Python 3.14.
|
||||
|
||||
Proton 7 predates Python's tar extraction-filter API. The known-good v41
|
||||
runtime used this compatibility shim; keeping it in the harness makes the
|
||||
exact launch recipe inspectable and reproducible.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import runpy
|
||||
import sys
|
||||
import tarfile
|
||||
from typing import Sequence
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> None:
|
||||
arguments = list(sys.argv[1:] if argv is None else argv)
|
||||
if not arguments:
|
||||
raise SystemExit("usage: proton_compat.py /path/to/proton [arguments...]")
|
||||
proton = Path(arguments[0]).expanduser().resolve(strict=True)
|
||||
proton_directory = str(proton.parent)
|
||||
if proton_directory not in sys.path:
|
||||
sys.path.insert(0, proton_directory)
|
||||
if hasattr(tarfile, "fully_trusted_filter"):
|
||||
tarfile.TarFile.extraction_filter = staticmethod(tarfile.fully_trusted_filter)
|
||||
sys.argv = [str(proton), *arguments[1:]]
|
||||
runpy.run_path(str(proton), run_name="__main__")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -11,7 +11,7 @@ from .filesystem import sha256_file
|
||||
|
||||
|
||||
_VALUE_RE = re.compile(r'^(?P<name>"(?:\\.|[^"\\])*")=(?P<value>.*)$')
|
||||
_SECTION_RE = re.compile(r"^\[(?P<name>.*)\](?:\s+[0-9]+)?$")
|
||||
_SECTION_RE = re.compile(r"^\[(?P<name>.*)](?:\s+[0-9]+)?$")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
@@ -29,18 +29,12 @@ class TestDisplay:
|
||||
@dataclass(frozen=True)
|
||||
class TestWatch:
|
||||
require_new_native_log: bool
|
||||
patterns: tuple[str, ...]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestCapture:
|
||||
process_maps: bool
|
||||
cwd: bool
|
||||
environment: bool
|
||||
dll_overrides: bool
|
||||
hashes: bool
|
||||
dxvk_log: bool
|
||||
native_log: bool
|
||||
strace_files: bool
|
||||
performance_stats: bool
|
||||
focus_before_seconds: float
|
||||
@@ -123,16 +117,10 @@ def load_testcase(value: str | Path) -> Testcase:
|
||||
env=_string_mapping(environment, "env"),
|
||||
watch=TestWatch(
|
||||
require_new_native_log=_boolean(watch, "require_new_native_log"),
|
||||
patterns=_string_tuple(watch, "patterns"),
|
||||
),
|
||||
capture=TestCapture(
|
||||
process_maps=_boolean(capture, "process_maps"),
|
||||
cwd=_boolean(capture, "cwd"),
|
||||
environment=_boolean(capture, "environment"),
|
||||
dll_overrides=_boolean(capture, "dll_overrides"),
|
||||
hashes=_boolean(capture, "hashes"),
|
||||
dxvk_log=_boolean(capture, "dxvk_log"),
|
||||
native_log=_boolean(capture, "native_log"),
|
||||
strace_files=_boolean(capture, "strace_files"),
|
||||
performance_stats=_optional_boolean(capture, "performance_stats", False),
|
||||
focus_before_seconds=_optional_nonnegative_number(
|
||||
|
||||
Reference in New Issue
Block a user