pltr-cli 0.4.0__py3-none-any.whl → 0.5.0__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.
- pltr/cli.py +8 -0
- pltr/commands/dataset.py +309 -0
- pltr/commands/mediasets.py +422 -0
- pltr/commands/orchestration.py +642 -0
- pltr/services/dataset.py +368 -10
- pltr/services/mediasets.py +293 -0
- pltr/services/orchestration.py +457 -0
- pltr/utils/formatting.py +638 -0
- {pltr_cli-0.4.0.dist-info → pltr_cli-0.5.0.dist-info}/METADATA +131 -4
- {pltr_cli-0.4.0.dist-info → pltr_cli-0.5.0.dist-info}/RECORD +13 -11
- pltr/services/dataset_full.py +0 -302
- pltr/services/dataset_v2.py +0 -128
- {pltr_cli-0.4.0.dist-info → pltr_cli-0.5.0.dist-info}/WHEEL +0 -0
- {pltr_cli-0.4.0.dist-info → pltr_cli-0.5.0.dist-info}/entry_points.txt +0 -0
- {pltr_cli-0.4.0.dist-info → pltr_cli-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Orchestration service wrapper for Foundry SDK v2 API.
|
|
3
|
+
Provides operations for managing builds, jobs, and schedules.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any, Optional, Dict, List
|
|
7
|
+
|
|
8
|
+
from .base import BaseService
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OrchestrationService(BaseService):
|
|
12
|
+
"""Service wrapper for Foundry orchestration operations using v2 API."""
|
|
13
|
+
|
|
14
|
+
def _get_service(self) -> Any:
|
|
15
|
+
"""Get the Foundry orchestration service."""
|
|
16
|
+
return self.client.orchestration
|
|
17
|
+
|
|
18
|
+
# Build operations
|
|
19
|
+
def get_build(self, build_rid: str) -> Dict[str, Any]:
|
|
20
|
+
"""
|
|
21
|
+
Get information about a specific build.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
build_rid: Build Resource Identifier
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Build information dictionary
|
|
28
|
+
"""
|
|
29
|
+
try:
|
|
30
|
+
build = self.service.Build.get(build_rid)
|
|
31
|
+
return self._format_build_info(build)
|
|
32
|
+
except Exception as e:
|
|
33
|
+
raise RuntimeError(f"Failed to get build {build_rid}: {e}")
|
|
34
|
+
|
|
35
|
+
def create_build(
|
|
36
|
+
self,
|
|
37
|
+
target: Dict[str, Any],
|
|
38
|
+
fallback_branches: Optional[Dict[str, Any]] = None,
|
|
39
|
+
abort_on_failure: Optional[bool] = None,
|
|
40
|
+
branch_name: Optional[str] = None,
|
|
41
|
+
force_build: Optional[bool] = None,
|
|
42
|
+
notifications_enabled: Optional[bool] = None,
|
|
43
|
+
retry_backoff_duration: Optional[int] = None,
|
|
44
|
+
retry_count: Optional[int] = None,
|
|
45
|
+
) -> Dict[str, Any]:
|
|
46
|
+
"""
|
|
47
|
+
Create a new build.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
target: Build target configuration
|
|
51
|
+
fallback_branches: Fallback branches configuration
|
|
52
|
+
abort_on_failure: Whether to abort on failure
|
|
53
|
+
branch_name: Branch name for the build
|
|
54
|
+
force_build: Force build even if no changes
|
|
55
|
+
notifications_enabled: Enable notifications
|
|
56
|
+
retry_backoff_duration: Retry backoff duration in milliseconds
|
|
57
|
+
retry_count: Number of retries
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Created build information
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
kwargs: Dict[str, Any] = {
|
|
64
|
+
"target": target,
|
|
65
|
+
"fallback_branches": fallback_branches or {},
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Add optional parameters if provided
|
|
69
|
+
if abort_on_failure is not None:
|
|
70
|
+
kwargs["abort_on_failure"] = abort_on_failure
|
|
71
|
+
if branch_name is not None:
|
|
72
|
+
kwargs["branch_name"] = branch_name
|
|
73
|
+
if force_build is not None:
|
|
74
|
+
kwargs["force_build"] = force_build
|
|
75
|
+
if notifications_enabled is not None:
|
|
76
|
+
kwargs["notifications_enabled"] = notifications_enabled
|
|
77
|
+
if retry_backoff_duration is not None:
|
|
78
|
+
kwargs["retry_backoff_duration"] = retry_backoff_duration
|
|
79
|
+
if retry_count is not None:
|
|
80
|
+
kwargs["retry_count"] = retry_count
|
|
81
|
+
|
|
82
|
+
build = self.service.Build.create(**kwargs)
|
|
83
|
+
return self._format_build_info(build)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
raise RuntimeError(f"Failed to create build: {e}")
|
|
86
|
+
|
|
87
|
+
def cancel_build(self, build_rid: str) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Cancel a build.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
build_rid: Build Resource Identifier
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
self.service.Build.cancel(build_rid)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
raise RuntimeError(f"Failed to cancel build {build_rid}: {e}")
|
|
98
|
+
|
|
99
|
+
def get_build_jobs(
|
|
100
|
+
self,
|
|
101
|
+
build_rid: str,
|
|
102
|
+
page_size: Optional[int] = None,
|
|
103
|
+
page_token: Optional[str] = None,
|
|
104
|
+
) -> Dict[str, Any]:
|
|
105
|
+
"""
|
|
106
|
+
Get jobs in a build.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
build_rid: Build Resource Identifier
|
|
110
|
+
page_size: Number of results per page
|
|
111
|
+
page_token: Token for pagination
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Jobs list with pagination info
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
kwargs: Dict[str, Any] = {"build_rid": build_rid}
|
|
118
|
+
if page_size is not None:
|
|
119
|
+
kwargs["page_size"] = page_size
|
|
120
|
+
if page_token is not None:
|
|
121
|
+
kwargs["page_token"] = page_token
|
|
122
|
+
|
|
123
|
+
response = self.service.Build.jobs(**kwargs)
|
|
124
|
+
return self._format_jobs_response(response)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
raise RuntimeError(f"Failed to get jobs for build {build_rid}: {e}")
|
|
127
|
+
|
|
128
|
+
def search_builds(
|
|
129
|
+
self,
|
|
130
|
+
page_size: Optional[int] = None,
|
|
131
|
+
page_token: Optional[str] = None,
|
|
132
|
+
**search_params,
|
|
133
|
+
) -> Dict[str, Any]:
|
|
134
|
+
"""
|
|
135
|
+
Search for builds.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
page_size: Number of results per page
|
|
139
|
+
page_token: Token for pagination
|
|
140
|
+
**search_params: Additional search parameters
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Search results with pagination info
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
kwargs: Dict[str, Any] = {}
|
|
147
|
+
if page_size is not None:
|
|
148
|
+
kwargs["page_size"] = page_size
|
|
149
|
+
if page_token is not None:
|
|
150
|
+
kwargs["page_token"] = page_token
|
|
151
|
+
kwargs.update(search_params)
|
|
152
|
+
|
|
153
|
+
response = self.service.Build.search(**kwargs)
|
|
154
|
+
return self._format_builds_search_response(response)
|
|
155
|
+
except Exception as e:
|
|
156
|
+
raise RuntimeError(f"Failed to search builds: {e}")
|
|
157
|
+
|
|
158
|
+
# Job operations
|
|
159
|
+
def get_job(self, job_rid: str) -> Dict[str, Any]:
|
|
160
|
+
"""
|
|
161
|
+
Get information about a specific job.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
job_rid: Job Resource Identifier
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Job information dictionary
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
job = self.service.Job.get(job_rid)
|
|
171
|
+
return self._format_job_info(job)
|
|
172
|
+
except Exception as e:
|
|
173
|
+
raise RuntimeError(f"Failed to get job {job_rid}: {e}")
|
|
174
|
+
|
|
175
|
+
def get_jobs_batch(self, job_rids: List[str]) -> Dict[str, Any]:
|
|
176
|
+
"""
|
|
177
|
+
Get multiple jobs in batch.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
job_rids: List of Job Resource Identifiers (max 500)
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Batch response with job information
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
if len(job_rids) > 500:
|
|
187
|
+
raise ValueError("Maximum batch size is 500 jobs")
|
|
188
|
+
|
|
189
|
+
body = [{"rid": rid} for rid in job_rids]
|
|
190
|
+
response = self.service.Job.get_batch(body)
|
|
191
|
+
return self._format_jobs_batch_response(response)
|
|
192
|
+
except Exception as e:
|
|
193
|
+
raise RuntimeError(f"Failed to get jobs batch: {e}")
|
|
194
|
+
|
|
195
|
+
# Schedule operations
|
|
196
|
+
def get_schedule(
|
|
197
|
+
self, schedule_rid: str, preview: Optional[bool] = None
|
|
198
|
+
) -> Dict[str, Any]:
|
|
199
|
+
"""
|
|
200
|
+
Get information about a specific schedule.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
schedule_rid: Schedule Resource Identifier
|
|
204
|
+
preview: Enable preview mode
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Schedule information dictionary
|
|
208
|
+
"""
|
|
209
|
+
try:
|
|
210
|
+
kwargs: Dict[str, Any] = {"schedule_rid": schedule_rid}
|
|
211
|
+
if preview is not None:
|
|
212
|
+
kwargs["preview"] = preview
|
|
213
|
+
|
|
214
|
+
schedule = self.service.Schedule.get(**kwargs)
|
|
215
|
+
return self._format_schedule_info(schedule)
|
|
216
|
+
except Exception as e:
|
|
217
|
+
raise RuntimeError(f"Failed to get schedule {schedule_rid}: {e}")
|
|
218
|
+
|
|
219
|
+
def create_schedule(
|
|
220
|
+
self,
|
|
221
|
+
action: Dict[str, Any],
|
|
222
|
+
description: Optional[str] = None,
|
|
223
|
+
display_name: Optional[str] = None,
|
|
224
|
+
trigger: Optional[Dict[str, Any]] = None,
|
|
225
|
+
scope_mode: Optional[str] = None,
|
|
226
|
+
preview: Optional[bool] = None,
|
|
227
|
+
) -> Dict[str, Any]:
|
|
228
|
+
"""
|
|
229
|
+
Create a new schedule.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
action: Schedule action configuration
|
|
233
|
+
description: Schedule description
|
|
234
|
+
display_name: Display name for the schedule
|
|
235
|
+
trigger: Trigger configuration
|
|
236
|
+
scope_mode: Scope mode for the schedule
|
|
237
|
+
preview: Enable preview mode
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Created schedule information
|
|
241
|
+
"""
|
|
242
|
+
try:
|
|
243
|
+
kwargs: Dict[str, Any] = {"action": action}
|
|
244
|
+
|
|
245
|
+
if description is not None:
|
|
246
|
+
kwargs["description"] = description
|
|
247
|
+
if display_name is not None:
|
|
248
|
+
kwargs["display_name"] = display_name
|
|
249
|
+
if trigger is not None:
|
|
250
|
+
kwargs["trigger"] = trigger
|
|
251
|
+
if scope_mode is not None:
|
|
252
|
+
kwargs["scope_mode"] = scope_mode
|
|
253
|
+
if preview is not None:
|
|
254
|
+
kwargs["preview"] = preview
|
|
255
|
+
|
|
256
|
+
schedule = self.service.Schedule.create(**kwargs)
|
|
257
|
+
return self._format_schedule_info(schedule)
|
|
258
|
+
except Exception as e:
|
|
259
|
+
raise RuntimeError(f"Failed to create schedule: {e}")
|
|
260
|
+
|
|
261
|
+
def delete_schedule(self, schedule_rid: str) -> None:
|
|
262
|
+
"""
|
|
263
|
+
Delete a schedule.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
schedule_rid: Schedule Resource Identifier
|
|
267
|
+
"""
|
|
268
|
+
try:
|
|
269
|
+
self.service.Schedule.delete(schedule_rid)
|
|
270
|
+
except Exception as e:
|
|
271
|
+
raise RuntimeError(f"Failed to delete schedule {schedule_rid}: {e}")
|
|
272
|
+
|
|
273
|
+
def pause_schedule(self, schedule_rid: str) -> None:
|
|
274
|
+
"""
|
|
275
|
+
Pause a schedule.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
schedule_rid: Schedule Resource Identifier
|
|
279
|
+
"""
|
|
280
|
+
try:
|
|
281
|
+
self.service.Schedule.pause(schedule_rid)
|
|
282
|
+
except Exception as e:
|
|
283
|
+
raise RuntimeError(f"Failed to pause schedule {schedule_rid}: {e}")
|
|
284
|
+
|
|
285
|
+
def unpause_schedule(self, schedule_rid: str) -> None:
|
|
286
|
+
"""
|
|
287
|
+
Unpause a schedule.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
schedule_rid: Schedule Resource Identifier
|
|
291
|
+
"""
|
|
292
|
+
try:
|
|
293
|
+
self.service.Schedule.unpause(schedule_rid)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
raise RuntimeError(f"Failed to unpause schedule {schedule_rid}: {e}")
|
|
296
|
+
|
|
297
|
+
def run_schedule(self, schedule_rid: str) -> None:
|
|
298
|
+
"""
|
|
299
|
+
Execute a schedule immediately.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
schedule_rid: Schedule Resource Identifier
|
|
303
|
+
"""
|
|
304
|
+
try:
|
|
305
|
+
self.service.Schedule.run(schedule_rid)
|
|
306
|
+
except Exception as e:
|
|
307
|
+
raise RuntimeError(f"Failed to run schedule {schedule_rid}: {e}")
|
|
308
|
+
|
|
309
|
+
def replace_schedule(
|
|
310
|
+
self,
|
|
311
|
+
schedule_rid: str,
|
|
312
|
+
action: Dict[str, Any],
|
|
313
|
+
description: Optional[str] = None,
|
|
314
|
+
display_name: Optional[str] = None,
|
|
315
|
+
trigger: Optional[Dict[str, Any]] = None,
|
|
316
|
+
scope_mode: Optional[str] = None,
|
|
317
|
+
preview: Optional[bool] = None,
|
|
318
|
+
) -> Dict[str, Any]:
|
|
319
|
+
"""
|
|
320
|
+
Replace an existing schedule.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
schedule_rid: Schedule Resource Identifier
|
|
324
|
+
action: Schedule action configuration
|
|
325
|
+
description: Schedule description
|
|
326
|
+
display_name: Display name for the schedule
|
|
327
|
+
trigger: Trigger configuration
|
|
328
|
+
scope_mode: Scope mode for the schedule
|
|
329
|
+
preview: Enable preview mode
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
Updated schedule information
|
|
333
|
+
"""
|
|
334
|
+
try:
|
|
335
|
+
kwargs: Dict[str, Any] = {
|
|
336
|
+
"schedule_rid": schedule_rid,
|
|
337
|
+
"action": action,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if description is not None:
|
|
341
|
+
kwargs["description"] = description
|
|
342
|
+
if display_name is not None:
|
|
343
|
+
kwargs["display_name"] = display_name
|
|
344
|
+
if trigger is not None:
|
|
345
|
+
kwargs["trigger"] = trigger
|
|
346
|
+
if scope_mode is not None:
|
|
347
|
+
kwargs["scope_mode"] = scope_mode
|
|
348
|
+
if preview is not None:
|
|
349
|
+
kwargs["preview"] = preview
|
|
350
|
+
|
|
351
|
+
schedule = self.service.Schedule.replace(**kwargs)
|
|
352
|
+
return self._format_schedule_info(schedule)
|
|
353
|
+
except Exception as e:
|
|
354
|
+
raise RuntimeError(f"Failed to replace schedule {schedule_rid}: {e}")
|
|
355
|
+
|
|
356
|
+
# Formatting methods
|
|
357
|
+
def _format_build_info(self, build: Any) -> Dict[str, Any]:
|
|
358
|
+
"""Format build information for consistent output."""
|
|
359
|
+
info = {}
|
|
360
|
+
|
|
361
|
+
# Extract available attributes
|
|
362
|
+
for attr in [
|
|
363
|
+
"rid",
|
|
364
|
+
"status",
|
|
365
|
+
"created_time",
|
|
366
|
+
"started_time",
|
|
367
|
+
"finished_time",
|
|
368
|
+
"created_by",
|
|
369
|
+
"branch_name",
|
|
370
|
+
"commit_hash",
|
|
371
|
+
]:
|
|
372
|
+
if hasattr(build, attr):
|
|
373
|
+
info[attr] = getattr(build, attr)
|
|
374
|
+
|
|
375
|
+
return info
|
|
376
|
+
|
|
377
|
+
def _format_job_info(self, job: Any) -> Dict[str, Any]:
|
|
378
|
+
"""Format job information for consistent output."""
|
|
379
|
+
info = {}
|
|
380
|
+
|
|
381
|
+
# Extract available attributes
|
|
382
|
+
for attr in [
|
|
383
|
+
"rid",
|
|
384
|
+
"status",
|
|
385
|
+
"created_time",
|
|
386
|
+
"started_time",
|
|
387
|
+
"finished_time",
|
|
388
|
+
"job_type",
|
|
389
|
+
"build_rid",
|
|
390
|
+
]:
|
|
391
|
+
if hasattr(job, attr):
|
|
392
|
+
info[attr] = getattr(job, attr)
|
|
393
|
+
|
|
394
|
+
return info
|
|
395
|
+
|
|
396
|
+
def _format_schedule_info(self, schedule: Any) -> Dict[str, Any]:
|
|
397
|
+
"""Format schedule information for consistent output."""
|
|
398
|
+
info = {}
|
|
399
|
+
|
|
400
|
+
# Extract available attributes
|
|
401
|
+
for attr in [
|
|
402
|
+
"rid",
|
|
403
|
+
"display_name",
|
|
404
|
+
"description",
|
|
405
|
+
"paused",
|
|
406
|
+
"created_time",
|
|
407
|
+
"created_by",
|
|
408
|
+
"modified_time",
|
|
409
|
+
"modified_by",
|
|
410
|
+
]:
|
|
411
|
+
if hasattr(schedule, attr):
|
|
412
|
+
info[attr] = getattr(schedule, attr)
|
|
413
|
+
|
|
414
|
+
# Handle nested objects
|
|
415
|
+
if hasattr(schedule, "trigger"):
|
|
416
|
+
info["trigger"] = str(schedule.trigger)
|
|
417
|
+
if hasattr(schedule, "action"):
|
|
418
|
+
info["action"] = str(schedule.action)
|
|
419
|
+
|
|
420
|
+
return info
|
|
421
|
+
|
|
422
|
+
def _format_jobs_response(self, response: Any) -> Dict[str, Any]:
|
|
423
|
+
"""Format jobs list response."""
|
|
424
|
+
result: Dict[str, Any] = {"jobs": []}
|
|
425
|
+
|
|
426
|
+
if hasattr(response, "data"):
|
|
427
|
+
result["jobs"] = [self._format_job_info(job) for job in response.data]
|
|
428
|
+
|
|
429
|
+
if hasattr(response, "next_page_token"):
|
|
430
|
+
result["next_page_token"] = response.next_page_token
|
|
431
|
+
|
|
432
|
+
return result
|
|
433
|
+
|
|
434
|
+
def _format_builds_search_response(self, response: Any) -> Dict[str, Any]:
|
|
435
|
+
"""Format builds search response."""
|
|
436
|
+
result: Dict[str, Any] = {"builds": []}
|
|
437
|
+
|
|
438
|
+
if hasattr(response, "data"):
|
|
439
|
+
result["builds"] = [
|
|
440
|
+
self._format_build_info(build) for build in response.data
|
|
441
|
+
]
|
|
442
|
+
|
|
443
|
+
if hasattr(response, "next_page_token"):
|
|
444
|
+
result["next_page_token"] = response.next_page_token
|
|
445
|
+
|
|
446
|
+
return result
|
|
447
|
+
|
|
448
|
+
def _format_jobs_batch_response(self, response: Any) -> Dict[str, Any]:
|
|
449
|
+
"""Format jobs batch response."""
|
|
450
|
+
result: Dict[str, Any] = {"jobs": []}
|
|
451
|
+
|
|
452
|
+
if hasattr(response, "data"):
|
|
453
|
+
for item in response.data:
|
|
454
|
+
if hasattr(item, "data"):
|
|
455
|
+
result["jobs"].append(self._format_job_info(item.data))
|
|
456
|
+
|
|
457
|
+
return result
|