From 99532087612390f5ba9f068725bc35c7b238f465 Mon Sep 17 00:00:00 2001 From: papertager <2567587994@qq.com> Date: Tue, 9 Jun 2026 22:12:23 +0800 Subject: [PATCH 1/2] Add mcoplib MACA environment snapshot tool --- tools/maca_env_snapshot.py | 59 +++++++++++++++++++++++++++++ unit_test/test_maca_env_snapshot.py | 16 ++++++++ 2 files changed, 75 insertions(+) create mode 100644 tools/maca_env_snapshot.py create mode 100644 unit_test/test_maca_env_snapshot.py diff --git a/tools/maca_env_snapshot.py b/tools/maca_env_snapshot.py new file mode 100644 index 0000000..2918f77 --- /dev/null +++ b/tools/maca_env_snapshot.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Collect a reproducible MACA validation environment snapshot.""" + +from __future__ import annotations + +import argparse +import json +import os +import platform +import shutil +import subprocess +import sys +from pathlib import Path + + +def _command_version(command: str, args: list[str]) -> dict[str, object]: + path = shutil.which(command) + if not path: + return {"path": "", "available": False, "version": ""} + completed = subprocess.run([path, *args], text=True, capture_output=True) + return { + "path": path, + "available": True, + "returncode": completed.returncode, + "version": (completed.stdout or completed.stderr).strip().splitlines()[:5], + } + + +def snapshot() -> dict[str, object]: + return { + "python": sys.version.split()[0], + "platform": platform.platform(), + "environment": { + "MACA_PATH": os.environ.get("MACA_PATH", ""), + "LD_LIBRARY_PATH": os.environ.get("LD_LIBRARY_PATH", ""), + "PYTHONPATH": os.environ.get("PYTHONPATH", ""), + }, + "tools": { + "mxcc": _command_version("mxcc", ["--version"]), + "cmake_maca": _command_version("cmake_maca", ["--version"]), + }, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", type=Path) + args = parser.parse_args() + + text = json.dumps(snapshot(), indent=2, ensure_ascii=False) + if args.output: + args.output.write_text(text + "\n", encoding="utf-8") + else: + print(text) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/unit_test/test_maca_env_snapshot.py b/unit_test/test_maca_env_snapshot.py new file mode 100644 index 0000000..586ac51 --- /dev/null +++ b/unit_test/test_maca_env_snapshot.py @@ -0,0 +1,16 @@ +import unittest + +from tools.maca_env_snapshot import snapshot + + +class MacaEnvSnapshotTest(unittest.TestCase): + def test_snapshot_has_expected_sections(self): + report = snapshot() + + self.assertIn("python", report) + self.assertIn("environment", report) + self.assertIn("tools", report) + + +if __name__ == "__main__": + unittest.main() From cb1f22a56f88353dd0875a31948cae3e8447d8c2 Mon Sep 17 00:00:00 2001 From: papertager <2567587994@qq.com> Date: Thu, 11 Jun 2026 00:57:34 +0800 Subject: [PATCH 2/2] Prevent env snapshot command hangs --- tools/maca_env_snapshot.py | 24 +++++++++++++++++------- unit_test/test_maca_env_snapshot.py | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/tools/maca_env_snapshot.py b/tools/maca_env_snapshot.py index 2918f77..65da2a9 100644 --- a/tools/maca_env_snapshot.py +++ b/tools/maca_env_snapshot.py @@ -17,13 +17,22 @@ def _command_version(command: str, args: list[str]) -> dict[str, object]: path = shutil.which(command) if not path: return {"path": "", "available": False, "version": ""} - completed = subprocess.run([path, *args], text=True, capture_output=True) - return { - "path": path, - "available": True, - "returncode": completed.returncode, - "version": (completed.stdout or completed.stderr).strip().splitlines()[:5], - } + try: + completed = subprocess.run([path, *args], text=True, capture_output=True, timeout=5) + version = (completed.stdout or completed.stderr).strip().splitlines()[:5] + return { + "path": path, + "available": True, + "returncode": completed.returncode, + "version": version, + } + except (subprocess.SubprocessError, OSError) as exc: + return { + "path": path, + "available": True, + "returncode": -1, + "version": [f"Error: {exc}"], + } def snapshot() -> dict[str, object]: @@ -49,6 +58,7 @@ def main() -> int: text = json.dumps(snapshot(), indent=2, ensure_ascii=False) if args.output: + args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text(text + "\n", encoding="utf-8") else: print(text) diff --git a/unit_test/test_maca_env_snapshot.py b/unit_test/test_maca_env_snapshot.py index 586ac51..d131997 100644 --- a/unit_test/test_maca_env_snapshot.py +++ b/unit_test/test_maca_env_snapshot.py @@ -1,6 +1,8 @@ +import subprocess +from unittest.mock import patch import unittest -from tools.maca_env_snapshot import snapshot +from tools.maca_env_snapshot import _command_version, snapshot class MacaEnvSnapshotTest(unittest.TestCase): @@ -11,6 +13,18 @@ def test_snapshot_has_expected_sections(self): self.assertIn("environment", report) self.assertIn("tools", report) + @patch("tools.maca_env_snapshot.shutil.which", return_value="/usr/bin/mxcc") + @patch( + "tools.maca_env_snapshot.subprocess.run", + side_effect=subprocess.TimeoutExpired(cmd=["mxcc", "--version"], timeout=5), + ) + def test_command_version_handles_timeout(self, _run, _which): + report = _command_version("mxcc", ["--version"]) + + self.assertTrue(report["available"]) + self.assertEqual(report["returncode"], -1) + self.assertIn("Error:", report["version"][0]) + if __name__ == "__main__": unittest.main()