from __future__ import annotations import shlex import json import subprocess def shell_quote(value: str) -> str: return shlex.quote(str(value)) def run_shell(script: str, timeout: float = 120.0) -> tuple[int, str, str]: try: r = subprocess.run( ["/bin/bash", "-lc", script], capture_output=True, text=True, timeout=timeout, ) return r.returncode, r.stdout or "", r.stderr or "" except Exception as exc: # noqa: BLE001 return 1, "", str(exc) def run_shell_as_admin(script: str, timeout: float = 180.0) -> tuple[int, str, str]: """Run a shell script through macOS' standard admin prompt. This avoids silent failures for commands like ``networksetup`` and ``scutil --set`` when the user is not currently root. """ apple_script = ( "do shell script " + json.dumps(script) + " with administrator privileges" ) try: r = subprocess.run( ["osascript", "-e", apple_script], capture_output=True, text=True, timeout=timeout, ) return r.returncode, r.stdout or "", r.stderr or "" except Exception as exc: # noqa: BLE001 return 1, "", str(exc)