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/__init__.py +1 -1
- pltr/cli.py +24 -0
- pltr/commands/admin.py +12 -2
- pltr/commands/functions.py +503 -0
- pltr/commands/language_models.py +515 -0
- pltr/commands/models.py +362 -0
- pltr/commands/project.py +21 -61
- pltr/commands/resource.py +0 -53
- pltr/commands/space.py +25 -303
- pltr/commands/streams.py +616 -0
- pltr/services/admin.py +15 -4
- pltr/services/dataset.py +2 -3
- pltr/services/folder.py +6 -1
- pltr/services/functions.py +223 -0
- pltr/services/language_models.py +281 -0
- pltr/services/models.py +179 -0
- pltr/services/project.py +87 -49
- pltr/services/resource.py +14 -72
- pltr/services/space.py +24 -175
- pltr/services/streams.py +290 -0
- {pltr_cli-0.12.0.dist-info → pltr_cli-0.13.0.dist-info}/METADATA +51 -2
- {pltr_cli-0.12.0.dist-info → pltr_cli-0.13.0.dist-info}/RECORD +25 -17
- {pltr_cli-0.12.0.dist-info → pltr_cli-0.13.0.dist-info}/WHEEL +0 -0
- {pltr_cli-0.12.0.dist-info → pltr_cli-0.13.0.dist-info}/entry_points.txt +0 -0
- {pltr_cli-0.12.0.dist-info → pltr_cli-0.13.0.dist-info}/licenses/LICENSE +0 -0
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[
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|