msfabricpysdkcore 0.0.12__tar.gz → 0.0.13__tar.gz

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 (47) hide show
  1. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/PKG-INFO +102 -1
  2. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/README.md +101 -0
  3. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/adminapi.py +49 -1
  4. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/coreapi.py +46 -1
  5. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/environment.py +11 -10
  6. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/item.py +147 -6
  7. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_admin_apis.py +20 -0
  8. msfabricpysdkcore-0.0.13/msfabricpysdkcore/tests/test_external_data_shares.py +51 -0
  9. msfabricpysdkcore-0.0.13/msfabricpysdkcore/tests/test_one_lake_data_access_security.py +65 -0
  10. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/workspace.py +42 -0
  11. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore.egg-info/PKG-INFO +102 -1
  12. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore.egg-info/SOURCES.txt +2 -0
  13. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/pyproject.toml +1 -1
  14. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/setup.py +1 -1
  15. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/LICENSE +0 -0
  16. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/__init__.py +0 -0
  17. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/admin_item.py +0 -0
  18. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/admin_workspace.py +0 -0
  19. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/auth.py +0 -0
  20. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/capacity.py +0 -0
  21. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/client.py +0 -0
  22. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/deployment_pipeline.py +0 -0
  23. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/domain.py +0 -0
  24. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/job_instance.py +0 -0
  25. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/lakehouse.py +0 -0
  26. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/long_running_operation.py +0 -0
  27. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/onelakeshortcut.py +0 -0
  28. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/otheritems.py +0 -0
  29. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/spark_custom_pool.py +0 -0
  30. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/__init__.py +0 -0
  31. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_datapipelines.py +0 -0
  32. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_deployment_pipeline.py +0 -0
  33. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_domains.py +0 -0
  34. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_environments.py +0 -0
  35. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_evenstreams.py +0 -0
  36. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_git.py +0 -0
  37. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_items_incl_lakehouse.py +0 -0
  38. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_jobs.py +0 -0
  39. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_kqldatabases.py +0 -0
  40. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_shortcuts.py +0 -0
  41. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_spark.py +0 -0
  42. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_sparkjobdefinition.py +0 -0
  43. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore/tests/test_workspaces_capacities.py +0 -0
  44. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore.egg-info/dependency_links.txt +0 -0
  45. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore.egg-info/requires.txt +0 -0
  46. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/msfabricpysdkcore.egg-info/top_level.txt +0 -0
  47. {msfabricpysdkcore-0.0.12 → msfabricpysdkcore-0.0.13}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: msfabricpysdkcore
3
- Version: 0.0.12
3
+ Version: 0.0.13
4
4
  Summary: A Python SDK for Microsoft Fabric
5
5
  Author: Andreas Rederer
6
6
  Project-URL: Homepage, https://github.com/DaSenf1860/ms-fabric-sdk-core
@@ -38,14 +38,17 @@ Currently it supports all Core APIs, Admin APIs, Lakehouse APIs and all other it
38
38
  - Core APIs
