robot-wrapper-sdk 0.2.6__tar.gz → 0.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/PKG-INFO +1 -1
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/pyproject.toml +1 -1
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/infrastructure/api_client.py +25 -1
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/infrastructure/robot_api_repository.py +33 -8
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/PKG-INFO +1 -1
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/README.md +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/examples/main.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/application/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/application/usecases.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/domain/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/domain/entities.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/domain/repositories.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/infrastructure/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/SOURCES.txt +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/dependency_links.txt +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/requires.txt +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/top_level.txt +0 -0
- {robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/setup.cfg +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import httpx
|
|
2
2
|
import os
|
|
3
3
|
from typing import Dict, Any, Optional
|
|
4
|
+
from httpx import RemoteProtocolError
|
|
4
5
|
|
|
5
6
|
def _extract_tokens(payload: Dict[str, Any]) -> tuple[Optional[str], Optional[str]]:
|
|
6
7
|
data = payload.get("data") if isinstance(payload, dict) else None
|
|
@@ -132,7 +133,30 @@ class HTTPClient:
|
|
|
132
133
|
full_path = f"/api/v1/developer{path}"
|
|
133
134
|
|
|
134
135
|
print(f"🚀 Requesting: {self.base_url}{full_path}")
|
|
135
|
-
|
|
136
|
+
last_err: Optional[Exception] = None
|
|
137
|
+
resp = None
|
|
138
|
+
for attempt in range(2):
|
|
139
|
+
try:
|
|
140
|
+
resp = self.client.request(method, full_path, **kwargs)
|
|
141
|
+
break
|
|
142
|
+
except Exception as err:
|
|
143
|
+
msg = str(err)
|
|
144
|
+
is_disconnect = isinstance(err, RemoteProtocolError) or "Server disconnected without sending a response" in msg
|
|
145
|
+
if not is_disconnect or attempt == 1:
|
|
146
|
+
raise
|
|
147
|
+
last_err = err
|
|
148
|
+
self.client.close()
|
|
149
|
+
self.client = httpx.Client(
|
|
150
|
+
base_url=self.base_url,
|
|
151
|
+
auth=RobotAuth(self._get_or_login, self._refresh),
|
|
152
|
+
proxy=self.proxy_url,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
if resp is None:
|
|
156
|
+
if last_err is not None:
|
|
157
|
+
raise last_err
|
|
158
|
+
raise RuntimeError("Request failed without response")
|
|
159
|
+
|
|
136
160
|
resp.raise_for_status()
|
|
137
161
|
try:
|
|
138
162
|
return dict(resp.json())
|
{robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_sdk/infrastructure/robot_api_repository.py
RENAMED
|
@@ -3,6 +3,33 @@ from .api_client import HTTPClient, AsyncHTTPClient
|
|
|
3
3
|
from ..domain.repositories import RobotRepository, AsyncRobotRepository
|
|
4
4
|
from ..domain.entities import Robot, RobotSecrets
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
def _extract_list_payload(resp: Dict[str, Any]) -> Tuple[List[Dict[str, Any]], int]:
|
|
8
|
+
container = resp.get("data") if isinstance(resp, dict) else None
|
|
9
|
+
if isinstance(container, dict):
|
|
10
|
+
items = container.get("data")
|
|
11
|
+
total = container.get("total", 0)
|
|
12
|
+
else:
|
|
13
|
+
items = container
|
|
14
|
+
total = resp.get("total", 0) if isinstance(resp, dict) else 0
|
|
15
|
+
|
|
16
|
+
if not isinstance(items, list):
|
|
17
|
+
return [], int(total) if isinstance(total, int) else 0
|
|
18
|
+
|
|
19
|
+
mapped = [item for item in items if isinstance(item, dict)]
|
|
20
|
+
return mapped, int(total) if isinstance(total, int) else 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _extract_items(resp: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
24
|
+
container = resp.get("data") if isinstance(resp, dict) else None
|
|
25
|
+
if isinstance(container, list):
|
|
26
|
+
return [item for item in container if isinstance(item, dict)]
|
|
27
|
+
if isinstance(container, dict):
|
|
28
|
+
nested = container.get("data")
|
|
29
|
+
if isinstance(nested, list):
|
|
30
|
+
return [item for item in nested if isinstance(item, dict)]
|
|
31
|
+
return []
|
|
32
|
+
|
|
6
33
|
class RobotAPIRepository(RobotRepository):
|
|
7
34
|
def __init__(self, client: HTTPClient):
|
|
8
35
|
self.client = client
|
|
@@ -28,8 +55,7 @@ class RobotAPIRepository(RobotRepository):
|
|
|
28
55
|
if project_id: params["project_id"] = project_id
|
|
29
56
|
|
|
30
57
|
resp = self.client.request("GET", "/robots", params=params)
|
|
31
|
-
data = resp
|
|
32
|
-
total = resp.get("total", 0)
|
|
58
|
+
data, total = _extract_list_payload(resp)
|
|
33
59
|
return [Robot(**r) for r in data], total
|
|
34
60
|
|
|
35
61
|
def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
@@ -38,7 +64,7 @@ class RobotAPIRepository(RobotRepository):
|
|
|
38
64
|
"/robots/login/acquire",
|
|
39
65
|
json={"limit": limit, "lock_minutes": lock_minutes},
|
|
40
66
|
)
|
|
41
|
-
data = resp
|
|
67
|
+
data = _extract_items(resp)
|
|
42
68
|
return [Robot(**r) for r in data]
|
|
43
69
|
|
|
44
70
|
def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
@@ -47,7 +73,7 @@ class RobotAPIRepository(RobotRepository):
|
|
|
47
73
|
"/robots/security-hardened/acquire",
|
|
48
74
|
json={"limit": limit, "lock_minutes": lock_minutes, "min_age_days": min_age_days},
|
|
49
75
|
)
|
|
50
|
-
data = resp
|
|
76
|
+
data = _extract_items(resp)
|
|
51
77
|
return [Robot(**r) for r in data]
|
|
52
78
|
|
|
53
79
|
def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
@@ -89,8 +115,7 @@ class AsyncRobotAPIRepository(AsyncRobotRepository):
|
|
|
89
115
|
if project_id: params["project_id"] = project_id
|
|
90
116
|
|
|
91
117
|
resp = await self.client.request("GET", "/robots", params=params)
|
|
92
|
-
data = resp
|
|
93
|
-
total = resp.get("total", 0)
|
|
118
|
+
data, total = _extract_list_payload(resp)
|
|
94
119
|
return [Robot(**r) for r in data], total
|
|
95
120
|
|
|
96
121
|
async def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
@@ -99,7 +124,7 @@ class AsyncRobotAPIRepository(AsyncRobotRepository):
|
|
|
99
124
|
"/robots/login/acquire",
|
|
100
125
|
json={"limit": limit, "lock_minutes": lock_minutes},
|
|
101
126
|
)
|
|
102
|
-
data = resp
|
|
127
|
+
data = _extract_items(resp)
|
|
103
128
|
return [Robot(**r) for r in data]
|
|
104
129
|
|
|
105
130
|
async def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
@@ -108,7 +133,7 @@ class AsyncRobotAPIRepository(AsyncRobotRepository):
|
|
|
108
133
|
"/robots/security-hardened/acquire",
|
|
109
134
|
json={"limit": limit, "lock_minutes": lock_minutes, "min_age_days": min_age_days},
|
|
110
135
|
)
|
|
111
|
-
data = resp
|
|
136
|
+
data = _extract_items(resp)
|
|
112
137
|
return [Robot(**r) for r in data]
|
|
113
138
|
|
|
114
139
|
async def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{robot_wrapper_sdk-0.2.6 → robot_wrapper_sdk-0.2.7}/robot_wrapper_sdk.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|