pltr-cli 0.11.0__py3-none-any.whl → 0.12.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/services/resource.py CHANGED
@@ -239,6 +239,184 @@ class ResourceService(BaseService):
239
239
  except Exception as e:
240
240
  raise RuntimeError(f"Failed to search resources: {e}")
241
241
 
242
+ # ==================== Trash Operations ====================
243
+
244
+ def delete_resource(self, resource_rid: str) -> None:
245
+ """
246
+ Move a resource to trash.
247
+
248
+ The resource can be restored later or permanently deleted.
249
+
250
+ Args:
251
+ resource_rid: Resource Identifier
252
+
253
+ Raises:
254
+ RuntimeError: If deletion fails
255
+ """
256
+ try:
257
+ self.service.Resource.delete(resource_rid, preview=True)
258
+ except Exception as e:
259
+ raise RuntimeError(f"Failed to delete resource {resource_rid}: {e}")
260
+
261
+ def restore_resource(self, resource_rid: str) -> None:
262
+ """
263
+ Restore a resource from trash.
264
+
265
+ This also restores any directly trashed ancestors.
266
+ Operation is ignored if the resource is not trashed.
267
+
268
+ Args:
269
+ resource_rid: Resource Identifier
270
+
271
+ Raises:
272
+ RuntimeError: If restoration fails
273
+ """
274
+ try:
275
+ self.service.Resource.restore(resource_rid, preview=True)
276
+ except Exception as e:
277
+ raise RuntimeError(f"Failed to restore resource {resource_rid}: {e}")
278
+
279
+ def permanently_delete_resource(self, resource_rid: str) -> None:
280
+ """
281
+ Permanently delete a resource from trash.
282
+
283
+ The resource must already be in the trash. This operation is irreversible.
284
+
285
+ Args:
286
+ resource_rid: Resource Identifier
287
+
288
+ Raises:
289
+ RuntimeError: If permanent deletion fails
290
+ """
291
+ try:
292
+ self.service.Resource.permanently_delete(resource_rid, preview=True)
293
+ except Exception as e:
294
+ raise RuntimeError(
295
+ f"Failed to permanently delete resource {resource_rid}: {e}"
296
+ )
297
+
298
+ # ==================== Markings Operations ====================
299
+
300
+ def add_markings(self, resource_rid: str, marking_ids: List[str]) -> None:
301
+ """
302
+ Add markings to a resource.
303
+
304
+ Args:
305
+ resource_rid: Resource Identifier
306
+ marking_ids: List of marking identifiers to add
307
+
308
+ Raises:
309
+ RuntimeError: If adding markings fails
310
+ """
311
+ try:
312
+ self.service.Resource.add_markings(
313
+ resource_rid, marking_ids=marking_ids, preview=True
314
+ )
315
+ except Exception as e:
316
+ raise RuntimeError(
317
+ f"Failed to add markings to resource {resource_rid}: {e}"
318
+ )
319
+
320
+ def remove_markings(self, resource_rid: str, marking_ids: List[str]) -> None:
321
+ """
322
+ Remove markings from a resource.
323
+
324
+ Args:
325
+ resource_rid: Resource Identifier
326
+ marking_ids: List of marking identifiers to remove
327
+
328
+ Raises:
329
+ RuntimeError: If removing markings fails
330
+ """
331
+ try:
332
+ self.service.Resource.remove_markings(
333
+ resource_rid, marking_ids=marking_ids, preview=True
334
+ )
335
+ except Exception as e:
336
+ raise RuntimeError(
337
+ f"Failed to remove markings from resource {resource_rid}: {e}"
338
+ )
339
+
340
+ def list_markings(
341
+ self,
342
+ resource_rid: str,
343
+ page_size: Optional[int] = None,
344
+ page_token: Optional[str] = None,
345
+ ) -> List[Dict[str, Any]]:
346
+ """
347
+ List markings directly applied to a resource.
348
+
349
+ Args:
350
+ resource_rid: Resource Identifier
351
+ page_size: Number of items per page (optional)
352
+ page_token: Pagination token (optional)
353
+
354
+ Returns:
355
+ List of marking information dictionaries
356
+ """
357
+ try:
358
+ markings = []
359
+ list_params: Dict[str, Any] = {"preview": True}
360
+
361
+ if page_size:
362
+ list_params["page_size"] = page_size
363
+ if page_token:
364
+ list_params["page_token"] = page_token
365
+
366
+ for marking in self.service.Resource.markings(resource_rid, **list_params):
367
+ markings.append(self._format_marking_info(marking))
368
+ return markings
369
+ except Exception as e:
370
+ raise RuntimeError(
371
+ f"Failed to list markings for resource {resource_rid}: {e}"
372
+ )
373
+
374
+ # ==================== Access & Batch Operations ====================
375
+
376
+ def get_access_requirements(self, resource_rid: str) -> Dict[str, Any]:
377
+ """
378
+ Get access requirements for a resource.
379
+
380
+ Returns the Organizations and Markings required to view the resource.
381
+
382
+ Args:
383
+ resource_rid: Resource Identifier
384
+
385
+ Returns:
386
+ Access requirements dictionary with organizations and markings
387
+ """
388
+ try:
389
+ requirements = self.service.Resource.get_access_requirements(
390
+ resource_rid, preview=True
391
+ )
392
+ return self._format_access_requirements(requirements)
393
+ except Exception as e:
394
+ raise RuntimeError(
395
+ f"Failed to get access requirements for resource {resource_rid}: {e}"
396
+ )
397
+
398
+ def get_resources_by_path_batch(self, paths: List[str]) -> List[Dict[str, Any]]:
399
+ """
400
+ Get multiple resources by their absolute paths in a single request.
401
+
402
+ Args:
403
+ paths: List of absolute paths (max 1000)
404
+
405
+ Returns:
406
+ List of resource information dictionaries
407
+ """
408
+ if len(paths) > 1000:
409
+ raise ValueError("Maximum batch size is 1000 paths")
410
+
411
+ try:
412
+ response = self.service.Resource.get_by_path_batch(body=paths, preview=True)
413
+ resources = []
414
+ for resource in response.resources:
415
+ resources.append(self._format_resource_info(resource))
416
+ return resources
417
+ except Exception as e:
418
+ raise RuntimeError(f"Failed to get resources by path batch: {e}")
419
+
242
420
  def _format_resource_info(self, resource: Any) -> Dict[str, Any]:
