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,172 @@
1
+ import sempy.fabric as fabric
2
+ import pandas as pd
3
+ from sempy_labs.directlake._generate_shared_expression import generate_shared_expression
4
+ from sempy_labs._helper_functions import retry
5
+ from sempy_labs.lakehouse._lakehouse import lakehouse_attached
6
+ from sempy_labs.tom import connect_semantic_model
7
+ from typing import Optional
8
+ from sempy._utils._log import log
9
+ import sempy_labs._icons as icons
10
+ from uuid import UUID
11
+
12
+
13
+ @log
14
+ def migrate_tables_columns_to_semantic_model(
15
+ dataset: str,
16
+ new_dataset: str,
17
+ workspace: Optional[str | UUID] = None,
18
+ new_dataset_workspace: Optional[str | UUID] = None,
19
+ lakehouse: Optional[str | UUID] = None,
20
+ lakehouse_workspace: Optional[str | UUID] = None,
21
+ ):
22
+ """
23
+ Adds tables/columns to the new Direct Lake semantic model based on an import/DirectQuery semantic model.
24
+
25
+ Parameters
26
+ ----------
27
+ dataset : str
28
+ Name of the import/DirectQuery semantic model.
29
+ new_dataset : str
30
+ Name of the Direct Lake semantic model.
31
+ workspace : str, default=None
32
+ The Fabric workspace name in which the import/DirectQuery semantic model exists.
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
+ new_dataset_workspace : str
36
+ The Fabric workspace name in which the Direct Lake semantic model will be created.
37
+ Defaults to None which resolves to the workspace of the attached lakehouse
38
+ or if no lakehouse attached, resolves to the workspace of the notebook.
39
+ lakehouse : str, default=None
40
+ The Fabric lakehouse used by the Direct Lake semantic model.
41
+ Defaults to None which resolves to the lakehouse attached to the notebook.
42
+ lakehouse_workspace : str, default=None
43
+ The Fabric workspace used by the lakehouse.
44
+ Defaults to None which resolves to the workspace of the attached lakehouse
45
+ or if no lakehouse attached, resolves to the workspace of the notebook.
46
+ """
47
+
48
+ if dataset == new_dataset:
49
+ raise ValueError(
50
+ f"{icons.red_dot} The 'dataset' and 'new_dataset' parameters are both set to '{dataset}'. These parameters must be set to different values."
51
+ )
52
+
53
+ icons.sll_tags.append("DirectLakeMigration")
54
+
55
+ # Check that lakehouse is attached to the notebook
56
+ if not lakehouse_attached() and (lakehouse is None and lakehouse_workspace is None):
57
+ raise ValueError(
58
+ f"{icons.red_dot} Lakehouse not attached to notebook and lakehouse/lakehouse_workspace are not specified. Please add your lakehouse to this notebook"
59
+ f" or specify the lakehouse/lakehouse_workspace parameters."
60
+ "To attach a lakehouse to a notebook, go to the the 'Explorer' window to the left, click 'Lakehouses' to add your lakehouse to this notebook"
61
+ "\nLearn more here: https://learn.microsoft.com/fabric/data-engineering/lakehouse-notebook-explore#add-or-remove-a-lakehouse"
62
+ )
63
+ shEx = generate_shared_expression(
64
+ item_name=lakehouse,
65
+ item_type="Lakehouse",
66
+ workspace=lakehouse_workspace,
67
+ use_sql_endpoint=False,
68
+ )
69
+
70
+ fabric.refresh_tom_cache(workspace=workspace)
71
+ dfC = fabric.list_columns(dataset=dataset, workspace=workspace)
72
+ dfT = fabric.list_tables(dataset=dataset, workspace=workspace)
73
+ dfT.rename(columns={"Type": "Table Type"}, inplace=True)
74
+ dfC = pd.merge(
75
+ dfC,
76
+ dfT[["Name", "Table Type"]],
77
+ left_on="Table Name",
78
+ right_on="Name",
79
+ how="left",
80
+ )
81
+ dfT_filt = dfT[dfT["Table Type"] == "Table"]
82
+ dfC_filt = dfC[
83
+ (dfC["Table Type"] == "Table")
84
+ & ~(dfC["Column Name"].str.startswith("RowNumber-"))
85
+ & (dfC["Type"] != "Calculated")
86
+ ]
87
+
88
+ print(f"{icons.in_progress} Updating '{new_dataset}' based on '{dataset}'...")
89
+
90
+ @retry(
91
+ sleep_time=1,
92
+ timeout_error_message=f"{icons.red_dot} Function timed out after 1 minute",
93
+ )
94
+ def dyn_connect():
95
+ with connect_semantic_model(
96
+ dataset=new_dataset, readonly=True, workspace=new_dataset_workspace
97
+ ) as tom:
98
+
99
+ tom.model
100
+
101
+ dyn_connect()
102
+
103
+ with connect_semantic_model(
104
+ dataset=new_dataset, readonly=False, workspace=new_dataset_workspace
105
+ ) as tom:
106
+
107
+ # Additional updates
108
+ tom.set_annotation(
109
+ object=tom.model, name="__PBI_TimeIntelligenceEnabled", value="0"
110
+ )
111
+ tom.set_annotation(
112
+ object=tom.model, name="PBI_QueryOrder", value='["DatabaseQuery"]'
113
+ )
114
+
115
+ # Begin migration
116
+ if not any(e.Name == "DatabaseQuery" for e in tom.model.Expressions):
117
+ tom.add_expression("DatabaseQuery", expression=shEx)
118
+ print(f"{icons.green_dot} The 'DatabaseQuery' expression has been added.")
119
+ tom.set_annotation(
120
+ object=tom.model.Expressions["DatabaseQuery"],
121
+ name="PBI_IncludeFutureArtifacts",
122
+ value="False",
123
+ )
124
+
125
+ for i, r in dfT_filt.iterrows():
126
+ tName = r["Name"]
127
+ tDC = r["Data Category"]
128
+ tHid = bool(r["Hidden"])
129
+ tDesc = r["Description"]
130
+ ent_name = tName # .replace(" ", "_")
131
+ for char in icons.special_characters:
132
+ ent_name = ent_name.replace(char, "")
133
+
134
+ if not any(t.Name == tName for t in tom.model.Tables):
135
+ tom.add_table(
136
+ name=tName,
137
+ description=tDesc,
138
+ data_category=tDC,
139
+ hidden=tHid,
140
+ )
141
+ tom.add_entity_partition(table_name=tName, entity_name=ent_name)
142
+ print(f"{icons.green_dot} The '{tName}' table has been added.")
143
+
144
+ for i, r in dfC_filt.iterrows():
145
+ tName = r["Table Name"]
146
+ cName = r["Column Name"]
147
+ scName = r["Source"].replace(" ", "_")
148
+ cHid = bool(r["Hidden"])
149
+ cDataType = r["Data Type"]
150
+ for char in icons.special_characters:
151
+ scName = scName.replace(char, "")
152
+
153
+ if scName.endswith("_"):
154
+ scName = scName[:-1]
155
+
156
+ if not any(
157
+ c.Name == cName and c.Parent.Name == tName for c in tom.all_columns()
158
+ ):
159
+ tom.add_data_column(
160
+ table_name=tName,
161
+ column_name=cName,
162
+ source_column=scName,
163
+ hidden=cHid,
164
+ data_type=cDataType,
165
+ )
166
+ print(
167
+ f"{icons.green_dot} The '{tName}'[{cName}] column has been added."
168
+ )
169
+
170
+ print(
171
+ f"\n{icons.green_dot} All regular tables and columns have been added to the '{new_dataset}' semantic model."
172
+ )
@@ -0,0 +1,71 @@
1
+ import pandas as pd
2
+ from typing import Optional
3
+ from .._list_functions import list_semantic_model_objects
4
+ from sempy._utils._log import log
5
+ import sempy_labs._icons as icons
6
+
7
+
8
+ @log
9
+ def migration_validation(
10
+ dataset: str,
11
+ new_dataset: str,
12
+ workspace: Optional[str] = None,
13
+ new_dataset_workspace: Optional[str] = None,
14
+ ) -> pd.DataFrame:
15
+ """
16
+ Shows the objects in the original semantic model and whether then were migrated successfully or not.
17
+
18
+ Parameters
19
+ ----------
20
+ dataset : str
21
+ Name of the import/DirectQuery semantic model.
22
+ new_dataset : str
23
+ Name of the Direct Lake semantic model.
24
+ workspace : str, default=None
25
+ The Fabric workspace name in which the import/DirectQuery semantic model exists.
26
+ Defaults to None which resolves to the workspace of the attached lakehouse
27
+ or if no lakehouse attached, resolves to the workspace of the notebook.
28
+ new_dataset_workspace : str
29
+ The Fabric workspace name in which the Direct Lake semantic model will be created.
30
+ Defaults to None which resolves to the workspace of the attached lakehouse
31
+ or if no lakehouse attached, resolves to the workspace of the notebook.
32
+
33
+ Returns
34
+ -------
35
+ pandas.DataFrame
36
+ A pandas dataframe showing a list of objects and whether they were successfully migrated. Also shows the % of objects which were migrated successfully.
37
+ """
38
+
39
+ if dataset == new_dataset:
40
+ raise ValueError(
41
+ f"{icons.red_dot} The 'dataset' and 'new_dataset' parameters are both set to '{dataset}'. These parameters must be set to different values."
42
+ )
43
+
44
+ icons.sll_tags.append("DirectLakeMigration")
45
+
46
+ dfA = list_semantic_model_objects(dataset=dataset, workspace=workspace)
47
+ dfB = list_semantic_model_objects(
48
+ dataset=new_dataset, workspace=new_dataset_workspace
49
+ )
50
+
51
+ def is_migrated(row):
52
+ if row["Object Type"] == "Calculated Table":
53
+ return (
54
+ (dfB["Parent Name"] == row["Parent Name"])
55
+ & (dfB["Object Name"] == row["Object Name"])
56
+ & (dfB["Object Type"].isin(["Calculated Table", "Table"]))
57
+ ).any()
58
+ else:
59
+ return (
60
+ (dfB["Parent Name"] == row["Parent Name"])
61
+ & (dfB["Object Name"] == row["Object Name"])
62
+ & (dfB["Object Type"] == row["Object Type"])
63
+ ).any()
64
+
65
+ dfA["Migrated"] = dfA.apply(is_migrated, axis=1)
66
+
67
+ denom = len(dfA)
68
+ num = len(dfA[dfA["Migrated"]])
69
+ print(f"{100 * round(num / denom,2)}% migrated")
70
+
71
+ return dfA
@@ -0,0 +1,131 @@
1
+ import sempy.fabric as fabric
2
+ import pandas as pd
3
+ import re
4
+ from ..tom import connect_semantic_model
5
+ from typing import Optional
6
+ from sempy._utils._log import log
7
+ import sempy_labs._icons as icons
8
+ from uuid import UUID
9
+ from .._helper_functions import (
10
+ resolve_workspace_name_and_id,
11
+ resolve_dataset_name_and_id,
12
+ save_as_delta_table,
13
+ retry,
14
+ )
15
+
16
+
17
+ @log
18
+ def refresh_calc_tables(dataset: str | UUID, workspace: Optional[str | UUID] = None):
19
+ """
20
+ Recreates the delta tables in the lakehouse based on the DAX expressions stored as model annotations in the Direct Lake semantic model.
21
+
22
+ Parameters
23
+ ----------
24
+ dataset : str | UUID
25
+ Name or ID of the semantic model.
26
+ workspace : str | UUID, default=None
27
+ The Fabric workspace name or ID.
28
+ Defaults to None which resolves to the workspace of the attached lakehouse
29
+ or if no lakehouse attached, resolves to the workspace of the notebook.
30
+ """
31
+
32
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
33
+ (dataset_name, dataset_id) = resolve_dataset_name_and_id(dataset, workspace_id)
34
+ icons.sll_tags.append("DirectLakeMigration")
35
+
36
+ @retry(
37
+ sleep_time=1,
38
+ timeout_error_message=f"{icons.red_dot} Function timed out after 1 minute",
39
+ )
40
+ def dyn_connect():
41
+ with connect_semantic_model(
42
+ dataset=dataset_id, readonly=True, workspace=workspace_id
43
+ ) as tom:
44
+
45
+ tom.model
46
+
47
+ dyn_connect()
48
+
49
+ with connect_semantic_model(
50
+ dataset=dataset_id, readonly=True, workspace=workspace_id
51
+ ) as tom:
52
+ for a in tom.model.Annotations:
53
+ if any(a.Name == t.Name for t in tom.model.Tables):
54
+ tName = a.Name
55
+ query = a.Value
56
+
57
+ if not query.startswith("EVALUATE"):
58
+ daxquery = "EVALUATE \n" + query
59
+ else:
60
+ daxquery = query
61
+
62
+ try:
63
+ df = fabric.evaluate_dax(
64
+ dataset=dataset_id,
65
+ dax_string=daxquery,
66
+ workspace=workspace_id,
67
+ )
68
+
69
+ # Update column names for non-field parameters
70
+ if query.find("NAMEOF") == -1:
71
+ for old_column_name in df.columns:
72
+ pattern = r"\[([^\]]+)\]"
73
+
74
+ matches = re.findall(pattern, old_column_name)
75
+ new_column_name = matches[0]
76
+ new_column_name = new_column_name.replace(" ", "")
77
+
78
+ df.rename(
79
+ columns={old_column_name: new_column_name},
80
+ inplace=True,
81
+ )
82
+
83
+ # Update data types for lakehouse columns
84
+ dataType = next(
85
+ str(c.DataType)
86
+ for c in tom.all_columns()
87
+ if c.Parent.Name == tName
88
+ and c.SourceColumn == new_column_name
89
+ )
90
+ # dfC_type = dfC[(dfC['Table Name'] == tName) & (dfC['Source'] == new_column_name)]
91
+ # dataType = dfC_type['Data Type'].iloc[0]
92
+
93
+ if dataType == "Int64":
94
+ df[new_column_name] = df[new_column_name].astype(int)
95
+ elif dataType in ["Decimal", "Double"]:
96
+ df[new_column_name] = df[new_column_name].astype(float)
97
+ elif dataType == "Boolean":
98
+ df[new_column_name] = df[new_column_name].astype(bool)
99
+ elif dataType == "DateTime":
100
+ df[new_column_name] = pd.to_datetime(
101
+ df[new_column_name]
102
+ )
103
+ else:
104
+ df[new_column_name] = df[new_column_name].astype(str)
105
+ # else:
106
+ # second_column_name = df.columns[1]
107
+ # third_column_name = df.columns[2]
108
+ # df[third_column_name] = df[third_column_name].astype(int)
109
+
110
+ # Remove calc columns from field parameters
111
+ # mask = df[second_column_name].isin(dfC_filt['Full Column Name'])
112
+ # df = df[~mask]
113
+
114
+ delta_table_name = tName.replace(" ", "_")
115
+ print(
116
+ f"{icons.in_progress} Refresh of the '{delta_table_name}' table within the lakehouse is in progress..."
117
+ )
118
+
119
+ save_as_delta_table(
120
+ dataframe=df,
121
+ table_name=delta_table_name,
122
+ write_mode="overwrite",
123
+ )
124
+
125
+ print(
126
+ f"{icons.green_dot} Calculated table '{tName}' has been refreshed as the '{delta_table_name.lower()}' table in the lakehouse."
127
+ )
128
+ except Exception as e:
129
+ raise ValueError(
130
+ f"{icons.red_dot} Failed to create calculated table '{tName}' as a delta table in the lakehouse."
131
+ ) from e
@@ -0,0 +1,15 @@
1
+ from ._refresh_catalog_metadata import (
2
+ refresh_catalog_metadata,
3
+ )
4
+ from ._discover import (
5
+ discover_catalogs,
6
+ discover_schemas,
7
+ discover_tables,
8
+ )
9
+
10
+ __all__ = [
11
+ "refresh_catalog_metadata",
12
+ "discover_catalogs",
13
+ "discover_schemas",
14
+ "discover_tables",
15
+ ]
@@ -0,0 +1,213 @@
1
+ from uuid import UUID
2
+ from typing import Optional
3
+ from sempy_labs._helper_functions import (
4
+ resolve_workspace_id,
5
+ _base_api,
6
+ _create_dataframe,
7
+ )
8
+ import pandas as pd
9
+ from sempy._utils._log import log
10
+
11
+
12
+ @log
13
+ def discover_catalogs(
14
+ databricks_workspace_connection_id: UUID,
15
+ workspace: Optional[str | UUID] = None,
16
+ max_results: Optional[int] = None,
17
+ ) -> pd.DataFrame:
18
+ """
19
+ Returns a list of catalogs from Unity Catalog.
20
+
21
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Catalogs <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-catalogs>`_.
22
+
23
+ Parameters
24
+ ----------
25
+ databricks_workspace_connection_id : uuid.UUID
26
+ The ID of the Databricks workspace connection.
27
+ workspace : str | uuid.UUID, default=None
28
+ The workspace name or ID.
29
+ Defaults to None which resolves to the workspace of the attached lakehouse
30
+ or if no lakehouse attached, resolves to the workspace of the notebook.
31
+ max_results : int, default=None
32
+ The maximum number of results to return. If not specified, all results are returned.
33
+
34
+ Returns
35
+ -------
36
+ pandas.DataFrame
37
+ A pandas dataframe showing a list of catalogs from Unity Catalog.
38
+ """
39
+
40
+ workspace_id = resolve_workspace_id(workspace)
41
+
42
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
43
+ if max_results:
44
+ url += f"&maxResults={max_results}"
45
+
46
+ responses = _base_api(request=url, uses_pagination=True)
47
+
48
+ columns = {
49
+ "Catalog Name": "str",
50
+ "Catalog Full Name": "str",
51
+ "Catalog Type": "str",
52
+ "Storage Location": "str",
53
+ }
54
+
55
+ df = _create_dataframe(columns=columns)
56
+
57
+ rows = []
58
+ for r in responses:
59
+ for i in r.get("value", []):
60
+ rows.append(
61
+ {
62
+ "Catalog Name": i.get("name"),
63
+ "Catalog Full Name": i.get("fullName"),
64
+ "Catalog Type": i.get("catalogType"),
65
+ "Storage Location": i.get("storageLocation"),
66
+ }
67
+ )
68
+
69
+ if rows:
70
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
71
+
72
+ return df
73
+
74
+
75
+ @log
76
+ def discover_schemas(
77
+ catalog: str,
78
+ databricks_workspace_connection_id: UUID,
79
+ workspace: Optional[str | UUID] = None,
80
+ max_results: Optional[int] = None,
81
+ ) -> pd.DataFrame:
82
+ """
83
+ Returns a list of schemas in the given catalog from Unity Catalog.
84
+
85
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Schemas <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-schemas>`_.
86
+
87
+ Parameters
88
+ ----------
89
+ catalog : str
90
+ The name of the catalog.
91
+ databricks_workspace_connection_id : uuid.UUID
92
+ The ID of the Databricks workspace connection.
93
+ workspace : str | uuid.UUID, default=None
94
+ The workspace name or ID.
95
+ Defaults to None which resolves to the workspace of the attached lakehouse
96
+ or if no lakehouse attached, resolves to the workspace of the notebook.
97
+ max_results : int, default=None
98
+ The maximum number of results to return. If not specified, all results are returned.
99
+
100
+ Returns
101
+ -------
102
+ pandas.DataFrame
103
+ A pandas dataframe showing a list of schemas in the given catalog from Unity Catalog.
104
+ """
105
+
106
+ workspace_id = resolve_workspace_id(workspace)
107
+
108
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs/{catalog}/schemas?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
109
+ if max_results:
110
+ url += f"&maxResults={max_results}"
111
+
112
+ responses = _base_api(request=url, uses_pagination=True)
113
+
114
+ columns = {
115
+ "Catalog Name": "str",
116
+ "Schema Name": "str",
117
+ "Schema Full Name": "str",
118
+ "Storage Location": "str",
119
+ }
120
+
121
+ df = _create_dataframe(columns=columns)
122
+
123
+ rows = []
124
+ for r in responses:
125
+ for i in r.get("value", []):
126
+ rows.append(
127
+ {
128
+ "Catalog Name": catalog,
129
+ "Schema Name": i.get("name"),
130
+ "Schema Full Name": i.get("fullName"),
131
+ "Storage Location": i.get("storageLocation"),
132
+ }
133
+ )
134
+
135
+ if rows:
136
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
137
+
138
+ return df
139
+
140
+
141
+ @log
142
+ def discover_tables(
143
+ catalog: str,
144
+ schema: str,
145
+ databricks_workspace_connection_id: UUID,
146
+ workspace: Optional[str | UUID] = None,
147
+ max_results: Optional[int] = None,
148
+ ) -> pd.DataFrame:
149
+ """
150
+ Returns a list of schemas in the given catalog from Unity Catalog.
151
+
152
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Tables <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-tables>`_.
153
+
154
+ Parameters
155
+ ----------
156
+ catalog : str
157
+ The name of the catalog.
158
+ schema : str
159
+ The name of the schema.
160
+ databricks_workspace_connection_id : uuid.UUID
161
+ The ID of the Databricks workspace connection.
162
+ workspace : str | uuid.UUID, default=None
163
+ The workspace name or ID.
164
+ Defaults to None which resolves to the workspace of the attached lakehouse
165
+ or if no lakehouse attached, resolves to the workspace of the notebook.
166
+ max_results : int, default=None
167
+ The maximum number of results to return. If not specified, all results are returned.
168
+
169
+ Returns
170
+ -------
171
+ pandas.DataFrame
172
+ A pandas dataframe showing a list of schemas in the given catalog from Unity Catalog.
173
+ """
174
+
175
+ workspace_id = resolve_workspace_id(workspace)
176
+
177
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs/{catalog}/schemas/{schema}/tables?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
178
+ if max_results:
179
+ url += f"&maxResults={max_results}"
180
+
181
+ responses = _base_api(request=url, uses_pagination=True)
182
+
183
+ columns = {
184
+ "Catalog Name": "str",
185
+ "Schema Name": "str",
186
+ "Table Name": "str",
187
+ "Table Full Name": "str",
188
+ "Storage Location": "str",
189
+ "Table Type": "str",
190
+ "Data Source Format": "str",
191
+ }
192
+
193
+ df = _create_dataframe(columns=columns)
194
+
195
+ rows = []
196
+ for r in responses:
197
+ for i in r.get("value", []):
198
+ rows.append(
199
+ {
200
+ "Catalog Name": catalog,
201
+ "Schema Name": schema,
202
+ "Table Name": i.get("name"),
203
+ "Table Full Name": i.get("fullName"),
204
+ "Storage Location": i.get("storageLocation"),
205
+ "Table Type": i.get("tableType"),
206
+ "Data Source Format": i.get("dataSourceFormat"),
207
+ }
208
+ )
209
+
210
+ if rows:
211
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
212
+
213
+ return df
@@ -0,0 +1,45 @@
1
+ from uuid import UUID
2
+ from typing import Optional
3
+ from sempy_labs._helper_functions import (
4
+ resolve_workspace_name_and_id,
5
+ resolve_item_name_and_id,
6
+ _base_api,
7
+ )
8
+ import sempy_labs._icons as icons
9
+ from sempy._utils._log import log
10
+
11
+
12
+ @log
13
+ def refresh_catalog_metadata(
14
+ mirrored_azure_databricks_catalog: str | UUID,
15
+ workspace: Optional[str | UUID] = None,
16
+ ):
17
+ """
18
+ Refresh Databricks catalog metadata in mirroredAzureDatabricksCatalogs Item.
19
+
20
+ This is a wrapper function for the following API: `Refresh Metadata - Items RefreshCatalogMetadata <https://learn.microsoft.com/rest/api/fabric/mirroredazuredatabrickscatalog/refresh-metadata/items-refresh-catalog-metadata>`_.
21
+
22
+ Parameters
23
+ ----------
24
+ mirrored_azure_databricks_catalog : str | uuid.UUID
25
+ The name or ID of the mirrored Azure Databricks catalog.
26
+ workspace : str | uuie.UUID, default=None
27
+ The workspace name or ID.
28
+ Defaults to None which resolves to the workspace of the attached lakehouse
29
+ or if no lakehouse attached, resolves to the workspace of the notebook
30
+ """
31
+
32
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
33
+ (catalog_name, catalog_id) = resolve_item_name_and_id(
34
+ mirrored_azure_databricks_catalog
35
+ )
36
+
37
+ _base_api(
38
+ request=f"/v1/workspaces/{workspace_id}/mirroredAzureDatabricksCatalogs/{catalog_id}/refreshCatalogMetadata",
39
+ method="post",
40
+ lro_return_status_code=True,
41
+ )
42
+
43
+ print(
44
+ f"{icons.green_dot} The '{catalog_name}' Databricks Catalog metadata within the '{workspace_name}' workspace has been refreshed."
45
+ )
@@ -0,0 +1,23 @@
1
+ from ._functions import (
2
+ list_ml_models,
3
+ create_ml_model,
4
+ delete_ml_model,
5
+ activate_ml_model_endpoint_version,
6
+ deactivate_all_ml_model_endpoint_versions,
7
+ deactivate_ml_model_endpoint_version,
8
+ list_ml_model_endpoint_versions,
9
+ score_ml_model_endpoint,
10
+ score_ml_model_endpoint_version,
11
+ )
12
+
13
+ __all__ = [
14
+ "list_ml_models",
15
+ "create_ml_model",
16
+ "delete_ml_model",
17
+ "activate_ml_model_endpoint_version",
18
+ "deactivate_all_ml_model_endpoint_versions",
19
+ "deactivate_ml_model_endpoint_version",
20
+ "list_ml_model_endpoint_versions",
21
+ "score_ml_model_endpoint",
22
+ "score_ml_model_endpoint_version",
23
+ ]