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,463 @@
1
+ from typing import Optional, List, Union, Tuple
2
+ from uuid import UUID
3
+ import sempy_labs._icons as icons
4
+ from sempy_labs._helper_functions import (
5
+ _is_valid_uuid,
6
+ _build_url,
7
+ _base_api,
8
+ _create_dataframe,
9
+ )
10
+ from sempy._utils._log import log
11
+ import numpy as np
12
+ import pandas as pd
13
+ from dateutil.parser import parse as dtparser
14
+
15
+
16
+ @log
17
+ def list_workspaces(
18
+ capacity: Optional[str | UUID] = None,
19
+ workspace: Optional[str | UUID] = None,
20
+ workspace_state: Optional[str] = None,
21
+ workspace_type: Optional[str] = None,
22
+ **kwargs,
23
+ ) -> pd.DataFrame:
24
+ """
25
+ Lists workspaces for the organization. This function is the admin version of list_workspaces.
26
+
27
+ This is a wrapper function for the following API: `Workspaces - List Workspaces - REST API (Admin) <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces>`_.
28
+
29
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
30
+
31
+ Parameters
32
+ ----------
33
+ capacity : str | uuid.UUID, default=None
34
+ Returns only the workspaces in the specified Capacity.
35
+ workspace : str | uuid.UUID, default=None
36
+ Returns the workspace with the specific name.
37
+ workspace_state : str, default=None
38
+ Return only the workspace with the requested state. You can find the possible states in `Workspace States <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces?tabs=HTTP#workspacestate>`_.
39
+ workspace_type : str, default=None
40
+ Return only the workspace of the specific type. You can find the possible types in `Workspace Types <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces?tabs=HTTP#workspacetype>`_.
41
+
42
+ Returns
43
+ -------
44
+ pandas.DataFrame
45
+ A pandas dataframe showing a list of workspaces for the organization.
46
+ """
47
+
48
+ from sempy_labs.admin._capacities import _resolve_capacity_name_and_id
49
+
50
+ if "filter" in kwargs:
51
+ print(
52
+ "The 'filter' parameter has been deprecated. Please remove this parameter from the function going forward."
53
+ )
54
+ del kwargs["filter"]
55
+
56
+ if "top" in kwargs:
57
+ print(
58
+ "The 'top' parameter has been deprecated. Please remove this parameter from the function going forward."
59
+ )
60
+ del kwargs["top"]
61
+
62
+ if "skip" in kwargs:
63
+ print(
64
+ "The 'skip' parameter has been deprecated. Please remove this parameter from the function going forward."
65
+ )
66
+ del kwargs["skip"]
67
+
68
+ columns = {
69
+ "Id": "string",
70
+ "Name": "string",
71
+ "State": "string",
72
+ "Type": "string",
73
+ "Capacity Id": "string",
74
+ }
75
+ df = _create_dataframe(columns=columns)
76
+
77
+ url = "/v1/admin/workspaces"
78
+ params = {}
79
+
80
+ if capacity is not None:
81
+ params["capacityId"] = _resolve_capacity_name_and_id(capacity)[1]
82
+
83
+ if workspace is not None and not _is_valid_uuid(workspace):
84
+ params["name"] = workspace
85
+
86
+ if workspace_state is not None:
87
+ params["state"] = workspace_state
88
+
89
+ if workspace_type is not None:
90
+ params["type"] = workspace_type
91
+
92
+ url = _build_url(url, params)
93
+
94
+ responses = _base_api(request=url, client="fabric_sp", uses_pagination=True)
95
+ workspaces = []
96
+
97
+ for r in responses:
98
+ workspaces = workspaces + r.get("workspaces", [])
99
+
100
+ if len(workspaces) > 0:
101
+ df = pd.DataFrame(workspaces)
102
+ df.rename(
103
+ columns={
104
+ "id": "Id",
105
+ "name": "Name",
106
+ "state": "State",
107
+ "type": "Type",
108
+ "capacityId": "Capacity Id",
109
+ },
110
+ inplace=True,
111
+ )
112
+
113
+ df["Capacity Id"] = df["Capacity Id"].str.lower()
114
+
115
+ if workspace is not None and _is_valid_uuid(workspace):
116
+ df = df[df["Id"] == workspace.lower()]
117
+
118
+ return df
119
+
120
+
121
+ @log
122
+ def assign_workspaces_to_capacity(
123
+ source_capacity: Optional[str | UUID] = None,
124
+ target_capacity: Optional[str | UUID] = None,
125
+ workspace: Optional[str | List[str] | UUID | List[UUID]] = None,
126
+ ):
127
+ """
128
+ Assigns a workspace to a capacity. This function is the admin version.
129
+
130
+ This is a wrapper function for the following API: `Admin - Capacities AssignWorkspacesToCapacity <https://learn.microsoft.com/rest/api/power-bi/admin/capacities-assign-workspaces-to-capacity>`_.
131
+
132
+ Parameters
133
+ ----------
134
+ source_capacity : str | uuid.UUID, default=None
135
+ The name of the source capacity. If the Workspace is not specified, this is parameter mandatory.
136
+ target_capacity : str | uuid.UUID, default=None
137
+ The name of the target capacity.
138
+ workspace : str | List[str] | uuid.UUID | List[uuid.UUID], default=None
139
+ The name or ID of the workspace(s).
140
+ Defaults to None which resolves to migrating all workspaces within the source capacity to the target capacity.
141
+ """
142
+ from sempy_labs.admin._capacities import _resolve_capacity_name_and_id
143
+
144
+ if target_capacity is None:
145
+ raise ValueError(
146
+ f"{icons.red_dot} The parameter 'target_capacity' is mandatory."
147
+ )
148
+
149
+ if source_capacity is None and workspace is None:
150
+ raise ValueError(
151
+ f"{icons.red_dot} The parameters 'source_capacity' or 'workspace' needs to be specified."
152
+ )
153
+
154
+ if workspace is None:
155
+ source_capacity_id = _resolve_capacity_name_and_id(source_capacity)[1]
156
+ dfW = list_workspaces(capacity=source_capacity_id)
157
+ workspaces = dfW["Id"].tolist()
158
+ else:
159
+ if isinstance(workspace, str) or isinstance(workspace, UUID):
160
+ workspace = [workspace]
161
+ if source_capacity is None:
162
+ dfW = list_workspaces()
163
+ else:
164
+ source_capacity_id = _resolve_capacity_name_and_id(source_capacity)[1]
165
+ dfW = list_workspaces(capacity=source_capacity_id)
166
+
167
+ # Extract names and IDs that are mapped in dfW
168
+ workspaces_names = dfW[dfW["Name"].isin(workspace)]["Name"].tolist()
169
+ workspaces_ids = dfW[dfW["Id"].isin(workspace)]["Id"].tolist()
170
+
171
+ # Combine IDs into the final workspaces list
172
+ workspaces = workspaces_ids + dfW[dfW["Name"].isin(workspace)]["Id"].tolist()
173
+
174
+ # Identify unmapped workspaces
175
+ unmapped_workspaces = [
176
+ item
177
+ for item in workspace
178
+ if item not in workspaces_names and item not in workspaces_ids
179
+ ]
180
+
181
+ if len(workspace) != len(workspaces):
182
+ raise ValueError(
183
+ f"{icons.red_dot} The following workspaces are invalid or not found in source capacity: {unmapped_workspaces}."
184
+ )
185
+
186
+ target_capacity_id = _resolve_capacity_name_and_id(target_capacity)[1]
187
+
188
+ workspaces = np.array(workspaces)
189
+ batch_size = 999
190
+ for i in range(0, len(workspaces), batch_size):
191
+ batch = workspaces[i : i + batch_size].tolist()
192
+ payload = {
193
+ "capacityMigrationAssignments": [
194
+ {
195
+ "targetCapacityObjectId": target_capacity_id.upper(),
196
+ "workspacesToAssign": batch,
197
+ }
198
+ ]
199
+ }
200
+
201
+ _base_api(
202
+ request="/v1.0/myorg/admin/capacities/AssignWorkspaces",
203
+ method="post",
204
+ payload=payload,
205
+ )
206
+
207
+ print(
208
+ f"{icons.green_dot} The workspaces have been assigned to the '{target_capacity}' capacity. A total of {len(workspaces)} were moved."
209
+ )
210
+
211
+
212
+ @log
213
+ def unassign_workspaces_from_capacity(
214
+ workspaces: str | List[str] | UUID | List[UUID],
215
+ ):
216
+ """
217
+ Unassigns workspace(s) from their capacity.
218
+
219
+ This is a wrapper function for the following API: `Admin - Capacities UnassignWorkspacesFromCapacity <https://learn.microsoft.com/rest/api/power-bi/admin/capacities-unassign-workspaces-from-capacity>`_.
220
+
221
+ Parameters
222
+ ----------
223
+ workspaces : str | List[str] | uuid.UUID | List[uuid.UUID]
224
+ The workspace name(s) or ID(s).
225
+ """
226
+ if isinstance(workspaces, str):
227
+ workspaces = [workspaces]
228
+
229
+ dfW = list_workspaces()
230
+ workspacesIds = dfW[dfW["Name"].isin(workspaces)]["Id"].tolist()
231
+ workspacesIds = workspacesIds + dfW[dfW["Id"].isin(workspaces)]["Id"].tolist()
232
+
233
+ if len(workspacesIds) != len(workspaces):
234
+ raise ValueError(
235
+ f"{icons.red_dot} Some of the workspaces provided are not valid."
236
+ )
237
+
238
+ payload = {"workspacesToUnassign": workspacesIds}
239
+ _base_api(
240
+ request="/v1.0/myorg/admin/capacities/UnassignWorkspaces",
241
+ method="post",
242
+ payload=payload,
243
+ )
244
+
245
+ print(
246
+ f"{icons.green_dot} A total of {len(workspacesIds)} workspaces have been unassigned."
247
+ )
248
+
249
+
250
+ @log
251
+ def list_modified_workspaces(
252
+ modified_since: Optional[str] = None,
253
+ exclude_inactive_workspaces: Optional[bool] = False,
254
+ exclude_personal_workspaces: Optional[bool] = False,
255
+ ) -> pd.DataFrame:
256
+ """
257
+ Gets a list of workspace IDs in the organization.
258
+
259
+ This is a wrapper function for the following API: `Admin - WorkspaceInfo GetModifiedWorkspaces <https://learn.microsoft.com/rest/api/power-bi/admin/workspace-info-get-modified-workspaces>`_.
260
+
261
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
262
+
263
+ Parameters
264
+ ----------
265
+ modified_since : str, default=None
266
+ Last modified date (must be in ISO compliant UTC format). Example: "2024-11-02T05:51:30" or "2024-11-02T05:51:30.0000000Z".
267
+ exclude_inactive_workspaces : bool, default=False
268
+ Whether to exclude inactive workspaces.
269
+ exclude_personal_workspaces : bool, default=False
270
+ Whether to exclude personal workspaces.
271
+
272
+ Returns
273
+ -------
274
+ pandas.DataFrame
275
+ A pandas dataframe showing a list of workspace IDs in the organization.
276
+ """
277
+ params = {}
278
+ url = "/v1.0/myorg/admin/workspaces/modified"
279
+
280
+ if modified_since is not None:
281
+ modified_since_dt = dtparser(modified_since)
282
+ params["modifiedSince"] = (
283
+ f"{modified_since_dt.isoformat(timespec='microseconds')}0Z"
284
+ )
285
+
286
+ if exclude_inactive_workspaces is not None:
287
+ params["excludeInActiveWorkspaces"] = exclude_inactive_workspaces
288
+
289
+ if exclude_personal_workspaces is not None:
290
+ params["excludePersonalWorkspaces"] = exclude_personal_workspaces
291
+
292
+ url = _build_url(url, params)
293
+ response = _base_api(request=url, client="fabric_sp")
294
+
295
+ df = pd.DataFrame(response.json()).rename(columns={"id": "Workspace Id"})
296
+
297
+ return df
298
+
299
+
300
+ @log
301
+ def list_workspace_access_details(
302
+ workspace: Optional[Union[str, UUID]] = None,
303
+ ) -> pd.DataFrame:
304
+ """
305
+ Shows a list of users (including groups and Service Principals) that have access to the specified workspace.
306
+
307
+ This is a wrapper function for the following API: `Workspaces - List Workspace Access Details <https://learn.microsoft.com/rest/api/fabric/admin/workspaces/list-workspace-access-details>`_.
308
+
309
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
310
+
311
+ Parameters
312
+ ----------
313
+ workspace : str | uuid.UUID, default=None
314
+ The workspace name or ID.
315
+ Defaults to None which resolves to the workspace of the attached lakehouse
316
+ or if no lakehouse attached, resolves to the workspace of the notebook.
317
+
318
+ Returns
319
+ -------
320
+ pandas.DataFrame
321
+ A pandas dataframe showing a list of users (including groups and Service Principals) that have access to the specified workspace.
322
+ """
323
+ (workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
324
+
325
+ columns = {
326
+ "User Id": "string",
327
+ "User Name": "string",
328
+ "User Type": "string",
329
+ "Workspace Name": "string",
330
+ "Workspace Id": "string",
331
+ "Workspace Role": "string",
332
+ }
333
+ df = _create_dataframe(columns=columns)
334
+
335
+ response = _base_api(
336
+ request=f"/v1/admin/workspaces/{workspace_id}/users", client="fabric_sp"
337
+ )
338
+
339
+ rows = []
340
+ for v in response.json().get("accessDetails", []):
341
+ rows.append(
342
+ {
343
+ "User Id": v.get("principal", {}).get("id"),
344
+ "User Name": v.get("principal", {}).get("displayName"),
345
+ "User Type": v.get("principal", {}).get("type"),
346
+ "Workspace Name": workspace_name,
347
+ "Workspace Id": workspace_id,
348
+ "Workspace Role": v.get("workspaceAccessDetails", {}).get(
349
+ "workspaceRole"
350
+ ),
351
+ }
352
+ )
353
+
354
+ if rows:
355
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
356
+
357
+ return df
358
+
359
+
360
+ @log
361
+ def _resolve_workspace_name(workspace_id: Optional[UUID] = None) -> str:
362
+ from sempy_labs._helper_functions import _get_fabric_context_setting
363
+ from sempy.fabric.exceptions import FabricHTTPException
364
+
365
+ if workspace_id is None:
366
+ workspace_id = _get_fabric_context_setting(name="trident.workspace.id")
367
+
368
+ try:
369
+ workspace_name = (
370
+ _base_api(
371
+ request=f"/v1/admin/workspaces/{workspace_id}", client="fabric_sp"
372
+ )
373
+ .json()
374
+ .get("name")
375
+ )
376
+ except FabricHTTPException:
377
+ raise ValueError(
378
+ f"{icons.red_dot} The '{workspace_id}' workspace was not found."
379
+ )
380
+ return workspace_name
381
+
382
+
383
+ @log
384
+ def _resolve_workspace_name_and_id(
385
+ workspace: str | UUID,
386
+ ) -> Tuple[str, UUID]:
387
+
388
+ from sempy_labs._helper_functions import _get_fabric_context_setting
389
+
390
+ if workspace is None:
391
+ workspace_id = _get_fabric_context_setting(name="trident.workspace.id")
392
+ workspace_name = _resolve_workspace_name(workspace_id)
393
+ elif _is_valid_uuid(workspace):
394
+ workspace_id = workspace
395
+ workspace_name = _resolve_workspace_name(workspace_id)
396
+ else:
397
+ dfW = list_workspaces(workspace=workspace)
398
+ if not dfW.empty:
399
+ workspace_name = dfW["Name"].iloc[0]
400
+ workspace_id = dfW["Id"].iloc[0]
401
+ else:
402
+ raise ValueError(
403
+ f"{icons.red_dot} The '{workspace}' workspace was not found."
404
+ )
405
+
406
+ return workspace_name, workspace_id
407
+
408
+
409
+ @log
410
+ def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
411
+ """
412
+ Shows a list of users that have access to the specified workspace.
413
+
414
+ This is a wrapper function for the following API: `Admin - Groups GetGroupUsersAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/groups-get-group-users-as-admin>`_.
415
+
416
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
417
+
418
+ Parameters
419
+ ----------
420
+ workspace : str | uuid.UUID, default=None
421
+ The workspace name or ID.
422
+ Defaults to None which resolves to the workspace of the attached lakehouse
423
+ or if no lakehouse attached, resolves to the workspace of the notebook.
424
+
425
+ Returns
426
+ -------
427
+ pandas.DataFrame
428
+ A pandas dataframe showing a list of users that have access to the specified workspace.
429
+ """
430
+
431
+ (workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
432
+
433
+ columns = {
434
+ "User Name": "string",
435
+ "Email Address": "string",
436
+ "Group User Access Right": "string",
437
+ "Identifier": "string",
438
+ "Graph Id": "string",
439
+ "Principal Type": "string",
440
+ }
441
+
442
+ df = _create_dataframe(columns=columns)
443
+
444
+ url = f"/v1.0/myorg/admin/groups/{workspace_id}/users"
445
+ response = _base_api(request=url, client="fabric_sp")
446
+
447
+ rows = []
448
+ for v in response.json().get("value", []):
449
+ rows.append(
450
+ {
451
+ "User Name": v.get("displayName"),
452
+ "Email Address": v.get("emailAddress"),
453
+ "Group User Access Right": v.get("groupUserAccessRight"),
454
+ "Identifier": v.get("identifier"),
455
+ "Graph Id": v.get("graphId"),
456
+ "Principal Type": v.get("principalType"),
457
+ }
458
+ )
459
+
460
+ if rows:
461
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
462
+
463
+ return df