cmdop 0.1.25__py3-none-any.whl → 0.1.27__py3-none-any.whl

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.
Files changed (36) hide show
  1. cmdop/__init__.py +9 -4
  2. cmdop/_generated/rpc_messages/browser_pb2.py +138 -138
  3. cmdop/_generated/rpc_messages/browser_pb2.pyi +6 -2
  4. cmdop/api/generated/machines/__init__.py +1 -1
  5. cmdop/api/generated/machines/enums.py +0 -112
  6. cmdop/api/generated/machines/machines__api__machine_sharing/client.py +21 -6
  7. cmdop/api/generated/machines/machines__api__machine_sharing/models.py +46 -19
  8. cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py +20 -5
  9. cmdop/api/generated/machines/machines__api__machines/client.py +90 -25
  10. cmdop/api/generated/machines/machines__api__machines/models.py +143 -125
  11. cmdop/api/generated/machines/machines__api__machines/sync_client.py +84 -19
  12. cmdop/api/generated/machines/schema.json +72 -0
  13. cmdop/api/generated/system/__init__.py +1 -1
  14. cmdop/api/generated/system/enums.py +0 -52
  15. cmdop/api/generated/system/schema.json +54 -0
  16. cmdop/api/generated/system/system__api__oauth/client.py +42 -12
  17. cmdop/api/generated/system/system__api__oauth/models.py +111 -85
  18. cmdop/api/generated/system/system__api__oauth/sync_client.py +38 -8
  19. cmdop/api/generated/system/system__api__system/client.py +98 -23
  20. cmdop/api/generated/system/system__api__system/models.py +83 -83
  21. cmdop/api/generated/system/system__api__system/sync_client.py +94 -19
  22. cmdop/api/generated/workspaces/__init__.py +1 -1
  23. cmdop/api/generated/workspaces/enums.py +0 -137
  24. cmdop/api/generated/workspaces/schema.json +47 -0
  25. cmdop/api/generated/workspaces/workspaces__api__workspaces/client.py +156 -41
  26. cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py +126 -85
  27. cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py +145 -29
  28. cmdop/helpers/__init__.py +0 -4
  29. cmdop/services/browser/service/sync.py +4 -0
  30. cmdop/services/files.py +159 -17
  31. {cmdop-0.1.25.dist-info → cmdop-0.1.27.dist-info}/METADATA +47 -19
  32. {cmdop-0.1.25.dist-info → cmdop-0.1.27.dist-info}/RECORD +34 -36
  33. cmdop/helpers/cleaner.py +0 -53
  34. cmdop/helpers/formatting.py +0 -15
  35. {cmdop-0.1.25.dist-info → cmdop-0.1.27.dist-info}/WHEEL +0 -0
  36. {cmdop-0.1.25.dist-info → cmdop-0.1.27.dist-info}/licenses/LICENSE +0 -0
@@ -9,6 +9,26 @@ from pydantic import BaseModel, ConfigDict, Field
9
9
  from ..enums import DeviceAuthorizeRequestAction, TokenErrorError, TokenRequestRequestGrantType, TokenRevokeRequestTokenTypeHint
10
10
 
11
11
 
12
+ class DeviceAuthorizeRequest(BaseModel):
13
+ """
14
+ Request body for POST /api/oauth/authorize User approves or denies device
15
+ code in browser.
16
+
17
+ Request model (no read-only fields).
18
+ """
19
+
20
+ model_config = ConfigDict(
21
+ validate_assignment=True,
22
+ extra="allow",
23
+ frozen=False,
24
+ )
25
+
26
+ user_code: str = Field(description='User code to authorize (e.g., ABC-XYZ)', min_length=1, max_length=10)
27
+ action: DeviceAuthorizeRequestAction = Field(description='User decision: approve or deny\n\n* `approve` - approve\n* `deny` - deny')
28
+ workspace_id: str | None = Field(None, description='Workspace ID to grant access to (required for approve)')
29
+
30
+
31
+
12
32
  class DeviceAuthorizeResponse(BaseModel):
13
33
  """
14
34
  Response for device authorization.
@@ -29,12 +49,11 @@ class DeviceAuthorizeResponse(BaseModel):
29
49
 
30
50
 
31
51
 
32
- class DeviceCodeResponse(BaseModel):
52
+ class DeviceCodeRequestRequest(BaseModel):
33
53
  """
