from __future__ import annotations import sys from pathlib import Path DIRECTORY = Path(__file__).resolve().parent EXAMPLE_NAME = "用户名密码ip.example.txt" PRIVATE_NAME = "用户名密码ip.txt" REQUIRED_KEYS = ( "设备", "主机名", "用户名", "密码", "IP", "SSH", "镜像默认用户名", "镜像默认账户密码", "镜像默认WiFi SSID", "镜像默认WiFi密码", ) PLACEHOLDER_MARKERS = ("<", ">", "示例", "example", "请填写", "待填写") class CredentialPreparationError(RuntimeError): """A safe, user-actionable credential preparation failure.""" def _parse_fields(path: Path) -> dict[str, str]: fields: dict[str, str] = {} for raw_line in path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#"): continue separator = ":" if ":" in line else ":" if ":" in line else None if separator is None: raise CredentialPreparationError("凭据文件含有无法识别的非注释行。") key, value = (part.strip() for part in line.split(separator, 1)) if not key or key in fields: raise CredentialPreparationError("凭据文件含有空字段名或重复字段。") fields[key] = value return fields def ensure_credentials(directory: Path = DIRECTORY) -> bool: example_path = directory / EXAMPLE_NAME private_path = directory / PRIVATE_NAME if not example_path.is_file(): raise CredentialPreparationError(f"缺少示例文件:{EXAMPLE_NAME}") if not private_path.exists(): payload = example_path.read_bytes() try: with private_path.open("xb") as stream: stream.write(payload) except FileExistsError: pass print(f"已创建私有凭据副本:测试相关资料/核桃派的用户名和密码和ip/{PRIVATE_NAME}") print("请填写全部字段后重新运行本检查;在此之前不要继续 SSH、部署或镜像定制。") return False if not private_path.is_file(): raise CredentialPreparationError(f"私有凭据路径不是普通文件:{PRIVATE_NAME}") fields = _parse_fields(private_path) missing = [key for key in REQUIRED_KEYS if key not in fields] if missing: raise CredentialPreparationError("凭据文件缺少字段:" + "、".join(missing)) unfinished = [ key for key in REQUIRED_KEYS if not fields[key] or any(marker.casefold() in fields[key].casefold() for marker in PLACEHOLDER_MARKERS) ] if unfinished: raise CredentialPreparationError("凭据文件仍有未填写字段:" + "、".join(unfinished)) print("私有凭据文件可用;未输出任何凭据值。") return True def main() -> int: try: return 0 if ensure_credentials() else 2 except (CredentialPreparationError, OSError, UnicodeError) as error: print(f"凭据检查未通过:{error}", file=sys.stderr) return 2 if __name__ == "__main__": raise SystemExit(main())