msfabricpysdkcore 0.0.13__py3-none-any.whl → 0.1.2__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.
Files changed (53) hide show
  1. msfabricpysdkcore/__init__.py +2 -1
  2. msfabricpysdkcore/admin_item.py +19 -45
  3. msfabricpysdkcore/admin_workspace.py +13 -60
  4. msfabricpysdkcore/adminapi.py +401 -476
  5. msfabricpysdkcore/auth.py +10 -6
  6. msfabricpysdkcore/client.py +124 -7
  7. msfabricpysdkcore/coreapi.py +2570 -822
  8. msfabricpysdkcore/deployment_pipeline.py +34 -146
  9. msfabricpysdkcore/domain.py +20 -219
  10. msfabricpysdkcore/environment.py +13 -172
  11. msfabricpysdkcore/fabric_azure_capacity.py +77 -0
  12. msfabricpysdkcore/fabric_azure_client.py +228 -0
  13. msfabricpysdkcore/item.py +55 -331
  14. msfabricpysdkcore/job_instance.py +8 -22
  15. msfabricpysdkcore/lakehouse.py +9 -118
  16. msfabricpysdkcore/long_running_operation.py +7 -37
  17. msfabricpysdkcore/onelakeshortcut.py +7 -21
  18. msfabricpysdkcore/otheritems.py +66 -91
  19. msfabricpysdkcore/spark_custom_pool.py +7 -47
  20. msfabricpysdkcore/tests/test_admin_apis.py +9 -10
  21. msfabricpysdkcore/tests/test_datapipelines.py +15 -18
  22. msfabricpysdkcore/tests/test_deployment_pipeline.py +3 -3
  23. msfabricpysdkcore/tests/test_domains.py +6 -5
  24. msfabricpysdkcore/tests/test_environments.py +54 -5
  25. msfabricpysdkcore/tests/test_evenhouses.py +47 -0
  26. msfabricpysdkcore/tests/test_evenstreams.py +20 -20
  27. msfabricpysdkcore/tests/test_external_data_shares.py +3 -3
  28. msfabricpysdkcore/tests/test_fabric_azure_client.py +78 -0
  29. msfabricpysdkcore/tests/test_git.py +8 -9
  30. msfabricpysdkcore/tests/test_items.py +81 -0
  31. msfabricpysdkcore/tests/test_jobs.py +2 -2
  32. msfabricpysdkcore/tests/test_kql_queryset.py +49 -0
  33. msfabricpysdkcore/tests/test_kqldatabases.py +3 -3
  34. msfabricpysdkcore/tests/test_lakehouse.py +84 -0
  35. msfabricpysdkcore/tests/test_ml_experiments.py +47 -0
  36. msfabricpysdkcore/tests/test_ml_models.py +47 -0
  37. msfabricpysdkcore/tests/test_notebooks.py +57 -0
  38. msfabricpysdkcore/tests/test_one_lake_data_access_security.py +2 -4
  39. msfabricpysdkcore/tests/test_other_items.py +45 -0
  40. msfabricpysdkcore/tests/test_reports.py +52 -0
  41. msfabricpysdkcore/tests/test_semantic_model.py +50 -0
  42. msfabricpysdkcore/tests/test_shortcuts.py +4 -4
  43. msfabricpysdkcore/tests/test_spark.py +9 -9
  44. msfabricpysdkcore/tests/test_sparkjobdefinition.py +2 -2
  45. msfabricpysdkcore/tests/test_warehouses.py +50 -0
  46. msfabricpysdkcore/tests/test_workspaces_capacities.py +16 -13
  47. msfabricpysdkcore/workspace.py +397 -1163
  48. {msfabricpysdkcore-0.0.13.dist-info → msfabricpysdkcore-0.1.2.dist-info}/METADATA +72 -10
  49. msfabricpysdkcore-0.1.2.dist-info/RECORD +55 -0
  50. {msfabricpysdkcore-0.0.13.dist-info → msfabricpysdkcore-0.1.2.dist-info}/WHEEL +1 -1
  51. msfabricpysdkcore-0.0.13.dist-info/RECORD +0 -41
  52. {msfabricpysdkcore-0.0.13.dist-info → msfabricpysdkcore-0.1.2.dist-info}/LICENSE +0 -0
  53. {msfabricpysdkcore-0.0.13.dist-info → msfabricpysdkcore-0.1.2.dist-info}/top_level.txt +0 -0
@@ -3,101 +3,66 @@ import json
3
3
  import os
4
4
  from time import sleep
5
5
 
6
- from msfabricpysdkcore.admin_item import AdminItem
7
6
  from msfabricpysdkcore.client import FabricClient
8
- from msfabricpysdkcore.domain import Domain
9
- from msfabricpysdkcore.admin_workspace import AdminWorkspace
10
7
 
11
8
  class FabricClientAdmin(FabricClient):
12
9
  """FabricClientAdmin class to interact with Fabric Admin APIs"""
13
10
 
14
11
  def __init__(self, tenant_id = None, client_id = None, client_secret = None) -> None:
15
12
  """Initialize FabricClientAdmin object"""
