Açıklama Yok

shuffle.py 3.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from typing import Any
  2. import httpx
  3. class ShuffleAdapter:
  4. def __init__(self, base_url: str, api_key: str) -> None:
  5. self.base_url = base_url.rstrip("/")
  6. self.api_key = api_key
  7. def _headers(self) -> dict[str, str]:
  8. if not self.api_key:
  9. return {}
  10. return {
  11. "Authorization": f"Bearer {self.api_key}",
  12. "X-Api-Key": self.api_key,
  13. }
  14. async def _request(
  15. self,
  16. method: str,
  17. path: str,
  18. params: dict[str, Any] | None = None,
  19. payload: dict[str, Any] | None = None,
  20. ) -> dict[str, Any]:
  21. path = path if path.startswith("/") else f"/{path}"
  22. url = f"{self.base_url}{path}"
  23. async with httpx.AsyncClient(timeout=25.0) as client:
  24. response = await client.request(
  25. method=method.upper(),
  26. url=url,
  27. params=params or None,
  28. json=payload or None,
  29. headers=self._headers(),
  30. )
  31. try:
  32. response.raise_for_status()
  33. except httpx.HTTPStatusError as exc:
  34. detail = response.text.strip()
  35. raise RuntimeError(
  36. f"Shuffle returned {response.status_code} for {url}. Response: {detail}"
  37. ) from exc
  38. return response.json() if response.content else {"status_code": response.status_code}
  39. async def health(self) -> dict[str, Any]:
  40. return await self._request("GET", "/api/v1/_ah/health")
  41. async def auth_test(self) -> dict[str, Any]:
  42. return await self._request("GET", "/api/v1/users/getinfo")
  43. async def list_workflows(self) -> dict[str, Any]:
  44. return await self._request("GET", "/api/v1/workflows")
  45. async def get_workflow(self, workflow_id: str) -> dict[str, Any]:
  46. return await self._request("GET", f"/api/v1/workflows/{workflow_id}")
  47. async def trigger_workflow(self, workflow_id: str, payload: dict[str, Any]) -> dict[str, Any]:
  48. return await self._request("POST", f"/api/v1/workflows/{workflow_id}/execute", payload=payload)
  49. async def list_apps(self) -> dict[str, Any]:
  50. return await self._request("GET", "/api/v1/apps")
  51. async def proxy(
  52. self,
  53. method: str,
  54. path: str,
  55. params: dict[str, Any] | None = None,
  56. payload: dict[str, Any] | None = None,
  57. ) -> dict[str, Any]:
  58. return await self._request(method=method, path=path, params=params, payload=payload)
  59. async def login(self, username: str, password: str) -> dict[str, Any]:
  60. return await self._request(
  61. "POST",
  62. "/api/v1/users/login",
  63. payload={"username": username, "password": password},
  64. )
  65. async def generate_apikey_from_login(self, username: str, password: str) -> dict[str, Any]:
  66. login_url = f"{self.base_url}/api/v1/users/login"
  67. api_key_url = f"{self.base_url}/api/v1/users/generateapikey"
  68. async with httpx.AsyncClient(timeout=25.0) as client:
  69. login_resp = await client.post(login_url, json={"username": username, "password": password})
  70. login_resp.raise_for_status()
  71. generate_resp = await client.get(api_key_url)
  72. try:
  73. generate_resp.raise_for_status()
  74. except httpx.HTTPStatusError as exc:
  75. detail = generate_resp.text.strip()
  76. raise RuntimeError(
  77. f"Shuffle returned {generate_resp.status_code} for {api_key_url}. Response: {detail}"
  78. ) from exc
  79. return generate_resp.json() if generate_resp.content else {"status_code": generate_resp.status_code}