executor.py python
82 lines 2.0 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 1 day ago
1 """Script execution without shell (§K9.5)."""
2
3 from __future__ import annotations
4
5 import os
6 import subprocess
7 from dataclasses import dataclass
8 from typing import Protocol
9
10
11 @dataclass(frozen=True)
12 class ExecResult:
13 """Result of executing a verify script."""
14
15 stdout: bytes
16 stderr: bytes
17 exit_code: int
18
19
20 class ScriptExecutor(Protocol):
21 """Protocol for argv-list script invocation."""
22
23 def exec_argv(
24 self,
25 argv: list[str],
26 *,
27 cwd: str,
28 env: dict[str, str] | None = None,
29 ) -> ExecResult:
30 """Run ``argv[0]`` with remaining args; no shell."""
31
32
33 @dataclass
34 class SubprocessScriptExecutor:
35 """Production executor using ``subprocess.run`` with argv list."""
36
37 def exec_argv(
38 self,
39 argv: list[str],
40 *,
41 cwd: str,
42 env: dict[str, str] | None = None,
43 ) -> ExecResult:
44 merged_env = os.environ.copy()
45 if env:
46 merged_env.update(env)
47 completed = subprocess.run(
48 argv,
49 cwd=cwd,
50 env=merged_env,
51 capture_output=True,
52 )
53 return ExecResult(
54 stdout=completed.stdout,
55 stderr=completed.stderr,
56 exit_code=completed.returncode,
57 )
58
59
60 @dataclass
61 class RecordingScriptExecutor:
62 """Test executor recording argv invocations."""
63
64 responses: dict[tuple[str, ...], ExecResult]
65 calls: list[tuple[list[str], str, dict[str, str] | None]]
66
67 def exec_argv(
68 self,
69 argv: list[str],
70 *,
71 cwd: str,
72 env: dict[str, str] | None = None,
73 ) -> ExecResult:
74 self.calls.append((list(argv), cwd, env))
75 key = tuple(argv)
76 if key in self.responses:
77 return self.responses[key]
78 script = argv[0] if argv else ""
79 for pattern, result in self.responses.items():
80 if pattern and pattern[0] == script:
81 return result
82 return ExecResult(stdout=b"", stderr=b"unmocked script", exit_code=127)
File History 2 commits
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 1 day ago
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439 feat: K1-P1 complete — agent provenance, build-verification… Sonnet 4.6 patch 52 days ago