16
- super().__init__(tenant_id, client_id, client_secret)
13
+ super().__init__(scope="https://api.fabric.microsoft.com/.default",
14
+ tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
17
15
 
18
-
19
- def list_domains(self, nonEmptyOnly=False):
20
- """List all domains in the tenant
21
-
22
- Args:
23
- nonEmptyOnly (bool): Whether to list only non-empty domains
24
- Returns:
25
- list: List of Domain objects"""
26
- url = "https://api.fabric.microsoft.com/v1/admin/domains"
27
- if nonEmptyOnly:
28
- url = f"{url}?nonEmptyOnly=True"
29
16
 
30
- for _ in range(10):
31
- response = requests.get(url=url, headers=self.auth.get_headers())
32
- if response.status_code == 429:
33
- print("Too many requests, waiting 10 seconds")
34
- sleep(10)
35
- continue
36
- if response.status_code not in (200, 429):
37
- print(response.status_code)
38
- print(response.text)
39
- raise Exception(f"Error listing domains: {response.text}")
40
- break
41
-
42
- resp_dict = json.loads(response.text)
43
- domains = resp_dict["domains"]
17
+ def long_running_operation(self, response_headers):
18
+ """Check the status of a long running operation"""
19
+ from msfabricpysdkcore.coreapi import FabricClientCore
20
+ fc = FabricClientCore(tenant_id=self.tenant_id, client_id=self.client_id, client_secret=self.client_secret, silent=True)
44
21
 
45
- domains = [Domain.from_dict(i, self.auth) for i in domains]
46
- return domains
47
-
48
- def get_domain_by_id(self, domain_id):
49
- """Method to get a domain by ID
22
+ return fc.long_running_operation(response_headers)
23
+
24
+ # Domain APIs
25
+
26
+ def assign_domain_workspaces_by_ids(self, domain_id, workspaces_ids):
27
+ """Assign workspaces to a domain by workspace IDs
50
28
 
51
29
  Args:
52
30
  domain_id (str): The ID of the domain
31
+ workspace_ids (list): The list of workspace IDs
32
+ wait_for_completion (bool): Whether to wait for the operation to complete
53
33
  Returns:
54
- Domain: The Domain object
34
+ int: The status code of the response
55
35
  """
56
- url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}"
57
- for _ in range(10):
58
- response = requests.get(url=url, headers=self.auth.get_headers())
59
- if response.status_code == 429:
60
- print("Too many requests, waiting 10 seconds")
61
- sleep(10)
62
- continue
63
- if response.status_code not in (200, 429):
64
- print(response.status_code)
65
- print(response.text)
66
- raise Exception(f"Error getting domain: {response.text}")
67
- break
68
-
69
- domain_dict = json.loads(response.text)
70
- domain = Domain.from_dict(domain_dict, self.auth)
71
- return domain
36
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/assignWorkspaces"
37
+ body = {
38
+ "workspacesIds": workspaces_ids
39
+ }
72
40
 
73
- def get_domain_by_name(self, domain_name):
74
- """Method to get a domain by name
75
-
76
- Args:
77
- domain_name (str): The name of the domain
78
- Returns:
79
- Domain: The Domain object
80
- """
81
- domains = self.list_domains()
82
- for domain in domains:
83
- if domain.display_name == domain_name:
84
- return domain
85
- raise ValueError("Domain not found")
41
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
42
+ error_message = "Error assigning workspaces by ids", return_format="response")
43
+
44
+ return response.status_code
86
45
 
87
- def get_domain(self, domain_id = None, domain_name = None):
88
- """Get a domain by ID or name
46
+ def assign_domains_workspaces_by_principals(self, domain_id, principals, wait_for_completion=True):
47
+ """Assign workspaces to a domain by principals
89
48
 
90
49
  Args:
91
50
  domain_id (str): The ID of the domain
92
- domain_name (str): The name of the domain
51
+ principals (list): The list of principal IDs
52
+ wait_for_completion (bool): Whether to wait for the operation to complete
93
53
  Returns:
94
- Domain: The Domain object
54
+ int: The status code of the response
95
55
  """
96
- if domain_id:
97
- return self.get_domain_by_id(domain_id)
98
- if domain_name:
99
- return self.get_domain_by_name(domain_name)
100
- raise ValueError("Either domain_id or domain_name must be provided")
56
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/assignWorkspacesByPrincipals"
57
+ body = {
58
+ "principals": principals
59
+ }
60
+
61
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [202, 429],
62
+ error_message = "Error assigning workspaces by principals", wait_for_completion=wait_for_completion,
63
+ return_format="response")
64
+
65
+ return response.status_code
101
66
 
102
67
  def create_domain(self, display_name, description = None, parent_domain_id = None):
103
68
  """Method to create a domain
@@ -109,7 +74,8 @@ class FabricClientAdmin(FabricClient):
109
74
  Returns:
110
75
  Domain: The Domain object
111
76
  """
112
- # POST https://api.fabric.microsoft.com/v1/admin/domains
77
+ from msfabricpysdkcore.domain import Domain
78
+
113
79
  url = "https://api.fabric.microsoft.com/v1/admin/domains"
114
80
  body = {
115
81
  "displayName": display_name
@@ -118,21 +84,11 @@ class FabricClientAdmin(FabricClient):
118
84
  body["description"] = description
119
85
  if parent_domain_id:
120
86
  body["parentDomainId"] = parent_domain_id
121
-
122
- for _ in range(10):
123
- response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
124
- if response.status_code == 429:
125
- print("Too many requests, waiting 10 seconds")
126
- sleep(10)
127
- continue
128
- if response.status_code not in (200, 201, 429):
129
- print(response.status_code)
130
- print(response.text)
131
- raise Exception(f"Error creating domain: {response.text}")
132
- break
133
-
134
- domain_dict = json.loads(response.text)
135
- domain = Domain.from_dict(domain_dict, self.auth)
87
+
88
+ domain_dict = self.calling_routine(url = url, operation = "POST", body = body, return_format="json",
89
+ response_codes = [200, 201, 429], error_message = "Error creating domain")
90
+
91
+ domain = Domain.from_dict(domain_dict, self)
136
92
  return domain
137
93
 
138
94
  def delete_domain(self, domain_id):
@@ -143,69 +99,103 @@ class FabricClientAdmin(FabricClient):
143
99
  Returns:
144
100
  status_code (int): The status code of the request
145
101
  """
146
- return self.get_domain_by_id(domain_id).delete()
147
102
 
148
- def update_domain(self, domain_id, description = None, display_name = None, contributors_scope = None):
149
- """Method to update a domain
103
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}"
104
+
105
+ response:requests.Response = self.calling_routine(url = url, operation = "DELETE", response_codes = [200, 429],
106
+ error_message = "Error deleting domain",
107
+ return_format="response")
108
+
109
+ return response.status_code
110
+
111
+ def get_domain_by_id(self, domain_id):
112
+ """Method to get a domain by ID
150
113
 
151
114
  Args:
152
115
  domain_id (str): The ID of the domain
153
116
  Returns:
154
117
  Domain: The Domain object
155
118
  """
