Unity Hub CLI wrapper.
| 20 | |
| 21 | |
| 22 | class HubCLI: |
| 23 | """Unity Hub CLI wrapper.""" |
| 24 | |
| 25 | def __init__(self, hub_path: Path | None = None) -> None: |
| 26 | """Initialize with optional custom Hub path. |
| 27 | |
| 28 | Args: |
| 29 | hub_path: Custom path to Hub CLI. If None, auto-detect. |
| 30 | |
| 31 | Raises: |
| 32 | HubNotFoundError: If Hub CLI cannot be found. |
| 33 | """ |
| 34 | self._hub_path = hub_path or locate_hub_cli() |
| 35 | if self._hub_path is None: |
| 36 | raise HubNotFoundError( |
| 37 | "Unity Hub CLI not found. Install Unity Hub or set UNITY_HUB_PATH.", |
| 38 | code="HUB_NOT_FOUND", |
| 39 | ) |
| 40 | |
| 41 | def _run_command( |
| 42 | self, |
| 43 | args: list[str], |
| 44 | timeout: float = 300.0, |
| 45 | ) -> subprocess.CompletedProcess[str]: |
| 46 | """Execute Hub CLI command. |
| 47 | |
| 48 | Args: |
| 49 | args: Command arguments (without hub path). |
| 50 | timeout: Command timeout in seconds. |
| 51 | |
| 52 | Returns: |
| 53 | CompletedProcess with stdout/stderr. |
| 54 | |
| 55 | Raises: |
| 56 | HubInstallError: If command fails. |
| 57 | """ |
| 58 | cmd = [str(self._hub_path), "--", "--headless", *args] |
| 59 | try: |
| 60 | result = subprocess.run( |
| 61 | cmd, |
| 62 | capture_output=True, |
| 63 | text=True, |
| 64 | timeout=timeout, |
| 65 | ) |
| 66 | return result |
| 67 | except subprocess.TimeoutExpired as e: |
| 68 | raise HubInstallError( |
| 69 | f"Hub CLI command timed out after {timeout}s", |
| 70 | code="HUB_TIMEOUT", |
| 71 | ) from e |
| 72 | except FileNotFoundError as e: |
| 73 | raise HubNotFoundError( |
| 74 | f"Hub CLI not found at {self._hub_path}", |
| 75 | code="HUB_NOT_FOUND", |
| 76 | ) from e |
| 77 | |
| 78 | def list_editors(self) -> list[HubEditorInfo]: |
| 79 | """List installed editors via Hub CLI. |