pltr-cli 0.4.0__py3-none-any.whl → 0.5.1__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.
@@ -0,0 +1,289 @@
1
+ """
2
+ Resource service wrapper for Foundry SDK filesystem API.
3
+ """
4
+
5
+ from typing import Any, Optional, Dict, List
6
+
7
+ from .base import BaseService
8
+
9
+
10
+ class ResourceService(BaseService):
11
+ """Service wrapper for Foundry resource operations using filesystem API."""
12
+
13
+ def _get_service(self) -> Any:
14
+ """Get the Foundry filesystem service."""
15
+ return self.client.filesystem
16
+
17
+ def get_resource(self, resource_rid: str) -> Dict[str, Any]:
18
+ """
19
+ Get information about a specific resource.
20
+
21
+ Args:
22
+ resource_rid: Resource Identifier
23
+
24
+ Returns:
25
+ Resource information dictionary
26
+ """
27
+ try:
28
+ resource = self.service.Resource.get(resource_rid, preview=True)
29
+ return self._format_resource_info(resource)
30
+ except Exception as e:
31
+ raise RuntimeError(f"Failed to get resource {resource_rid}: {e}")
32
+
33
+ def list_resources(
34
+ self,
35
+ folder_rid: Optional[str] = None,
36
+ resource_type: Optional[str] = None,
37
+ page_size: Optional[int] = None,
38
+ page_token: Optional[str] = None,
39
+ ) -> List[Dict[str, Any]]:
40
+ """
41
+ List resources, optionally filtered by folder and type.
42
+
43
+ Args:
44
+ folder_rid: Folder Resource Identifier to filter by (optional)
45
+ resource_type: Resource type to filter by (optional)
46
+ page_size: Number of items per page (optional)
47
+ page_token: Pagination token (optional)
48
+
49
+ Returns:
50
+ List of resource information dictionaries
51
+ """
52
+ try:
53
+ resources = []
54
+ list_params: Dict[str, Any] = {"preview": True}
55
+
56
+ if folder_rid:
57
+ list_params["folder_rid"] = folder_rid
58
+ if resource_type:
59
+ list_params["resource_type"] = resource_type
60
+ if page_size:
61
+ list_params["page_size"] = page_size
62
+ if page_token:
63
+ list_params["page_token"] = page_token
64
+
65
+ # The list method returns an iterator
66
+ for resource in self.service.Resource.list(**list_params):
67
+ resources.append(self._format_resource_info(resource))
68
+ return resources
69
+ except Exception as e:
70
+ raise RuntimeError(f"Failed to list resources: {e}")
71
+
72
+ def get_resources_batch(self, resource_rids: List[str]) -> List[Dict[str, Any]]:
73
+ """
74
+ Get multiple resources in a single request.
75
+
76
+ Args:
77
+ resource_rids: List of resource RIDs (max 1000)
78
+
79
+ Returns:
80
+ List of resource information dictionaries
81
+ """
82
+ if len(resource_rids) > 1000:
83
+ raise ValueError("Maximum batch size is 1000 resources")
84
+
85
+ try:
86
+ response = self.service.Resource.get_batch(body=resource_rids, preview=True)
87
+ resources = []
88
+ for resource in response.resources:
89
+ resources.append(self._format_resource_info(resource))
90
+ return resources
91
+ except Exception as e:
92
+ raise RuntimeError(f"Failed to get resources batch: {e}")
93
+
94
+ def get_resource_metadata(self, resource_rid: str) -> Dict[str, Any]:
95
+ """
96
+ Get metadata for a specific resource.
97
+
98
+ Args:
99
+ resource_rid: Resource Identifier
100
+
101
+ Returns:
102
+ Resource metadata dictionary
103
+ """
104
+ try:
105
+ metadata = self.service.Resource.get_metadata(resource_rid, preview=True)
106
+ return self._format_metadata(metadata)
107
+ except Exception as e:
108
+ raise RuntimeError(
109
+ f"Failed to get metadata for resource {resource_rid}: {e}"
110
+ )
111
+
112
+ def set_resource_metadata(
113
+ self, resource_rid: str, metadata: Dict[str, Any]
114
+ ) -> Dict[str, Any]:
115
+ """
116
+ Set metadata for a specific resource.
117
+
118
+ Args:
119
+ resource_rid: Resource Identifier
120
+ metadata: Metadata dictionary to set
121
+
122
+ Returns:
123
+ Updated resource metadata
124
+ """
125
+ try:
126
+ updated_metadata = self.service.Resource.set_metadata(
127
+ resource_rid=resource_rid,
128
+ body=metadata,
129
+ preview=True,
130
+ )
131
+ return self._format_metadata(updated_metadata)
132
+ except Exception as e:
133
+ raise RuntimeError(
134
+ f"Failed to set metadata for resource {resource_rid}: {e}"
135
+ )
136
+
137
+ def delete_resource_metadata(self, resource_rid: str, keys: List[str]) -> None:
138
+ """
139
+ Delete specific metadata keys for a resource.
140
+
141
+ Args:
142
+ resource_rid: Resource Identifier
143
+ keys: List of metadata keys to delete
144
+
145
+ Raises:
146
+ RuntimeError: If deletion fails
147
+ """
148
+ try:
149
+ self.service.Resource.delete_metadata(
150
+ resource_rid=resource_rid,
151
+ body={"keys": keys},
152
+ preview=True,
153
+ )
154
+ except Exception as e:
155
+ raise RuntimeError(
156
+ f"Failed to delete metadata for resource {resource_rid}: {e}"
157
+ )
158
+
159
+ def move_resource(
160
+ self, resource_rid: str, target_folder_rid: str
161
+ ) -> Dict[str, Any]:
162
+ """
163
+ Move a resource to a different folder.
164
+
165
+ Args:
166
+ resource_rid: Resource Identifier
167
+ target_folder_rid: Target folder Resource Identifier
168
+
169
+ Returns:
170
+ Updated resource information
171
+ """
172
+ try:
173
+ resource = self.service.Resource.move(
174
+ resource_rid=resource_rid,
175
+ body={"target_folder_rid": target_folder_rid},
176
+ preview=True,
177
+ )
178
+ return self._format_resource_info(resource)
179
+ except Exception as e:
180
+ raise RuntimeError(f"Failed to move resource {resource_rid}: {e}")
181
+
182
+ def search_resources(
183
+ self,
184
+ query: str,
185
+ resource_type: Optional[str] = None,
186
+ folder_rid: Optional[str] = None,
187
+ page_size: Optional[int] = None,
188
+ page_token: Optional[str] = None,
189
+ ) -> List[Dict[str, Any]]:
190
+ """
191
+ Search for resources by query string.
192
+
193
+ Args:
194
+ query: Search query string
195
+ resource_type: Resource type to filter by (optional)
196
+ folder_rid: Folder to search within (optional)
197
+ page_size: Number of items per page (optional)
198
+ page_token: Pagination token (optional)
199
+
200
+ Returns:
201
+ List of matching resource information dictionaries
202
+ """
203
+ try:
204
+ resources = []
205
+ search_params: Dict[str, Any] = {
206
+ "query": query,
207
+ "preview": True,
208
+ }
209
+
210
+ if resource_type:
211
+ search_params["resource_type"] = resource_type
212
+ if folder_rid:
213
+ search_params["folder_rid"] = folder_rid
214
+ if page_size:
215
+ search_params["page_size"] = page_size
216
+ if page_token:
217
+ search_params["page_token"] = page_token
218
+
219
+ # The search method returns an iterator
220
+ for resource in self.service.Resource.search(**search_params):
221
+ resources.append(self._format_resource_info(resource))
222
+ return resources
223
+ except Exception as e:
224
+ raise RuntimeError(f"Failed to search resources: {e}")
225
+
226
+ def _format_resource_info(self, resource: Any) -> Dict[str, Any]:
227
+ """
228
+ Format resource information for consistent output.
229
+
230
+ Args:
231
+ resource: Resource object from Foundry SDK
232
+
233
+ Returns:
234
+ Formatted resource information dictionary
235
+ """
236
+ return {
237
+ "rid": getattr(resource, "rid", None),
238
+ "display_name": getattr(resource, "display_name", None),
239
+ "name": getattr(resource, "name", None),
240
+ "description": getattr(resource, "description", None),
241
+ "path": getattr(resource, "path", None),
242
+ "type": getattr(resource, "type", None),
243
+ "folder_rid": getattr(resource, "folder_rid", None),
244
+ "created_by": getattr(resource, "created_by", None),
245
+ "created_time": self._format_timestamp(
246
+ getattr(resource, "created_time", None)
247
+ ),
248
+ "modified_by": getattr(resource, "modified_by", None),
249
+ "modified_time": self._format_timestamp(
250
+ getattr(resource, "modified_time", None)
251
+ ),
252
+ "size_bytes": getattr(resource, "size_bytes", None),
253
+ "trash_status": getattr(resource, "trash_status", None),
254
+ }
255
+
256
+ def _format_metadata(self, metadata: Any) -> Dict[str, Any]:
257
+ """
258
+ Format metadata for consistent output.
259
+
260
+ Args:
261
+ metadata: Metadata object from Foundry SDK
262
+
263
+ Returns:
264
+ Formatted metadata dictionary
265
+ """
266
+ if hasattr(metadata, "__dict__"):
267
+ return dict(metadata.__dict__)
268
+ elif isinstance(metadata, dict):
269
+ return metadata
270
+ else:
271
+ return {"raw": str(metadata)}
272
+
273
+ def _format_timestamp(self, timestamp: Any) -> Optional[str]:
274
+ """
275
+ Format timestamp for display.
276
+
277
+ Args:
278
+ timestamp: Timestamp object from SDK
279
+
280
+ Returns:
281
+ Formatted timestamp string or None
282
+ """
283
+ if timestamp is None:
284
+ return None
285
+
286
+ # Handle different timestamp formats from the SDK
287
+ if hasattr(timestamp, "time"):
288
+ return str(timestamp.time)
289
+ return str(timestamp)
@@ -0,0 +1,321 @@
1
+ """
2
+ Resource Role service wrapper for Foundry SDK filesystem API.
3
+ """
4
+
5
+ from typing import Any, Optional, Dict, List
6
+
7
+ from .base import BaseService
8
+
9
+
10
+ class ResourceRoleService(BaseService):
11
+ """Service wrapper for Foundry resource role operations using filesystem API."""
12
+
13
+ def _get_service(self) -> Any:
14
+ """Get the Foundry filesystem service."""
15
+ return self.client.filesystem
16
+
17
+ def grant_role(
18
+ self,
19
+ resource_rid: str,
20
+ principal_id: str,
21
+ principal_type: str,
22
+ role_name: str,
23
+ ) -> Dict[str, Any]:
24
+ """
25
+ Grant a role to a principal on a resource.
26
+
27
+ Args:
28
+ resource_rid: Resource Identifier
29
+ principal_id: Principal (user/group) identifier
30
+ principal_type: Principal type ('User' or 'Group')
31
+ role_name: Role name to grant
32
+
33
+ Returns:
34
+ Role grant information
35
+ """
36
+ try:
37
+ role_grant: Dict[str, Any] = {
38
+ "principal_id": principal_id,
39
+ "principal_type": principal_type,
40
+ "role_name": role_name,
41
+ }
42
+
43
+ result = self.service.ResourceRole.grant(
44
+ resource_rid=resource_rid,
45
+ body=role_grant,
46
+ preview=True,
47
+ )
48
+ return self._format_role_grant(result)
49
+ except Exception as e:
50
+ raise RuntimeError(
51
+ f"Failed to grant role '{role_name}' to {principal_type} '{principal_id}' on resource {resource_rid}: {e}"
52
+ )
53
+
54
+ def revoke_role(
55
+ self,
56
+ resource_rid: str,
57
+ principal_id: str,
58
+ principal_type: str,
59
+ role_name: str,
60
+ ) -> None:
61
+ """
62
+ Revoke a role from a principal on a resource.
63
+
64
+ Args:
65
+ resource_rid: Resource Identifier
66
+ principal_id: Principal (user/group) identifier
67
+ principal_type: Principal type ('User' or 'Group')
68
+ role_name: Role name to revoke
69
+
70
+ Raises:
71
+ RuntimeError: If revocation fails
72
+ """
73
+ try:
74
+ role_revocation: Dict[str, Any] = {
75
+ "principal_id": principal_id,
76
+ "principal_type": principal_type,
77
+ "role_name": role_name,
78
+ }
79
+
80
+ self.service.ResourceRole.revoke(
81
+ resource_rid=resource_rid,
82
+ body=role_revocation,
83
+ preview=True,
84
+ )
85
+ except Exception as e:
86
+ raise RuntimeError(
87
+ f"Failed to revoke role '{role_name}' from {principal_type} '{principal_id}' on resource {resource_rid}: {e}"
88
+ )
89
+
90
+ def list_resource_roles(
91
+ self,
92
+ resource_rid: str,
93
+ principal_type: Optional[str] = None,
94
+ page_size: Optional[int] = None,
95
+ page_token: Optional[str] = None,
96
+ ) -> List[Dict[str, Any]]:
97
+ """
98
+ List all roles granted on a resource.
99
+
100
+ Args:
101
+ resource_rid: Resource Identifier
102
+ principal_type: Filter by principal type ('User' or 'Group', optional)
103
+ page_size: Number of items per page (optional)
104
+ page_token: Pagination token (optional)
105
+
106
+ Returns:
107
+ List of role grant information dictionaries
108
+ """
109
+ try:
110
+ role_grants = []
111
+ list_params: Dict[str, Any] = {"preview": True}
112
+
113
+ if principal_type:
114
+ list_params["principal_type"] = principal_type
115
+ if page_size:
116
+ list_params["page_size"] = page_size
117
+ if page_token:
118
+ list_params["page_token"] = page_token
119
+
120
+ # The list method returns an iterator
121
+ for role_grant in self.service.ResourceRole.list(
122
+ resource_rid, **list_params
123
+ ):
124
+ role_grants.append(self._format_role_grant(role_grant))
125
+ return role_grants
126
+ except Exception as e:
127
+ raise RuntimeError(f"Failed to list roles for resource {resource_rid}: {e}")
128
+
129
+ def get_principal_roles(
130
+ self,
131
+ principal_id: str,
132
+ principal_type: str,
133
+ resource_rid: Optional[str] = None,
134
+ page_size: Optional[int] = None,
135
+ page_token: Optional[str] = None,
136
+ ) -> List[Dict[str, Any]]:
137
+ """
138
+ Get all roles granted to a principal, optionally filtered by resource.
139
+
140
+ Args:
141
+ principal_id: Principal (user/group) identifier
142
+ principal_type: Principal type ('User' or 'Group')
143
+ resource_rid: Filter by resource RID (optional)
144
+ page_size: Number of items per page (optional)
145
+ page_token: Pagination token (optional)
146
+
147
+ Returns:
148
+ List of role grant information dictionaries
149
+ """
150
+ try:
151
+ role_grants = []
152
+ list_params = {
153
+ "principal_id": principal_id,
154
+ "principal_type": principal_type,
155
+ "preview": True,
156
+ }
157
+
158
+ if resource_rid:
159
+ list_params["resource_rid"] = resource_rid
160
+ if page_size:
161
+ list_params["page_size"] = page_size
162
+ if page_token:
163
+ list_params["page_token"] = page_token
164
+
165
+ # The get_principal_roles method returns an iterator
166
+ for role_grant in self.service.ResourceRole.get_principal_roles(
167
+ **list_params
168
+ ):
169
+ role_grants.append(self._format_role_grant(role_grant))
170
+ return role_grants
171
+ except Exception as e:
172
+ raise RuntimeError(
173
+ f"Failed to get roles for {principal_type} '{principal_id}': {e}"
174
+ )
175
+
176
+ def bulk_grant_roles(
177
+ self,
178
+ resource_rid: str,
179
+ role_grants: List[Dict[str, str]],
180
+ ) -> List[Dict[str, Any]]:
181
+ """
182
+ Grant multiple roles in a single request.
183
+
184
+ Args:
185
+ resource_rid: Resource Identifier
186
+ role_grants: List of role grant specifications, each containing:
187
+ - principal_id: Principal identifier
188
+ - principal_type: 'User' or 'Group'
189
+ - role_name: Role name to grant
190
+
191
+ Returns:
192
+ List of granted role information dictionaries
193
+ """
194
+ try:
195
+ result = self.service.ResourceRole.bulk_grant(
196
+ resource_rid=resource_rid,
197
+ body={"role_grants": role_grants},
198
+ preview=True,
199
+ )
200
+
201
+ granted_roles = []
202
+ if hasattr(result, "role_grants"):
203
+ for role_grant in result.role_grants:
204
+ granted_roles.append(self._format_role_grant(role_grant))
205
+
206
+ return granted_roles
207
+ except Exception as e:
208
+ raise RuntimeError(
209
+ f"Failed to bulk grant roles on resource {resource_rid}: {e}"
210
+ )
211
+
212
+ def bulk_revoke_roles(
213
+ self,
214
+ resource_rid: str,
215
+ role_revocations: List[Dict[str, str]],
216
+ ) -> None:
217
+ """
218
+ Revoke multiple roles in a single request.
219
+
220
+ Args:
221
+ resource_rid: Resource Identifier
222
+ role_revocations: List of role revocation specifications, each containing:
223
+ - principal_id: Principal identifier
224
+ - principal_type: 'User' or 'Group'
225
+ - role_name: Role name to revoke
226
+
227
+ Raises:
228
+ RuntimeError: If revocation fails
229
+ """
230
+ try:
231
+ self.service.ResourceRole.bulk_revoke(
232
+ resource_rid=resource_rid,
233
+ body={"role_revocations": role_revocations},
234
+ preview=True,
235
+ )
236
+ except Exception as e:
237
+ raise RuntimeError(
238
+ f"Failed to bulk revoke roles on resource {resource_rid}: {e}"
239
+ )
240
+
241
+ def get_available_roles(self, resource_rid: str) -> List[Dict[str, Any]]:
242
+ """
243
+ Get all available roles for a resource type.
244
+
245
+ Args:
246
+ resource_rid: Resource Identifier
247
+
248
+ Returns:
249
+ List of available role information dictionaries
250
+ """
251
+ try:
252
+ roles = []
253
+ for role in self.service.ResourceRole.get_available_roles(
254
+ resource_rid, preview=True
255
+ ):
256
+ roles.append(self._format_role_info(role))
257
+ return roles
258
+ except Exception as e:
259
+ raise RuntimeError(
260
+ f"Failed to get available roles for resource {resource_rid}: {e}"
261
+ )
262
+
263
+ def _format_role_grant(self, role_grant: Any) -> Dict[str, Any]:
264
+ """
265
+ Format role grant information for consistent output.
266
+
267
+ Args:
268
+ role_grant: Role grant object from Foundry SDK
269
+
270
+ Returns:
271
+ Formatted role grant information dictionary
272
+ """
273
+ return {
274
+ "resource_rid": getattr(role_grant, "resource_rid", None),
275
+ "principal_id": getattr(role_grant, "principal_id", None),
276
+ "principal_type": getattr(role_grant, "principal_type", None),
277
+ "role_name": getattr(role_grant, "role_name", None),
278
+ "granted_by": getattr(role_grant, "granted_by", None),
279
+ "granted_time": self._format_timestamp(
280
+ getattr(role_grant, "granted_time", None)
281
+ ),
282
+ "expires_at": self._format_timestamp(
283
+ getattr(role_grant, "expires_at", None)
284
+ ),
285
+ }
286
+
287
+ def _format_role_info(self, role: Any) -> Dict[str, Any]:
288
+ """
289
+ Format role information for consistent output.
290
+
291
+ Args:
292
+ role: Role object from Foundry SDK
293
+
294
+ Returns:
295
+ Formatted role information dictionary
296
+ """
297
+ return {
298
+ "name": getattr(role, "name", None),
299
+ "display_name": getattr(role, "display_name", None),
300
+ "description": getattr(role, "description", None),
301
+ "permissions": getattr(role, "permissions", []),
302
+ "is_owner_like": getattr(role, "is_owner_like", False),
303
+ }
304
+
305
+ def _format_timestamp(self, timestamp: Any) -> Optional[str]:
306
+ """
307
+ Format timestamp for display.
308
+
309
+ Args:
310
+ timestamp: Timestamp object from SDK
311
+
312
+ Returns:
313
+ Formatted timestamp string or None
314
+ """
315
+ if timestamp is None:
316
+ return None
317
+
318
+ # Handle different timestamp formats from the SDK
319
+ if hasattr(timestamp, "time"):
320
+ return str(timestamp.time)
321
+ return str(timestamp)