Skip to content
File

Blob: src/pyodide/tool_utils.py

python51 lines
1import subprocess
2import sys
3from base64 import b64encode
4from contextlib import contextmanager
5from hashlib import file_digest
6from pathlib import Path
7from time import time
8from typing import Any
9 
10 
11def run(
12 cmd: list[str | Path],
13 cwd: Path | str | None = None,
14 env: dict[str, str] | None = None,
15) -> subprocess.CompletedProcess[Any]:
16 """Execute a command and exit on failure with error output."""
17 res = subprocess.run(
18 cmd, capture_output=True, text=True, check=False, cwd=cwd, env=env
19 )
20 if res.returncode:
21 print("Invocation failed:")
22 print(res.stdout)
23 print(res.stderr)
24 sys.exit(res.returncode)
25 return res
26 
27 
28def bytesdigest(p: Path | str) -> bytes:
29 """Calculate SHA256 digest of a file as bytes."""
30 return file_digest(Path(p).open("rb"), "sha256").digest()
31 
32 
33def hexdigest(p: Path | str) -> str:
34 """Calculate SHA256 digest of a file as hex string."""
35 digest = bytesdigest(p)
36 return "".join(hex(e)[2:].zfill(2) for e in digest)
37 
38 
39def b64digest(p: Path | str):
40 return "sha256-" + b64encode(bytesdigest(p)).decode()
41 
42 
43@contextmanager
44def timing(name: str):
45 """Context manager to time operations and print elapsed time."""
46 print(f"Making {name}...")
47 start = time()
48 yield
49 elapsed = time() - start
50 print(f" {elapsed:.2f}s")