156
- domain = self.get_domain_by_id(domain_id)
157
- return domain.update(description = description, display_name = display_name, contributors_scope = contributors_scope)
158
-
159
- def list_domain_workspaces(self, domain_id, workspace_objects = False):
160
- """List workspaces in a domain
119
+ from msfabricpysdkcore.domain import Domain
120
+
121
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}"
122
+
123
+ domain_dict = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429], error_message = "Error getting domain",
124
+ return_format="json")
125
+ domain = Domain.from_dict(domain_dict, self)
126
+ return domain
127
+
128
+ def get_domain_by_name(self, domain_name):
129
+ """Method to get a domain by name
161
130
 
162
131
  Args:
163
- domain_id (str): The ID of the domain
132
+ domain_name (str): The name of the domain
164
133
  Returns:
165
- list: List of Workspace objects
134
+ Domain: The Domain object
166
135
  """
167
- domain = self.get_domain_by_id(domain_id)
168
- return domain.list_domain_workspaces(workspace_objects=workspace_objects)
136
+ domains = self.list_domains()
137
+ domains = [domain for domain in domains if domain.display_name == domain_name]
138
+ if len(domains) > 0:
139
+ return self.get_domain_by_id(domains[0].id)
140
+ raise ValueError("Domain not found")
169
141
 
170
- def assign_domain_workspaces_by_capacities(self, domain_id, capacities_ids, wait_for_completion=True):
171
- """Assign workspaces to a domain by capacities
142
+ def get_domain(self, domain_id = None, domain_name = None):
143
+ """Get a domain by ID or name
172
144
 
173
145
  Args:
174
146
  domain_id (str): The ID of the domain
175
- capacities (list): The list of capacity IDs
176
- wait_for_completion (bool): Whether to wait for the operation to complete
147
+ domain_name (str): The name of the domain
177
148
  Returns:
178
- int: The status code of the response
149
+ Domain: The Domain object
179
150
  """
180
- domain = self.get_domain_by_id(domain_id)
181
- return domain.assign_workspaces_by_capacities(capacities_ids, wait_for_completion)
151
+ if domain_id:
152
+ return self.get_domain_by_id(domain_id)
153
+ if domain_name:
154
+ return self.get_domain_by_name(domain_name)
155
+ raise ValueError("Either domain_id or domain_name must be provided")
182
156
 
183
- def assign_domain_workspaces_by_ids(self, domain_id, workspace_ids):
184
- """Assign workspaces to a domain by workspace IDs
157
+ def list_domain_workspaces(self, domain_id, workspace_objects = False):
158
+ """List workspaces in a domain
185
159
 
186
160
  Args:
187
161
  domain_id (str): The ID of the domain
188
- workspace_ids (list): The list of workspace IDs
189
- wait_for_completion (bool): Whether to wait for the operation to complete
190
162
  Returns:
191
- int: The status code of the response
163
+ list: List of Workspace objects
192
164
  """
193
- domain = self.get_domain_by_id(domain_id)
194
- return domain.assign_workspaces_by_ids(workspace_ids)
165
+
166
+
167
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/workspaces"
168
+
169
+ workspaces = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429], error_message = "Error listing domain workspaces",
170
+ return_format="value_json", paging=True)
171
+
172
+ if workspace_objects:
173
+ from msfabricpysdkcore import FabricClientCore
174
+ fc = FabricClientCore(tenant_id=self.tenant_id, client_id=self.client_id, client_secret=self.client_secret, silent=True)
175
+ workspaces = [fc.get_workspace_by_id(workspace["id"]) for workspace in workspaces]
176
+
177
+ return workspaces
195
178
 
196
- def assign_domains_workspaces_by_principals(self, domain_id, principals, wait_for_completion=True):
197
- """Assign workspaces to a domain by principals
179
+ def list_domains(self, nonEmptyOnly=False):
180
+ """List all domains in the tenant
198
181
 
199
182
  Args:
200
- domain_id (str): The ID of the domain
201
- principals (list): The list of principal IDs
202
- wait_for_completion (bool): Whether to wait for the operation to complete
183
+ nonEmptyOnly (bool): Whether to list only non-empty domains
203
184
  Returns:
204
- int: The status code of the response
205
- """
206
- domain = self.get_domain_by_id(domain_id)
207
- return domain.assign_workspaces_by_principals(principals=principals, wait_for_completion=wait_for_completion)
208
-
185
+ list: List of Domain objects"""
186
+ from msfabricpysdkcore.domain import Domain
187
+
188
+ url = "https://api.fabric.microsoft.com/v1/admin/domains"
189
+ if nonEmptyOnly:
190
+ url = f"{url}?nonEmptyOnly=True"
191
+
192
+ resp_dict = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429], error_message = "Error listing domains",
193
+ return_format="json")
194
+ domains = resp_dict["domains"]
195
+
196
+ domains = [Domain.from_dict(i, self) for i in domains]
197
+ return domains
198
+
209
199
  def role_assignments_bulk_assign(self, domain_id, type, principals):
210
200
  """Assign a role to principals in bulk