243
421
  """
244
422
  Format resource information for consistent output.
@@ -303,3 +481,52 @@ class ResourceService(BaseService):
303
481
  if hasattr(timestamp, "time"):
304
482
  return str(timestamp.time)
305
483
  return str(timestamp)
484
+
485
+ def _format_marking_info(self, marking: Any) -> Dict[str, Any]:
486
+ """
487
+ Format marking information for consistent output.
488
+
489
+ Args:
490
+ marking: Marking object from Foundry SDK
491
+
492
+ Returns:
493
+ Formatted marking information dictionary
494
+ """
495
+ return {
496
+ "marking_id": getattr(marking, "marking_id", None),
497
+ "display_name": getattr(marking, "display_name", None),
498
+ "description": getattr(marking, "description", None),
499
+ "category_id": getattr(marking, "category_id", None),
500
+ "category_display_name": getattr(marking, "category_display_name", None),
501
+ }
502
+
503
+ def _format_access_requirements(self, requirements: Any) -> Dict[str, Any]:
504
+ """
505
+ Format access requirements for consistent output.
506
+
507
+ Args:
508
+ requirements: AccessRequirements object from Foundry SDK
509
+
510
+ Returns:
511
+ Formatted access requirements dictionary
512
+ """
513
+ organizations = []
514
+ markings = []
515
+
516
+ if hasattr(requirements, "organizations"):
517
+ for org in getattr(requirements, "organizations", []) or []:
518
+ organizations.append(
519
+ {
520
+ "organization_rid": getattr(org, "organization_rid", None),
521
+ "display_name": getattr(org, "display_name", None),
522
+ }
523
+ )
524
+
525
+ if hasattr(requirements, "markings"):
526
+ for marking in getattr(requirements, "markings", []) or []:
527
+ markings.append(self._format_marking_info(marking))
528
+
529
+ return {
530
+ "organizations": organizations,
531
+ "markings": markings,
532
+ }
pltr/services/sql.py CHANGED
@@ -30,6 +30,7 @@ class SqlService(BaseService):
30
30
  fallback_branch_ids: Optional[List[str]] = None,
31
31
  timeout: int = 300,
32
32
  format: str = "table",
33
+ preview: bool = True,
33
34
  ) -> Dict[str, Any]:
34
35
  """