34
- Response body for POST /api/oauth/device Returns device code info for CLI to
35
- display to user.
54
+ Request body for POST /api/oauth/device Client sends metadata about itself.
36
55
 
37
- Response model (includes read-only fields).
56
+ Request model (no read-only fields).
38
57
  """
39
58
 
40
59
  model_config = ConfigDict(
@@ -43,18 +62,17 @@ class DeviceCodeResponse(BaseModel):
43
62
  frozen=False,
44
63
  )
45
64
 
46
- device_code: str = Field(description='Device code for polling (not shown to user)')
47
- user_code: str = Field(description='Human-readable code to show user (e.g., ABC-XYZ)')
48
- verification_uri: str = Field(description='URL where user authorizes (e.g., https://cmdop.com/device)')
49
- expires_in: int = Field(description='Seconds until device code expires (typically 900)')
50
- interval: int = Field(description='Polling interval in seconds (typically 5)')
65
+ client_name: str | None = Field(None, description='Client application name', min_length=1, max_length=100)
66
+ client_version: str | None = Field(None, description='Client version (e.g., 1.0.0)', max_length=50)
67
+ client_hostname: str | None = Field(None, description='Client machine hostname', max_length=255)
68
+ client_platform: str | None = Field(None, description='OS platform: darwin, linux, windows', max_length=50)
51
69
 
52
70
 
53
71
 
54
- class TokenResponse(BaseModel):
72
+ class DeviceCodeResponse(BaseModel):
55
73
  """
56
- Response body for POST /api/oauth/token Returns access token and refresh
57
- token.
74
+ Response body for POST /api/oauth/device Returns device code info for CLI to
75
+ display to user.
58
76
 
59
77
  Response model (includes read-only fields).
60
78
  """
@@ -65,23 +83,20 @@ class TokenResponse(BaseModel):
65
83
  frozen=False,
66
84
  )
67
85
 
68
- access_token: str = Field(description='Access token (clit_...)')
69
- refresh_token: str = Field(description='Refresh token (clitr_...)')
70
- token_type: str = Field(None, description='Token type (always Bearer)')
71
- expires_in: int = Field(description='Access token expiry in seconds')
72
- scope: str = Field(None, description='Token scope')
73
- workspace_id: str = Field(description='Workspace ID')
74
- workspace_name: str = Field(description='Workspace name')
75
- user_id: str = Field(description='User ID')
76
- user_email: str = Field(None, description='User email (optional)')
86
+ device_code: str = Field(description='Device code for polling (not shown to user)')
87
+ user_code: str = Field(description='Human-readable code to show user (e.g., ABC-XYZ)')
88
+ verification_uri: str = Field(description='URL where user authorizes (e.g., https://cmdop.com/device)')
89
+ expires_in: int = Field(description='Seconds until device code expires (typically 900)')
90
+ interval: int = Field(description='Polling interval in seconds (typically 5)')
77
91
 
78
92
 
79
93
 
80
- class TokenError(BaseModel):
94
+ class TokenRevokeRequest(BaseModel):
81
95
  """
82
- Error response for POST /api/oauth/token OAuth 2.0 standard error format.
96
+ Request body for POST /api/oauth/revoke Revoke access token or refresh
97
+ token.
83
98
 
84
- Response model (includes read-only fields).
99
+ Request model (no read-only fields).
85
100
  """
86
101
 
87
102
  model_config = ConfigDict(
@@ -90,17 +105,17 @@ class TokenError(BaseModel):
90
105
  frozen=False,
91
106
  )
92
107
 
93
- error: TokenErrorError = Field(description='OAuth error code\n\n* `authorization_pending` - authorization_pending\n* `slow_down` - slow_down\n* `access_denied` - access_denied\n* `expired_token` - expired_token\n* `invalid_grant` - invalid_grant')
94
- error_description: str = Field(None, description='Human-readable error description')
108
+ token: str = Field(description='Token to revoke (access or refresh)', min_length=1)
109
+ token_type_hint: TokenRevokeRequestTokenTypeHint | None = Field(None, description='Hint about token type (optional)\n\n* `access_token` - access_token\n* `refresh_token` - refresh_token')
95
110
 
96
111
 
97
112
 
98
- class TokenInfo(BaseModel):
113
+ class TokenRequestRequest(BaseModel):
99
114
  """
