pltr-cli 0.12.0__py3-none-any.whl → 0.13.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/project.py CHANGED
@@ -3,6 +3,7 @@ Project service wrapper for Foundry SDK filesystem API.
3
3
  """
4
4
 
5
5
  from typing import Any, Optional, Dict, List
6
+ import inspect
6
7
 
7
8
  from .base import BaseService
8
9
 
@@ -21,7 +22,7 @@ class ProjectService(BaseService):
21
22
  description: Optional[str] = None,
22
23
  organization_rids: Optional[List[str]] = None,
23
24
  default_roles: Optional[List[str]] = None,
24
- role_grants: Optional[List[Dict[str, Any]]] = None,
25
+ role_grants: Optional[Any] = None,
25
26
  ) -> Dict[str, Any]:
26
27
  """
27
28
  Create a new project.
@@ -38,25 +39,84 @@ class ProjectService(BaseService):
38
39
  Created project information
39
40
  """
40
41
  try:
41
- # Prepare the create request payload
42
- create_request: Dict[str, Any] = {
42
+ normalized_role_grants: Dict[str, List[Dict[str, Any]]] = {}
43
+ if role_grants is None:
44
+ from .admin import AdminService
45
+
46
+ current_user = AdminService(profile=self.profile).get_current_user()
47
+ user_id = (
48
+ current_user.get("id")
49
+ or current_user.get("user_id")
50
+ or current_user.get("userId")
51
+ )
52
+ if not user_id:
53
+ raise RuntimeError(
54
+ "Unable to determine current user id for owner role grant"
55
+ )
56
+ normalized_role_grants = {
57
+ "compass:manage": [
58
+ {
59
+ "principal_id": user_id,
60
+ "principal_type": "USER",
61
+ }
62
+ ]
63
+ }
64
+ elif role_grants:
65
+ if isinstance(role_grants, dict):
66
+ normalized_role_grants = role_grants
67
+ elif isinstance(role_grants, list):
68
+ for grant in role_grants:
69
+ if not isinstance(grant, dict):
70
+ raise ValueError(
71
+ "role_grants list entries must be dictionaries"
72
+ )
73
+ role_name = grant.get("role_name")
74
+ if not role_name:
75
+ raise ValueError(
76
+ "role_grants entries must include role_name"
77
+ )
78
+ principal = {
79
+ key: value
80
+ for key, value in grant.items()
81
+ if key != "role_name"
82
+ }
83
+ normalized_role_grants.setdefault(role_name, []).append(
84
+ principal
85
+ )
86
+ else:
87
+ raise ValueError("role_grants must be a dict or a list of dicts")
88
+
89
+ if normalized_role_grants:
90
+ for principals in normalized_role_grants.values():
91
+ for principal in principals:
92
+ principal_type = principal.get("principal_type")
93
+ if isinstance(principal_type, str):
94
+ principal["principal_type"] = principal_type.upper()
95
+
96
+ create_params: Dict[str, Any] = {
43
97
  "display_name": display_name,
44
98
  "space_rid": space_rid,
99
+ "description": description,
100
+ "organization_rids": organization_rids if organization_rids else [],
101
+ "default_roles": default_roles if default_roles else [],
102
+ "role_grants": normalized_role_grants,
45
103
  }
46
104
 
47
- if description:
48
- create_request["description"] = description
49
- if organization_rids:
50
- create_request["organization_rids"] = organization_rids
51
- if default_roles:
52
- create_request["default_roles"] = default_roles
53
- if role_grants:
54
- create_request["role_grants"] = role_grants
55
-
56
- project = self.service.Project.create(
57
- body=create_request,
58
- preview=True,
59
- )
105
+ create_fn = self.service.Project.create
106
+ try:
107
+ params = inspect.signature(create_fn).parameters
108
+ supports_kwargs = "display_name" in params or any(
109
+ param.kind == inspect.Parameter.VAR_KEYWORD
110
+ for param in params.values()
111
+ )
112
+ if supports_kwargs:
113
+ project = create_fn(**create_params, preview=True)
114
+ elif "body" in params:
115
+ project = create_fn(body=create_params, preview=True)
116
+ else:
117
+ project = create_fn(**create_params, preview=True)
118
+ except (TypeError, ValueError):
119
+ project = create_fn(**create_params, preview=True)
60
120
  return self._format_project_info(project)
61
121
  except Exception as e:
62
122
  raise RuntimeError(f"Failed to create project '{display_name}': {e}")
@@ -134,57 +194,35 @@ class ProjectService(BaseService):
134
194
  description: Optional[str] = None,
135
195
  ) -> Dict[str, Any]:
136
196
  """
