semantic-link-labs 0.4.2__py3-none-any.whl → 0.5.0__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.
Potentially problematic release.
This version of semantic-link-labs might be problematic. Click here for more details.
- {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/METADATA +1 -1
- semantic_link_labs-0.5.0.dist-info/RECORD +53 -0
- {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +27 -3
- sempy_labs/_ai.py +12 -32
- sempy_labs/_clear_cache.py +1 -3
- sempy_labs/_connections.py +39 -38
- sempy_labs/_generate_semantic_model.py +9 -14
- sempy_labs/_helper_functions.py +3 -12
- sempy_labs/_icons.py +1 -0
- sempy_labs/_list_functions.py +915 -391
- sempy_labs/_model_auto_build.py +2 -4
- sempy_labs/_model_bpa.py +26 -30
- sempy_labs/_model_dependencies.py +7 -13
- sempy_labs/_one_lake_integration.py +2 -5
- sempy_labs/_query_scale_out.py +12 -30
- sempy_labs/_refresh_semantic_model.py +5 -15
- sempy_labs/_translations.py +1 -1
- sempy_labs/_vertipaq.py +3 -10
- sempy_labs/directlake/_directlake_schema_compare.py +3 -9
- sempy_labs/directlake/_directlake_schema_sync.py +2 -6
- sempy_labs/directlake/_fallback.py +2 -6
- sempy_labs/directlake/_get_shared_expression.py +3 -9
- sempy_labs/directlake/_guardrails.py +3 -5
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +3 -4
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +1 -2
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +3 -7
- sempy_labs/directlake/_update_directlake_partition_entity.py +2 -8
- sempy_labs/directlake/_warm_cache.py +5 -8
- sempy_labs/lakehouse/_get_lakehouse_columns.py +1 -1
- sempy_labs/lakehouse/_get_lakehouse_tables.py +3 -5
- sempy_labs/lakehouse/_lakehouse.py +1 -3
- sempy_labs/lakehouse/_shortcuts.py +2 -5
- sempy_labs/migration/_create_pqt_file.py +4 -13
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +2 -6
- sempy_labs/migration/_migration_validation.py +4 -0
- sempy_labs/migration/_refresh_calc_tables.py +2 -0
- sempy_labs/report/_generate_report.py +2 -6
- sempy_labs/report/_report_functions.py +30 -73
- sempy_labs/report/_report_rebind.py +39 -39
- sempy_labs/tom/_model.py +141 -183
- semantic_link_labs-0.4.2.dist-info/RECORD +0 -53
- {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/top_level.txt +0 -0
sempy_labs/_model_auto_build.py
CHANGED
|
@@ -41,9 +41,7 @@ def model_auto_build(
|
|
|
41
41
|
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
workspace_id = fabric.get_workspace_id()
|
|
46
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
44
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
47
45
|
|
|
48
46
|
if lakehouse_workspace is None:
|
|
49
47
|
lakehouse_workspace = workspace
|
|
@@ -60,7 +58,7 @@ def model_auto_build(
|
|
|
60
58
|
|
|
61
59
|
create_blank_semantic_model(dataset=dataset, workspace=workspace)
|
|
62
60
|
|
|
63
|
-
with connect_semantic_model(dataset=dataset, workspace=workspace) as tom:
|
|
61
|
+
with connect_semantic_model(dataset=dataset, workspace=workspace, readonly=False) as tom:
|
|
64
62
|
|
|
65
63
|
# DL Only
|
|
66
64
|
expr = get_shared_expression(lakehouse=lakehouse, workspace=lakehouse_workspace)
|
sempy_labs/_model_bpa.py
CHANGED
|
@@ -11,7 +11,7 @@ from sempy_labs.lakehouse._get_lakehouse_tables import get_lakehouse_tables
|
|
|
11
11
|
from sempy_labs.lakehouse._lakehouse import lakehouse_attached
|
|
12
12
|
from typing import List, Optional, Union
|
|
13
13
|
from sempy._utils._log import log
|
|
14
|
-
|
|
14
|
+
import sempy_labs._icons as icons
|
|
15
15
|
|
|
16
16
|
def model_bpa_rules():
|
|
17
17
|
"""
|
|
@@ -70,8 +70,8 @@ def model_bpa_rules():
|
|
|
70
70
|
"Table",
|
|
71
71
|
"Warning",
|
|
72
72
|
"Avoid using many-to-many relationships on tables used for dynamic row level security",
|
|
73
|
-
lambda df: (df["Used in M2M Relationship"]
|
|
74
|
-
& (df["Used in Dynamic RLS"]
|
|
73
|
+
lambda df: (df["Used in M2M Relationship"] == True)
|
|
74
|
+
& (df["Used in Dynamic RLS"] == True),
|
|
75
75
|
"Using many-to-many relationships on tables which use dynamic row level security can cause serious query performance degradation. This pattern's performance problems compound when snowflaking multiple many-to-many relationships against a table which contains row level security. Instead, use one of the patterns shown in the article below where a single dimension table relates many-to-one to a security table.",
|
|
76
76
|
"https://www.elegantbi.com/post/dynamicrlspatterns",
|
|
77
77
|
),
|
|
@@ -88,12 +88,12 @@ def model_bpa_rules():
|
|
|
88
88
|
"Column",
|
|
89
89
|
"Warning",
|
|
90
90
|
"Set IsAvailableInMdx to false on non-attribute columns",
|
|
91
|
-
lambda df: (df["Is Direct Lake"]
|
|
92
|
-
& (df["Is Available in MDX"]
|
|
93
|
-
& ((df["Hidden"]
|
|
94
|
-
& (df["Used in Sort By"]
|
|
95
|
-
& (df["Used in Hierarchy"]
|
|
96
|
-
& (df["Sort By Column"]
|
|
91
|
+
lambda df: (df["Is Direct Lake"] == False)
|
|
92
|
+
& (df["Is Available in MDX"] == True)
|
|
93
|
+
& ((df["Hidden"] == True) | (df["Parent Is Hidden"] == True))
|
|
94
|
+
& (df["Used in Sort By"] == False)
|
|
95
|
+
& (df["Used in Hierarchy"] == False)
|
|
96
|
+
& (df["Sort By Column"] == None),
|
|
97
97
|
"To speed up processing time and conserve memory after processing, attribute hierarchies should not be built for columns that are never used for slicing by MDX clients. In other words, all hidden columns that are not used as a Sort By Column or referenced in user hierarchies should have their IsAvailableInMdx property set to false. The IsAvailableInMdx property is not relevant for Direct Lake models.",
|
|
98
98
|
"https://blog.crossjoin.co.uk/2018/07/02/isavailableinmdx-ssas-tabular",
|
|
99
99
|
),
|
|
@@ -219,7 +219,7 @@ def model_bpa_rules():
|
|
|
219
219
|
"Table",
|
|
220
220
|
"Warning",
|
|
221
221
|
"Large tables should be partitioned",
|
|
222
|
-
lambda df: (df["Is Direct Lake"]
|
|
222
|
+
lambda df: (df["Is Direct Lake"] == False)
|
|
223
223
|
& (df["Partition Count"] == 1)
|
|
224
224
|
& (df["Row Count"] > 25000000),
|
|
225
225
|
"Large tables should be partitioned in order to optimize processing. This is not relevant for semantic models in Direct Lake mode as they can only have one partition per table.",
|
|
@@ -306,11 +306,11 @@ def model_bpa_rules():
|
|
|
306
306
|
"Column",
|
|
307
307
|
"Warning",
|
|
308
308
|
"Set IsAvailableInMdx to true on necessary columns",
|
|
309
|
-
lambda df: (df["Is Direct Lake"]
|
|
310
|
-
& (df["Is Available in MDX"]
|
|
309
|
+
lambda df: (df["Is Direct Lake"] == False)
|
|
310
|
+
& (df["Is Available in MDX"] == False)
|
|
311
311
|
& (
|
|
312
|
-
(df["Used in Sort By"]
|
|
313
|
-
| (df["Used in Hierarchy"]
|
|
312
|
+
(df["Used in Sort By"] == True)
|
|
313
|
+
| (df["Used in Hierarchy"] == True)
|
|
314
314
|
| (df["Sort By Column"] != None)
|
|
315
315
|
),
|
|
316
316
|
"In order to avoid errors, ensure that attribute hierarchies are enabled if a column is used for sorting another column, used in a hierarchy, used in variations, or is sorted by another column. The IsAvailableInMdx property is not relevant for Direct Lake models.",
|
|
@@ -320,8 +320,8 @@ def model_bpa_rules():
|
|
|
320
320
|
"Table",
|
|
321
321
|
"Error",
|
|
322
322
|
"Avoid the USERELATIONSHIP function and RLS against the same table",
|
|
323
|
-
lambda df: (df["USERELATIONSHIP Used"]
|
|
324
|
-
& (df["Used in RLS"]
|
|
323
|
+
lambda df: (df["USERELATIONSHIP Used"] == True)
|
|
324
|
+
& (df["Used in RLS"] == True),
|
|
325
325
|
"The USERELATIONSHIP function may not be used against a table which also leverages row-level security (RLS). This will generate an error when using the particular measure in a visual. This rule will highlight the table which is used in a measure's USERELATIONSHIP function as well as RLS.",
|
|
326
326
|
"https://blog.crossjoin.co.uk/2013/05/10/userelationship-and-tabular-row-security",
|
|
327
327
|
),
|
|
@@ -494,7 +494,7 @@ def model_bpa_rules():
|
|
|
494
494
|
"Table",
|
|
495
495
|
"Warning",
|
|
496
496
|
"Ensure tables have relationships",
|
|
497
|
-
lambda df: (df["Used in Relationship"]
|
|
497
|
+
lambda df: (df["Used in Relationship"] == False)
|
|
498
498
|
& (df["Type"] != "Calculation Group"),
|
|
499
499
|
"This rule highlights tables which are not connected to any other table in the model with a relationship.",
|
|
500
500
|
),
|
|
@@ -511,7 +511,7 @@ def model_bpa_rules():
|
|
|
511
511
|
"Column",
|
|
512
512
|
"Info",
|
|
513
513
|
"Visible objects with no description",
|
|
514
|
-
lambda df: (df["Hidden"]
|
|
514
|
+
lambda df: (df["Hidden"] == False) & (df["Description"].str.len() == 0),
|
|
515
515
|
"Calculation groups have no function unless they have calculation items.",
|
|
516
516
|
),
|
|
517
517
|
(
|
|
@@ -595,7 +595,7 @@ def model_bpa_rules():
|
|
|
595
595
|
"Column",
|
|
596
596
|
"Info",
|
|
597
597
|
"Hide foreign keys",
|
|
598
|
-
lambda df: (df["Foreign Key"]) & (df["Hidden"]
|
|
598
|
+
lambda df: (df["Foreign Key"]) & (df["Hidden"] == False),
|
|
599
599
|
"Foreign keys should always be hidden.",
|
|
600
600
|
),
|
|
601
601
|
(
|
|
@@ -603,7 +603,7 @@ def model_bpa_rules():
|
|
|
603
603
|
"Column",
|
|
604
604
|
"Info",
|
|
605
605
|
"Mark primary keys",
|
|
606
|
-
lambda df: (df["Primary Key"]) & (df["Key"]
|
|
606
|
+
lambda df: (df["Primary Key"]) & (df["Key"] == False),
|
|
607
607
|
"Set the 'Key' property to 'True' for primary key columns within the column properties.",
|
|
608
608
|
),
|
|
609
609
|
(
|
|
@@ -744,9 +744,7 @@ def run_model_bpa(
|
|
|
744
744
|
message="This pattern is interpreted as a regular expression, and has match groups.",
|
|
745
745
|
)
|
|
746
746
|
|
|
747
|
-
|
|
748
|
-
workspace_id = fabric.get_workspace_id()
|
|
749
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
747
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
750
748
|
|
|
751
749
|
if rules_dataframe is None:
|
|
752
750
|
rules_dataframe = model_bpa_rules()
|
|
@@ -951,7 +949,7 @@ def run_model_bpa(
|
|
|
951
949
|
dfD["Has Date Table"] = any(
|
|
952
950
|
(r["Parent Data Category"] == "Time")
|
|
953
951
|
& (r["Data Type"] == "DateTime")
|
|
954
|
-
& (r["Key"]
|
|
952
|
+
& (r["Key"] == True)
|
|
955
953
|
for i, r in dfC.iterrows()
|
|
956
954
|
)
|
|
957
955
|
# dfC['In Date Table'] = dfC['Table Name'].isin(dfT.loc[dfT['Data Category'] == "Time", 'Name'])
|
|
@@ -1033,7 +1031,7 @@ def run_model_bpa(
|
|
|
1033
1031
|
dfM.at[i, "Has Fully Qualified Measure Reference"] = True
|
|
1034
1032
|
|
|
1035
1033
|
dfR["Inactive without USERELATIONSHIP"] = False
|
|
1036
|
-
for i, r in dfR[dfR["Active"]
|
|
1034
|
+
for i, r in dfR[dfR["Active"] == False].iterrows():
|
|
1037
1035
|
fromTable = r["From Table"]
|
|
1038
1036
|
fromColumn = r["From Column"]
|
|
1039
1037
|
toTable = r["To Table"]
|
|
@@ -1184,10 +1182,8 @@ def run_model_bpa(
|
|
|
1184
1182
|
if export:
|
|
1185
1183
|
lakeAttach = lakehouse_attached()
|
|
1186
1184
|
if lakeAttach is False:
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
)
|
|
1190
|
-
return
|
|
1185
|
+
raise ValueError(f"{icons.red_dot} In order to save the Best Practice Analyzer results, a lakehouse must be attached to the notebook. Please attach a lakehouse to this notebook.")
|
|
1186
|
+
|
|
1191
1187
|
dfExport = finalDF.copy()
|
|
1192
1188
|
delta_table_name = "modelbparesults"
|
|
1193
1189
|
|
|
@@ -1230,7 +1226,7 @@ def run_model_bpa(
|
|
|
1230
1226
|
spark_df = spark.createDataFrame(dfExport)
|
|
1231
1227
|
spark_df.write.mode("append").format("delta").saveAsTable(delta_table_name)
|
|
1232
1228
|
print(
|
|
1233
|
-
f"
|
|
1229
|
+
f"{icons.green_dot} Model Best Practice Analyzer results for the '{dataset}' semantic model have been appended to the '{delta_table_name}' delta table."
|
|
1234
1230
|
)
|
|
1235
1231
|
|
|
1236
1232
|
if return_dataframe:
|
|
@@ -25,9 +25,7 @@ def get_measure_dependencies(dataset: str, workspace: Optional[str] = None):
|
|
|
25
25
|
Shows all dependencies for all measures in the semantic model.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
workspace_id = fabric.get_workspace_id()
|
|
30
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
28
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
31
29
|
|
|
32
30
|
dep = fabric.evaluate_dax(
|
|
33
31
|
dataset=dataset,
|
|
@@ -63,11 +61,11 @@ def get_measure_dependencies(dataset: str, workspace: Optional[str] = None):
|
|
|
63
61
|
axis=1,
|
|
64
62
|
)
|
|
65
63
|
|
|
66
|
-
while any(df["Done"]
|
|
64
|
+
while any(df["Done"] == False):
|
|
67
65
|
for i, r in df.iterrows():
|
|
68
66
|
rObjFull = r["Referenced Full Object Name"]
|
|
69
67
|
rObj = r["Referenced Object"]
|
|
70
|
-
if r["Done"]
|
|
68
|
+
if r["Done"] == False:
|
|
71
69
|
dep_filt = dep[dep["Full Object Name"] == rObjFull]
|
|
72
70
|
|
|
73
71
|
for index, dependency in dep_filt.iterrows():
|
|
@@ -150,9 +148,7 @@ def get_model_calc_dependencies(dataset: str, workspace: Optional[str] = None):
|
|
|
150
148
|
Shows all dependencies for all objects in the semantic model.
|
|
151
149
|
"""
|
|
152
150
|
|
|
153
|
-
|
|
154
|
-
workspace_id = fabric.get_workspace_id()
|
|
155
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
151
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
156
152
|
|
|
157
153
|
dep = fabric.evaluate_dax(
|
|
158
154
|
dataset=dataset,
|
|
@@ -191,11 +187,11 @@ def get_model_calc_dependencies(dataset: str, workspace: Optional[str] = None):
|
|
|
191
187
|
lambda row: False if row["Referenced Object Type"] in objs else True, axis=1
|
|
192
188
|
)
|
|
193
189
|
|
|
194
|
-
while any(df["Done"]
|
|
190
|
+
while any(df["Done"] == False):
|
|
195
191
|
for i, r in df.iterrows():
|
|
196
192
|
rObjFull = r["Referenced Full Object Name"]
|
|
197
193
|
rObj = r["Referenced Object"]
|
|
198
|
-
if r["Done"]
|
|
194
|
+
if r["Done"] == False:
|
|
199
195
|
dep_filt = dep[dep["Full Object Name"] == rObjFull]
|
|
200
196
|
|
|
201
197
|
for index, dependency in dep_filt.iterrows():
|
|
@@ -282,9 +278,7 @@ def measure_dependency_tree(
|
|
|
282
278
|
|
|
283
279
|
"""
|
|
284
280
|
|
|
285
|
-
|
|
286
|
-
workspace_id = fabric.get_workspace_id()
|
|
287
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
281
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
288
282
|
|
|
289
283
|
dfM = fabric.list_measures(dataset=dataset, workspace=workspace)
|
|
290
284
|
dfM_filt = dfM[dfM["Measure Name"] == measure_name]
|
|
@@ -42,10 +42,7 @@ def export_model_to_onelake(
|
|
|
42
42
|
dfD_filt = dfD[dfD["Dataset Name"] == dataset]
|
|
43
43
|
|
|
44
44
|
if len(dfD_filt) == 0:
|
|
45
|
-
|
|
46
|
-
f"{icons.red_dot} The '{dataset}' semantic model does not exist in the '{workspace}' workspace."
|
|
47
|
-
)
|
|
48
|
-
return
|
|
45
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' semantic model does not exist in the '{workspace}' workspace.")
|
|
49
46
|
|
|
50
47
|
tmsl = f"""
|
|
51
48
|
{{
|
|
@@ -104,7 +101,7 @@ def export_model_to_onelake(
|
|
|
104
101
|
dfP_filt = dfP[
|
|
105
102
|
(dfP["Mode"] == "Import")
|
|
106
103
|
& (dfP["Source Type"] != "CalculationGroup")
|
|
107
|
-
& (dfP["Parent System Managed"]
|
|
104
|
+
& (dfP["Parent System Managed"] == False)
|
|
108
105
|
]
|
|
109
106
|
dfC = fabric.list_columns(dataset=dataset, workspace=workspace)
|
|
110
107
|
tmc = pd.DataFrame(dfP.groupby("Table Name")["Mode"].nunique()).reset_index()
|
sempy_labs/_query_scale_out.py
CHANGED
|
@@ -44,10 +44,7 @@ def qso_sync(dataset: str, workspace: Optional[str] = None):
|
|
|
44
44
|
f"{icons.green_dot} QSO sync initiated for the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
45
45
|
)
|
|
46
46
|
else:
|
|
47
|
-
|
|
48
|
-
f"{icons.red_dot} QSO sync failed for the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
49
|
-
)
|
|
50
|
-
|
|
47
|
+
raise ValueError(f"{icons.red_dot} QSO sync failed for the '{dataset}' semantic model within the '{workspace}' workspace.")
|
|
51
48
|
|
|
52
49
|
def qso_sync_status(dataset: str, workspace: Optional[str] = None):
|
|
53
50
|
"""
|
|
@@ -189,7 +186,7 @@ def disable_qso(dataset: str, workspace: Optional[str] = None):
|
|
|
189
186
|
)
|
|
190
187
|
return df
|
|
191
188
|
else:
|
|
192
|
-
|
|
189
|
+
raise ValueError(f"{icons.red_dot} {response.status_code}")
|
|
193
190
|
|
|
194
191
|
|
|
195
192
|
def set_qso(
|
|
@@ -256,16 +253,9 @@ def set_qso(
|
|
|
256
253
|
)
|
|
257
254
|
return df
|
|
258
255
|
else:
|
|
259
|
-
|
|
256
|
+
raise ValueError(f"{icons.red_dot} {response.status_code}")
|
|
260
257
|
else:
|
|
261
|
-
|
|
262
|
-
f"{icons.red_dot} Failed to set the '{dataset}' semantic model within the '{workspace}' workspace to large semantic model storage format. This is a prerequisite for enabling Query Scale Out."
|
|
263
|
-
)
|
|
264
|
-
print(
|
|
265
|
-
"https://learn.microsoft.com/power-bi/enterprise/service-premium-scale-out#prerequisites"
|
|
266
|
-
)
|
|
267
|
-
return
|
|
268
|
-
|
|
258
|
+
raise ValueError(f"{icons.red_dot} Failed to set the '{dataset}' semantic model within the '{workspace}' workspace to large semantic model storage format. This is a prerequisite for enabling Query Scale Out.\n\"https://learn.microsoft.com/power-bi/enterprise/service-premium-scale-out#prerequisites\"")
|
|
269
259
|
|
|
270
260
|
def set_semantic_model_storage_format(
|
|
271
261
|
dataset: str, storage_format: str, workspace: Optional[str] = None
|
|
@@ -311,10 +301,7 @@ def set_semantic_model_storage_format(
|
|
|
311
301
|
elif storage_format == "Small":
|
|
312
302
|
request_body = {"targetStorageMode": "Abf"}
|
|
313
303
|
else:
|
|
314
|
-
|
|
315
|
-
f"{icons.red_dot} Invalid storage format value. Valid options: {storageFormats}."
|
|
316
|
-
)
|
|
317
|
-
return
|
|
304
|
+
raise ValueError(f"{icons.red_dot} Invalid storage format value. Valid options: {storageFormats}.")
|
|
318
305
|
|
|
319
306
|
client = fabric.PowerBIRestClient()
|
|
320
307
|
response = client.patch(
|
|
@@ -326,8 +313,7 @@ def set_semantic_model_storage_format(
|
|
|
326
313
|
f"{icons.green_dot} Semantic model storage format set to '{storage_format}'."
|
|
327
314
|
)
|
|
328
315
|
else:
|
|
329
|
-
|
|
330
|
-
|
|
316
|
+
raise ValueError(f"{icons.red_dot} {response.status_code}")
|
|
331
317
|
|
|
332
318
|
def list_qso_settings(dataset: Optional[str] = None, workspace: Optional[str] = None):
|
|
333
319
|
"""
|
|
@@ -370,21 +356,17 @@ def list_qso_settings(dataset: Optional[str] = None, workspace: Optional[str] =
|
|
|
370
356
|
client = fabric.PowerBIRestClient()
|
|
371
357
|
response = client.get(f"/v1.0/myorg/groups/{workspace_id}/datasets")
|
|
372
358
|
for v in response.json()["value"]:
|
|
373
|
-
tsm = v
|
|
359
|
+
tsm = v.get("targetStorageMode")
|
|
374
360
|
if tsm == "Abf":
|
|
375
361
|
sm = "Small"
|
|
376
362
|
else:
|
|
377
363
|
sm = "Large"
|
|
378
364
|
new_data = {
|
|
379
|
-
"Dataset Id": v
|
|
380
|
-
"Dataset Name": v
|
|
365
|
+
"Dataset Id": v.get("id"),
|
|
366
|
+
"Dataset Name": v.get("name"),
|
|
381
367
|
"Storage Mode": sm,
|
|
382
|
-
"QSO Auto Sync Enabled": v
|
|
383
|
-
|
|
384
|
-
],
|
|
385
|
-
"QSO Max Read Only Replicas": v["queryScaleOutSettings"][
|
|
386
|
-
"maxReadOnlyReplicas"
|
|
387
|
-
],
|
|
368
|
+
"QSO Auto Sync Enabled": v.get("queryScaleOutSettings",{}).get("autoSyncReadOnlyReplicas"),
|
|
369
|
+
"QSO Max Read Only Replicas": v.get("queryScaleOutSettings",{}).get("maxReadOnlyReplicas"),
|
|
388
370
|
}
|
|
389
371
|
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
390
372
|
|
|
@@ -444,4 +426,4 @@ def set_workspace_default_storage_format(
|
|
|
444
426
|
f"{icons.green_dot} The default storage format for the '{workspace}' workspace has been updated to '{storage_format}."
|
|
445
427
|
)
|
|
446
428
|
else:
|
|
447
|
-
|
|
429
|
+
raise ValueError(f"{icons.red_dot} {response.status_code}")
|
|
@@ -41,9 +41,7 @@ def refresh_semantic_model(
|
|
|
41
41
|
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
workspace_id = fabric.get_workspace_id()
|
|
46
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
44
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
47
45
|
|
|
48
46
|
if refresh_type is None:
|
|
49
47
|
refresh_type = "full"
|
|
@@ -81,10 +79,7 @@ def refresh_semantic_model(
|
|
|
81
79
|
]
|
|
82
80
|
|
|
83
81
|
if refresh_type not in refreshTypes:
|
|
84
|
-
|
|
85
|
-
f"{icons.red_dot} Invalid refresh type. Refresh type must be one of these values: {refreshTypes}."
|
|
86
|
-
)
|
|
87
|
-
return
|
|
82
|
+
raise ValueError(f"{icons.red_dot} Invalid refresh type. Refresh type must be one of these values: {refreshTypes}.")
|
|
88
83
|
|
|
89
84
|
if len(objects) == 0:
|
|
90
85
|
requestID = fabric.refresh_dataset(
|
|
@@ -119,10 +114,7 @@ def refresh_semantic_model(
|
|
|
119
114
|
if status == "Completed":
|
|
120
115
|
break
|
|
121
116
|
elif status == "Failed":
|
|
122
|
-
|
|
123
|
-
f"{icons.red_dot} The refresh of the '{dataset}' semantic model within the '{workspace}' workspace has failed."
|
|
124
|
-
)
|
|
125
|
-
return
|
|
117
|
+
raise ValueError(f"{icons.red_dot} The refresh of the '{dataset}' semantic model within the '{workspace}' workspace has failed.")
|
|
126
118
|
elif status == "Cancelled":
|
|
127
119
|
print(
|
|
128
120
|
f"{icons.yellow_dot} The refresh of the '{dataset}' semantic model within the '{workspace}' workspace has been cancelled."
|
|
@@ -163,10 +155,8 @@ def cancel_dataset_refresh(
|
|
|
163
155
|
|
|
164
156
|
if request_id is None:
|
|
165
157
|
if len(rr_filt) == 0:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
)
|
|
169
|
-
return
|
|
158
|
+
raise ValueError(f"{icons.red_dot} There are no active Enhanced API refreshes of the '{dataset}' semantic model within the '{workspace}' workspace.")
|
|
159
|
+
|
|
170
160
|
request_id = rr_filt["Request Id"].iloc[0]
|
|
171
161
|
|
|
172
162
|
dataset_id = resolve_dataset_id(dataset=dataset, workspace=workspace)
|
sempy_labs/_translations.py
CHANGED
|
@@ -35,7 +35,7 @@ def translate_semantic_model(
|
|
|
35
35
|
from synapse.ml.services import Translate
|
|
36
36
|
from pyspark.sql.functions import col, flatten
|
|
37
37
|
from pyspark.sql import SparkSession
|
|
38
|
-
from .tom import connect_semantic_model
|
|
38
|
+
from sempy_labs.tom import connect_semantic_model
|
|
39
39
|
|
|
40
40
|
if isinstance(languages, str):
|
|
41
41
|
languages = [languages]
|
sempy_labs/_vertipaq.py
CHANGED
|
@@ -56,9 +56,7 @@ def vertipaq_analyzer(
|
|
|
56
56
|
"ignore", message="createDataFrame attempted Arrow optimization*"
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
workspace_id = fabric.get_workspace_id()
|
|
61
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
59
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
62
60
|
|
|
63
61
|
if lakehouse_workspace is None:
|
|
64
62
|
lakehouse_workspace = workspace
|
|
@@ -102,9 +100,7 @@ def vertipaq_analyzer(
|
|
|
102
100
|
dfI_filt = dfI[(dfI["Id"] == sqlEndpointId)]
|
|
103
101
|
|
|
104
102
|
if len(dfI_filt) == 0:
|
|
105
|
-
|
|
106
|
-
f"{icons.red_dot} The lakehouse (SQL Endpoint) used by the '{dataset}' semantic model does not reside in the '{lakehouse_workspace}' workspace. Please update the lakehouse_workspace parameter."
|
|
107
|
-
)
|
|
103
|
+
raise ValueError(f"{icons.red_dot} The lakehouse (SQL Endpoint) used by the '{dataset}' semantic model does not reside in the '{lakehouse_workspace}' workspace. Please update the lakehouse_workspace parameter.")
|
|
108
104
|
else:
|
|
109
105
|
lakehouseName = dfI_filt["Display Name"].iloc[0]
|
|
110
106
|
|
|
@@ -437,10 +433,7 @@ def vertipaq_analyzer(
|
|
|
437
433
|
if export in ["table", "zip"]:
|
|
438
434
|
lakeAttach = lakehouse_attached()
|
|
439
435
|
if lakeAttach is False:
|
|
440
|
-
|
|
441
|
-
f"{icons.red_dot} In order to save the Vertipaq Analyzer results, a lakehouse must be attached to the notebook. Please attach a lakehouse to this notebook."
|
|
442
|
-
)
|
|
443
|
-
return
|
|
436
|
+
raise ValueError(f"{icons.red_dot} In order to save the Vertipaq Analyzer results, a lakehouse must be attached to the notebook. Please attach a lakehouse to this notebook.")
|
|
444
437
|
|
|
445
438
|
if export == "table":
|
|
446
439
|
spark = SparkSession.builder.getOrCreate()
|
|
@@ -40,9 +40,7 @@ def direct_lake_schema_compare(
|
|
|
40
40
|
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
workspace_id = fabric.get_workspace_id()
|
|
45
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
43
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
46
44
|
|
|
47
45
|
if lakehouse_workspace is None:
|
|
48
46
|
lakehouse_workspace = workspace
|
|
@@ -57,14 +55,10 @@ def direct_lake_schema_compare(
|
|
|
57
55
|
dfI_filt = dfI[(dfI["Id"] == sqlEndpointId)]
|
|
58
56
|
|
|
59
57
|
if len(dfI_filt) == 0:
|
|
60
|
-
|
|
61
|
-
f"{icons.red_dot} The SQL Endpoint in the '{dataset}' semantic model in the '{workspace} workspace does not point to the '{lakehouse}' lakehouse in the '{lakehouse_workspace}' workspace as specified."
|
|
62
|
-
)
|
|
63
|
-
return
|
|
58
|
+
raise ValueError(f"{icons.red_dot} The SQL Endpoint in the '{dataset}' semantic model in the '{workspace} workspace does not point to the '{lakehouse}' lakehouse in the '{lakehouse_workspace}' workspace as specified.")
|
|
64
59
|
|
|
65
60
|
if not any(r["Mode"] == "DirectLake" for i, r in dfP.iterrows()):
|
|
66
|
-
|
|
67
|
-
return
|
|
61
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake mode.")
|
|
68
62
|
|
|
69
63
|
dfT = list_tables(dataset, workspace)
|
|
70
64
|
dfC = fabric.list_columns(dataset=dataset, workspace=workspace)
|
|
@@ -46,8 +46,7 @@ def direct_lake_schema_sync(
|
|
|
46
46
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
47
47
|
import System
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
workspace = fabric.resolve_workspace_name()
|
|
49
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
51
50
|
|
|
52
51
|
if lakehouse_workspace is None:
|
|
53
52
|
lakehouse_workspace = workspace
|
|
@@ -62,10 +61,7 @@ def direct_lake_schema_sync(
|
|
|
62
61
|
dfI_filt = dfI[(dfI["Id"] == sqlEndpointId)]
|
|
63
62
|
|
|
64
63
|
if len(dfI_filt) == 0:
|
|
65
|
-
|
|
66
|
-
f"{icons.red_dot} The SQL Endpoint in the '{dataset}' semantic model in the '{workspace} workspace does not point to the '{lakehouse}' lakehouse in the '{lakehouse_workspace}' workspace as specified."
|
|
67
|
-
)
|
|
68
|
-
return
|
|
64
|
+
raise ValueError(f"{icons.red_dot} The SQL Endpoint in the '{dataset}' semantic model in the '{workspace} workspace does not point to the '{lakehouse}' lakehouse in the '{lakehouse_workspace}' workspace as specified.")
|
|
69
65
|
|
|
70
66
|
dfP = fabric.list_partitions(dataset=dataset, workspace=workspace)
|
|
71
67
|
dfP_filt = dfP[dfP["Source Type"] == "Entity"]
|
|
@@ -23,17 +23,13 @@ def check_fallback_reason(dataset: str, workspace: Optional[str] = None):
|
|
|
23
23
|
The tables in the semantic model and their fallback reason.
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
workspace_id = fabric.get_workspace_id()
|
|
28
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
26
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
29
27
|
|
|
30
28
|
dfP = fabric.list_partitions(dataset=dataset, workspace=workspace)
|
|
31
29
|
dfP_filt = dfP[dfP["Mode"] == "DirectLake"]
|
|
32
30
|
|
|
33
31
|
if len(dfP_filt) == 0:
|
|
34
|
-
|
|
35
|
-
f"{icons.yellow_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models."
|
|
36
|
-
)
|
|
32
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models.")
|
|
37
33
|
else:
|
|
38
34
|
df = fabric.evaluate_dax(
|
|
39
35
|
dataset=dataset,
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import sempy
|
|
2
2
|
import sempy.fabric as fabric
|
|
3
|
-
from sempy_labs._helper_functions import
|
|
4
|
-
resolve_lakehouse_name,
|
|
5
|
-
resolve_workspace_name_and_id,
|
|
6
|
-
)
|
|
3
|
+
from sempy_labs._helper_functions import resolve_lakehouse_name
|
|
7
4
|
from sempy_labs._list_functions import list_lakehouses
|
|
8
5
|
from typing import Optional
|
|
9
6
|
import sempy_labs._icons as icons
|
|
@@ -30,7 +27,7 @@ def get_shared_expression(
|
|
|
30
27
|
Shows the expression which can be used to connect a Direct Lake semantic model to its SQL Endpoint.
|
|
31
28
|
"""
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
34
31
|
if lakehouse is None:
|
|
35
32
|
lakehouse_id = fabric.get_lakehouse_id()
|
|
36
33
|
lakehouse = resolve_lakehouse_name(lakehouse_id)
|
|
@@ -43,10 +40,7 @@ def get_shared_expression(
|
|
|
43
40
|
provStatus = lakeDetail["SQL Endpoint Provisioning Status"].iloc[0]
|
|
44
41
|
|
|
45
42
|
if provStatus == "InProgress":
|
|
46
|
-
|
|
47
|
-
f"{icons.red_dot} The SQL Endpoint for the '{lakehouse}' lakehouse within the '{workspace}' workspace has not yet been provisioned. Please wait until it has been provisioned."
|
|
48
|
-
)
|
|
49
|
-
return
|
|
43
|
+
raise ValueError(f"{icons.red_dot} The SQL Endpoint for the '{lakehouse}' lakehouse within the '{workspace}' workspace has not yet been provisioned. Please wait until it has been provisioned.")
|
|
50
44
|
|
|
51
45
|
sh = (
|
|
52
46
|
'let\n\tdatabase = Sql.Database("'
|
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
|
4
4
|
from typing import List, Optional, Union
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def get_direct_lake_guardrails():
|
|
7
|
+
def get_direct_lake_guardrails() -> pd.DataFrame:
|
|
8
8
|
"""
|
|
9
9
|
Shows the guardrails for when Direct Lake semantic models will fallback to Direct Query based on Microsoft's `online documentation <https://learn.microsoft.com/power-bi/enterprise/directlake-overview>`_.
|
|
10
10
|
|
|
@@ -44,9 +44,7 @@ def get_sku_size(workspace: Optional[str] = None):
|
|
|
44
44
|
The SKU size for a workspace.
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
workspace_id = fabric.get_workspace_id()
|
|
49
|
-
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
47
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
50
48
|
|
|
51
49
|
dfC = fabric.list_capacities()
|
|
52
50
|
dfW = fabric.list_workspaces().sort_values(by="Name", ascending=True)
|
|
@@ -62,7 +60,7 @@ def get_sku_size(workspace: Optional[str] = None):
|
|
|
62
60
|
return sku_value
|
|
63
61
|
|
|
64
62
|
|
|
65
|
-
def get_directlake_guardrails_for_sku(sku_size: str):
|
|
63
|
+
def get_directlake_guardrails_for_sku(sku_size: str) -> pd.DataFrame:
|
|
66
64
|
"""
|
|
67
65
|
Shows the guardrails for Direct Lake based on the SKU used by your workspace's capacity.
|
|
68
66
|
* Use the result of the 'get_sku_size' function as an input for this function's sku_size parameter.*
|
|
@@ -8,7 +8,7 @@ from sempy._utils._log import log
|
|
|
8
8
|
import sempy_labs._icons as icons
|
|
9
9
|
|
|
10
10
|
@log
|
|
11
|
-
def list_direct_lake_model_calc_tables(dataset: str, workspace: Optional[str] = None):
|
|
11
|
+
def list_direct_lake_model_calc_tables(dataset: str, workspace: Optional[str] = None) -> pd.DataFrame:
|
|
12
12
|
"""
|
|
13
13
|
Shows the calculated tables and their respective DAX expression for a Direct Lake model (which has been migrated from import/DirectQuery).
|
|
14
14
|
|
|
@@ -27,8 +27,7 @@ def list_direct_lake_model_calc_tables(dataset: str, workspace: Optional[str] =
|
|
|
27
27
|
A pandas dataframe showing the calculated tables which were migrated to Direct Lake and whose DAX expressions are stored as model annotations.
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
workspace = fabric.resolve_workspace_name()
|
|
30
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
32
31
|
|
|
33
32
|
df = pd.DataFrame(columns=["Table Name", "Source Expression"])
|
|
34
33
|
|
|
@@ -39,7 +38,7 @@ def list_direct_lake_model_calc_tables(dataset: str, workspace: Optional[str] =
|
|
|
39
38
|
is_direct_lake = tom.is_direct_lake()
|
|
40
39
|
|
|
41
40
|
if not is_direct_lake:
|
|
42
|
-
|
|
41
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake mode.")
|
|
43
42
|
else:
|
|
44
43
|
dfA = list_annotations(dataset, workspace)
|
|
45
44
|
dfT = list_tables(dataset, workspace)
|
|
@@ -30,8 +30,7 @@ def show_unsupported_direct_lake_objects(
|
|
|
30
30
|
|
|
31
31
|
pd.options.mode.chained_assignment = None
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
workspace = fabric.resolve_workspace_name()
|
|
33
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
35
34
|
|
|
36
35
|
dfT = list_tables(dataset, workspace)
|
|
37
36
|
dfC = fabric.list_columns(dataset=dataset, workspace=workspace)
|
|
@@ -40,7 +40,7 @@ def update_direct_lake_model_lakehouse_connection(
|
|
|
40
40
|
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
workspace = fabric.resolve_workspace_name(workspace)
|
|
44
44
|
|
|
45
45
|
if lakehouse_workspace is None:
|
|
46
46
|
lakehouse_workspace = workspace
|
|
@@ -54,17 +54,13 @@ def update_direct_lake_model_lakehouse_connection(
|
|
|
54
54
|
dfI_filt = dfI[(dfI["Display Name"] == lakehouse)]
|
|
55
55
|
|
|
56
56
|
if len(dfI_filt) == 0:
|
|
57
|
-
|
|
58
|
-
f"{icons.red_dot} The '{lakehouse}' lakehouse does not exist within the '{lakehouse_workspace}' workspace. Therefore it cannot be used to support the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
59
|
-
)
|
|
57
|
+
raise ValueError(f"{icons.red_dot} The '{lakehouse}' lakehouse does not exist within the '{lakehouse_workspace}' workspace. Therefore it cannot be used to support the '{dataset}' semantic model within the '{workspace}' workspace.")
|
|
60
58
|
|
|
61
59
|
dfP = fabric.list_partitions(dataset=dataset, workspace=workspace)
|
|
62
60
|
dfP_filt = dfP[dfP["Mode"] == "DirectLake"]
|
|
63
61
|
|
|
64
62
|
if len(dfP_filt) == 0:
|
|
65
|
-
|
|
66
|
-
f"{icons.yellow_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models."
|
|
67
|
-
)
|
|
63
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models.")
|
|
68
64
|
else:
|
|
69
65
|
with connect_semantic_model(
|
|
70
66
|
dataset=dataset, readonly=False, workspace=workspace
|