100
- Response for GET /api/oauth/token/info Returns information about current
101
- token.
115
+ Request body for POST /api/oauth/token CLI polls with device_code until
116
+ approved.
102
117
 
103
- Response model (includes read-only fields).
118
+ Request model (no read-only fields).
104
119
  """
105
120
 
106
121
  model_config = ConfigDict(
@@ -109,28 +124,17 @@ class TokenInfo(BaseModel):
109
124
  frozen=False,
110
125
  )
111
126
 
112
- id: Any = ...
113
- access_token_prefix: str = Field(description='First 12 characters for identification', max_length=12)
114
- workspace_id: str = ...
115
- workspace_name: str = ...
116
- user_id: str = ...
117
- username: str = ...
118
- client_name: str = Field(None, max_length=100)
119
- client_version: str = Field(None, max_length=50)
120
- client_hostname: str = Field(None, max_length=255)
121
- client_platform: str = Field(None, description='OS platform: darwin, linux, windows', max_length=50)
122
- created_at: Any = ...
123
- access_token_expires_at: str = ...
124
- refresh_token_expires_at: str = ...
125
- last_used_at: str | None = Field(None, description='Last time access token was used')
126
- is_expired: Any = ...
127
- is_refresh_expired: Any = ...
127
+ grant_type: TokenRequestRequestGrantType = Field(description='OAuth grant type\n\n* `urn:ietf:params:oauth:grant-type:device_code` - Device Code Flow\n* `refresh_token` - Refresh Token')
128
+ device_code: str | None = Field(None, description='Device code from initial request (for device flow)', min_length=1)
129
+ refresh_token: str | None = Field(None, description='Refresh token (for token refresh)', min_length=1)
128
130
 
129
131
 
130
132
 
131
- class PaginatedTokenListList(BaseModel):
133
+ class TokenResponse(BaseModel):
132
134
  """
133
-
135
+ Response body for POST /api/oauth/token Returns access token and refresh
136
+ token.
137
+
134
138
  Response model (includes read-only fields).
135
139
  """
136
140
 
@@ -140,24 +144,23 @@ class PaginatedTokenListList(BaseModel):
140
144
  frozen=False,
141
145
  )
142
146
 
143
- count: int = Field(description='Total number of items across all pages')
144
- page: int = Field(description='Current page number (1-based)')
145
- pages: int = Field(description='Total number of pages')
146
- page_size: int = Field(description='Number of items per page')
147
- has_next: bool = Field(description='Whether there is a next page')
148
- has_previous: bool = Field(description='Whether there is a previous page')
149
- next_page: int | None = Field(None, description='Next page number (null if no next page)')
150
- previous_page: int | None = Field(None, description='Previous page number (null if no previous page)')
151
- results: list[dict[str, Any]] = Field(description='Array of items for current page')
147
+ access_token: str = Field(description='Access token (clit_...)')
148
+ refresh_token: str = Field(description='Refresh token (clitr_...)')
149
+ token_type: str | None = Field(None, description='Token type (always Bearer)')
150
+ expires_in: int = Field(description='Access token expiry in seconds')
151
+ scope: str | None = Field(None, description='Token scope')
152
+ workspace_id: str = Field(description='Workspace ID')
153
+ workspace_name: str = Field(description='Workspace name')
154
+ user_id: str = Field(description='User ID')
155
+ user_email: str | None = Field(None, description='User email (optional)')
152
156
 
153
157
 
154
158
 
155
- class DeviceAuthorizeRequest(BaseModel):
159
+ class TokenError(BaseModel):
156
160
  """
157
- Request body for POST /api/oauth/authorize User approves or denies device
158
- code in browser.
161
+ Error response for POST /api/oauth/token OAuth 2.0 standard error format.
159
162
 