137
- Update project information.
197
+ Update project information using replace().
138
198
 
139
199
  Args:
140
200
  project_rid: Project Resource Identifier
141
- display_name: New display name (optional)
201
+ display_name: New display name (optional, fetches current if not provided)
142
202
  description: New description (optional)
143
203
 
144
204
  Returns:
145
205
  Updated project information
146
206
  """
147
- update_request: Dict[str, Any] = {}
148
- if display_name:
149
- update_request["display_name"] = display_name
150
- if description:
151
- update_request["description"] = description
152
-
153
- if not update_request:
207
+ if not display_name and not description:
154
208
  raise ValueError("At least one field must be provided for update")
155
209
 
156
210
  try:
157
- project = self.service.Project.update(
211
+ # Fetch current project to get display_name if not provided (required for replace)
212
+ if not display_name:
213
+ current_project = self.service.Project.get(project_rid, preview=True)
214
+ display_name = current_project.display_name
215
+
216
+ project = self.service.Project.replace(
158
217
  project_rid=project_rid,
159
- body=update_request,
218
+ display_name=display_name,
219
+ description=description,
160
220
  preview=True,
161
221
  )
162
222
  return self._format_project_info(project)
163
223
  except Exception as e:
164
224
  raise RuntimeError(f"Failed to update project {project_rid}: {e}")
165
225
 
166
- def get_projects_batch(self, project_rids: List[str]) -> List[Dict[str, Any]]:
167
- """
168
- Get multiple projects in a single request.
169
-
170
- Args:
171
- project_rids: List of project RIDs (max 1000)
172
-
173
- Returns:
174
- List of project information dictionaries
175
- """
176
- if len(project_rids) > 1000:
177
- raise ValueError("Maximum batch size is 1000 projects")
178
-
179
- try:
180
- response = self.service.Project.get_batch(body=project_rids, preview=True)
181
- projects = []
182
- for project in response.projects:
183
- projects.append(self._format_project_info(project))
184
- return projects
185
- except Exception as e:
186
- raise RuntimeError(f"Failed to get projects batch: {e}")
187
-
188
226
  # ==================== Organization Operations ====================
189
227
 
190
228
  def add_organizations(self, project_rid: str, organization_rids: List[str]) -> None:
pltr/services/resource.py CHANGED
@@ -4,6 +4,11 @@ Resource service wrapper for Foundry SDK filesystem API.
4
4
 
5
5
  from typing import Any, Optional, Dict, List
6
6
 
7
+ from foundry_sdk.v2.filesystem.models import (
8
+ GetResourcesBatchRequestElement,
9
+ GetByPathResourcesBatchRequestElement,
10
+ )
11
+
7
12
  from .base import BaseService
8
13
 
9
14
 
@@ -99,7 +104,11 @@ class ResourceService(BaseService):
99
104
  raise ValueError("Maximum batch size is 1000 resources")
100
105
 
101
106
  try:
102
- response = self.service.Resource.get_batch(body=resource_rids, preview=True)
107
+ elements = [
108
+ GetResourcesBatchRequestElement(resource_rid=rid)
109
+ for rid in resource_rids
110
+ ]
111
+ response = self.service.Resource.get_batch(body=elements, preview=True)
103
112
  resources = []
104
113
  for resource in response.resources:
105
114
  resources.append(self._format_resource_info(resource))
@@ -125,76 +134,6 @@ class ResourceService(BaseService):
125
134
  f"Failed to get metadata for resource {resource_rid}: {e}"
126
135
  )
127
136
 
128
- def set_resource_metadata(
129
- self, resource_rid: str, metadata: Dict[str, Any]
130
- ) -> Dict[str, Any]:
131
- """
132
- Set metadata for a specific resource.
133
-
134
- Args:
135
- resource_rid: Resource Identifier
136
- metadata: Metadata dictionary to set
137
-
138
- Returns:
139
- Updated resource metadata
140
- """
141
- try:
142
- updated_metadata = self.service.Resource.set_metadata(
143
- resource_rid=resource_rid,
144
- body=metadata,
145
- preview=True,
146
- )
147
- return self._format_metadata(updated_metadata)
148
- except Exception as e:
149
- raise RuntimeError(
150
- f"Failed to set metadata for resource {resource_rid}: {e}"
151
- )
152
-
153
- def delete_resource_metadata(self, resource_rid: str, keys: List[str]) -> None:
154
- """
155
- Delete specific metadata keys for a resource.
156
-
157
- Args:
158
- resource_rid: Resource Identifier
159
- keys: List of metadata keys to delete
160
-
161
- Raises:
162
- RuntimeError: If deletion fails
163
- """
164
- try:
165
- self.service.Resource.delete_metadata(
166
- resource_rid=resource_rid,
167
- body={"keys": keys},
168
- preview=True,
169
- )
170
- except Exception as e:
171
- raise RuntimeError(
172
- f"Failed to delete metadata for resource {resource_rid}: {e}"
173
- )
174
-
175
- def move_resource(
176
- self, resource_rid: str, target_folder_rid: str
177
- ) -> Dict[str, Any]:
178
- """
179
- Move a resource to a different folder.
180
-
181
- Args:
182
- resource_rid: Resource Identifier
183
- target_folder_rid: Target folder Resource Identifier
184
-
185
- Returns:
186
- Updated resource information
187
- """
188
- try:
189
- resource = self.service.Resource.move(
190
- resource_rid=resource_rid,
191
- body={"target_folder_rid": target_folder_rid},
192
- preview=True,
193
- )
194
- return self._format_resource_info(resource)
195
- except Exception as e:
196
- raise RuntimeError(f"Failed to move resource {resource_rid}: {e}")
197
-
198
137
  def search_resources(
199
138
  self,
200
139
  query: str,
@@ -409,7 +348,10 @@ class ResourceService(BaseService):
409
348
  raise ValueError("Maximum batch size is 1000 paths")
410
349
 
411
350
  try:
412
- response = self.service.Resource.get_by_path_batch(body=paths, preview=True)
351
+ elements = [GetByPathResourcesBatchRequestElement(path=p) for p in paths]
352
+ response = self.service.Resource.get_by_path_batch(
353
+ body=elements, preview=True
354
+ )
413
355
  resources = []
414
356
  for resource in response.resources:
415
357
  resources.append(self._format_resource_info(resource))
pltr/services/space.py CHANGED
@@ -17,7 +17,9 @@ class SpaceService(BaseService):
17
17
  def create_space(
18
18
  self,
19
19
  display_name: str,
20
- organization_rid: str,
20
+ enrollment_rid: str,
21
+ organizations: List[str],
22
+ deletion_policy_organizations: List[str],
21
23
  description: Optional[str] = None,
22
24
  default_roles: Optional[List[str]] = None,
23
25
  role_grants: Optional[List[Dict[str, Any]]] = None,
@@ -27,7 +29,9 @@ class SpaceService(BaseService):
27
29
 
28
30
  Args:
29
31
  display_name: Space display name
30
- organization_rid: Organization Resource Identifier
32
+ enrollment_rid: Enrollment Resource Identifier
33
+ organizations: List of organization RIDs
34
+ deletion_policy_organizations: List of organization RIDs for deletion policy
31
35
  description: Space description (optional)
32
36
  default_roles: List of default role names (optional)
33
37
  role_grants: List of role grant specifications (optional)
@@ -36,21 +40,14 @@ class SpaceService(BaseService):
36
40
  Created space information
37
41
  """