211
201
 
@@ -216,8 +206,18 @@ class FabricClientAdmin(FabricClient):
216
206
  Returns:
217
207
  int: The status code of the response
218
208
  """
219
- domain = self.get_domain_by_id(domain_id)
220
- return domain.role_assignments_bulk_assign(type, principals)
209
+
210
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/roleAssignments/bulkAssign"
211
+ body = {
212
+ "type": type,
213
+ "principals": principals
214
+ }
215
+
216
+ response: requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
217
+ error_message = "Error bulk assigning role assignments",
218
+ return_format="response")
219
+
220
+ return response.status_code
221
221
 
222
222
  def role_assignments_bulk_unassign(self, domain_id, type, principals):
223
223
  """Unassign a role from principals in bulk
@@ -229,9 +229,18 @@ class FabricClientAdmin(FabricClient):
229
229
  Returns:
230
230
  int: The status code of the response
231
231
  """
232
- domain = self.get_domain_by_id(domain_id)
233
- return domain.role_assignments_bulk_unassign(type, principals)
234
-
232
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/roleAssignments/bulkUnassign"
233
+ body = {
234
+ "type": type,
235
+ "principals": principals
236
+ }
237
+
238
+ response: requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
239
+ error_message = "Error bulk unassigning role assignments",
240
+ return_format="response")
241
+
242
+ return response.status_code
243
+
235
244
  def unassign_all_domain_workspaces(self, domain_id):
236
245
  """Unassign all workspaces from a domain
237
246
 
@@ -240,8 +249,12 @@ class FabricClientAdmin(FabricClient):
240
249
  Returns:
241
250
  int: The status code of the response
242
251
  """
243
- domain = self.get_domain_by_id(domain_id)
244
- return domain.unassign_all_workspaces()
252
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/unassignAllWorkspaces"
253
+
254
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", response_codes = [200, 429],
255
+ error_message = "Error unassigning all workspaces",
256
+ return_format="response")
257
+ return response.status_code
245
258
 
246
259
  def unassign_domain_workspaces_by_ids(self, domain_id, workspace_ids):
247
260
  """Unassign workspaces from a domain by workspace IDs
@@ -252,127 +265,159 @@ class FabricClientAdmin(FabricClient):
252
265
  Returns:
253
266
  int: The status code of the response
254
267
  """
255
- domain = self.get_domain_by_id(domain_id)
256
- return domain.unassign_workspaces_by_ids(workspace_ids=workspace_ids)
268
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/unassignWorkspaces"
269
+ body = {
270
+ "workspacesIds": workspace_ids
271
+ }
272
+
273
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
274
+ error_message = "Error unassigning workspaces by ids",
275
+ return_format="response")
276
+
277
+ return response.status_code
257
278
 
258
- def get_workspace(self, workspace_id):
259
- """Get a workspace by ID
279
+ def update_domain(self, domain_id, description = None, display_name = None, contributors_scope = None, return_item = "Default"):
280
+ """Method to update a domain
260
281
 
261
282
  Args:
262
- workspace_id (str): The ID of the workspace
283
+ domain_id (str): The ID of the domain
263
284
  Returns:
264
- Workspace: The Workspace object
285
+ Domain: The Domain object
265
286
  """
287
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}"
288
+ body = {}
289
+ if description:
290
+ body["description"] = description
291
+
292
+ if display_name:
293
+ body["displayName"] = display_name
294
+
295
+ if contributors_scope:
296
+ body["contributorsScope"] = contributors_scope
297
+
298
+ response_json = self.calling_routine(url = url, operation = "PATCH", body = body,
299
+ response_codes = [200, 429], error_message = "Error updating domain",
300
+ return_format="json")
301
+
302
+ if return_item == "Default":
303
+ print("""Warning: Updating a domain currently will make invoke an additional API call to get the domain object.
304
+ This default behaviour will change in newer versions of the SDK.
305
+ To keep this behaviour, set return_item=True in the function call.""")
306
+ if return_item:
307
+ return self.get_domain_by_id(domain_id)
308
+ return response_json
266
309
 
267
- url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}"
268
- for _ in range(10):
269
- response = requests.get(url=url, headers=self.auth.get_headers())
270
- if response.status_code == 429:
271
- print("Too many requests, waiting 10 seconds")
272
- sleep(10)
273
- continue
274
- if response.status_code not in (200, 429):
275
- print(response.status_code)
276
- print(response.text)
277
- raise Exception(f"Error getting workspace: {response.text}")
278
- break
279
-
280
- workspace_dict = json.loads(response.text)
281
- workspace = AdminWorkspace.from_dict(workspace_dict, self.auth)
282
- return workspace
283
310
 
284
- def get_workspace_access_details(self, workspace_id):
285
- """Get the access details of the workspace
311
+ def assign_domain_workspaces_by_capacities(self, domain_id, capacities_ids, wait_for_completion=True):
312
+ """Assign workspaces to a domain by capacities
286
313
 
287
314
  Args:
288
- workspace_id (str): The ID of the workspace
315
+ domain_id (str): The ID of the domain
316
+ capacities (list): The list of capacity IDs
317
+ wait_for_completion (bool): Whether to wait for the operation to complete
289
318
  Returns:
290
- dict: The access details of the workspace
319
+ int: The status code of the response
291
320
  """
292
- print("DEPRECATED: Use list_workspace_access_details instead")
293
- return self.list_workspace_access_details(workspace_id)
321
+ url = f"https://api.fabric.microsoft.com/v1/admin/domains/{domain_id}/assignWorkspacesByCapacities"
294
322
 
295
- def list_workspace_access_details(self, workspace_id):
296
- """Get the access details of the workspace
323
+ body = {
324
+ "capacitiesIds": capacities_ids
325
+ }
326
+
327
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [202, 429],
328
+ error_message = "Error assigning workspaces by capacities", wait_for_completion=wait_for_completion,
329
+ return_format="response")
330
+
331
+ return response.status_code
332
+
333
+ # External Data Share APIs
334
+
335
+ def list_external_data_shares(self):
336
+ # GET https://api.fabric.microsoft.com/v1/admin/items/externalDataShares
337
+ """List external data shares
297
338
 
339
+ Returns:
340
+ list: The list of external data shares
341
+ """
342
+ url = "https://api.fabric.microsoft.com/v1/admin/items/externalDataShares"
343
+
344
+
345
+ items: list = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
346
+ error_message = "Error listing external data shares",
347
+ return_format="value_json", paging=True)
348
+
349
+ return items
350
+
351
+ def revoke_external_data_share(self, external_data_share_id, item_id, workspace_id):
352
+ """Revoke an external data share
298
353
  Args:
354
+ external_data_share_id (str): The ID of the external data share
355
+ item_id (str): The ID of the item
299
356
  workspace_id (str): The ID of the workspace
300
357
  Returns:
301
- dict: The access details of the workspace
358
+ int: The status code of the response
302
359
  """
303
- ws = self.get_workspace(workspace_id)
304
- return ws.list_workspace_access_details()
360
+ url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/items/{item_id}/externalDataShares/{external_data_share_id}/revoke"
361
+
362
+ response:requests.Response = self.calling_routine(url = url, operation = "POST", response_codes = [200, 429],
363
+ error_message = "Error revoking external data share",
364
+ return_format="response")
365
+
366
+ return response.status_code
367
+
368
+ # Items APIs
305
369
 
306
- def list_workspaces(self, capacity_id = None, name=None, state=None, type=None, continuationToken = None):
307
- """List all workspaces
370
+ def get_item(self, item_id, workspace_id, type = None):
371
+ """Get an item from the workspace
308
372
 
309
373
  Args:
310
- capacity_id (str): The ID of the capacity
374
+ item_id (str): The ID of the item
375
+ workspace_id (str): The ID of the workspace
376
+ type (str): The type of the item
311
377
  Returns:
312
- list: List of Workspace objects
378
+ AdminItem: The item object
313
379
  """
314
- #GET https://api.fabric.microsoft.com/v1/admin/workspaces?type={type}&capacityId={capacityId}&name={name}&state={state}&continuationToken={continuationToken}
315
- url = "https://api.fabric.microsoft.com/v1/admin/workspaces"
316
- first_parameter = False
380
+ from msfabricpysdkcore.admin_item import AdminItem
381
+
382
+ url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/items/{item_id}"
317
383
  if type:
318
- url = f"{url}?type={type}"
319
- first_parameter = True
320
- if capacity_id:
321
- if first_parameter:
322
- url = f"{url}&capacityId={capacity_id}"
323
- else:
324
- url = f"{url}?capacityId={capacity_id}"
384
+ url += f"?type={type}"
325
385
 
326
- if name:
327
- if first_parameter:
328
- url = f"{url}&name={name}"
329
- else:
330
- url = f"{url}?name={name}"
386
+ response_json: dict = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
387
+ error_message = "Error getting item", return_format="json")
388
+
389
+ return AdminItem.from_dict(response_json, self)
390
+
391
+
392
+ def list_item_access_details(self, workspace_id, item_id, type=None):
393
+ """Get the access details of the item
331
394
 
332
- if state:
333
- if first_parameter:
334
- url = f"{url}&state={state}"
335
- else:
336
- url = f"{url}?state={state}"
395
+ Args:
396
+ workspace_id (str): The ID of the workspace
397
+ item_id (str): The ID of the item
398
+ type (str): The type of the item
399
+ Returns:
400
+ dict: The access details of the item
401
+ """
402
+ url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/items/{item_id}/users"
337
403
 
338
- if continuationToken:
339
- if first_parameter:
340
- url = f"{url}&continuationToken={continuationToken}"
341
- else:
342
- url = f"{url}?continuationToken={continuationToken}"
343
-
344
- for _ in range(10):
345
- response = requests.get(url=url, headers=self.auth.get_headers())
346
- if response.status_code == 429:
347
- print("Too many requests, waiting 10 seconds")
348
- sleep(10)
349
- continue
350
- if response.status_code not in (200, 429):
351
- print(response.status_code)
352
- print(response.text)
353
- raise Exception(f"Error listing workspaces: {response.text}")
354
- break
355
-
356
- resp_dict = json.loads(response.text)
357
- workspaces = resp_dict["workspaces"]
358
-
359
- workspaces = [AdminWorkspace.from_dict(i, self.auth) for i in workspaces]
360
-
361
- if "continuationToken" in resp_dict and resp_dict["continuationToken"] is not None:
362
- workspaces_next = self.list_workspaces(capacity_id=capacity_id, name=name, state=state, type=type,
363
- continuationToken=resp_dict["continuationToken"])
364
- workspaces.extend(workspaces_next)
404
+ if type:
405
+ url += f"?type={type}"
365
406
 
366
- return workspaces
367
-
407
+ response_json: dict = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
408
+ error_message = "Error getting item access details", return_format="json")
409
+
410
+ return response_json
411
+
368
412
  def list_items(self, workspace_id = None, capacity_id = None, type=None,
369
- state=None, continuationToken = None):
413
+ state=None):
370
414
  """List all items
371
415
 
372
416
  Returns:
373
417
  list: The list of items in the workspace
