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,149 @@
1
+ import pandas as pd
2
+ from uuid import UUID
3
+ from typing import Optional
4
+ from sempy._utils._log import log
5
+ from sempy_labs._helper_functions import (
6
+ _base_api,
7
+ _create_dataframe,
8
+ resolve_item_id,
9
+ resolve_workspace_id,
10
+ resolve_item_name_and_id,
11
+ resolve_workspace_name_and_id,
12
+ )
13
+ import sempy_labs._icons as icons
14
+
15
+
16
+ @log
17
+ def list_graph_models(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
18
+ """
19
+ Shows the graph models within a workspace.
20
+
21
+ This is a wrapper function for the following API: `Items - List Graph Models <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/list-graph-models>`_.
22
+
23
+ Parameters
24
+ ----------
25
+ workspace : str | uuid.UUID, default=None
26
+ The Fabric workspace name or ID.
27
+ Defaults to None which resolves to the workspace of the attached lakehouse
28
+ or if no lakehouse attached, resolves to the workspace of the notebook.
29
+
30
+ Returns
31
+ -------
32
+ pandas.DataFrame
33
+ A pandas dataframe showing the graph models within a workspace.
34
+ """
35
+
36
+ columns = {
37
+ "Graph Model Name": "string",
38
+ "Graph Model Id": "string",
39
+ "Description": "string",
40
+ "OneLake Root Path": "string",
41
+ }
42
+ df = _create_dataframe(columns=columns)
43
+
44
+ workspace_id = resolve_workspace_id(workspace)
45
+
46
+ responses = _base_api(
47
+ request=f"/v1/workspaces/{workspace_id}/GraphModels",
48
+ uses_pagination=True,
49
+ )
50
+
51
+ rows = []
52
+ for r in responses:
53
+ for v in r.get("value", []):
54
+ rows.append(
55
+ {
56
+ "Graph Model Name": v.get("displayName"),
57
+ "Graph Model Id": v.get("id"),
58
+ "Description": v.get("description"),
59
+ "OneLake Root Path": v.get("properties", {}).get("oneLakeRootPath"),
60
+ }
61
+ )
62
+
63
+ if rows:
64
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
65
+
66
+ return df
67
+
68
+
69
+ @log
70
+ def execute_query(
71
+ graph_model: str | UUID, query: str, workspace: Optional[str | UUID] = None
72
+ ) -> dict:
73
+ """
74
+ Executes a query on the specified graph model.
75
+
76
+ This is a wrapper function for the following API: `Items - ExecuteQuery <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/execute-query(preview)>`_.
77
+
78
+ Parameters
79
+ ----------
80
+ graph_model : str | uuid.UUID
81
+ The graph model name or ID.
82
+ query : str
83
+ The query string.
84
+ workspace : str | uuid.UUID, default=None
85
+ The Fabric workspace name or ID.
86
+ Defaults to None which resolves to the workspace of the attached lakehouse
87
+ or if no lakehouse attached, resolves to the workspace of the notebook.
88
+
89
+ Returns
90
+ -------
91
+ dict
92
+ The response from the API.
93
+ """
94
+
95
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
96
+ (item_name, item_id) = resolve_item_name_and_id(
97
+ item=graph_model, type="GraphModel", workspace=workspace_id
98
+ )
99
+
100
+ payload = {
101
+ "query": query,
102
+ }
103
+ response = _base_api(
104
+ request=f"/v1/workspaces/{workspace_id}/GraphModels/{item_id}/executeQuery?preview=True",
105
+ method="post",
106
+ payload=payload,
107
+ )
108
+
109
+ print(
110
+ f"{icons.green_dot} Executed query on Graph Model '{item_name}' in workspace '{workspace_name}' successfully."
111
+ )
112
+
113
+ return response.json()
114
+
115
+
116
+ @log
117
+ def get_queryable_graph_type(
118
+ graph_model: str | UUID, workspace: Optional[str | UUID] = None
119
+ ) -> dict:
120
+ """
121
+ Gets the current queryable graph type.
122
+
123
+ This is a wrapper function for the following API: `Items - GetQueryableGraphType <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/get-queryable-graph-type(preview)>`_.
124
+
125
+ Parameters
126
+ ----------
127
+ graph_model : str | uuid.UUID
128
+ The graph model name or ID.
129
+ workspace : str | uuid.UUID, default=None
130
+ The Fabric workspace name or ID.
131
+ Defaults to None which resolves to the workspace of the attached lakehouse
132
+ or if no lakehouse attached, resolves to the workspace of the notebook.
133
+
134
+ Returns
135
+ -------
136
+ dict
137
+ A dictionary showing the current queryable graph type.
138
+ """
139
+
140
+ workspace_id = resolve_workspace_id(workspace)
141
+ item_id = resolve_item_id(
142
+ item=graph_model, type="GraphModel", workspace=workspace_id
143
+ )
144
+
145
+ response = _base_api(
146
+ request=f"/v1/workspaces/{workspace_id}/GraphModels/{item_id}/getQueryableGraphType?preview=True"
147
+ )
148
+
149
+ return response.json()
@@ -0,0 +1,67 @@
1
+ from ._get_lakehouse_columns import (
2
+ get_lakehouse_columns,
3
+ )
4
+ from ._get_lakehouse_tables import (
5
+ get_lakehouse_tables,
6
+ )
7
+ from ._lakehouse import (
8
+ lakehouse_attached,
9
+ optimize_lakehouse_tables,
10
+ vacuum_lakehouse_tables,
11
+ run_table_maintenance,
12
+ list_lakehouses,
13
+ )
14
+ from ._shortcuts import (
15
+ # create_shortcut,
16
+ create_shortcut_onelake,
17
+ delete_shortcut,
18
+ reset_shortcut_cache,
19
+ list_shortcuts,
20
+ )
21
+ from ._blobs import (
22
+ recover_lakehouse_object,
23
+ list_blobs,
24
+ )
25
+ from ._livy_sessions import (
26
+ list_livy_sessions,
27
+ )
28
+ from ._helper import (
29
+ is_v_ordered,
30
+ delete_lakehouse,
31
+ update_lakehouse,
32
+ load_table,
33
+ )
34
+ from ._materialized_lake_views import (
35
+ refresh_materialized_lake_views,
36
+ )
37
+ from ._schemas import (
38
+ list_schemas,
39
+ schema_exists,
40
+ is_schema_enabled,
41
+ )
42
+
43
+ __all__ = [
44
+ "get_lakehouse_columns",
45
+ "get_lakehouse_tables",
46
+ "lakehouse_attached",
47
+ "optimize_lakehouse_tables",
48
+ # create_shortcut,
49
+ "create_shortcut_onelake",
50
+ "delete_shortcut",
51
+ "vacuum_lakehouse_tables",
52
+ "reset_shortcut_cache",
53
+ "run_table_maintenance",
54
+ "list_shortcuts",
55
+ "recover_lakehouse_object",
56
+ "list_blobs",
57
+ "list_livy_sessions",
58
+ "is_v_ordered",
59
+ "delete_lakehouse",
60
+ "update_lakehouse",
61
+ "load_table",
62
+ "refresh_materialized_lake_views",
63
+ "list_lakehouses",
64
+ "list_schemas",
65
+ "schema_exists",
66
+ "is_schema_enabled",
67
+ ]
@@ -0,0 +1,247 @@
1
+ from sempy_labs._helper_functions import (
2
+ resolve_workspace_id,
3
+ resolve_lakehouse_id,
4
+ _xml_to_dict,
5
+ _create_dataframe,
6
+ _update_dataframe_datatypes,
7
+ )
8
+ from sempy._utils._log import log
9
+ from uuid import UUID
10
+ from typing import Optional, List
11
+ import sempy_labs._icons as icons
12
+ import xml.etree.ElementTree as ET
13
+ import pandas as pd
14
+ from sempy.fabric.exceptions import FabricHTTPException
15
+
16
+
17
+ @log
18
+ def _request_blob_api(
19
+ request: str,
20
+ method: str = "get",
21
+ payload: Optional[dict] = None,
22
+ status_codes: int | List[int] = 200,
23
+ uses_pagination: bool = False,
24
+ ):
25
+
26
+ import requests
27
+ import notebookutils
28
+ from sempy.fabric.exceptions import FabricHTTPException
29
+
30
+ if isinstance(status_codes, int):
31
+ status_codes = [status_codes]
32
+
33
+ token = notebookutils.credentials.getToken("storage")
34
+
35
+ headers = {
36
+ "Authorization": f"Bearer {token}",
37
+ "Content-Type": "application/xml",
38
+ "x-ms-version": "2025-05-05",
39
+ }
40
+
41
+ base_url = "https://onelake.blob.fabric.microsoft.com/"
42
+ full_url = f"{base_url}{request}"
43
+ results = []
44
+
45
+ while True:
46
+ response = requests.request(
47
+ method.upper(),
48
+ full_url,
49
+ headers=headers,
50
+ data=payload if method.lower() != "get" else None,
51
+ )
52
+
53
+ if response.status_code not in status_codes:
54
+ raise FabricHTTPException(response)
55
+
56
+ if not uses_pagination:
57
+ return response
58
+
59
+ # Parse XML to find blobs and NextMarker
60
+ root = ET.fromstring(response.content)
61
+ results.append(root)
62
+
63
+ next_marker = root.findtext(".//NextMarker")
64
+ if not next_marker:
65
+ break # No more pages
66
+
67
+ # Append the marker to the original request (assuming query string format)
68
+ delimiter = "&" if "?" in request else "?"
69
+ full_url = f"{base_url}{request}{delimiter}marker={next_marker}"
70
+
71
+ return results
72
+
73
+
74
+ @log
75
+ def list_blobs(
76
+ lakehouse: Optional[str | UUID] = None,
77
+ workspace: Optional[str | UUID] = None,
78
+ container: Optional[str] = None,
79
+ ) -> pd.DataFrame:
80
+ """
81
+ Returns a list of blobs for a given lakehouse.
82
+
83
+ This function leverages the following API: `List Blobs <https://learn.microsoft.com/rest/api/storageservices/list-blobs?tabs=microsoft-entra-id>`_.
84
+
85
+ Parameters
86
+ ----------
87
+ lakehouse : str | uuid.UUID, default=None
88
+ The Fabric lakehouse name or ID.
89
+ Defaults to None which resolves to the lakehouse attached to the notebook.
90
+ workspace : str | uuid.UUID, default=None
91
+ The Fabric workspace name or ID used by the lakehouse.
92
+ Defaults to None which resolves to the workspace of the attached lakehouse
93
+ or if no lakehouse attached, resolves to the workspace of the notebook.
94
+ container : str, default=None
95
+ The container name to list blobs from. If None, lists all blobs in the lakehouse.
96
+ Valid values are "Tables" or "Files". If not specified, the function will list all blobs in the lakehouse.
97
+
98
+ Returns
99
+ -------
100
+ pandas.DataFrame
101
+ A pandas dataframe showing a list of blobs in the lakehouse.
102
+ """
103
+
104
+ workspace_id = resolve_workspace_id(workspace)
105
+ lakehouse_id = resolve_lakehouse_id(lakehouse, workspace_id)
106
+
107
+ if container is None:
108
+ path_prefix = f"{workspace_id}/{lakehouse_id}"
109
+ else:
110
+ if container not in ["Tables", "Files"]:
111
+ raise ValueError(
112
+ f"{icons.red_dot} Invalid container '{container}' within the file_path parameter. Expected 'Tables' or 'Files'."
113
+ )
114
+ path_prefix = f"{workspace_id}/{lakehouse_id}/{container}"
115
+
116
+ columns = {
117
+ "Blob Name": "str",
118
+ "Is Deleted": "bool",
119
+ "Deletion Id": "str",
120
+ "Creation Time": "datetime",
121
+ "Expiry Time": "datetime",
122
+ "Etag": "str",
123
+ "Resource Type": "str",
124
+ "Content Length": "int",
125
+ "Content Type": "str",
126
+ "Content Encoding": "str",
127
+ "Content Language": "str",
128
+ "Content CRC64": "str",
129
+ "Content MD5": "str",
130
+ "Cache Control": "str",
131
+ "Content Disposition": "str",
132
+ "Blob Type": "str",
133
+ "Access Tier": "str",
134
+ "Access Tier Inferred": "str",
135
+ "Server Encrypted": "bool",
136
+ "Deleted Time": "str",
137
+ "Remaining Retention Days": "str",
138
+ }
139
+
140
+ df = _create_dataframe(columns=columns)
141
+
142
+ url = f"{path_prefix}?restype=container&comp=list&include=deleted"
143
+
144
+ responses = _request_blob_api(
145
+ request=url,
146
+ uses_pagination=True,
147
+ )
148
+
149
+ rows = []
150
+ for root in responses:
151
+ response_json = _xml_to_dict(root)
152
+
153
+ blobs = (
154
+ response_json.get("EnumerationResults", {}).get("Blobs", {}).get("Blob", [])
155
+ )
156
+
157
+ if isinstance(blobs, dict):
158
+ blobs = [blobs]
159
+
160
+ for blob in blobs:
161
+ p = blob.get("Properties", {})
162
+ rows.append(
163
+ {
164
+ "Blob Name": blob.get("Name"),
165
+ "Is Deleted": blob.get("Deleted", False),
166
+ "Deletion Id": blob.get("DeletionId"),
167
+ "Creation Time": p.get("Creation-Time"),
168
+ "Expiry Time": p.get("Expiry-Time"),
169
+ "Etag": p.get("Etag"),
170
+ "Resource Type": p.get("ResourceType"),
171
+ "Content Length": p.get("Content-Length"),
172
+ "Content Type": p.get("Content-Type"),
173
+ "Content Encoding": p.get("Content-Encoding"),
174
+ "Content Language": p.get("Content-Language"),
175
+ "Content CRC64": p.get("Content-CRC64"),
176
+ "Content MD5": p.get("Content-MD5"),
177
+ "Cache Control": p.get("Cache-Control"),
178
+ "Content Disposition": p.get("Content-Disposition"),
179
+ "Blob Type": p.get("BlobType"),
180
+ "Access Tier": p.get("AccessTier"),
181
+ "Access Tier Inferred": p.get("AccessTierInferred"),
182
+ "Server Encrypted": p.get("ServerEncrypted"),
183
+ "Deleted Time": p.get("DeletedTime"),
184
+ "Remaining Retention Days": p.get("RemainingRetentionDays"),
185
+ }
186
+ )
187
+
188
+ if rows:
189
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
190
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
191
+
192
+ return df
193
+
194
+
195
+ @log
196
+ def recover_lakehouse_object(
197
+ file_path: str,
198
+ lakehouse: Optional[str | UUID] = None,
199
+ workspace: Optional[str | UUID] = None,
200
+ ):
201
+ """
202
+ Recovers an object (i.e. table, file, folder) in a lakehouse from a deleted state. Only `soft-deleted objects <https://learn.microsoft.com/fabric/onelake/onelake-disaster-recovery#soft-delete-for-onelake-files>`_ can be recovered (deleted for less than 7 days).
203
+
204
+ Parameters
205
+ ----------
206
+ file_path : str
207
+ The file path of the object to restore. For example: "Tables/my_delta_table".
208
+ lakehouse : str | uuid.UUID, default=None
209
+ The Fabric lakehouse name or ID.
210
+ Defaults to None which resolves to the lakehouse attached to the notebook.
211
+ workspace : str | uuid.UUID, default=None
212
+ The Fabric workspace name or ID used by the lakehouse.
213
+ Defaults to None which resolves to the workspace of the attached lakehouse
214
+ or if no lakehouse attached, resolves to the workspace of the notebook.
215
+ """
216
+
217
+ workspace_id = resolve_workspace_id(workspace)
218
+ lakehouse_id = resolve_lakehouse_id(lakehouse, workspace_id)
219
+
220
+ blob_name = f"{lakehouse_id}/{file_path}"
221
+
222
+ container = file_path.split("/")[0]
223
+ if container not in ["Tables", "Files"]:
224
+ raise ValueError(
225
+ f"{icons.red_dot} Invalid container '{container}' within the file_path parameter. Expected 'Tables' or 'Files'."
226
+ )
227
+
228
+ # Undelete the blob
229
+ print(f"{icons.in_progress} Attempting to recover the '{blob_name}' blob...")
230
+
231
+ try:
232
+ _request_blob_api(
233
+ request=f"{workspace_id}/{lakehouse_id}/{file_path}?comp=undelete",
234
+ method="put",
235
+ )
236
+ print(
237
+ f"{icons.green_dot} The '{blob_name}' blob recover attempt was successful."
238
+ )
239
+ except FabricHTTPException as e:
240
+ if e.status_code == 404:
241
+ print(
242
+ f"{icons.warning} The '{blob_name}' blob was not found. No action taken."
243
+ )
244
+ else:
245
+ print(
246
+ f"{icons.red_dot} An error occurred while recovering the '{blob_name}' blob: {e}"
247
+ )
@@ -0,0 +1,102 @@
1
+ import pandas as pd
2
+ import re
3
+ from sempy_labs._helper_functions import (
4
+ format_dax_object_name,
5
+ resolve_workspace_name_and_id,
6
+ resolve_lakehouse_name_and_id,
7
+ _create_dataframe,
8
+ _get_delta_table,
9
+ _pure_python_notebook,
10
+ )
11
+ from typing import Optional
12
+ from sempy._utils._log import log
13
+ from uuid import UUID
14
+ import sempy_labs._icons as icons
15
+
16
+
17
+ @log
18
+ def get_lakehouse_columns(
19
+ lakehouse: Optional[str | UUID] = None, workspace: Optional[str | UUID] = None
20
+ ) -> pd.DataFrame:
21
+ """
22
+ Shows the tables and columns of a lakehouse and their respective properties. This function can be executed in either a PySpark or pure Python notebook. Note that data types may show differently when using PySpark vs pure Python.
23
+
24
+ Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
25
+
26
+ Parameters
27
+ ----------
28
+ lakehouse : str | uuid.UUID, default=None
29
+ The Fabric lakehouse name or ID.
30
+ Defaults to None which resolves to the lakehouse attached to the notebook.
31
+ lakehouse_workspace : str | uuid.UUID, default=None
32
+ The Fabric workspace name or ID used by the lakehouse.
33
+ Defaults to None which resolves to the workspace of the attached lakehouse
34
+ or if no lakehouse attached, resolves to the workspace of the notebook.
35
+
36
+ Returns
37
+ -------
38
+ pandas.DataFrame
39
+ Shows the tables/columns within a lakehouse and their properties.
40
+ """
41
+ from ._get_lakehouse_tables import get_lakehouse_tables
42
+
43
+ columns = {
44
+ "Workspace Name": "string",
45
+ "Lakehouse Name": "string",
46
+ "Table Name": "string",
47
+ "Column Name": "string",
48
+ "Full Column Name": "string",
49
+ "Data Type": "string",
50
+ }
51
+ df = _create_dataframe(columns=columns)
52
+
53
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
54
+ (lakehouse_name, lakehouse_id) = resolve_lakehouse_name_and_id(
55
+ lakehouse=lakehouse, workspace=workspace_id
56
+ )
57
+
58
+ tables = get_lakehouse_tables(
59
+ lakehouse=lakehouse_id, workspace=workspace_id, extended=False, count_rows=False
60
+ )
61
+ tables_filt = tables[tables["Format"] == "delta"]
62
+
63
+ def add_column_metadata(table_name, col_name, data_type):
64
+ new_rows.append(
65
+ {
66
+ "Workspace Name": workspace_name,
67
+ "Lakehouse Name": lakehouse_name,
68
+ "Table Name": table_name,
69
+ "Column Name": col_name,
70
+ "Full Column Name": format_dax_object_name(table_name, col_name),
71
+ "Data Type": data_type,
72
+ }
73
+ )
74
+
75
+ new_rows = []
76
+
77
+ for _, r in tables_filt.iterrows():
78
+ table_name = r["Table Name"]
79
+ path = r["Location"]
80
+
81
+ if _pure_python_notebook():
82
+ from deltalake import DeltaTable
83
+
84
+ table_schema = DeltaTable(path).schema()
85
+
86
+ for field in table_schema.fields:
87
+ col_name = field.name
88
+ match = re.search(r'"(.*?)"', str(field.type))
89
+ if not match:
90
+ raise ValueError(
91
+ f"{icons.red_dot} Could not find data type for column {col_name}."
92
+ )
93
+ data_type = match.group(1)
94
+ add_column_metadata(table_name, col_name, data_type)
95
+ else:
96
+ delta_table = _get_delta_table(path=path)
97
+ table_df = delta_table.toDF()
98
+
99
+ for col_name, data_type in table_df.dtypes:
100
+ add_column_metadata(table_name, col_name, data_type)
101
+
102
+ return pd.concat([df, pd.DataFrame(new_rows)], ignore_index=True)