semantic-link-labs 0.12.8__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 (243) hide show
  1. semantic_link_labs-0.12.8.dist-info/METADATA +354 -0
  2. semantic_link_labs-0.12.8.dist-info/RECORD +243 -0
  3. semantic_link_labs-0.12.8.dist-info/WHEEL +5 -0
  4. semantic_link_labs-0.12.8.dist-info/licenses/LICENSE +21 -0
  5. semantic_link_labs-0.12.8.dist-info/top_level.txt +1 -0
  6. sempy_labs/__init__.py +606 -0
  7. sempy_labs/_a_lib_info.py +2 -0
  8. sempy_labs/_ai.py +437 -0
  9. sempy_labs/_authentication.py +264 -0
  10. sempy_labs/_bpa_translation/_model/_translations_am-ET.po +869 -0
  11. sempy_labs/_bpa_translation/_model/_translations_ar-AE.po +908 -0
  12. sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +968 -0
  13. sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +963 -0
  14. sempy_labs/_bpa_translation/_model/_translations_cs-CZ.po +943 -0
  15. sempy_labs/_bpa_translation/_model/_translations_da-DK.po +945 -0
  16. sempy_labs/_bpa_translation/_model/_translations_de-DE.po +988 -0
  17. sempy_labs/_bpa_translation/_model/_translations_el-GR.po +993 -0
  18. sempy_labs/_bpa_translation/_model/_translations_es-ES.po +971 -0
  19. sempy_labs/_bpa_translation/_model/_translations_fa-IR.po +933 -0
  20. sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +942 -0
  21. sempy_labs/_bpa_translation/_model/_translations_fr-FR.po +994 -0
  22. sempy_labs/_bpa_translation/_model/_translations_ga-IE.po +967 -0
  23. sempy_labs/_bpa_translation/_model/_translations_he-IL.po +902 -0
  24. sempy_labs/_bpa_translation/_model/_translations_hi-IN.po +944 -0
  25. sempy_labs/_bpa_translation/_model/_translations_hu-HU.po +963 -0
  26. sempy_labs/_bpa_translation/_model/_translations_id-ID.po +946 -0
  27. sempy_labs/_bpa_translation/_model/_translations_is-IS.po +939 -0
  28. sempy_labs/_bpa_translation/_model/_translations_it-IT.po +986 -0
  29. sempy_labs/_bpa_translation/_model/_translations_ja-JP.po +846 -0
  30. sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +839 -0
  31. sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +967 -0
  32. sempy_labs/_bpa_translation/_model/_translations_nl-NL.po +978 -0
  33. sempy_labs/_bpa_translation/_model/_translations_pl-PL.po +962 -0
  34. sempy_labs/_bpa_translation/_model/_translations_pt-BR.po +962 -0
  35. sempy_labs/_bpa_translation/_model/_translations_pt-PT.po +957 -0
  36. sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +968 -0
  37. sempy_labs/_bpa_translation/_model/_translations_ru-RU.po +964 -0
  38. sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +952 -0
  39. sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +950 -0
  40. sempy_labs/_bpa_translation/_model/_translations_sv-SE.po +942 -0
  41. sempy_labs/_bpa_translation/_model/_translations_ta-IN.po +976 -0
  42. sempy_labs/_bpa_translation/_model/_translations_te-IN.po +947 -0
  43. sempy_labs/_bpa_translation/_model/_translations_th-TH.po +924 -0
  44. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +953 -0
  45. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +961 -0
  46. sempy_labs/_bpa_translation/_model/_translations_zh-CN.po +804 -0
  47. sempy_labs/_bpa_translation/_model/_translations_zu-ZA.po +969 -0
  48. sempy_labs/_capacities.py +1198 -0
  49. sempy_labs/_capacity_migration.py +660 -0
  50. sempy_labs/_clear_cache.py +351 -0
  51. sempy_labs/_connections.py +610 -0
  52. sempy_labs/_dashboards.py +69 -0
  53. sempy_labs/_data_access_security.py +98 -0
  54. sempy_labs/_data_pipelines.py +162 -0
  55. sempy_labs/_dataflows.py +668 -0
  56. sempy_labs/_dax.py +501 -0
  57. sempy_labs/_daxformatter.py +80 -0
  58. sempy_labs/_delta_analyzer.py +467 -0
  59. sempy_labs/_delta_analyzer_history.py +301 -0
  60. sempy_labs/_dictionary_diffs.py +221 -0
  61. sempy_labs/_documentation.py +147 -0
  62. sempy_labs/_domains.py +51 -0
  63. sempy_labs/_eventhouses.py +182 -0
  64. sempy_labs/_external_data_shares.py +230 -0
  65. sempy_labs/_gateways.py +521 -0
  66. sempy_labs/_generate_semantic_model.py +521 -0
  67. sempy_labs/_get_connection_string.py +84 -0
  68. sempy_labs/_git.py +543 -0
  69. sempy_labs/_graphQL.py +90 -0
  70. sempy_labs/_helper_functions.py +2833 -0
  71. sempy_labs/_icons.py +149 -0
  72. sempy_labs/_job_scheduler.py +609 -0
  73. sempy_labs/_kql_databases.py +149 -0
  74. sempy_labs/_kql_querysets.py +124 -0
  75. sempy_labs/_kusto.py +137 -0
  76. sempy_labs/_labels.py +124 -0
  77. sempy_labs/_list_functions.py +1720 -0
  78. sempy_labs/_managed_private_endpoints.py +253 -0
  79. sempy_labs/_mirrored_databases.py +416 -0
  80. sempy_labs/_mirrored_warehouses.py +60 -0
  81. sempy_labs/_ml_experiments.py +113 -0
  82. sempy_labs/_model_auto_build.py +140 -0
  83. sempy_labs/_model_bpa.py +557 -0
  84. sempy_labs/_model_bpa_bulk.py +378 -0
  85. sempy_labs/_model_bpa_rules.py +859 -0
  86. sempy_labs/_model_dependencies.py +343 -0
  87. sempy_labs/_mounted_data_factories.py +123 -0
  88. sempy_labs/_notebooks.py +441 -0
  89. sempy_labs/_one_lake_integration.py +151 -0
  90. sempy_labs/_onelake.py +131 -0
  91. sempy_labs/_query_scale_out.py +433 -0
  92. sempy_labs/_refresh_semantic_model.py +435 -0
  93. sempy_labs/_semantic_models.py +468 -0
  94. sempy_labs/_spark.py +455 -0
  95. sempy_labs/_sql.py +241 -0
  96. sempy_labs/_sql_audit_settings.py +207 -0
  97. sempy_labs/_sql_endpoints.py +214 -0
  98. sempy_labs/_tags.py +201 -0
  99. sempy_labs/_translations.py +43 -0
  100. sempy_labs/_user_delegation_key.py +44 -0
  101. sempy_labs/_utils.py +79 -0
  102. sempy_labs/_vertipaq.py +1021 -0
  103. sempy_labs/_vpax.py +388 -0
  104. sempy_labs/_warehouses.py +234 -0
  105. sempy_labs/_workloads.py +140 -0
  106. sempy_labs/_workspace_identity.py +72 -0
  107. sempy_labs/_workspaces.py +595 -0
  108. sempy_labs/admin/__init__.py +170 -0
  109. sempy_labs/admin/_activities.py +167 -0
  110. sempy_labs/admin/_apps.py +145 -0
  111. sempy_labs/admin/_artifacts.py +65 -0
  112. sempy_labs/admin/_basic_functions.py +463 -0
  113. sempy_labs/admin/_capacities.py +508 -0
  114. sempy_labs/admin/_dataflows.py +45 -0
  115. sempy_labs/admin/_datasets.py +186 -0
  116. sempy_labs/admin/_domains.py +522 -0
  117. sempy_labs/admin/_external_data_share.py +100 -0
  118. sempy_labs/admin/_git.py +72 -0
  119. sempy_labs/admin/_items.py +265 -0
  120. sempy_labs/admin/_labels.py +211 -0
  121. sempy_labs/admin/_reports.py +241 -0
  122. sempy_labs/admin/_scanner.py +118 -0
  123. sempy_labs/admin/_shared.py +82 -0
  124. sempy_labs/admin/_sharing_links.py +110 -0
  125. sempy_labs/admin/_tags.py +131 -0
  126. sempy_labs/admin/_tenant.py +503 -0
  127. sempy_labs/admin/_tenant_keys.py +89 -0
  128. sempy_labs/admin/_users.py +140 -0
  129. sempy_labs/admin/_workspaces.py +236 -0
  130. sempy_labs/deployment_pipeline/__init__.py +23 -0
  131. sempy_labs/deployment_pipeline/_items.py +580 -0
  132. sempy_labs/directlake/__init__.py +57 -0
  133. sempy_labs/directlake/_autosync.py +58 -0
  134. sempy_labs/directlake/_directlake_schema_compare.py +120 -0
  135. sempy_labs/directlake/_directlake_schema_sync.py +161 -0
  136. sempy_labs/directlake/_dl_helper.py +274 -0
  137. sempy_labs/directlake/_generate_shared_expression.py +94 -0
  138. sempy_labs/directlake/_get_directlake_lakehouse.py +62 -0
  139. sempy_labs/directlake/_get_shared_expression.py +34 -0
  140. sempy_labs/directlake/_guardrails.py +96 -0
  141. sempy_labs/directlake/_list_directlake_model_calc_tables.py +70 -0
  142. sempy_labs/directlake/_show_unsupported_directlake_objects.py +90 -0
  143. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +239 -0
  144. sempy_labs/directlake/_update_directlake_partition_entity.py +259 -0
  145. sempy_labs/directlake/_warm_cache.py +236 -0
  146. sempy_labs/dotnet_lib/dotnet.runtime.config.json +10 -0
  147. sempy_labs/environment/__init__.py +23 -0
  148. sempy_labs/environment/_items.py +212 -0
  149. sempy_labs/environment/_pubstage.py +223 -0
  150. sempy_labs/eventstream/__init__.py +37 -0
  151. sempy_labs/eventstream/_items.py +263 -0
  152. sempy_labs/eventstream/_topology.py +652 -0
  153. sempy_labs/graph/__init__.py +59 -0
  154. sempy_labs/graph/_groups.py +651 -0
  155. sempy_labs/graph/_sensitivity_labels.py +120 -0
  156. sempy_labs/graph/_teams.py +125 -0
  157. sempy_labs/graph/_user_licenses.py +96 -0
  158. sempy_labs/graph/_users.py +516 -0
  159. sempy_labs/graph_model/__init__.py +15 -0
  160. sempy_labs/graph_model/_background_jobs.py +63 -0
  161. sempy_labs/graph_model/_items.py +149 -0
  162. sempy_labs/lakehouse/__init__.py +67 -0
  163. sempy_labs/lakehouse/_blobs.py +247 -0
  164. sempy_labs/lakehouse/_get_lakehouse_columns.py +102 -0
  165. sempy_labs/lakehouse/_get_lakehouse_tables.py +274 -0
  166. sempy_labs/lakehouse/_helper.py +250 -0
  167. sempy_labs/lakehouse/_lakehouse.py +351 -0
  168. sempy_labs/lakehouse/_livy_sessions.py +143 -0
  169. sempy_labs/lakehouse/_materialized_lake_views.py +157 -0
  170. sempy_labs/lakehouse/_partitioning.py +165 -0
  171. sempy_labs/lakehouse/_schemas.py +217 -0
  172. sempy_labs/lakehouse/_shortcuts.py +440 -0
  173. sempy_labs/migration/__init__.py +35 -0
  174. sempy_labs/migration/_create_pqt_file.py +238 -0
  175. sempy_labs/migration/_direct_lake_to_import.py +105 -0
  176. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +398 -0
  177. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +148 -0
  178. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +533 -0
  179. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +172 -0
  180. sempy_labs/migration/_migration_validation.py +71 -0
  181. sempy_labs/migration/_refresh_calc_tables.py +131 -0
  182. sempy_labs/mirrored_azure_databricks_catalog/__init__.py +15 -0
  183. sempy_labs/mirrored_azure_databricks_catalog/_discover.py +213 -0
  184. sempy_labs/mirrored_azure_databricks_catalog/_refresh_catalog_metadata.py +45 -0
  185. sempy_labs/ml_model/__init__.py +23 -0
  186. sempy_labs/ml_model/_functions.py +427 -0
  187. sempy_labs/report/_BPAReportTemplate.json +232 -0
  188. sempy_labs/report/__init__.py +55 -0
  189. sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
  190. sempy_labs/report/_bpareporttemplate/.platform +11 -0
  191. sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
  192. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
  193. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
  194. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
  195. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
  196. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
  197. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
  198. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
  199. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
  200. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
  201. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
  202. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
  203. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
  204. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
  205. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
  206. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
  207. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
  208. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
  209. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
  210. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
  211. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
  212. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
  213. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
  214. sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
  215. sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
  216. sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
  217. sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
  218. sempy_labs/report/_download_report.py +76 -0
  219. sempy_labs/report/_export_report.py +257 -0
  220. sempy_labs/report/_generate_report.py +427 -0
  221. sempy_labs/report/_paginated.py +76 -0
  222. sempy_labs/report/_report_bpa.py +354 -0
  223. sempy_labs/report/_report_bpa_rules.py +115 -0
  224. sempy_labs/report/_report_functions.py +581 -0
  225. sempy_labs/report/_report_helper.py +227 -0
  226. sempy_labs/report/_report_list_functions.py +110 -0
  227. sempy_labs/report/_report_rebind.py +149 -0
  228. sempy_labs/report/_reportwrapper.py +3100 -0
  229. sempy_labs/report/_save_report.py +147 -0
  230. sempy_labs/snowflake_database/__init__.py +10 -0
  231. sempy_labs/snowflake_database/_items.py +105 -0
  232. sempy_labs/sql_database/__init__.py +21 -0
  233. sempy_labs/sql_database/_items.py +201 -0
  234. sempy_labs/sql_database/_mirroring.py +79 -0
  235. sempy_labs/theme/__init__.py +12 -0
  236. sempy_labs/theme/_org_themes.py +129 -0
  237. sempy_labs/tom/__init__.py +3 -0
  238. sempy_labs/tom/_model.py +5977 -0
  239. sempy_labs/variable_library/__init__.py +19 -0
  240. sempy_labs/variable_library/_functions.py +403 -0
  241. sempy_labs/warehouse/__init__.py +28 -0
  242. sempy_labs/warehouse/_items.py +234 -0
  243. sempy_labs/warehouse/_restore_points.py +309 -0
