from __future__ import annotations import platform import shutil import subprocess class CredentialDialogError(RuntimeError): """Raised when the local macOS credential dialog cannot return a value.""" def _dialog_text(prompt: str, hidden: bool) -> str: if platform.system() != "Darwin": raise CredentialDialogError("Secure credential dialogs are supported only on macOS") osascript = shutil.which("osascript") if osascript is None: raise CredentialDialogError("osascript is unavailable") hidden_clause = " with hidden answer" if hidden else "" script = ( f'text returned of (display dialog "{prompt}" default answer ""' f'{hidden_clause} buttons {{"Отмена", "Продолжить"}} ' 'default button "Продолжить" cancel button "Отмена")' ) try: result = subprocess.run( [osascript, "-e", script], check=False, capture_output=True, text=True, timeout=300, ) except (OSError, subprocess.SubprocessError) as exc: raise CredentialDialogError("macOS credential dialog failed") from exc if result.returncode != 0: raise CredentialDialogError("Credential entry was cancelled") value = result.stdout.rstrip("\r\n") if not value: raise CredentialDialogError("Credential value must not be empty") return value def prompt_wifi_credentials() -> tuple[str, str]: """Collect Wi-Fi credentials locally without placing them in command arguments.""" ssid = _dialog_text("Имя Wi-Fi сети, к которой подключён Mac", hidden=False) password = _dialog_text("Пароль этой Wi-Fi сети", hidden=True) return ssid, password