|
1 | 1 | """ |
2 | 2 | Clone a team — copy its channels, apps, tabs, settings, and/or members. |
3 | 3 |
|
4 | | -Uses the ``ClonableTeamParts`` enum as a bitset so you can select |
5 | | -exactly what to copy. The clone operation is async; this example |
6 | | -polls the source team's ``operations`` collection until it completes. |
| 4 | +The clone operation is async; ``execute_query_and_wait`` polls until |
| 5 | +the operation completes. |
7 | 6 |
|
8 | | -Typical provisioning pattern: bootstrap a new project from a template |
9 | | -team that already has the right channel structure and app setup. |
10 | | -
|
11 | | -Requires delegated permission ``Team.Create`` or ``Group.ReadWrite.All``. |
12 | | -
|
13 | | -Note: the SDK's ``team.clone()`` helper is a stub that doesn't pass |
14 | | -the required body parameters yet. This example uses the underlying |
15 | | -``ServiceOperationQuery`` directly to send the proper payload. |
16 | | -
|
17 | | -https://learn.microsoft.com/en-us/graph/api/team-clone |
| 7 | +Requires delegated permission Team.Create or Group.ReadWrite.All. |
18 | 8 | """ |
19 | 9 |
|
20 | | -import sys |
21 | | -import time |
22 | | - |
23 | 10 | from office365.graph_client import GraphClient |
24 | 11 | from office365.teams.clonableteamparts import ClonableTeamParts |
25 | | -from office365.teams.team import Team |
26 | 12 | from tests import test_client_id, test_password, test_tenant, test_username |
27 | 13 |
|
28 | 14 |
|
29 | | -def poll_clone_completion(team: Team, max_wait_sec: int = 120) -> bool: |
30 | | - """Poll the team's operations list waiting for a clone to succeed/fail.""" |
31 | | - for attempt in range(1, (max_wait_sec // 10) + 1): |
32 | | - time.sleep(10) |
33 | | - ops = team.operations.get().execute_query() |
34 | | - for op in ops: |
35 | | - print(f" [{attempt * 10}s] Operation status: {op.status}") |
36 | | - if op.status == "succeeded": |
37 | | - return True |
38 | | - elif op.status == "failed": |
39 | | - err = op.properties.get("error", {}) |
40 | | - print(f" Error: {err.get('message', 'unknown')}") |
41 | | - return False |
42 | | - return False |
43 | | - |
44 | | - |
45 | 15 | def main(): |
46 | 16 | client = GraphClient(tenant=test_tenant).with_username_and_password(test_client_id, test_username, test_password) |
47 | 17 |
|
48 | | - # — Step 1: pick a source team — |
49 | 18 | teams = client.teams.get().top(1).execute_query() |
50 | | - if len(teams) == 0: |
51 | | - sys.exit("No source team found.") |
| 19 | + if not teams: |
| 20 | + print("No source team found.") |
| 21 | + return |
52 | 22 |
|
53 | 23 | source_team = teams[0] |
54 | 24 | print(f"Source team: {source_team.display_name}") |
55 | 25 |
|
56 | | - print("Cloning (this may take 60+ seconds)...\n") |
57 | | - target_team = source_team.clone( |
| 26 | + print("Cloning...") |
| 27 | + source_team.clone( |
58 | 28 | f"{source_team.display_name}_cloned", |
59 | 29 | f"{source_team.display_name}_cloned", |
60 | 30 | ClonableTeamParts.channels, |
61 | 31 | source_team.visibility, |
62 | 32 | ).execute_query_and_wait() |
| 33 | + print("Clone completed.") |
63 | 34 |
|
64 | 35 |
|
65 | 36 | if __name__ == "__main__": |
|
0 commit comments