@@ -0,0 +1,186 @@
1
+ import pandas as pd
2
+ from typing import Optional
3
+ from sempy_labs._helper_functions import (
4
+ _build_url,
5
+ _base_api,
6
+ _create_dataframe,
7
+ _update_dataframe_datatypes,
8
+ _is_valid_uuid,
9
+ )
10
+ from uuid import UUID
11
+ import sempy_labs._icons as icons
12
+ from sempy._utils._log import log
13
+
14
+
15
+ @log
16
+ def list_datasets(
17
+ top: Optional[int] = None,
18
+ filter: Optional[str] = None,
19
+ skip: Optional[int] = None,
20
+ ) -> pd.DataFrame:
21
+ """
22
+ Shows a list of datasets for the organization.
23
+
24
+ This is a wrapper function for the following API: `Admin - Datasets GetDatasetsAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/datasets-get-datasets-as-admin>`_.
25
+
26
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
27
+
28
+ Parameters
29
+ ----------
30
+ top : int, default=None
31
+ Returns only the first n results.
32
+ filter : str, default=None
33
+ Returns a subset of a results based on Odata filter query parameter condition.
34
+ skip : int, default=None
35
+ Skips the first n results.
36
+
37
+ Returns
38
+ -------
39
+ pandas.DataFrame
40
+ A pandas dataframe showing a list of datasets for the organization.
41
+ """
42
+
43
+ columns = {
44
+ "Dataset Id": "string",
45
+ "Dataset Name": "string",
46
+ "Web URL": "string",
47
+ "Add Rows API Enabled": "bool",
48
+ "Configured By": "string",
49
+ "Is Refreshable": "bool",
50
+ "Is Effective Identity Required": "bool",
51
+ "Is Effective Identity Roles Required": "bool",
52
+ "Target Storage Mode": "string",
53
+ "Created Date": "datetime",
54
+ "Content Provider Type": "string",
55
+ "Create Report Embed URL": "string",
56
+ "QnA Embed URL": "string",
57
+ "Upstream Datasets": "list",
58
+ "Users": "list",
59
+ "Is In Place Sharing Enabled": "bool",
60
+ "Workspace Id": "string",
61
+ "Auto Sync Read Only Replicas": "bool",
62
+ "Max Read Only Replicas": "int",
63
+ }
64
+
65
+ df = _create_dataframe(columns=columns)
66
+
67
+ params = {}
68
+ url = "/v1.0/myorg/admin/datasets"
69
+
70
+ if top is not None:
71
+ params["$top"] = top
72
+
73
+ if filter is not None:
74
+ params["$filter"] = filter
75
+
76
+ if skip is not None:
77
+ params["$skip"] = skip
78
+
79
+ url = _build_url(url, params)
80
+ response = _base_api(request=url, client="fabric_sp")
81
+
82
+ rows = []
83
+ for v in response.json().get("value", []):
84
+ rows.append(
85
+ {
86
+ "Dataset Id": v.get("id"),
87
+ "Dataset Name": v.get("name"),
88
+ "Web URL": v.get("webUrl"),
89
+ "Add Rows API Enabled": v.get("addRowsAPIEnabled"),
90
+ "Configured By": v.get("configuredBy"),
91
+ "Is Refreshable": v.get("isRefreshable"),
92
+ "Is Effective Identity Required": v.get("isEffectiveIdentityRequired"),
93
+ "Is Effective Identity Roles Required": v.get(
94
+ "isEffectiveIdentityRolesRequired"
95
+ ),
96
+ "Target Storage Mode": v.get("targetStorageMode"),
97
+ "Created Date": pd.to_datetime(v.get("createdDate")),
98
+ "Content Provider Type": v.get("contentProviderType"),
99
+ "Create Report Embed URL": v.get("createReportEmbedURL"),
100
+ "QnA Embed URL": v.get("qnaEmbedURL"),
101
+ "Upstream Datasets": v.get("upstreamDatasets", []),
102
+ "Users": v.get("users", []),
103
+ "Is In Place Sharing Enabled": v.get("isInPlaceSharingEnabled"),
104
+ "Workspace Id": v.get("workspaceId"),
105
+ "Auto Sync Read Only Replicas": v.get("queryScaleOutSettings", {}).get(
106
+ "autoSyncReadOnlyReplicas"
107
+ ),
108
+ "Max Read Only Replicas": v.get("queryScaleOutSettings", {}).get(
109
+ "maxReadOnlyReplicas"
110
+ ),
111
+ }
112
+ )
113
+
114
+ if rows:
115
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
116
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
117
+
118
+ return df
119
+
120
+
121
+ @log
122
+ def _resolve_dataset_id(dataset: str | UUID) -> str:
123
+ if _is_valid_uuid(dataset):
124
+ return dataset
125
+ else:
126
+ df = list_datasets()
127
+ df_filt = df[df["Dataset Name"] == dataset]
128
+ if df_filt.empty:
129
+ raise ValueError(f"{icons.red_dot} The '{dataset}' dataset does not exist.")
130
+ return df_filt["Dataset Id"].iloc[0]
131
+
132
+
133
+ @log
134
+ def list_dataset_users(dataset: str | UUID) -> pd.DataFrame:
135
+ """
136
+ Shows a list of users that have access to the specified dataset.
137
+
138
+ This is a wrapper function for the following API: `Admin - Datasets GetDatasetUsersAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/datasets-get-dataset-users-as-admin>`_.
139
+
140
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
141
+
142
+ Parameters
143
+ ----------
144
+ dataset : str | uuid.UUID
145
+ The name or ID of the dataset.
146
+
147
+ Returns
148
+ -------
149
+ pandas.DataFrame
150
+ A pandas dataframe showing a list of users that have access to the specified dataset.
151
+ """
152
+
153
+ dataset_id = _resolve_dataset_id(dataset)
154
+
155
+ columns = {
156
+ "User Name": "string",
157
+ "Email Address": "string",
158
+ "Dataset User Access Right": "string",
159
+ "Identifier": "string",
160
+ "Graph Id": "string",
161
+ "Principal Type": "string",
162
+ }
163
+
164
+ df = _create_dataframe(columns=columns)
165
+
166
+ url = f"/v1.0/myorg/admin/datasets/{dataset_id}/users"
167
+ response = _base_api(request=url, client="fabric_sp")
168
+
169
+ rows = []
170
+ for v in response.json().get("value", []):
171
+ rows.append(
172
+ {
173
+ "User Name": v.get("displayName"),
174
+ "Email Address": v.get("emailAddress"),
175
+ "Dataset User Access Right": v.get("datasetUserAccessRight"),
176
+ "Identifier": v.get("identifier"),
177
+ "Graph Id": v.get("graphId"),
178
+ "Principal Type": v.get("principalType"),
179
+ }
180
+ )
181
+
182
+ if rows:
183
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
184
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
185
+
186
+ return df
@@ -0,0 +1,522 @@
1
+ from typing import Optional, List
2
+ import sempy_labs._icons as icons
3
+ import pandas as pd
4
+ from uuid import UUID
5
+ from sempy_labs.admin._basic_functions import list_workspaces
6
+ from sempy_labs._helper_functions import (
7
+ _base_api,
8
+ _create_dataframe,
9
+ _is_valid_uuid,
10
+ )
11
+ from sempy._utils._log import log
12
+
13
+
14
+ @log
15
+ def resolve_domain_id(domain: Optional[str | UUID] = None, **kwargs) -> UUID:
16
+ """
17
+ Obtains the domain Id for a given domain name.
18
+
19
+ Parameters
20
+ ----------
21
+ domain_name : str | uuid.UUID
22
+ The domain name or ID
23
+
24
+ Returns
25
+ -------
26
+ uuid.UUID
27
+ The domain Id.
28
+ """
29
+
30
+ if "domain_name" in kwargs:
31
+ domain = kwargs["domain_name"]
32
+ print(
33
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
34
+ )
35
+
36
+ if domain is None:
37
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
38
+
39
+ if _is_valid_uuid(domain):
40
+ return domain
41
+
42
+ dfL = list_domains()
43
+ dfL_filt = dfL[dfL["Domain Name"] == domain]
44
+ if dfL_filt.empty:
45
+ raise ValueError(f"{icons.red_dot} '{domain}' is not a valid domain name.")
46
+
47
+ return dfL_filt["Domain ID"].iloc[0]
48
+
49
+
50
+ @log
51
+ def resolve_domain_name(domain: Optional[str | UUID], **kwargs) -> UUID:
52
+ """
53
+ Obtains the domain name for a given domain ID.
54
+
55
+ Parameters
56
+ ----------
57
+ domain : str | uuid.UUID
58
+ The domain name or ID
59
+
60
+ Returns
61
+ -------
62
+ str
63
+ The domain Name.
64
+ """
65
+
66
+ if "domain_name" in kwargs:
67
+ domain = kwargs["domain_name"]
68
+ print(
69
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
70
+ )
71
+
72
+ if domain is None:
73
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
74
+
75
+ if not _is_valid_uuid(domain):
76
+ return domain
77
+
78
+ dfL = list_domains()
79
+ dfL_filt = dfL[dfL["Domain ID"] == domain]
80
+ if dfL_filt.empty:
81
+ raise ValueError(f"{icons.red_dot} '{domain}' is not a valid domain name.")
82
+
83
+ return dfL_filt["Domain Name"].iloc[0]
84
+
85
+
86
+ @log
87
+ def list_domains(non_empty_only: bool = False) -> pd.DataFrame:
88
+ """
89
+ Shows a list of domains.
90
+
91
+ This is a wrapper function for the following API: `Domains - List Domains <https://learn.microsoft.com/rest/api/fabric/admin/domains/list-domains>`_.
92
+
93
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
94
+
95
+ Parameters
96
+ ----------
97
+ non_empty_only : bool, default=False
98
+ When True, only return domains that have at least one workspace containing an item.
99
+ Defaults to False.
100
+
101
+ Returns
102
+ -------
103
+ pandas.DataFrame
104
+ A pandas dataframe showing a list of the domains.
105
+ """
106
+
107
+ columns = {
108
+ "Domain ID": "string",
109
+ "Domain Name": "string",
110
+ "Description": "string",
111
+ "Parent Domain ID": "string",
112
+ "Contributors Scope": "string",
113
+ }
114
+ df = _create_dataframe(columns=columns)
115
+
116
+ url = "/v1/admin/domains"
117
+ if non_empty_only:
118
+ url = f"{url}?nonEmptyOnly=True"
119
+
120
+ response = _base_api(request=url, client="fabric_sp")
121
+
122
+ rows = []
123
+ for v in response.json().get("domains", []):
124
+ rows.append(
125
+ {
126
+ "Domain ID": v.get("id"),
127
+ "Domain Name": v.get("displayName"),
128
+ "Description": v.get("description"),
129
+ "Parent Domain ID": v.get("parentDomainId"),
130
+ "Contributors Scope": v.get("contributorsScope"),
131
+ }
132
+ )
133
+
134
+ if rows:
135
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
136
+
137
+ return df
138
+
139
+
140
+ @log
141
+ def list_domain_workspaces(domain: Optional[str] = None, **kwargs) -> pd.DataFrame:
142
+ """
143
+ Shows a list of workspaces within the domain.
144
+
145
+ This is a wrapper function for the following API: `Domains - List Domain Workspaces <https://learn.microsoft.com/rest/api/fabric/admin/domains/list-domain-workspaces>`_.
146
+
147
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
148
+
149
+ Parameters
150
+ ----------
151
+ domain : str | uuid.UUID
152
+ The domain name or ID.
153
+
154
+ Returns
155
+ -------
156
+ pandas.DataFrame
157
+ A pandas dataframe showing a list of workspaces within the domain.
158
+ """
159
+
160
+ if "domain_name" in kwargs:
161
+ domain = kwargs["domain_name"]
162
+ print(
163
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
164
+ )
165
+
166
+ if domain is None:
167
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
168
+
169
+ domain_id = resolve_domain_id(domain)
170
+
171
+ columns = {
172
+ "Workspace ID": "string",
173
+ "Workspace Name": "string",
174
+ }
175
+ df = _create_dataframe(columns=columns)
176
+
177
+ response = _base_api(
178
+ request=f"/v1/admin/domains/{domain_id}/workspaces", client="fabric_sp"
179
+ )
180
+
181
+ rows = []
182
+ for v in response.json().get("value", []):
183
+ rows.append(
184
+ {
185
+ "Workspace ID": v.get("id"),
186
+ "Workspace Name": v.get("displayName"),
187
+ }
188
+ )
189
+
190
+ if rows:
191
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
192
+
193
+ return df
194
+
195
+
196
+ @log
197
+ def create_domain(
198
+ domain_name: str,
199
+ description: Optional[str] = None,
200
+ parent_domain: Optional[str | UUID] = None,
201
+ **kwargs,
202
+ ):
203
+ """
204
+ Creates a new domain.
205
+
206
+ This is a wrapper function for the following API: `Domains - Create Domain <https://learn.microsoft.com/rest/api/fabric/admin/domains/create-domain>`_.
207
+
208
+ Parameters
209
+ ----------
210
+ domain_name : str
211
+ The domain name.
212
+ description : str, default=None
213
+ The domain description.
214
+ parent_domain : str | uuid.UUID, default=None
215
+ The parent domain name or ID.
216
+ """
217
+
218
+ if "parent_domain_name" in kwargs:
219
+ parent_domain = kwargs["parent_domain_name"]
220
+ print(
221
+ f"{icons.warning} The 'parent_domain_name' parameter is deprecated. Please use 'parent_domain' instead."
222
+ )
223
+
224
+ if parent_domain is not None:
225
+ parent_domain_id = resolve_domain_id(domain=parent_domain)
226
+
227
+ payload = {}
228
+ payload["displayName"] = domain_name
229
+ if description is not None:
230
+ payload["description"] = description
231
+ if parent_domain is not None:
232
+ payload["parentDomainId"] = parent_domain_id
233
+
234
+ _base_api(
235
+ request="/v1/admin/domains", method="post", payload=payload, status_codes=201
236
+ )
237
+
238
+ print(f"{icons.green_dot} The '{domain_name}' domain has been created.")
239
+
240
+
241
+ @log
242
+ def delete_domain(domain: Optional[str | UUID], **kwargs):
243
+ """
244
+ Deletes a domain.
245
+
246
+ This is a wrapper function for the following API: `Domains - Delete Domain <https://learn.microsoft.com/rest/api/fabric/admin/domains/delete-domain>`_.
247
+
248
+ Parameters
249
+ ----------
250
+ domain : str | uuid.UUID
251
+ The domain name or ID.
252
+ """
253
+
254
+ if "domain_name" in kwargs:
255
+ domain = kwargs["domain_name"]
256
+ print(
257
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
258
+ )
259
+
260
+ if domain is None:
261
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
262
+
263
+ domain_id = resolve_domain_id(domain)
264
+ _base_api(request=f"/v1/admin/domains/{domain_id}", method="delete")
265
+
266
+ print(f"{icons.green_dot} The '{domain}' domain has been deleted.")
267
+
268
+
269
+ @log
270
+ def update_domain(
271
+ domain: Optional[str | UUID] = None,
272
+ description: Optional[str] = None,
273
+ contributors_scope: Optional[str] = None,
274
+ **kwargs,
275
+ ):
276
+ """
277
+ Updates a domain's properties.
278
+
279
+ This is a wrapper function for the following API: `Domains - Update Domain <https://learn.microsoft.com/rest/api/fabric/admin/domains/update-domain>`_.
280
+
281
+ Parameters
282
+ ----------
283
+ domain : str | uuid.UUID
284
+ The domain name or ID.
285
+ description : str, default=None
286
+ The domain description.
287
+ contributors_scope : str, default=None
288
+ The domain `contributor scope <https://learn.microsoft.com/rest/api/fabric/admin/domains/update-domain?tabs=HTTP#contributorsscopetype>`_.
289
+ """
290
+
291
+ if "domain_name" in kwargs:
292
+ domain = kwargs["domain_name"]
293
+ print(
294
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
295
+ )
296
+
297
+ if domain is None:
298
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
299
+ contributors_scopes = ["AdminsOnly", "AllTenant", "SpecificUsersAndGroups"]
300
+
301
+ if contributors_scope not in contributors_scopes:
302
+ raise ValueError(
303
+ f"{icons.red_dot} Invalid contributors scope. Valid options: {contributors_scopes}."
304
+ )
305
+
306
+ domain_id = resolve_domain_id(domain)
307
+ domain_name = resolve_domain_name(domain)
308
+
309
+ payload = {}
310
+ payload["displayName"] = domain_name
311
+
312
+ if description is not None:
313
+ payload["description"] = description
314
+ if contributors_scope is not None:
315
+ payload["contributorsScope"] = contributors_scope
316
+
317
+ _base_api(request=f"/v1/admin/domains/{domain_id}", method="patch", payload=payload)
318
+
319
+ print(f"{icons.green_dot} The '{domain_name}' domain has been updated.")
320
+
321
+
322
+ @log
323
+ def assign_domain_workspaces_by_capacities(
324
+ domain: str | UUID,
325
+ capacity_names: str | List[str],
326
+ **kwargs,
327
+ ):
328
+ """
329
+ Assigns all workspaces that reside on the specified capacities to the specified domain.
330
+
331
+ This is a wrapper function for the following API: `Domains - Assign Domain Workspaces By Capacities <https://learn.microsoft.com/rest/api/fabric/admin/domains/assign-domain-workspaces-by-capacities>`_.
332
+
333
+ Parameters
334
+ ----------
335
+ domain : str | uuid.UUID
336
+ The domain name or ID.
337
+ capacity_names : str | List[str]
338
+ The capacity names.
339
+ """
340
+
341
+ from sempy_labs.admin._capacities import list_capacities
342
+
343
+ if "domain_name" in kwargs:
344
+ domain = kwargs["domain_name"]
345
+ print(
346
+ f"{icons.warning} The 'domain_name' parameter is deprecated. Please use 'domain' instead."
347
+ )
348
+
349
+ if domain is None:
350
+ raise ValueError(f"{icons.red_dot} Please provide a domain.")
351
+ domain_id = resolve_domain_id(domain)
352
+
353
+ if isinstance(capacity_names, str):
354
+ capacity_names = [capacity_names]
355
+
356
+ dfC = list_capacities()
357
+
358
+ # Check for invalid capacities
359
+ invalid_capacities = [
360
+ name for name in capacity_names if name not in dfC["Display Name"].values
361
+ ]
362
+
363
+ if len(invalid_capacities) == 1:
364
+ raise ValueError(
365
+ f"{icons.red_dot} The {invalid_capacities} capacity is not valid."
366
+ )
367
+ elif len(invalid_capacities) > 1:
368
+ raise ValueError(
369
+ f"{icons.red_dot} The {invalid_capacities} capacities are not valid."
370
+ )
371
+
372
+ # Get list of capacity Ids for the payload
373
+ dfC_filt = dfC[dfC["Display Name"].isin(capacity_names)]
374
+ capacity_list = list(dfC_filt["Id"].str.upper())
375
+
376
+ payload = {"capacitiesIds": capacity_list}
377
+
378
+ _base_api(
379
+ request=f"/v1/admin/domains/{domain_id}/assignWorkspacesByCapacities",
380
+ method="post",
381
+ payload=payload,
382
+ lro_return_status_code=True,
383
+ status_codes=202,
384
+ )
385
+
386
+ print(
387
+ f"{icons.green_dot} The workspaces in the {capacity_names} capacities have been assigned to the '{domain}' domain."
388
+ )
389
+
390
+
391
+ @log
392
+ def assign_domain_workspaces(domain: str | UUID, workspace_names: str | List[str]):
393
+ """
394
+ Assigns workspaces to the specified domain by workspace.
395
+
396
+ This is a wrapper function for the following API: `Domains - Assign Domain Workspaces By Ids <https://learn.microsoft.com/rest/api/fabric/admin/domains/assign-domain-workspaces-by-ids>`_.
397
+
398
+ Parameters
399
+ ----------
400
+ domain : str | uuid.UUID
401
+ The domain name or ID.
402
+ workspace_names : str | List[str]
403
+ The Fabric workspace(s).
404
+ """
405
+
406
+ domain_id = resolve_domain_id(domain)
407
+
408
+ if isinstance(workspace_names, str):
409
+ workspace_names = [workspace_names]
410
+
411
+ dfW = list_workspaces()
412
+
413
+ # Check for invalid capacities
414
+ invalid_workspaces = [
415
+ name for name in workspace_names if name not in dfW["Name"].values
416
+ ]
417
+
418
+ if len(invalid_workspaces) == 1:
419
+ raise ValueError(
420
+ f"{icons.red_dot} The {invalid_workspaces} workspace is not valid."
421
+ )
422
+ elif len(invalid_workspaces) > 1:
423
+ raise ValueError(
424
+ f"{icons.red_dot} The {invalid_workspaces} workspaces are not valid."
425
+ )
426
+
427
+ dfW_filt = dfW[dfW["Name"].isin(workspace_names)]
428
+ workspace_list = list(dfW_filt["Id"])
429
+
430
+ payload = {"workspacesIds": workspace_list}
431
+
432
+ _base_api(
433
+ request=f"/v1/admin/domains/{domain_id}/assignWorkspaces",
434
+ method="post",
435
+ payload=payload,
436
+ )
437
+
438
+ print(
439
+ f"{icons.green_dot} The {workspace_names} workspaces have been assigned to the '{domain}' domain."
440
+ )
441
+
442
+
443
+ @log
444
+ def unassign_all_domain_workspaces(domain: str | UUID):
445
+ """
446
+ Unassigns all workspaces from the specified domain.
447
+
448
+ This is a wrapper function for the following API: `Domains - Unassign All Domain Workspaces <https://learn.microsoft.com/rest/api/fabric/admin/domains/unassign-all-domain-workspaces>`_.
449
+
450
+ Parameters
451
+ ----------
452
+ domain : str | uuid.UUID
453
+ The domain name or ID.
454
+ """
455
+
456
+ domain_id = resolve_domain_id(domain)
457
+
458
+ _base_api(
459
+ request=f"/v1/admin/domains/{domain_id}/unassignAllWorkspaces",
460
+ method="post",
461
+ lro_return_status_code=True,
462
+ status_codes=200,
463
+ )
464
+
465
+ print(
466
+ f"{icons.green_dot} All workspaces assigned to the '{domain}' domain have been unassigned."
467
+ )
468
+
469
+
470
+ @log
471
+ def unassign_domain_workspaces(
472
+ domain: str | UUID,
473
+ workspace_names: str | List[str],
474
+ ):
475
+ """
476
+ Unassigns workspaces from the specified domain by workspace.
477
+
478
+ This is a wrapper function for the following API: `Domains - Unassign Domain Workspaces By Ids <https://learn.microsoft.com/rest/api/fabric/admin/domains/unassign-domain-workspaces-by-ids>`_.
479
+
480
+ Parameters
481
+ ----------
482
+ domain : str | uuid.UUID
483
+ The domain name or ID.
484
+ workspace_names : str | List[str]
485
+ The Fabric workspace(s).
486
+ """
487
+
488
+ domain_id = resolve_domain_id(domain)
489
+
490
+ if isinstance(workspace_names, str):
491
+ workspace_names = [workspace_names]
492
+
493
+ dfW = list_workspaces()
494
+
495
+ # Check for invalid capacities
496
+ invalid_workspaces = [
497
+ name for name in workspace_names if name not in dfW["Name"].values
498
+ ]
499
+
500
+ if len(invalid_workspaces) == 1:
501
+ raise ValueError(
502
+ f"{icons.red_dot} The {invalid_workspaces} workspace is not valid."
503
+ )
504
+ elif len(invalid_workspaces) > 1:
505
+ raise ValueError(
506
+ f"{icons.red_dot} The {invalid_workspaces} workspaces are not valid."
507
+ )
508
+
509
+ dfW_filt = dfW[dfW["Name"].isin(workspace_names)]
510
+ workspace_list = list(dfW_filt["Id"])
511
+
512
+ payload = {"workspacesIds": workspace_list}
513
+
514
+ _base_api(
515
+ request=f"/v1/admin/domains/{domain_id}/unassignWorkspaces",
516
+ method="post",
517
+ payload=payload,
518
+ )
519
+
520
+ print(
521
+ f"{icons.green_dot} The {workspace_names} workspaces assigned to the '{domain}' domain have been unassigned."
522
+ )