38
42
  try:
39
- # Prepare the create request payload
40
- create_request: Dict[str, Any] = {
41
- "display_name": display_name,
42
- "organization_rid": organization_rid,
43
- }
44
-
45
- if description:
46
- create_request["description"] = description
47
- if default_roles:
48
- create_request["default_roles"] = default_roles
49
- if role_grants:
50
- create_request["role_grants"] = role_grants
51
-
52
43
  space = self.service.Space.create(
53
- body=create_request,
44
+ display_name=display_name,
45
+ enrollment_rid=enrollment_rid,
46
+ organizations=organizations,
47
+ deletion_policy_organizations=deletion_policy_organizations,
48
+ description=description,
49
+ default_roles=default_roles if default_roles else [],
50
+ role_grants=role_grants if role_grants else [],
54
51
  preview=True,
55
52
  )
56
53
  return self._format_space_info(space)
@@ -115,29 +112,29 @@ class SpaceService(BaseService):
115
112
  description: Optional[str] = None,
116
113
  ) -> Dict[str, Any]:
117
114
  """
118
- Update space information.
115
+ Update space information using replace().
119
116
 
120
117
  Args:
121
118
  space_rid: Space Resource Identifier
122
- display_name: New display name (optional)
119
+ display_name: New display name (optional, fetches current if not provided)
123
120
  description: New description (optional)
124
121
 
125
122
  Returns:
126
123
  Updated space information
127
124
  """