35
36
  Execute a SQL query and wait for completion.
@@ -39,6 +40,7 @@ class SqlService(BaseService):
39
40
  fallback_branch_ids: Optional list of branch IDs for fallback
40
41
  timeout: Maximum time to wait for query completion (seconds)
41
42
  format: Output format for results ('table', 'json', 'raw')
43
+ preview: Enable preview mode (required for SQL API, defaults to True)
42
44
 
43
45
  Returns:
44
46
  Dictionary containing query results and metadata
@@ -49,19 +51,23 @@ class SqlService(BaseService):
49
51
  try:
50
52
  # Submit the query
51
53
  status = self.service.execute(
52
- query=query, fallback_branch_ids=fallback_branch_ids
54
+ query=query, fallback_branch_ids=fallback_branch_ids, preview=preview
53
55
  )
54
56
 
55
57
  # If the query completed immediately
56
58
  if isinstance(status, SucceededQueryStatus):
57
- return self._format_completed_query(status.query_id, format)
59
+ return self._format_completed_query(
60
+ status.query_id, format, preview=preview
61
+ )
58
62
  elif isinstance(status, FailedQueryStatus):
59
63
  raise RuntimeError(f"Query failed: {status.error_message}")
60
64
  elif isinstance(status, CanceledQueryStatus):
61
65
  raise RuntimeError("Query was canceled")
62
66
  elif isinstance(status, RunningQueryStatus):
63
67
  # Wait for completion
64
- return self._wait_for_query_completion(status.query_id, timeout, format)
68
+ return self._wait_for_query_completion(
69
+ status.query_id, timeout, format, preview=preview
70
+ )
65
71
  else:
66
72
  raise RuntimeError(f"Unknown query status type: {type(status)}")
67
73
 
@@ -71,7 +77,10 @@ class SqlService(BaseService):
71
77
  raise RuntimeError(f"Failed to execute query: {e}")
72
78
 
73
79
  def submit_query(
74
- self, query: str, fallback_branch_ids: Optional[List[str]] = None
80
+ self,
81
+ query: str,
82
+ fallback_branch_ids: Optional[List[str]] = None,
83
+ preview: bool = True,
75
84
  ) -> Dict[str, Any]:
76
85
  """
77
86
  Submit a SQL query without waiting for completion.
@@ -79,6 +88,7 @@ class SqlService(BaseService):
79
88
  Args:
80
89
  query: SQL query string
81
90
  fallback_branch_ids: Optional list of branch IDs for fallback
91
+ preview: Enable preview mode (required for SQL API, defaults to True)
82
92
 
83
93
  Returns:
84
94
  Dictionary containing query ID and initial status
@@ -88,18 +98,19 @@ class SqlService(BaseService):
88
98
  """
89
99
  try:
90
100
  status = self.service.execute(
91
- query=query, fallback_branch_ids=fallback_branch_ids
101
+ query=query, fallback_branch_ids=fallback_branch_ids, preview=preview
92
102
  )
93
103
  return self._format_query_status(status)
94
104
  except Exception as e:
95
105
  raise RuntimeError(f"Failed to submit query: {e}")
96
106
 
97
- def get_query_status(self, query_id: str) -> Dict[str, Any]:
107
+ def get_query_status(self, query_id: str, preview: bool = True) -> Dict[str, Any]:
98
108
  """
99
109
  Get the status of a submitted query.
100
110
 
101
111
  Args:
102
112
  query_id: Query identifier
113
+ preview: Enable preview mode (required for SQL API, defaults to True)
103
114
 
104
115
  Returns:
105
116
  Dictionary containing query status information
@@ -108,18 +119,21 @@ class SqlService(BaseService):
108
119
  RuntimeError: If status check fails
109
120
  """