160
- Request model (no read-only fields).
163
+ Response model (includes read-only fields).
161
164
  """
162
165
 
163
166
  model_config = ConfigDict(
@@ -166,17 +169,17 @@ class DeviceAuthorizeRequest(BaseModel):
166
169
  frozen=False,
167
170
  )
168
171
 
169
- user_code: str = Field(description='User code to authorize (e.g., ABC-XYZ)', min_length=1, max_length=10)
170
- action: DeviceAuthorizeRequestAction = Field(description='User decision: approve or deny\n\n* `approve` - approve\n* `deny` - deny')
171
- workspace_id: str | None = Field(None, description='Workspace ID to grant access to (required for approve)')
172
+ error: TokenErrorError = Field(description='OAuth error code\n\n* `authorization_pending` - authorization_pending\n* `slow_down` - slow_down\n* `access_denied` - access_denied\n* `expired_token` - expired_token\n* `invalid_grant` - invalid_grant')
173
+ error_description: str | None = Field(None, description='Human-readable error description')
172
174
 
173
175
 
174
176
 
175
- class DeviceCodeRequestRequest(BaseModel):
177
+ class TokenInfo(BaseModel):
176
178
  """
177
- Request body for POST /api/oauth/device Client sends metadata about itself.
179
+ Response for GET /api/oauth/token/info Returns information about current
180
+ token.
178
181
 
179
- Request model (no read-only fields).
182
+ Response model (includes read-only fields).
180
183
  """
181
184
 
182
185
  model_config = ConfigDict(
@@ -185,19 +188,30 @@ class DeviceCodeRequestRequest(BaseModel):
185
188
  frozen=False,
186
189
  )
187
190
 
188
- client_name: str = Field(None, description='Client application name', min_length=1, max_length=100)
189
- client_version: str = Field(None, description='Client version (e.g., 1.0.0)', max_length=50)
190
- client_hostname: str = Field(None, description='Client machine hostname', max_length=255)
191
- client_platform: str = Field(None, description='OS platform: darwin, linux, windows', max_length=50)
191
+ id: Any = ...
192
+ access_token_prefix: str = Field(description='First 12 characters for identification', max_length=12)
193
+ workspace_id: str = ...
194
+ workspace_name: str = ...
195
+ user_id: str = ...
196
+ username: str = ...
197
+ client_name: str | None = Field(None, max_length=100)
198
+ client_version: str | None = Field(None, max_length=50)
199
+ client_hostname: str | None = Field(None, max_length=255)
200
+ client_platform: str | None = Field(None, description='OS platform: darwin, linux, windows', max_length=50)
201
+ created_at: Any = ...
202
+ access_token_expires_at: str = ...
203
+ refresh_token_expires_at: str = ...
204
+ last_used_at: str | None = Field(None, description='Last time access token was used')
205
+ is_expired: Any = ...
206
+ is_refresh_expired: Any = ...
192
207
 
193
208
 
194
209
 
195
- class TokenRevokeRequest(BaseModel):
210
+ class TokenList(BaseModel):
196
211
  """
197
- Request body for POST /api/oauth/revoke Revoke access token or refresh
198
- token.
212
+ Serializer for listing user's CLI tokens.
199
213
 
200
- Request model (no read-only fields).
214
+ Response model (includes read-only fields).
201
215
  """
202
216
 
203
217
  model_config = ConfigDict(
@@ -206,17 +220,23 @@ class TokenRevokeRequest(BaseModel):
206
220
  frozen=False,
207
221
  )
208
222
 
209
- token: str = Field(description='Token to revoke (access or refresh)', min_length=1)
210
- token_type_hint: TokenRevokeRequestTokenTypeHint = Field(None, description='Hint about token type (optional)\n\n* `access_token` - access_token\n* `refresh_token` - refresh_token')
223
+ id: Any = ...
224
+ access_token_prefix: str = Field(description='First 12 characters for identification', max_length=12)
225
+ workspace_name: str = ...
226
+ client_name: str | None = Field(None, max_length=100)
227
+ client_hostname: str | None = Field(None, max_length=255)
228
+ client_platform: str | None = Field(None, description='OS platform: darwin, linux, windows', max_length=50)
229
+ created_at: Any = ...
230
+ last_used_at: str | None = Field(None, description='Last time access token was used')
231
+ revoked_at: str | None = None
232
+ is_active: Any = ...
211
233
 
212
234
 
213
235
 
214
- class TokenRequestRequest(BaseModel):
236
+ class PaginatedTokenListList(BaseModel):
215
237
  """