374
418
  """
375
-
419
+ from msfabricpysdkcore.admin_item import AdminItem
420
+
376
421
  url = f"https://api.fabric.microsoft.com/v1/admin/items"
377
422
  first_parameter = False
378
423
  if workspace_id:
@@ -383,327 +428,207 @@ class FabricClientAdmin(FabricClient):
383
428
  url = f"{url}&capacityId={capacity_id}"
384
429
  else:
385
430
  url = f"{url}?capacityId={capacity_id}"
431
+ first_parameter = True
386
432
  if type:
387
433
  if first_parameter:
388
434
  url = f"{url}&type={type}"
389
435
  else:
390
436
  url = f"{url}?type={type}"
437
+ first_parameter = True
391
438
  if state:
392
439
  if first_parameter:
393
440
  url = f"{url}&state={state}"
394
441
  else:
395
442
  url = f"{url}?state={state}"
396
- if continuationToken:
397
- if first_parameter:
398
- url = f"{url}&continuationToken={continuationToken}"
399
- else:
400
- url = f"{url}?continuationToken={continuationToken}"
401
-
402
- for _ in range(10):
403
- response = requests.get(url=url, headers=self.auth.get_headers())
404
- if response.status_code == 429:
405
- print("Too many requests, waiting 10 seconds")
406
- sleep(10)
407
- continue
408
- if response.status_code not in (200, 429):
409
- print(response.status_code)
410
- print(response.text)
411
- raise Exception(f"Error listing items: {response.text}")
412
- break
413
- resp_dict = json.loads(response.text)
414
- items = [AdminItem.from_dict(item, self.auth) for item in resp_dict["itemEntities"]]
415
-
416
- if "continuationToken" in items and items["continuationToken"] is not None:
417
- items_next = self.list_items(workspace_id=workspace_id, capacity_id=capacity_id, type=type,
418
- state=state, continuationToken=items["continuationToken"])
419
- items.extend(items_next)
420
443
 
444
+ items = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
445
+ error_message = "Error listing items", return_format="itemEntities", paging=True)
446
+
447
+ items = [AdminItem.from_dict(item, self) for item in items]
421
448
  return items
422
449
 
423
- def get_item(self, item_id, workspace_id, type = None):
424
- """Get an item from the workspace
425
-
450
+ # Labels APIs
451
+
452
+
453
+ def bulk_remove_labels(self, items):
454
+ """Remove labels in bulk
426
455
  Args:
427
- item_id (str): The ID of the item
428
- workspace_id (str): The ID of the workspace
429
- type (str): The type of the item
456
+ items (list): The list of item IDs
430
457
  Returns:
431
- AdminItem: The item object
432
- """
433
- ws = self.get_workspace(workspace_id)
434
- return ws.get_item(item_id, type)
435
-
458
+ dict: The response from the API"""
436
459
 
437
- def get_tenant_settings(self):
438
- """Get the tenant settings
439
-
440
- Returns:
441
- dict: The tenant settings
442
- """
443
- print("DEPRECATED: Use list_tenant_settings instead")
444
- return self.list_tenant_settings()
445
-
446
- def list_tenant_settings(self):
447
- """Get the tenant settings
460
+ url = "https://api.fabric.microsoft.com/v1/admin/items/bulkRemoveLabels"
461
+
462
+ if len(items) > 2000:
463
+ self.bulk_remove_labels(items[2000:])
464
+ items = items[:2000]
448
465
 
466
+ body = {
467
+ "items": items
468
+ }
469
+
470
+ response_json: dict = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
471
+ error_message = "Error removing labels", return_format="json")
472
+
473
+ return response_json
474
+
475
+ def bulk_set_labels(self, items, label_id, assignment_method = None, delegated_principal = None):
476
+ """Set labels in bulk
477
+ Args:
478
+ items (list): The list of item IDs
479
+ label_id (str): The ID of the label
480
+ assignment_method (str): The assignment method
481
+ delegated_principal (str): The delegated principal
449
482
  Returns:
450
- dict: The tenant settings
483
+ dict: The response from the API
451
484
  """
452
- url = "https://api.fabric.microsoft.com/v1/admin/tenantsettings"
453
- for _ in range(10):
454
- response = requests.get(url=url, headers=self.auth.get_headers())
455
- if response.status_code == 429:
456
- print("Too many requests, waiting 10 seconds")
457
- sleep(10)
458
- continue
459
- if response.status_code not in (200, 429):
460
- print(response.status_code)
461
- print(response.text)
462
- raise Exception(f"Error getting tenant settings: {response.text}")
463
- break
464
-
465
- return json.loads(response.text)
466
-
467
485
 
468
- def list_capacities_tenant_settings_overrides(self, continuationToken = None):
486
+ url = "https://api.fabric.microsoft.com/v1/admin/items/bulkSetLabels"
487
+
488
+ if len(items) > 2000:
489
+ self.bulk_set_labels(items[2000:], label_id, assignment_method, delegated_principal)
490
+ items = items[:2000]
491
+
492
+ body = {
493
+ "items": items,
494
+ "labelId": label_id
495
+ }
496
+ if assignment_method:
497
+ body["assignmentMethod"] = assignment_method
498
+
499
+ if delegated_principal:
500
+ body["delegatedPrincipal"] = delegated_principal
501
+
502
+ response_json: dict = self.calling_routine(url = url, operation = "POST", body = body, response_codes = [200, 429],
503
+ error_message = "Error setting labels", return_format="json")
504
+
505
+ return response_json
506
+
507
+ # Tenant Settings APIs
508
+
509
+ def list_capacities_tenant_settings_overrides(self):
469
510
  """Returns list of tenant setting overrides that override at the capacities
470
511
 
471
512
  Returns:
472
513
  list: The capacities tenant settings overrides
473
514
  """
474
515
  url = "https://api.fabric.microsoft.com/v1/admin/capacities/delegatedTenantSettingOverrides"