110
121
  try:
111
- status = self.service.get_status(query_id)
122
+ status = self.service.get_status(query_id, preview=preview)
112
123
  return self._format_query_status(status)
113
124
  except Exception as e:
114
125
  raise RuntimeError(f"Failed to get query status: {e}")
115
126
 
116
- def get_query_results(self, query_id: str, format: str = "table") -> Dict[str, Any]:
127
+ def get_query_results(
128
+ self, query_id: str, format: str = "table", preview: bool = True
129
+ ) -> Dict[str, Any]:
117
130
  """
118
131
  Get the results of a completed query.
119
132
 
120
133
  Args:
121
134
  query_id: Query identifier
122
135
  format: Output format ('table', 'json', 'raw')
136
+ preview: Enable preview mode (required for SQL API, defaults to True)
123
137
 
124
138
  Returns:
125
139
  Dictionary containing query results
@@ -129,7 +143,7 @@ class SqlService(BaseService):
129
143
  """
130
144
  try:
131
145
  # First check if the query has completed successfully
132
- status = self.service.get_status(query_id)
146
+ status = self.service.get_status(query_id, preview=preview)
133
147
  if not isinstance(status, SucceededQueryStatus):
134
148
  status_info = self._format_query_status(status)
135
149
  if isinstance(status, FailedQueryStatus):
@@ -142,7 +156,7 @@ class SqlService(BaseService):
142
156
  raise RuntimeError(f"Query status: {status_info['status']}")
143
157
 
144
158
  # Get the results
145
- results_bytes = self.service.get_results(query_id)
159
+ results_bytes = self.service.get_results(query_id, preview=preview)
146
160
  return self._format_query_results(results_bytes, format)
147
161
 
148
162
  except Exception as e:
@@ -150,12 +164,13 @@ class SqlService(BaseService):
150
164
  raise
151
165
  raise RuntimeError(f"Failed to get query results: {e}")
152
166
 
153
- def cancel_query(self, query_id: str) -> Dict[str, Any]:
167
+ def cancel_query(self, query_id: str, preview: bool = True) -> Dict[str, Any]:
154
168
  """
155
169
  Cancel a running query.
156
170
 
157
171
  Args:
158
172
  query_id: Query identifier
173
+ preview: Enable preview mode (required for SQL API, defaults to True)
159
174
 
160
175
  Returns:
161
176
  Dictionary containing cancellation status
@@ -164,15 +179,19 @@ class SqlService(BaseService):
164
179
  RuntimeError: If cancellation fails
165
180
  """
166
181
  try:
167
- self.service.cancel(query_id)
182
+ self.service.cancel(query_id, preview=preview)
168
183
  # Get updated status after cancellation
169
- status = self.service.get_status(query_id)
184
+ status = self.service.get_status(query_id, preview=preview)
170
185
  return self._format_query_status(status)
171
186
  except Exception as e:
172
187
  raise RuntimeError(f"Failed to cancel query: {e}")
173
188
 
174
189
  def wait_for_completion(
175
- self, query_id: str, timeout: int = 300, poll_interval: int = 2
190
+ self,
191
+ query_id: str,
192
+ timeout: int = 300,
193
+ poll_interval: int = 2,
194
+ preview: bool = True,
176
195
  ) -> Dict[str, Any]:
177
196
  """
178
197
  Wait for a query to complete.
@@ -181,6 +200,7 @@ class SqlService(BaseService):
181
200
  query_id: Query identifier
182
201
  timeout: Maximum time to wait (seconds)
183
202
  poll_interval: Time between status checks (seconds)
203
+ preview: Enable preview mode (required for SQL API, defaults to True)
184
204
 
185
205
  Returns:
186
206
  Dictionary containing final query status
@@ -192,7 +212,7 @@ class SqlService(BaseService):
192
212
 
193
213
  while time.time() - start_time < timeout:
194
214
  try:
195
- status = self.service.get_status(query_id)
215
+ status = self.service.get_status(query_id, preview=preview)
196
216
 
197
217
  if isinstance(status, SucceededQueryStatus):
198
218
  return self._format_query_status(status)
@@ -216,7 +236,7 @@ class SqlService(BaseService):
216
236
  raise RuntimeError(f"Query timed out after {timeout} seconds")
217
237
 
218
238
  def _wait_for_query_completion(
219
- self, query_id: str, timeout: int, format: str
239
+ self, query_id: str, timeout: int, format: str, preview: bool = True
220
240
  ) -> Dict[str, Any]:
221
241
  """
222
242
  Wait for query completion and return formatted results.
@@ -225,28 +245,32 @@ class SqlService(BaseService):
225
245
  query_id: Query identifier
226
246
  timeout: Maximum wait time
227
247
  format: Result format
248
+ preview: Enable preview mode (required for SQL API, defaults to True)
228
249
 
229
250
  Returns:
230
251
  Dictionary with query results
231
252
  """
232
253
  # Wait for completion
233
- self.wait_for_completion(query_id, timeout)
254
+ self.wait_for_completion(query_id, timeout, preview=preview)
234
255
 
235
256
  # Get results
236
- return self._format_completed_query(query_id, format)
257
+ return self._format_completed_query(query_id, format, preview=preview)
237
258
 
238
- def _format_completed_query(self, query_id: str, format: str) -> Dict[str, Any]:
259
+ def _format_completed_query(
260
+ self, query_id: str, format: str, preview: bool = True
261
+ ) -> Dict[str, Any]:
239
262
  """
240
263
  Format a completed query's results.
241
264
 
242
265
  Args:
243
266
  query_id: Query identifier
244
267
  format: Result format
268
+ preview: Enable preview mode (required for SQL API, defaults to True)
245
269
 
246
270
  Returns:
247
271
  Formatted query results
248
272
  """
249
- results_bytes = self.service.get_results(query_id)
273
+ results_bytes = self.service.get_results(query_id, preview=preview)
250
274
  results = self._format_query_results(results_bytes, format)
251
275
 
252
276
  return {
@@ -0,0 +1,53 @@
1
+ """
2
+ Third-party applications service wrapper for Foundry SDK.
3
+ Provides access to third-party application management operations.
4
+ """
5
+
6
+ from typing import Any, Dict
7
+
8
+ from .base import BaseService
9
+
10
+
11
+ class ThirdPartyApplicationsService(BaseService):
12
+ """Service wrapper for Foundry third-party applications operations."""
13
+
14
+ def _get_service(self) -> Any:
15
+ """Get the Foundry third-party applications service."""
16
+ return self.client.third_party_applications.ThirdPartyApplication
17
+
18
+ def get_application(
19
+ self, application_rid: str, preview: bool = False
20
+ ) -> Dict[str, Any]:
21
+ """
22
+ Get information about a specific third-party application.
23
+
24
+ Args:
25
+ application_rid: Third-party application Resource Identifier
26
+ Expected format: ri.third-party-applications.<realm>.third-party-application.<locator>
27
+ Example: ri.third-party-applications.main.third-party-application.my-app-123
28
+ preview: Enable preview mode (default: False)
29
+
30
+ Returns:
31
+ Third-party application information dictionary containing:
32
+ - rid: Application resource identifier
33
+ - name: Application name
34
+ - description: Application description (if available)
35
+ - status: Application status (if available)
36
+
37
+ Raises:
38
+ RuntimeError: If the operation fails
39
+
40
+ Example:
41
+ >>> service = ThirdPartyApplicationsService()
42
+ >>> app = service.get_application(
43
+ ... "ri.third-party-applications.main.third-party-application.my-app"
44
+ ... )
45
+ >>> print(app['name'])
46
+ """
47
+ try:
48
+ application = self.service.get(application_rid, preview=preview)
49
+ return self._serialize_response(application)
50
+ except Exception as e:
51
+ raise RuntimeError(
52
+ f"Failed to get third-party application {application_rid}: {e}"
53
+ )