216
- Request body for POST /api/oauth/token CLI polls with device_code until
217
- approved.
218
-
219
- Request model (no read-only fields).
238
+
239
+ Response model (includes read-only fields).
220
240
  """
221
241
 
222
242
  model_config = ConfigDict(
@@ -225,9 +245,15 @@ class TokenRequestRequest(BaseModel):
225
245
  frozen=False,
226
246
  )
227
247
 
228
- grant_type: TokenRequestRequestGrantType = Field(description='OAuth grant type\n\n* `urn:ietf:params:oauth:grant-type:device_code` - Device Code Flow\n* `refresh_token` - Refresh Token')
229
- device_code: str = Field(None, description='Device code from initial request (for device flow)', min_length=1)
230
- refresh_token: str = Field(None, description='Refresh token (for token refresh)', min_length=1)
248
+ count: int = Field(description='Total number of items across all pages')
249
+ page: int = Field(description='Current page number (1-based)')
250
+ pages: int = Field(description='Total number of pages')
251
+ page_size: int = Field(description='Number of items per page')
252
+ has_next: bool = Field(description='Whether there is a next page')
253
+ has_previous: bool = Field(description='Whether there is a previous page')
254
+ next_page: int | None = Field(None, description='Next page number (null if no next page)')
255
+ previous_page: int | None = Field(None, description='Previous page number (null if no previous page)')
256
+ results: list[TokenList] = Field(description='Array of items for current page')
231
257
 
232
258
 
233
259
 
@@ -21,7 +21,12 @@ class SyncSystemOauthAPI:
21
21
  """
22
22
  url = "/api/system/oauth/authorize/"
23
23
  response = self._client.post(url, json=data.model_dump(exclude_unset=True))
24
- response.raise_for_status()
24
+ if not response.is_success:
25
+ try:
26
+ error_body = response.json()
27
+ except Exception:
28
+ error_body = response.text
29
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
25
30
  return DeviceAuthorizeResponse.model_validate(response.json())
26
31
 
27
32
 
@@ -33,7 +38,12 @@ class SyncSystemOauthAPI:
33
38
  """
34
39
  url = "/api/system/oauth/device/"
35
40
  response = self._client.post(url, json=data.model_dump(exclude_unset=True))
36
- response.raise_for_status()
41
+ if not response.is_success:
42
+ try:
43
+ error_body = response.json()
44
+ except Exception:
45
+ error_body = response.text
46
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
37
47
  return DeviceCodeResponse.model_validate(response.json())
38
48
 
39
49
 
@@ -45,7 +55,12 @@ class SyncSystemOauthAPI:
45
55
  """
46
56
  url = "/api/system/oauth/revoke/"
47
57
  response = self._client.post(url, json=data.model_dump(exclude_unset=True))
48
- response.raise_for_status()
58
+ if not response.is_success:
59
+ try:
60
+ error_body = response.json()
61
+ except Exception:
62
+ error_body = response.text
63
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
49
64
 
50
65
 
51
66
  def system_oauth_token_create(self, data: TokenRequestRequest) -> TokenResponse:
@@ -56,7 +71,12 @@ class SyncSystemOauthAPI:
56
71
  """
57
72
  url = "/api/system/oauth/token/"
58
73
  response = self._client.post(url, json=data.model_dump(exclude_unset=True))
59
- response.raise_for_status()
74
+ if not response.is_success:
75
+ try:
76
+ error_body = response.json()
77
+ except Exception:
78
+ error_body = response.text
79
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
60
80
  return TokenResponse.model_validate(response.json())
61
81
 
62
82
 
@@ -68,19 +88,29 @@ class SyncSystemOauthAPI:
68
88
  """
69
89
  url = "/api/system/oauth/token/info/"
70
90
  response = self._client.get(url)
71
- response.raise_for_status()
91
+ if not response.is_success:
92
+ try:
93
+ error_body = response.json()
94
+ except Exception:
95
+ error_body = response.text
96
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
72
97
  return TokenInfo.model_validate(response.json())
73
98
 
74
99
 
75
- def system_oauth_tokens_list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedTokenListList]:
100
+ def system_oauth_tokens_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedTokenListList]:
76
101
  """
77
102
  List user tokens
78
103
 
79
104
  List all CLI tokens for authenticated user.
80
105
  """
81
106
  url = "/api/system/oauth/tokens/"