475
- if continuationToken:
476
- url = f"{url}?continuationToken={continuationToken}"
477
-
478
- for _ in range(10):
479
- response = requests.get(url=url, headers=self.auth.get_headers())
480
- if response.status_code == 429:
481
- print("Too many requests, waiting 10 seconds")
482
- sleep(10)
483
- continue
484
- if response.status_code not in (200, 429):
485
- print(response.status_code)
486
- print(response.text)
487
- raise Exception(f"Error getting capacities tenant settings overrides: {response.text}")
488
- break
489
-
490
- resp_dict = json.loads(response.text)
491
- overrides = resp_dict["Overrides"]
492
-
493
- if "continuationToken" in resp_dict and resp_dict["continuationToken"] is not None:
494
- overrides_next = self.list_capacities_tenant_settings_overrides(continuationToken=resp_dict["continuationToken"])
495
- overrides.extend(overrides_next)
496
-
497
- return overrides
498
-
499
- def get_capacities_tenant_settings_overrides(self):
500
- """Returns list of tenant setting overrides that override at the capacities
501
-
502
- Returns:
503
- list: The capacities tenant settings overrides
504
- """
505
- print("DEPRECATED: Use list_capacities_tenant_settings_overrides instead")
506
- return self.list_capacities_tenant_settings_overrides()
507
-
508
516
 
509
- def get_access_entities(self, user_id, type = None):
510
- """Get the access entities for a user
517
+
518
+ items: list = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
519
+ error_message = "Error listing capacities tenant settings overrides",
520
+ return_format="Overrides", paging=True)
521
+
522
+ return items
523
+
524
+ def list_tenant_settings(self):
525
+ """Get the tenant settings
511
526
 
512
- Args:
513
- user_id (str): The ID of the user
514
- type (str): The type of the access entity
515
- continuationToken (str): The continuation token
516
527
  Returns:
517
- list: The list of access entities
528
+ dict: The tenant settings
518
529
  """
519
- print("DEPRECATED: Use list_access_entities instead")
520
- return self.list_access_entities(user_id, type)
530
+ url = "https://api.fabric.microsoft.com/v1/admin/tenantsettings"
531
+
532
+ response_json = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
533
+ error_message = "Error getting tenant settings", return_format="json")
534
+ return response_json
535
+
536
+ # Users APIs
521
537
 
522
- def list_access_entities(self, user_id, type = None, continuationToken = None):
538
+ def list_access_entities(self, user_id, type = None):
523
539
  """Get the access entities for a user
524
540
 
525
541
  Args:
526
542
  user_id (str): The ID of the user
527
543
  type (str): The type of the access entity
528
- continuationToken (str): The continuation token
529
544
  Returns:
530
545
  list: The list of access entities
531
546
  """
532
547
 
533
548
  url = f"https://api.fabric.microsoft.com/v1/admin/users/{user_id}/access"
534
549
 
535
- first_parameter = False
536
550
  if type:
537
551
  url = f"{url}?type={type}"
538
- first_parameter = True
539
- if continuationToken:
540
- if first_parameter:
541
- url = f"{url}&continuationToken={continuationToken}"
542
- else:
543
- url = f"{url}?continuationToken={continuationToken}"
544
-
545
- for _ in range(10):
546
- response = requests.get(url=url, headers=self.auth.get_headers())
547
- if response.status_code == 429:
548
- print("Too many requests, waiting 10 seconds")
549
- sleep(10)
550
- continue
551
- if response.status_code not in (200, 429):
552
- print(response.status_code)
553
- print(response.text)
554
- raise Exception(f"Error getting access entities: {response.text}")
555
- break
556
-
557
- resp_dict = json.loads(response.text)
558
- access_entities = resp_dict["accessEntities"]
559
-
560
- if "continuationToken" in resp_dict and resp_dict["continuationToken"] is not None:
561
- access_entities_next = self.list_access_entities(user_id, type, continuationToken=resp_dict["continuationToken"])
562
- resp_dict["accessEntities"].extend(access_entities_next)
563
-
552
+
553
+ access_entities: list = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
554
+ error_message = "Error getting access entities", return_format="accessEntities", paging=True)
555
+
564
556
  return access_entities
557
+
558
+ # Workspaces APIs
565
559
 
566
- def list_item_access_details(self, workspace_id, item_id, type=None):
567
- """Get the access details of the item
560
+ def get_workspace(self, workspace_id):
561
+ """Get a workspace by ID
568
562
 
569
563
  Args:
570
564
  workspace_id (str): The ID of the workspace
571
- item_id (str): The ID of the item
572
- type (str): The type of the item
573
565
  Returns:
574
- dict: The access details of the item
566
+ Workspace: The Workspace object
575
567
  """
576
- ws = self.get_workspace(workspace_id)
577
- item = ws.get_item(item_id, type)
578
- return item.list_item_access_details(type)
568
+ from msfabricpysdkcore.admin_workspace import AdminWorkspace
569
+
570
+ url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}"
571
+
572
+ response_json: dict = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
573
+ error_message = "Error getting workspace", return_format="json")
579
574
 
580
- def get_item_access_details(self, workspace_id, item_id, type=None):
581
- """Get the access details of the item
575
+ workspace = AdminWorkspace.from_dict(response_json, self)
576
+ return workspace
577
+
578
+ def list_workspace_access_details(self, workspace_id):
579
+ """Get the access details of the workspace
582
580
 
583
581
  Args:
584
582
  workspace_id (str): The ID of the workspace
585
- item_id (str): The ID of the item
586
- type (str): The type of the item
587
583
  Returns:
588
- dict: The access details of the item
584
+ dict: The access details of the workspace
589
585
  """
590
- print("DEPRECATED: Use list_item_access_details instead")
591
- return self.list_item_access_details(workspace_id, item_id, type)
592
-
593
- def bulk_set_labels(self, items, label_id, assignment_method = None, delegated_principal = None):
594
- """Set labels in bulk"""
595
- # POST https://api.fabric.microsoft.com/v1/admin/items/bulkSetLabels
596
-
597
- url = "https://api.fabric.microsoft.com/v1/admin/items/bulkSetLabels"
598
-
599
- if len(items) > 2000:
600
- self.bulk_set_labels(items[2000:], label_id, assignment_method, delegated_principal)
601
- items = items[:2000]
602
-
603
- body = {
604
- "items": items,
605
- "labelId": label_id
606
- }
607
- if assignment_method:
608
- body["assignmentMethod"] = assignment_method
609
-
610
- if delegated_principal:
611
- body["delegatedPrincipal"] = delegated_principal
586
+ url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/users"
612
587
 
613
- for _ in range(10):
614
- response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
615
- if response.status_code == 429:
616
- print("Too many requests, waiting 10 seconds")
617
- sleep(10)
618
- continue
619
- if response.status_code not in (200, 429):
620
- print(response.status_code)
621
- print(response.text)
622
- raise Exception(f"Error setting labels: {response.text}")
623
- break
624
-
625
- response = json.loads(response.text)
626
- return response
588
+ response_json = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
589
+ error_message = "Error getting workspace access details", return_format="json")
590
+ return response_json
627
591
 
628
592
 
629
- def bulk_remove_labels(self, items):
630
- """Remove labels in bulk
593
+ def list_workspaces(self, capacity_id = None, name=None, state=None, type=None, continuationToken = None):
594
+ """List all workspaces
595
+
631
596
  Args:
632
- items (list): The list of item IDs
633
-
597
+ capacity_id (str): The ID of the capacity
634
598
  Returns:
635
- dict: The response from the API"""
636
- # POST https://api.fabric.microsoft.com/v1/admin/items/bulkRemoveLabels
637
-
638
- url = "https://api.fabric.microsoft.com/v1/admin/items/bulkRemoveLabels"
599
+ list: List of Workspace objects
600
+ """
601
+ from msfabricpysdkcore.admin_workspace import AdminWorkspace
639
602
 
640
- if len(items) > 2000:
641
- self.bulk_remove_labels(items[2000:])
642
- items = items[:2000]
643
-
644
- body = {
645
- "items": items
646
- }
603
+ url = "https://api.fabric.microsoft.com/v1/admin/workspaces"
604
+ first_parameter = False
605
+ if type:
606
+ url = f"{url}?type={type}"
607
+ first_parameter = True
608
+ if capacity_id:
609
+ if first_parameter:
610
+ url = f"{url}&capacityId={capacity_id}"
611
+ else:
612
+ url = f"{url}?capacityId={capacity_id}"
613
+ first_parameter = True
647
614
 
648
- for _ in range(10):
649
- response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
650
- if response.status_code == 429:
651
- print("Too many requests, waiting 10 seconds")
652
- sleep(10)
653
- continue
654
- if response.status_code not in (200, 429):
655
- print(response.status_code)
656
- print(response.text)
657
- raise Exception(f"Error removing labels: {response.text}")
658
- break
659
-
660
- response = json.loads(response.text)
661
- return response
662
-
663
- def list_external_data_shares(self, continuationToken = None):
664
- # GET https://api.fabric.microsoft.com/v1/admin/items/externalDataShares
665
- """List external data shares
615
+ if name:
616
+ if first_parameter:
617
+ url = f"{url}&name={name}"
618
+ else:
619
+ url = f"{url}?name={name}"
620
+ first_parameter = True
666
621
 
667
- Returns:
668
- list: The list of external data shares
669
- """
670
- url = "https://api.fabric.microsoft.com/v1/admin/items/externalDataShares"
671
-
672
- if continuationToken:
673
- url = f"{url}?continuationToken={continuationToken}"
674
-
675
- for _ in range(10):
676
- response = requests.get(url=url, headers=self.auth.get_headers())
677
- if response.status_code == 429:
678
- print("Too many requests, waiting 10 seconds")
679
- sleep(10)
680
- continue
681
- if response.status_code not in (200, 429):
682
- raise Exception(f"Error listing external data shares: {response.status_code}, {response.text}")
683
- break
684
-
685
- response = json.loads(response.text)
686
- list_data_shares = response["value"]
687
-
688
- if "continuationToken" in response and response["continuationToken"] is not None:
689
- list_data_shares_next = self.list_external_data_shares(continuationToken=response["continuationToken"])
690
- list_data_shares.extend(list_data_shares_next)
691
- return list_data_shares
692
-
693
- def revoke_external_data_share(self, external_data_share_id, item_id, workspace_id):
694
- # POST https://api.fabric.microsoft.com/v1/admin/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}/revoke
695
- """Revoke an external data share"""
696
- url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/items/{item_id}/externalDataShares/{external_data_share_id}/revoke"
622
+ if state:
623
+ if first_parameter:
624
+ url = f"{url}&state={state}"
625
+ else:
626
+ url = f"{url}?state={state}"
627
+ first_parameter = True
697
628
 
698
- for _ in range(10):
699
- response = requests.post(url=url, headers=self.auth.get_headers())
700
- if response.status_code == 429:
701
- print("Too many requests, waiting 10 seconds")
702
- sleep(10)
703
- continue
704
- if response.status_code not in (200, 429):
705
- raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
706
- break
629
+ workspaces: list = self.calling_routine(url = url, operation = "GET", response_codes = [200, 429],
630
+ error_message = "Error listing workspaces", return_format="workspaces", paging=True)
707
631
 
708
- return response.status_code
632
+ workspaces = [AdminWorkspace.from_dict(i, self) for i in workspaces]
709
633
 
634
+ return workspaces