128
- update_request: Dict[str, Any] = {}
129
- if display_name:
130
- update_request["display_name"] = display_name
131
- if description:
132
- update_request["description"] = description
133
-
134
- if not update_request:
125
+ if not display_name and not description:
135
126
  raise ValueError("At least one field must be provided for update")
136
127
 
137
128
  try:
138
- space = self.service.Space.update(
129
+ # Fetch current space to get display_name if not provided (required for replace)
130
+ if not display_name:
131
+ current_space = self.service.Space.get(space_rid, preview=True)
132
+ display_name = current_space.display_name
133
+
134
+ space = self.service.Space.replace(
139
135
  space_rid=space_rid,
140
- body=update_request,
136
+ display_name=display_name,
137
+ description=description,
141
138
  preview=True,
142
139
  )
143
140
  return self._format_space_info(space)
@@ -159,135 +156,6 @@ class SpaceService(BaseService):
159
156
  except Exception as e:
160
157
  raise RuntimeError(f"Failed to delete space {space_rid}: {e}")
161
158
 
162
- def get_spaces_batch(self, space_rids: List[str]) -> List[Dict[str, Any]]:
163
- """
164
- Get multiple spaces in a single request.
165
-
166
- Args:
167
- space_rids: List of space RIDs (max 1000)
168
-
169
- Returns:
170
- List of space information dictionaries
171
- """
172
- if len(space_rids) > 1000:
173
- raise ValueError("Maximum batch size is 1000 spaces")
174
-
175
- try:
176
- response = self.service.Space.get_batch(body=space_rids, preview=True)
177
- spaces = []
178
- for space in response.spaces:
179
- spaces.append(self._format_space_info(space))
180
- return spaces
181
- except Exception as e:
182
- raise RuntimeError(f"Failed to get spaces batch: {e}")
183
-
184
- def get_space_members(
185
- self,
186
- space_rid: str,
187
- principal_type: Optional[str] = None,
188
- page_size: Optional[int] = None,
189
- page_token: Optional[str] = None,
190
- ) -> List[Dict[str, Any]]:
191
- """
192
- Get all members (users/groups) of a space.
193
-
194
- Args:
195
- space_rid: Space Resource Identifier
196
- principal_type: Filter by principal type ('User' or 'Group', optional)
197
- page_size: Number of items per page (optional)
198
- page_token: Pagination token (optional)
199
-
200
- Returns:
201
- List of space member information dictionaries
202
- """
203
- try:
204
- members = []
205
- list_params: Dict[str, Any] = {"preview": True}
206
-
207
- if principal_type:
208
- list_params["principal_type"] = principal_type
209
- if page_size:
210
- list_params["page_size"] = page_size
211
- if page_token:
212
- list_params["page_token"] = page_token
213
-
214
- # The get_members method returns an iterator
215
- for member in self.service.Space.get_members(space_rid, **list_params):
216
- members.append(self._format_member_info(member))
217
- return members
218
- except Exception as e:
219
- raise RuntimeError(f"Failed to get members for space {space_rid}: {e}")
220
-
221
- def add_space_member(
222
- self,
223
- space_rid: str,
224
- principal_id: str,
225
- principal_type: str,
226
- role_name: str,
227
- ) -> Dict[str, Any]:
228
- """
229
- Add a member to a space with a specific role.
230
-
231
- Args:
232
- space_rid: Space Resource Identifier
233
- principal_id: Principal (user/group) identifier
234
- principal_type: Principal type ('User' or 'Group')
235
- role_name: Role name to grant
236
-
237
- Returns:
238
- Space member information
239
- """
240
- try:
241
- member_request: Dict[str, Any] = {
242
- "principal_id": principal_id,
243
- "principal_type": principal_type,
244
- "role_name": role_name,
245
- }
246
-
247
- result = self.service.Space.add_member(
248
- space_rid=space_rid,
249
- body=member_request,
250
- preview=True,
251
- )
252
- return self._format_member_info(result)
253
- except Exception as e:
254
- raise RuntimeError(
255
- f"Failed to add {principal_type} '{principal_id}' to space {space_rid}: {e}"
256
- )
257
-
258
- def remove_space_member(
259
- self,
260
- space_rid: str,
261
- principal_id: str,
262
- principal_type: str,
263
- ) -> None:
264
- """
265
- Remove a member from a space.
266
-
267
- Args:
268
- space_rid: Space Resource Identifier
269
- principal_id: Principal (user/group) identifier
270
- principal_type: Principal type ('User' or 'Group')
271
-
272
- Raises:
273
- RuntimeError: If removal fails
274
- """
275
- try:
276
- member_removal: Dict[str, Any] = {
277
- "principal_id": principal_id,
278
- "principal_type": principal_type,
279
- }
280
-
281
- self.service.Space.remove_member(
282
- space_rid=space_rid,
283
- body=member_removal,
284
- preview=True,
285
- )
286
- except Exception as e:
287
- raise RuntimeError(
288
- f"Failed to remove {principal_type} '{principal_id}' from space {space_rid}: {e}"
289
- )
290
-
291
159
  def _format_space_info(self, space: Any) -> Dict[str, Any]:
292
160
  """
293
161
  Format space information for consistent output.
@@ -316,25 +184,6 @@ class SpaceService(BaseService):
316
184
  "type": "space",
317
185
  }
318
186
 
319
- def _format_member_info(self, member: Any) -> Dict[str, Any]:
320
- """
321
- Format space member information for consistent output.
322
-
323
- Args:
324
- member: Member object from Foundry SDK
325
-
326
- Returns:
327
- Formatted member information dictionary
328
- """
329
- return {
330
- "space_rid": getattr(member, "space_rid", None),
331
- "principal_id": getattr(member, "principal_id", None),
332
- "principal_type": getattr(member, "principal_type", None),
333
- "role_name": getattr(member, "role_name", None),
334
- "added_by": getattr(member, "added_by", None),
335
- "added_time": self._format_timestamp(getattr(member, "added_time", None)),
336
- }
337
-
338
187
  def _format_timestamp(self, timestamp: Any) -> Optional[str]:
339
188
  """
340
189
  Format timestamp for display.