82
- response = self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None})
83
- response.raise_for_status()
107
+ response = self._client.get(url, params={"ordering": ordering if ordering is not None else None, "page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "search": search if search is not None else None})
108
+ if not response.is_success:
109
+ try:
110
+ error_body = response.json()
111
+ except Exception:
112
+ error_body = response.text
113
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
84
114
  return PaginatedTokenListList.model_validate(response.json())
85
115
 
86
116
 
@@ -12,13 +12,18 @@ class SystemSystemAPI:
12
12
  """Initialize sub-client with shared httpx client."""
13
13
  self._client = client
14
14
 
15
- async def alerts_list(self, page: int | None = None, page_size: int | None = None, read: bool | None = None, type: str | None = None, workspace: str | None = None) -> list[PaginatedAlertList]:
15
+ async def alerts_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, read: bool | None = None, search: str | None = None, type: str | None = None, workspace: str | None = None) -> list[PaginatedAlertList]:
16
16
  """
17
17
  List alerts with filters.
18
18
  """
19
19
  url = "/api/system/alerts/"
20
- response = await self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "read": read if read is not None else None, "type": type if type is not None else None, "workspace": workspace if workspace is not None else None})
21
- response.raise_for_status()
20
+ response = await self._client.get(url, params={"ordering": ordering if ordering is not None else None, "page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "read": read if read is not None else None, "search": search if search is not None else None, "type": type if type is not None else None, "workspace": workspace if workspace is not None else None})
21
+ if not response.is_success:
22
+ try:
23
+ error_body = response.json()
24
+ except Exception:
25
+ error_body = response.text
26
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
22
27
  return PaginatedAlertList.model_validate(response.json())
23
28
 
24
29
 
@@ -27,8 +32,13 @@ class SystemSystemAPI:
27
32
  ViewSet for Alert operations. System notifications for important events.
28
33
  """
29
34
  url = "/api/system/alerts/"
30
- response = await self._client.post(url, json=data.model_dump())
31
- response.raise_for_status()
35
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
36
+ if not response.is_success:
37
+ try:
38
+ error_body = response.json()
39
+ except Exception:
40
+ error_body = response.text
41
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
32
42
  return AlertCreate.model_validate(response.json())
33
43
 
34
44
 
@@ -38,7 +48,12 @@ class SystemSystemAPI:
38
48
  """
39
49
  url = f"/api/system/alerts/{id}/"
40
50
  response = await self._client.get(url)
41
- response.raise_for_status()
51
+ if not response.is_success:
52
+ try:
53
+ error_body = response.json()
54
+ except Exception:
55
+ error_body = response.text
56
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
42
57
  return Alert.model_validate(response.json())
43
58
 
44
59
 
@@ -47,8 +62,13 @@ class SystemSystemAPI:
47
62
  ViewSet for Alert operations. System notifications for important events.
48
63
  """
49
64
  url = f"/api/system/alerts/{id}/"
50
- response = await self._client.put(url, json=data.model_dump())
51
- response.raise_for_status()
65
+ response = await self._client.put(url, json=data.model_dump(exclude_unset=True))
66
+ if not response.is_success:
67
+ try:
68
+ error_body = response.json()
69
+ except Exception:
70
+ error_body = response.text
71
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
52
72
  return Alert.model_validate(response.json())
53
73
 
54
74
 
@@ -57,8 +77,13 @@ class SystemSystemAPI:
57
77
  ViewSet for Alert operations. System notifications for important events.
58
78
  """
59
79
  url = f"/api/system/alerts/{id}/"
60
- response = await self._client.patch(url, json=data.model_dump() if data is not None else None)
61
- response.raise_for_status()
80
+ response = await self._client.patch(url, json=data.model_dump(exclude_unset=True) if data is not None else None)
81
+ if not response.is_success:
82
+ try:
83
+ error_body = response.json()
84
+ except Exception:
85
+ error_body = response.text
86
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
62
87
  return Alert.model_validate(response.json())
63
88
 
64
89
 
@@ -68,7 +93,12 @@ class SystemSystemAPI:
68
93
  """
69
94
  url = f"/api/system/alerts/{id}/"
70
95
  response = await self._client.delete(url)
71
- response.raise_for_status()
96
+ if not response.is_success:
97
+ try:
98
+ error_body = response.json()
99
+ except Exception:
100
+ error_body = response.text
101
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
72
102
  return None
73
103
 
74
104
 
@@ -78,7 +108,12 @@ class SystemSystemAPI:
78
108
  """
79
109
  url = f"/api/system/alerts/{id}/mark-as-read/"
80
110
  response = await self._client.post(url)
81
- response.raise_for_status()
111
+ if not response.is_success:
112
+ try:
113
+ error_body = response.json()
114
+ except Exception:
115
+ error_body = response.text
116
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
82
117
  return Alert.model_validate(response.json())
83
118
 
84
119
 
@@ -88,17 +123,27 @@ class SystemSystemAPI:
88
123
  """
89
124
  url = "/api/system/alerts/mark-all-as-read/"
90
125
  response = await self._client.post(url)
91
- response.raise_for_status()
126
+ if not response.is_success:
127
+ try:
128
+ error_body = response.json()
129
+ except Exception:
130
+ error_body = response.text
131
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
92
132
  return None
93
133
 
94
134
 
95
- async def api_keys_list(self, page: int | None = None, page_size: int | None = None, workspace: str | None = None) -> list[PaginatedApiKeyList]:
135
+ async def api_keys_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None, workspace: str | None = None) -> list[PaginatedApiKeyList]:
96
136
  """
97
137
  List API keys with filters.
98
138
  """
99
139
  url = "/api/system/api-keys/"
100
- response = await self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "workspace": workspace if workspace is not None else None})
101
- response.raise_for_status()
140
+ response = await self._client.get(url, params={"ordering": ordering if ordering is not None else None, "page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "search": search if search is not None else None, "workspace": workspace if workspace is not None else None})
141
+ if not response.is_success:
142
+ try:
143
+ error_body = response.json()
144
+ except Exception:
145
+ error_body = response.text
146
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
102
147
  return PaginatedApiKeyList.model_validate(response.json())
103
148
 
104
149
 
@@ -107,8 +152,13 @@ class SystemSystemAPI:
107
152
  Create new API key (raw key shown only once).
108
153
  """
109
154
  url = "/api/system/api-keys/"
110
- response = await self._client.post(url, json=data.model_dump())
111
- response.raise_for_status()
155
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
156
+ if not response.is_success:
157
+ try:
158
+ error_body = response.json()
159
+ except Exception:
160
+ error_body = response.text
161
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
112
162
  return ApiKeyResponse.model_validate(response.json())
113
163
 
114
164
 
@@ -119,7 +169,12 @@ class SystemSystemAPI:
119
169
  """
120
170
  url = f"/api/system/api-keys/{id}/"
121
171
  response = await self._client.get(url)
122
- response.raise_for_status()
172
+ if not response.is_success:
173
+ try:
174
+ error_body = response.json()
175
+ except Exception:
176
+ error_body = response.text
177
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
123
178
  return ApiKey.model_validate(response.json())
124
179
 
125
180
 
@@ -130,7 +185,12 @@ class SystemSystemAPI:
130
185
  """
131
186
  url = f"/api/system/api-keys/{id}/"
132
187
  response = await self._client.put(url)
133
- response.raise_for_status()
188
+ if not response.is_success:
189
+ try:
190
+ error_body = response.json()
191
+ except Exception:
192
+ error_body = response.text
193
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
134
194
  return ApiKey.model_validate(response.json())
135
195
 
136
196
 
@@ -141,7 +201,12 @@ class SystemSystemAPI:
141
201
  """
142
202
  url = f"/api/system/api-keys/{id}/"
143
203
  response = await self._client.patch(url)
144
- response.raise_for_status()
204
+ if not response.is_success:
205
+ try:
206
+ error_body = response.json()
207
+ except Exception:
208
+ error_body = response.text
209
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
145
210
  return ApiKey.model_validate(response.json())
146
211
 
147
212
 
@@ -152,7 +217,12 @@ class SystemSystemAPI:
152
217
  """
153
218
  url = f"/api/system/api-keys/{id}/"
154
219
  response = await self._client.delete(url)
155
- response.raise_for_status()
220
+ if not response.is_success:
221
+ try:
222
+ error_body = response.json()
223
+ except Exception:
224
+ error_body = response.text
225
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
156
226
  return None
157
227
 
158
228
 
@@ -162,7 +232,12 @@ class SystemSystemAPI:
162
232
  """
163
233
  url = f"/api/system/api-keys/{id}/regenerate/"
164
234
  response = await self._client.post(url)
165
- response.raise_for_status()
235
+ if not response.is_success:
236
+ try:
237
+ error_body = response.json()
238
+ except Exception:
239
+ error_body = response.text
240
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
166
241
  return ApiKeyResponse.model_validate(response.json())
167
242
 
168
243