diff --git a/pyairtable/api/enterprise.py b/pyairtable/api/enterprise.py index 7b970cb0..557097e0 100644 --- a/pyairtable/api/enterprise.py +++ b/pyairtable/api/enterprise.py @@ -50,6 +50,9 @@ class _urls(UrlBuilder): #: URL for moving user groups between enterprise accounts. move_groups = meta / "moveGroups" + #: URL for moving workspaces between enterprise accounts. + move_workspaces = meta / "moveWorkspaces" + def user(self, user_id: str) -> Url: """ URL for retrieving information about a single user. @@ -469,6 +472,32 @@ def move_groups( ) return MoveGroupsResponse.from_api(response, self.api, context=self) + def move_workspaces( + self, + workspace_ids: Iterable[str], + target: Union[str, Self], + ) -> "MoveWorkspacesResponse": + """ + Move one or more workspaces from the current enterprise account + into a different enterprise account within the same organization. + + See `Move workspaces `__. + + Args: + workspace_ids: The list of workspace IDs. + target: The ID of the target enterprise, or an instance of :class:`~pyairtable.Enterprise`. + """ + if isinstance(target, Enterprise): + target = target.id + response = self.api.post( + self.urls.move_workspaces, + json={ + "workspaceIds": workspace_ids, + "targetEnterpriseAccountId": target, + }, + ) + return MoveWorkspacesResponse.from_api(response, self.api, context=self) + class UserRemoved(AirtableModel): """ @@ -573,6 +602,15 @@ class MoveGroupsResponse(AirtableModel): errors: List[MoveError] = pydantic.Field(default_factory=list) +class MoveWorkspacesResponse(AirtableModel): + """ + Returned by `Move workspaces `__. + """ + + moved_workspaces: List[NestedId] = pydantic.Field(default_factory=list) + errors: List[MoveError] = pydantic.Field(default_factory=list) + + rebuild_models(vars()) diff --git a/scripts/find_model_changes.py b/scripts/find_model_changes.py index e2e0396c..4c661357 100644 --- a/scripts/find_model_changes.py +++ b/scripts/find_model_changes.py @@ -31,6 +31,9 @@ "pyairtable.api.enterprise:DeleteUsersResponse.Error": "operations:delete-users-by-email:response:schema:@errors:items", "pyairtable.api.enterprise:ManageUsersResponse": "operations:manage-user-membership:response:schema", "pyairtable.api.enterprise:ManageUsersResponse.Error": "operations:manage-user-membership:response:schema:@errors:items", + "pyairtable.api.enterprise:MoveError": "operations:move-workspaces:response:schema:@errors:items", + "pyairtable.api.enterprise:MoveGroupsResponse": "operations:move-user-groups:response:schema", + "pyairtable.api.enterprise:MoveWorkspacesResponse": "operations:move-workspaces:response:schema", "pyairtable.models.audit:AuditLogResponse": "operations:audit-log-events:response:schema", "pyairtable.models.audit:AuditLogEvent": "operations:audit-log-events:response:schema:@events:items", "pyairtable.models.audit:AuditLogEvent.Context": "operations:audit-log-events:response:schema:@events:items:@context", diff --git a/tests/test_api_enterprise.py b/tests/test_api_enterprise.py index 93f8bad2..68e6e833 100644 --- a/tests/test_api_enterprise.py +++ b/tests/test_api_enterprise.py @@ -459,3 +459,20 @@ def test_move_groups(api, enterprise, enterprise_mocks): "groupIds": group_ids, } assert set(m.id for m in result.moved_groups) == set(group_ids) + + +def test_move_workspaces(api, enterprise, enterprise_mocks): + other_id = fake_id("ent") + workspace_ids = [fake_id("wsp") for _ in range(3)] + enterprise_mocks.move_workspaces_json["movedWorkspaces"] = [ + {"id": workspace_id} for workspace_id in workspace_ids + ] + for target in [other_id, api.enterprise(other_id)]: + enterprise_mocks.move_workspaces.reset() + result = enterprise.move_workspaces(workspace_ids, target) + assert enterprise_mocks.move_workspaces.call_count == 1 + assert enterprise_mocks.move_workspaces.last_request.json() == { + "targetEnterpriseAccountId": other_id, + "workspaceIds": workspace_ids, + } + assert set(m.id for m in result.moved_workspaces) == set(workspace_ids)