39
39
  - [Capacities](#working-with-capacities)
40
40
  - [Deployment Pipelines](#deployment-pipelines)
41
+ - [External Data Shares](#external-data-shares)
41
42
  - [Git](#working-with-git)
42
43
  - [Items](#working-with-items)
43
44
  - [Job Scheduler](#working-with-job-scheduler)
44
45
  - [Long Running Operations](#long-running-operations)
46
+ - [OneLakeDataAccessSecurity](#one-lake-data-access-security)
45
47
  - [OneLakeShortcuts](#working-with-one-lake-shortcuts)
46
48
  - [Workspaces](#working-with-workspaces)
47
49
  - Admin APIs
48
50
  - [Domains](#admin-api-for-domains)
51
+ - [External Data Shares](#admin-api-for-external-data-shares)
49
52
  - [Items](#admin-api-for-items)
50
53
  - [Labels](#admin-api-for-labels)
51
54
  - [Tenants](#admin-api-for-tenants)
@@ -249,6 +252,43 @@ response = pipe.deploy(source_stage_id=dev_stage.id,target_stage_id=prod_stage.i
249
252
 
250
253
  ```
251
254
 
255
+ ### External Data Shares
256
+
257
+ ```python
258
+ from msfabricpysdkcore.coreapi import FabricClientCore
259
+
260
+ fc = FabricClientCore()
261
+
262
+ workspace_id = 'yxcvyxcvyxcv'
263
+ item_id = 'sdfsdfsdfsf'
264
+
265
+
266
+ # Create
267
+
268
+ recipient = {
269
+ "userPrincipalName": "lisa4@fabrikam.com"
270
+ }
271
+ paths=["Files/external"]
272
+
273
+ data_share = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
274
+
275
+ # Get
276
+
277
+ data_share2 = fc.get_external_data_share(workspace_id, item_id, data_share['id'])
278
+
279
+ # List
280
+
281
+ data_share_list = fc.list_external_data_shares_in_item(workspace_id, item_id)
282
+
283
+ data_share_ids = [ds['id'] for ds in data_share_list]
284
+
285
+ # Revoke
286
+
287
+ response_code = fc.revoke_external_data_share(workspace_id, item_id, data_share['id'])
288
+
289
+ ```
290
+
291
+
252
292
  ### Working with items
253
293
 
254
294
  ```python
@@ -452,6 +492,44 @@ results = fc.get_operation_results(operation_id)
452
492
 
453
493
  ```
454
494
 
495
+ ### One Lake Data Access Security
496
+
497
+ ```python
498
+ from msfabricpysdkcore import FabricClientCore
499
+
500
+ fc = FabricClientCore()
501
+
502
+ workspace_id = "d8aafgasdsdbe5"
503
+ item_id = "503hsdfhs48364"
504
+
505
+ # List
506
+
507
+ resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
508
+
509
+ roles = resp[0]
510
+ etag = resp[1]
511
+
512
+
513
+ # Create or Update
514
+
515
+ role1 = roles[1]
516
+
517
+ item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
518
+ +
519
+ if 'ReadAll' in item_access:
520
+ item_access = ['Read', 'Write', 'Execute']
521
+ else:
522
+ item_access.append('ReadAll')
523
+
524
+ role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
525
+ roles[1] = role1
526
+
527
+ resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
528
+ item_id=item_id,
529
+ data_access_roles=roles,
530
+ etag_match={"If-Match":etag})
531
+
532
+ ```
455
533
 
456
534
  ### Admin API for Workspaces
457
535
 
@@ -611,6 +689,29 @@ status_code = fca.role_assignments_bulk_unassign(domain.id, "Contributors", [pri
611
689
  status_code = fca.delete_domain(domain.id)
612
690
  ```
613
691
 
692
+ ### Admin API for External Data Shares
693
+
694
+ ```python
695
+ from msfabricpysdkcore import FabricClientAdmin
696
+
697
+ fca = FabricClientAdmin()
698
+
699
+ # List external data shares
700
+
701
+ data_shares = fca.list_external_data_shares()
702
+ ws = fca.list_workspaces(name="testworkspace")[0]
703
+
704
+ data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
705
+
706
+ # Revoke external data share
707
+
708
+ fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
709
+ item_id = data_shares[0]['itemId'],
710
+ workspace_id = data_shares[0]['workspaceId'])
711
+
712
+
713
+ ```
714
+
614
715
 
615
716
  Note: This SDK is not an official SDK from Microsoft. It is a community project and not supported by Microsoft. Use it at your own risk.
616
717
  Also the API is still in preview and might change. This SDK is not yet feature complete and might not cover all APIs yet. Feel free to contribute to this project to make it better.
@@ -23,14 +23,17 @@ Currently it supports all Core APIs, Admin APIs, Lakehouse APIs and all other it
23
23
  - Core APIs
24
24
  - [Capacities](#working-with-capacities)
25
25
  - [Deployment Pipelines](#deployment-pipelines)
26
+ - [External Data Shares](#external-data-shares)
26
27
  - [Git](#working-with-git)
27
28
  - [Items](#working-with-items)
28
29
  - [Job Scheduler](#working-with-job-scheduler)
29
30
  - [Long Running Operations](#long-running-operations)
31
+ - [OneLakeDataAccessSecurity](#one-lake-data-access-security)
30
32
  - [OneLakeShortcuts](#working-with-one-lake-shortcuts)
31
33
  - [Workspaces](#working-with-workspaces)
32
34
  - Admin APIs
33
35
  - [Domains](#admin-api-for-domains)
36
+ - [External Data Shares](#admin-api-for-external-data-shares)
34
37
  - [Items](#admin-api-for-items)
35
38
  - [Labels](#admin-api-for-labels)
36
39
  - [Tenants](#admin-api-for-tenants)
@@ -234,6 +237,43 @@ response = pipe.deploy(source_stage_id=dev_stage.id,target_stage_id=prod_stage.i
234
237
 
235
238
  ```
236
239
 
240
+ ### External Data Shares
241
+
242
+ ```python
243
+ from msfabricpysdkcore.coreapi import FabricClientCore
244
+
245
+ fc = FabricClientCore()
246
+
247
+ workspace_id = 'yxcvyxcvyxcv'
248
+ item_id = 'sdfsdfsdfsf'
249
+
250
+
251
+ # Create
252
+
253
+ recipient = {
254
+ "userPrincipalName": "lisa4@fabrikam.com"
255
+ }
256
+ paths=["Files/external"]
257
+
258
+ data_share = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
259
+
260
+ # Get
261
+
262
+ data_share2 = fc.get_external_data_share(workspace_id, item_id, data_share['id'])
263
+
264
+ # List
265
+
266
+ data_share_list = fc.list_external_data_shares_in_item(workspace_id, item_id)
267
+
268
+ data_share_ids = [ds['id'] for ds in data_share_list]
269
+
270
+ # Revoke
271
+
272
+ response_code = fc.revoke_external_data_share(workspace_id, item_id, data_share['id'])
273
+
274
+ ```
275
+
276
+
237
277
  ### Working with items
238
278
 
239
279
  ```python
@@ -437,6 +477,44 @@ results = fc.get_operation_results(operation_id)
437
477
 
438
478
  ```
439
479
 
480
+ ### One Lake Data Access Security
481
+
482
+ ```python
483
+ from msfabricpysdkcore import FabricClientCore
484
+
485
+ fc = FabricClientCore()
486
+
487
+ workspace_id = "d8aafgasdsdbe5"
488
+ item_id = "503hsdfhs48364"
489
+
490
+ # List
491
+
492
+ resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
493
+
494
+ roles = resp[0]
495
+ etag = resp[1]
496
+
497
+
498
+ # Create or Update
499
+
500
+ role1 = roles[1]
501
+
502
+ item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
503
+ +
504
+ if 'ReadAll' in item_access:
505
+ item_access = ['Read', 'Write', 'Execute']
506
+ else:
507
+ item_access.append('ReadAll')
508
+
509
+ role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
510
+ roles[1] = role1
511
+
512
+ resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
513
+ item_id=item_id,
514
+ data_access_roles=roles,
515
+ etag_match={"If-Match":etag})
516
+
517
+ ```
440
518
 
441
519
  ### Admin API for Workspaces
442
520
 
@@ -596,6 +674,29 @@ status_code = fca.role_assignments_bulk_unassign(domain.id, "Contributors", [pri
596
674
  status_code = fca.delete_domain(domain.id)
597
675
  ```
598
676
 
677
+ ### Admin API for External Data Shares
678
+
679
+ ```python
680
+ from msfabricpysdkcore import FabricClientAdmin
681
+
682
+ fca = FabricClientAdmin()
683
+
684
+ # List external data shares
685
+
686
+ data_shares = fca.list_external_data_shares()
687
+ ws = fca.list_workspaces(name="testworkspace")[0]
688
+
689
+ data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
690
+
691
+ # Revoke external data share
692
+
693
+ fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
694
+ item_id = data_shares[0]['itemId'],
695
+ workspace_id = data_shares[0]['workspaceId'])
696
+
697
+
698
+ ```
699
+
599
700
 
600
701
  Note: This SDK is not an official SDK from Microsoft. It is a community project and not supported by Microsoft. Use it at your own risk.
601
702
  Also the API is still in preview and might change. This SDK is not yet feature complete and might not cover all APIs yet. Feel free to contribute to this project to make it better.
@@ -658,4 +658,52 @@ class FabricClientAdmin(FabricClient):
658
658
  break
659
659
 
660
660
  response = json.loads(response.text)
661
- return response
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
666
+
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"
697
+
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
707
+
708
+ return response.status_code
709
+
@@ -1011,4 +1011,49 @@ class FabricClientCore(FabricClient):
1011
1011
  return ws.update_spark_settings(automatic_log=automatic_log,
1012
1012
  environment=environment,
1013
1013
  high_concurrency=high_concurrency,
1014
- pool=pool)
1014
+ pool=pool)
1015
+
1016
+
1017
+ # External Data Shares
1018
+
1019
+ # create
1020
+
1021
+ def create_external_data_share(self, workspace_id, item_id, paths, recipient):
1022
+ ws = self.get_workspace_by_id(workspace_id)
1023
+ return ws.create_external_data_share(item_id=item_id, paths = paths, recipient = recipient)
1024
+
1025
+ # get
1026
+
1027
+ def get_external_data_share(self, workspace_id, item_id, external_data_share_id):
1028
+ ws = self.get_workspace_by_id(workspace_id)
1029
+ return ws.get_external_data_share(item_id=item_id, external_data_share_id=external_data_share_id)
1030
+
1031
+ # list
1032
+
1033
+ def list_external_data_shares_in_item(self, workspace_id, item_id):
1034
+ ws = self.get_workspace_by_id(workspace_id)
1035
+ return ws.list_external_data_shares_in_item(item_id=item_id)
1036
+
1037
+ # revoke
1038
+
1039
+ def revoke_external_data_share(self, workspace_id, item_id, external_data_share_id):
1040
+ ws = self.get_workspace_by_id(workspace_id)
1041
+ return ws.revoke_external_data_share(item_id=item_id, external_data_share_id=external_data_share_id)
1042
+
1043
+
1044
+ # One Lake Data Access Security
1045
+
1046
+ # create and update
1047
+
1048
+ def create_or_update_data_access_roles(self, workspace_id, item_id, data_access_roles, dryrun = False, etag_match = None):
1049
+ ws = self.get_workspace_by_id(workspace_id)
1050
+ item = ws.get_item(item_id=item_id).create_or_update_data_access_roles(data_access_roles = data_access_roles,
1051
+ dryrun = dryrun, etag_match = etag_match)
1052
+ return item
1053
+
1054
+ # list
1055
+
1056
+ def list_data_access_roles(self, workspace_id, item_id):
1057
+ ws = self.get_workspace_by_id(workspace_id)
1058
+ item = ws.get_item(item_id=item_id)
1059
+ return item.list_data_access_roles()
@@ -135,16 +135,17 @@ class Environment(Item):
135
135
  # POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/environments/{environmentId}/staging/libraries
136
136
  raise NotImplementedError("Not implemented yet")
137
137
  # url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/environments/{self.id}/staging/libraries"
138
-
139
- # for _ in range(10):
140
- # response = requests.post(url=url, files={'file': file_path}, headers=self.auth.get_headers())
141
- # if response.status_code == 429:
142
- # print("Too many requests, waiting 10 seconds")
143
- # sleep(10)
144
- # continue
145
- # if response.status_code not in (200, 429):
146
- # raise Exception(f"Error uploading staging libraries: {response.status_code}, {response.text}")
147
- # break
138
+ # with open(file_path, 'rb') as f:
139
+ # files = {"upload_file.whl": f}
140
+ # for _ in range(10):
141
+ # response = requests.post(url=url, files=files, headers=self.auth.get_headers())
142
+ # if response.status_code == 429:
143
+ # print("Too many requests, waiting 10 seconds")
144
+ # sleep(10)
145
+ # continue
146
+ # if response.status_code not in (200, 429):
147
+ # raise Exception(f"Error uploading staging libraries: {response.status_code}, {response.text}")
148
+ # break
148
149
 
149
150
  # return json.loads(response.text)
150
151
 
@@ -6,7 +6,6 @@ from msfabricpysdkcore.onelakeshortcut import OneLakeShortcut
6
6
  from msfabricpysdkcore.job_instance import JobInstance
7
7
  from msfabricpysdkcore.long_running_operation import check_long_running_operation
8
8
 
9
-
10
9
  class Item:
11
10
  """Class to represent a item in Microsoft Fabric"""
12
11
 
@@ -247,10 +246,7 @@ class Item:
247
246
  sleep(10)
248
247
  continue
249
248
  if response.status_code not in (200, 429):
250
- print(response.status_code)
251
- print(response.text)
252
-
253
- raise Exception(f"Error getting job instance: {response.text}")
249
+ raise Exception(f"Error getting job instance: {response.status_code}, {response.text}")
254
250
  break
255
251
 
256
252
  job_dict = json.loads(response.text)
@@ -268,4 +264,149 @@ class Item:
268
264
  def load_table(self, table_name, path_type, relative_path,
269
265
  file_extension = None, format_options = None,
270
266
  mode = None, recursive = None, wait_for_completion = True):
271
- raise NotImplementedError("Load table only works on Lakehouse Items")
267
+ raise NotImplementedError("Load table only works on Lakehouse Items")
268
+
269
+ def create_external_data_share(self, paths, recipient):
270
+ # POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares
271
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares"
272
+
273
+ body = {
274
+ 'paths': paths,
275
+ 'recipient': recipient
276
+ }
277
+
278
+ for _ in range(10):
279
+ response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
280
+ if response.status_code == 429:
281
+ print("Too many requests, waiting 10 seconds")
282
+ sleep(10)
283
+ continue
284
+ if response.status_code not in (201, 429):
285
+ raise Exception(f"Error creating external data share: {response.status_code}, {response.text}")
286
+ break
287
+ return json.loads(response.text)
288
+
289
+ def get_external_data_share(self, external_data_share_id):
290
+ # GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}
291
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares/{external_data_share_id}"
292
+
293
+ for _ in range(10):
294
+ response = requests.get(url=url, headers=self.auth.get_headers())
295
+ if response.status_code == 429:
296
+ print("Too many requests, waiting 10 seconds")
297
+ sleep(10)
298
+ continue
299
+ if response.status_code not in (200, 429):
300
+ raise Exception(f"Error getting external data share: {response.status_code}, {response.text}")
301
+ break
302
+ return json.loads(response.text)
303
+
304
+ def list_external_data_shares_in_item(self, continuationToken = None):
305
+ # GET GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares?continuationToken={continuationToken}
306
+
307
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares"
308
+
309
+ if continuationToken:
310
+ url += f"?continuationToken={continuationToken}"
311
+
312
+ for _ in range(10):
313
+ response = requests.get(url=url, headers=self.auth.get_headers())
314
+ if response.status_code == 429:
315
+ print("Too many requests, waiting 10 seconds")
316
+ sleep(10)
317
+ continue
318
+
319
+ if response.status_code not in (200, 429):
320
+ raise Exception(f"Error listing external data shares: {response.status_code}, {response.text}")
321
+ break
322
+
323
+ resp = json.loads(response.text)
324
+ external_data_shares = resp['value']
325
+
326
+ if 'continuationToken' in resp:
327
+ external_data_shares_new = self.list_external_data_shares_in_item(continuationToken=resp['continuationToken'])
328
+ external_data_shares.extend(external_data_shares_new)
329
+
330
+ return external_data_shares
331
+
332
+ def revoke_external_data_share(self, external_data_share_id):
333
+ # POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}/revoke
334
+
335
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares/{external_data_share_id}/revoke"
336
+
337
+ for _ in range(10):
338
+ response = requests.post(url=url, headers=self.auth.get_headers())
339
+ if response.status_code == 429:
340
+ print("Too many requests, waiting 10 seconds")
341
+ sleep(10)
342
+ continue
343
+ if response.status_code not in (200, 429):
344
+ raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
345
+ break
346
+
347
+ return response.status_code
348
+
349
+
350
+ # One Lake data access security
351
+
352
+ def list_data_access_roles(self, continuationToken = None):
353
+ # GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/dataAccessRoles
354
+
355
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/dataAccessRoles"
356
+
357
+ if continuationToken:
358
+ url += f"?continuationToken={continuationToken}"
359
+
360
+ for _ in range(10):
361
+ response = requests.get(url=url, headers=self.auth.get_headers())
362
+ if response.status_code == 429:
363
+ print("Too many requests, waiting 10 seconds")
364
+ sleep(10)
365
+ continue
366
+ if response.status_code not in (200, 429):
367
+ raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
368
+ break
369
+
370
+ resp_dict = json.loads(response.text)
371
+ data_access_roles = resp_dict['value']
372
+ etag = response.headers.get('ETag', None)
373
+
374
+ if 'continuationToken' in resp_dict and resp_dict['continuationToken']:
375
+ data_access_roles_new, etag = self.list_data_access_roles(continuationToken=resp_dict['continuationToken'])
376
+ data_access_roles.extend(data_access_roles_new)
377
+
378
+ return data_access_roles, etag
379
+
380
+ def create_or_update_data_access_roles(self, data_access_roles, dryrun = False, etag_match = None):
381
+ # PUT https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/dataAccessRoles
382
+
383
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/dataAccessRoles"
384
+
385
+ if dryrun:
386
+ url += "?dryrun=true"
387
+
388
+ if etag_match:
389
+ if 'If-Match' in etag_match:
390
+ headers = self.auth.get_headers()
391
+ headers['If-Match'] = etag_match['If-Match']
392
+ elif 'If-None-Match' in etag_match:
393
+ headers = self.auth.get_headers()
394
+ headers['If-None-Match'] = etag_match['If-None-Match']
395
+ else:
396
+ raise Exception("Etag match should include If-Match or If-None-Match")
397
+ else:
398
+ headers = self.auth.get_headers()
399
+
400
+ body = {"value" : data_access_roles}
401
+
402
+ for _ in range(10):
403
+ response = requests.put(url=url, headers=headers, json=body)
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
+ raise Exception(f"Error creating or updating data access roles: {response.status_code}, {response.text}")
410
+ break
411
+
412
+ return response
@@ -77,3 +77,23 @@ class TestFabricClientCore(unittest.TestCase):
77
77
  self.assertEqual(resp["itemsChangeLabelStatus"][0]["status"], "Succeeded")
78
78
  resp = fca.bulk_remove_labels(items=items)
79
79
  self.assertEqual(resp["itemsChangeLabelStatus"][0]["status"], "Succeeded")
80
+
81
+ def test_admin_external_data_shares(self):
82
+
83
+ fca = self.fca
84
+
85
+ data_shares = fca.list_external_data_shares()
86
+ ws = fca.list_workspaces(name="testworkspace")[0]
87
+
88
+ data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
89
+
90
+ self.assertGreater(len(data_shares), 0)
91
+ fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
92
+ item_id = data_shares[0]['itemId'],
93
+ workspace_id = data_shares[0]['workspaceId'])
94
+ data_shares = fca.list_external_data_shares()
95
+ ws = fca.list_workspaces(name="testworkspace")[0]
96
+
97
+ data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
98
+
99
+ self.assertEqual(data_shares[0]['status'], 'Revoked')
@@ -0,0 +1,51 @@
1
+ import unittest
2
+ from dotenv import load_dotenv
3
+ from msfabricpysdkcore.coreapi import FabricClientCore
4
+
5
+ load_dotenv()
6
+
7
+ class TestFabricClientCore(unittest.TestCase):
8
+
9
+ def __init__(self, *args, **kwargs):
10
+ super(TestFabricClientCore, self).__init__(*args, **kwargs)
11
+ self.fc = FabricClientCore()
12
+
13
+ def test_external_data_shares(self):
14
+
15
+ fc = self.fc
16
+
17
+ workspace_id = 'c3352d34-0b54-40f0-b204-cc964b1beb8d'
18
+ item_id = 'e2c09c89-bf97-4f71-bdeb-36338795ec36'
19
+
20
+ recipient = {
21
+ "userPrincipalName": "lisa4@fabrikam.com"
22
+ }
23
+ paths=["Files/external"]
24
+
25
+ resp = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
26
+ self.assertIsNotNone(resp)
27
+ self.assertIn('id', resp)
28
+
29
+
30
+ get = fc.get_external_data_share(workspace_id, item_id, resp['id'])
31
+ self.assertIsNotNone(get)
32
+ self.assertEqual(get['id'], resp['id'])
33
+
34
+
35
+ resp = fc.list_external_data_shares_in_item(workspace_id, item_id)
36
+ self.assertGreater(len(resp), 0)
37
+
38
+ data_share_ids = [ds['id'] for ds in resp]
39
+ self.assertIn(get['id'], data_share_ids)
40
+
41
+
42
+ resp = fc.revoke_external_data_share(workspace_id, item_id, get['id'])
43
+ self.assertEqual(resp, 200)
44
+
45
+ get2 = fc.get_external_data_share(workspace_id, item_id, get['id'])
46
+ self.assertIsNotNone(get2)
47
+
48
+ self.assertEqual(get['id'], get2['id'])
49
+ self.assertEqual(get2['status'], 'Revoked')
50
+
51
+
@@ -0,0 +1,65 @@
1
+ import unittest
2
+ from dotenv import load_dotenv
3
+ from msfabricpysdkcore.coreapi import FabricClientCore
4
+
5
+ load_dotenv()
6
+
7
+ class TestFabricClientCore(unittest.TestCase):
8
+
9
+ def __init__(self, *args, **kwargs):
10
+ super(TestFabricClientCore, self).__init__(*args, **kwargs)
11
+ self.fc = FabricClientCore()
12
+
13
+ def test_one_lake_data_access_security(self):
14
+
15
+ fc = self.fc
16
+
17
+ workspace_id = "d8a5abe0-9eed-406d-ab46-343bc57ddbe5"
18
+ item_id = "50368cf3-29e7-4a09-aaf0-289fb5748364"
19
+
20
+ resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
21
+ self.assertEqual(len(resp), 2)
22
+
23
+ roles = resp[0]
24
+ etag = resp[1]
25
+
26
+ role1 = roles[1]
27
+
28
+ self.assertIn('members', role1)
29
+ self.assertIn('fabricItemMembers', role1['members'])
30
+ self.assertGreater(len(role1['members']['fabricItemMembers']), 0)
31
+ self.assertIn('itemAccess', role1['members']['fabricItemMembers'][0])
32
+
33
+
34
+
35
+ item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
36
+ item_access_old = list(item_access)
37
+ if 'ReadAll' in item_access:
38
+ item_access = ['Read', 'Write', 'Execute']
39
+ else:
40
+ item_access.append('ReadAll')
41
+
42
+ role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
43
+ roles[1] = role1
44
+
45
+ resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
46
+ item_id=item_id,
47
+ data_access_roles=roles,
48
+ etag_match={"If-Match":etag})
49
+
50
+
51
+ resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
52
+ self.assertEqual(len(resp), 2)
53
+
54
+ roles = resp[0]
55
+ etag = resp[1]
56
+
57
+ role1 = roles[1]
58
+
59
+ self.assertIn('members', role1)
60
+ self.assertIn('fabricItemMembers', role1['members'])
61
+ self.assertGreater(len(role1['members']['fabricItemMembers']), 0)
62
+ self.assertIn('itemAccess', role1['members']['fabricItemMembers'][0])
63
+
64
+ item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
65
+ self.assertNotEqual(item_access, item_access_old)
@@ -1472,3 +1472,45 @@ class Workspace:
1472
1472
 
1473
1473
  return json.loads(response.text)
1474
1474
 
1475
+ # External Data Shares
1476
+
1477
+ # create
1478
+
1479
+ def create_external_data_share(self, item_id, paths, recipient):
1480
+ item = self.get_item(item_id=item_id)
1481
+ return item.create_external_data_share(paths = paths, recipient = recipient)
1482
+
1483
+ # get
1484
+
1485
+ def get_external_data_share(self, item_id, external_data_share_id):
1486
+ item = self.get_item(item_id=item_id)
1487
+ return item.get_external_data_share(external_data_share_id=external_data_share_id)
1488
+
1489
+
1490
+ # list
1491
+
1492
+ def list_external_data_shares_in_item(self, item_id):
1493
+ item = self.get_item(item_id=item_id)
1494
+ return item.list_external_data_shares_in_item()
1495
+
1496
+ # revoke
1497
+
1498
+ def revoke_external_data_share(self, item_id, external_data_share_id):
1499
+ item = self.get_item(item_id=item_id)
1500
+ return item.revoke_external_data_share(external_data_share_id=external_data_share_id)
1501
+
1502
+
1503
+ # One Lake Data Access Security
1504
+
1505
+ # create and update
1506
+
1507
+ def create_or_update_data_access_roles(self, item_id, data_access_roles, dryrun = False, etag_match = None):
1508
+ item = self.get_item(item_id=item_id).create_or_update_data_access_roles(data_access_roles = data_access_roles,
1509
+ dryrun = dryrun, etag_match = etag_match)
1510
+ return item
1511
+
1512
+ # list
1513
+
1514
+ def list_data_access_roles(self, item_id):
1515
+ item = self.get_item(item_id=item_id)
1516
+ return item.list_data_access_roles()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: msfabricpysdkcore
3
- Version: 0.0.12
3
+ Version: 0.0.13
4
4
  Summary: A Python SDK for Microsoft Fabric
5
5
  Author: Andreas Rederer
6
6
  Project-URL: Homepage, https://github.com/DaSenf1860/ms-fabric-sdk-core
@@ -38,14 +38,17 @@ Currently it supports all Core APIs, Admin APIs, Lakehouse APIs and all other it
38
38
  - Core APIs
39
39
  - [Capacities](#working-with-capacities)
40
40
  - [Deployment Pipelines](#deployment-pipelines)
41
+ - [External Data Shares](#external-data-shares)
41
42
  - [Git](#working-with-git)
42
43
  - [Items](#working-with-items)
43
44
  - [Job Scheduler](#working-with-job-scheduler)
44
45
  - [Long Running Operations](#long-running-operations)
46
+ - [OneLakeDataAccessSecurity](#one-lake-data-access-security)
45
47
  - [OneLakeShortcuts](#working-with-one-lake-shortcuts)
46
48
  - [Workspaces](#working-with-workspaces)
47
49
  - Admin APIs
48
50
  - [Domains](#admin-api-for-domains)
51
+ - [External Data Shares](#admin-api-for-external-data-shares)
49
52
  - [Items](#admin-api-for-items)
50
53
  - [Labels](#admin-api-for-labels)
51
54
  - [Tenants](#admin-api-for-tenants)
@@ -249,6 +252,43 @@ response = pipe.deploy(source_stage_id=dev_stage.id,target_stage_id=prod_stage.i
249
252
 
250
253
  ```
251
254
 
255
+ ### External Data Shares
256
+
257
+ ```python
258
+ from msfabricpysdkcore.coreapi import FabricClientCore
259
+
260
+ fc = FabricClientCore()
261
+
262
+ workspace_id = 'yxcvyxcvyxcv'
263
+ item_id = 'sdfsdfsdfsf'
264
+
265
+
266
+ # Create
267
+
268
+ recipient = {
269
+ "userPrincipalName": "lisa4@fabrikam.com"
270
+ }
271
+ paths=["Files/external"]
272
+
273
+ data_share = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
274
+
275
+ # Get
276
+
277
+ data_share2 = fc.get_external_data_share(workspace_id, item_id, data_share['id'])
278
+
279
+ # List
280
+
281
+ data_share_list = fc.list_external_data_shares_in_item(workspace_id, item_id)
282
+
283
+ data_share_ids = [ds['id'] for ds in data_share_list]
284
+
285
+ # Revoke
286
+
287
+ response_code = fc.revoke_external_data_share(workspace_id, item_id, data_share['id'])
288
+
289
+ ```
290
+
291
+
252
292
  ### Working with items
253
293
 
254
294
  ```python
@@ -452,6 +492,44 @@ results = fc.get_operation_results(operation_id)
452
492
 
453
493
  ```
454
494
 
495
+ ### One Lake Data Access Security
496
+
497
+ ```python
498
+ from msfabricpysdkcore import FabricClientCore
499
+
500
+ fc = FabricClientCore()
501
+
502
+ workspace_id = "d8aafgasdsdbe5"
503
+ item_id = "503hsdfhs48364"
504
+
505
+ # List
506
+
507
+ resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
508
+
509
+ roles = resp[0]
510
+ etag = resp[1]
511
+
512
+
513
+ # Create or Update
514
+
515
+ role1 = roles[1]
516
+
517
+ item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
518
+ +
519
+ if 'ReadAll' in item_access:
520
+ item_access = ['Read', 'Write', 'Execute']
521
+ else:
522
+ item_access.append('ReadAll')
523
+
524
+ role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
525
+ roles[1] = role1
526
+
527
+ resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
528
+ item_id=item_id,
529
+ data_access_roles=roles,
530
+ etag_match={"If-Match":etag})
531
+
532
+ ```
455
533
 
456
534
  ### Admin API for Workspaces
457
535
 
@@ -611,6 +689,29 @@ status_code = fca.role_assignments_bulk_unassign(domain.id, "Contributors", [pri
611
689
  status_code = fca.delete_domain(domain.id)
612
690
  ```
613
691
 
692
+ ### Admin API for External Data Shares
693
+
694
+ ```python
695
+ from msfabricpysdkcore import FabricClientAdmin
696
+
697
+ fca = FabricClientAdmin()
698
+
699
+ # List external data shares
700
+
701
+ data_shares = fca.list_external_data_shares()
702
+ ws = fca.list_workspaces(name="testworkspace")[0]
703
+
704
+ data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
705
+
706
+ # Revoke external data share
707
+
708
+ fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
709
+ item_id = data_shares[0]['itemId'],
710
+ workspace_id = data_shares[0]['workspaceId'])
711
+
712
+
713
+ ```
714
+
614
715
 
615
716
  Note: This SDK is not an official SDK from Microsoft. It is a community project and not supported by Microsoft. Use it at your own risk.
616
717
  Also the API is still in preview and might change. This SDK is not yet feature complete and might not cover all APIs yet. Feel free to contribute to this project to make it better.
@@ -33,10 +33,12 @@ msfabricpysdkcore/tests/test_deployment_pipeline.py
33
33
  msfabricpysdkcore/tests/test_domains.py
34
34
  msfabricpysdkcore/tests/test_environments.py
35
35
  msfabricpysdkcore/tests/test_evenstreams.py
36
+ msfabricpysdkcore/tests/test_external_data_shares.py
36
37
  msfabricpysdkcore/tests/test_git.py
37
38
  msfabricpysdkcore/tests/test_items_incl_lakehouse.py
38
39
  msfabricpysdkcore/tests/test_jobs.py
39
40
  msfabricpysdkcore/tests/test_kqldatabases.py
41
+ msfabricpysdkcore/tests/test_one_lake_data_access_security.py
40
42
  msfabricpysdkcore/tests/test_shortcuts.py
41
43
  msfabricpysdkcore/tests/test_spark.py
42
44
  msfabricpysdkcore/tests/test_sparkjobdefinition.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "msfabricpysdkcore"
7
- version = "0.0.12"
7
+ version = "0.0.13"
8
8
  dynamic = ["dependencies"]
9
9
  authors = [
10
10
  { name="Andreas Rederer"},
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='msfabricpysdkcore',
5
- version='0.12',
5
+ version='0.13',
6
6
  packages=find_packages(),
7
7
  install_requires=[
8
8
  'requests>=2.30.0',