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