(
method: str,
url: str,
*,
timeout: float,
data: bytes | None = None,
headers: dict[str, str] | None = None,
)
| 63 | |
| 64 | |
| 65 | def _request_json( |
| 66 | method: str, |
| 67 | url: str, |
| 68 | *, |
| 69 | timeout: float, |
| 70 | data: bytes | None = None, |
| 71 | headers: dict[str, str] | None = None, |
| 72 | ) -> Any: |
| 73 | req = urllib.request.Request(url, data=data, method=method, headers=headers or {}) |
| 74 | try: |
| 75 | with urllib.request.urlopen(req, timeout=timeout) as resp: |
| 76 | raw = resp.read().decode("utf-8") |
| 77 | except urllib.error.HTTPError as exc: |
| 78 | detail = exc.read().decode("utf-8", errors="replace") |
| 79 | raise ModlyCliError(f"HTTP {exc.code} from {url}: {detail}", code=f"HTTP_{exc.code}", http_status=exc.code) from exc |
| 80 | except urllib.error.URLError as exc: |
| 81 | raise ModlyCliError(f"Cannot reach Modly API at {url}: {exc.reason}", code="API_UNAVAILABLE") from exc |
| 82 | try: |
| 83 | return json.loads(raw) if raw else {} |
| 84 | except json.JSONDecodeError as exc: |
| 85 | raise ModlyCliError(f"Expected JSON from {url}, got: {raw[:500]}", code="INVALID_JSON_RESPONSE") from exc |
| 86 | |
| 87 | |
| 88 | def _download(url: str, dest: Path, *, timeout: float) -> int: |
no test coverage detected