semantic-link-labs 0.4.1__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.1.dist-info/LICENSE +21 -0
- semantic_link_labs-0.4.1.dist-info/METADATA +22 -0
- semantic_link_labs-0.4.1.dist-info/RECORD +52 -0
- semantic_link_labs-0.4.1.dist-info/WHEEL +5 -0
- semantic_link_labs-0.4.1.dist-info/top_level.txt +1 -0
- sempy_labs/__init__.py +154 -0
- sempy_labs/_ai.py +496 -0
- sempy_labs/_clear_cache.py +39 -0
- sempy_labs/_connections.py +234 -0
- sempy_labs/_dax.py +70 -0
- sempy_labs/_generate_semantic_model.py +280 -0
- sempy_labs/_helper_functions.py +506 -0
- sempy_labs/_icons.py +4 -0
- sempy_labs/_list_functions.py +1372 -0
- sempy_labs/_model_auto_build.py +143 -0
- sempy_labs/_model_bpa.py +1354 -0
- sempy_labs/_model_dependencies.py +341 -0
- sempy_labs/_one_lake_integration.py +155 -0
- sempy_labs/_query_scale_out.py +447 -0
- sempy_labs/_refresh_semantic_model.py +184 -0
- sempy_labs/_tom.py +3766 -0
- sempy_labs/_translations.py +378 -0
- sempy_labs/_vertipaq.py +893 -0
- sempy_labs/directlake/__init__.py +45 -0
- sempy_labs/directlake/_directlake_schema_compare.py +110 -0
- sempy_labs/directlake/_directlake_schema_sync.py +128 -0
- sempy_labs/directlake/_fallback.py +62 -0
- sempy_labs/directlake/_get_directlake_lakehouse.py +69 -0
- sempy_labs/directlake/_get_shared_expression.py +59 -0
- sempy_labs/directlake/_guardrails.py +84 -0
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +54 -0
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +89 -0
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +81 -0
- sempy_labs/directlake/_update_directlake_partition_entity.py +64 -0
- sempy_labs/directlake/_warm_cache.py +210 -0
- sempy_labs/lakehouse/__init__.py +24 -0
- sempy_labs/lakehouse/_get_lakehouse_columns.py +81 -0
- sempy_labs/lakehouse/_get_lakehouse_tables.py +250 -0
- sempy_labs/lakehouse/_lakehouse.py +85 -0
- sempy_labs/lakehouse/_shortcuts.py +296 -0
- sempy_labs/migration/__init__.py +29 -0
- sempy_labs/migration/_create_pqt_file.py +239 -0
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +429 -0
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py +150 -0
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +524 -0
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +165 -0
- sempy_labs/migration/_migration_validation.py +227 -0
- sempy_labs/migration/_refresh_calc_tables.py +129 -0
- sempy_labs/report/__init__.py +35 -0
- sempy_labs/report/_generate_report.py +253 -0
- sempy_labs/report/_report_functions.py +855 -0
- sempy_labs/report/_report_rebind.py +131 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
import sempy
|
|
2
|
+
import sempy.fabric as fabric
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sempy_labs._helper_functions import resolve_dataset_id
|
|
5
|
+
from typing import List, Optional, Union
|
|
6
|
+
import sempy_labs._icons as icons
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def qso_sync(dataset: str, workspace: Optional[str] = None):
|
|
10
|
+
"""
|
|
11
|
+
Triggers a query scale-out sync of read-only replicas for the specified dataset from the specified workspace.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
dataset : str
|
|
16
|
+
Name of the semantic model.
|
|
17
|
+
workspace : str, default=None
|
|
18
|
+
The Fabric workspace name.
|
|
19
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
20
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# https://learn.microsoft.com/en-us/rest/api/power-bi/datasets/trigger-query-scale-out-sync-in-group
|
|
28
|
+
|
|
29
|
+
if workspace is None:
|
|
30
|
+
workspace_id = fabric.get_workspace_id()
|
|
31
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
32
|
+
else:
|
|
33
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
34
|
+
|
|
35
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
36
|
+
|
|
37
|
+
client = fabric.PowerBIRestClient()
|
|
38
|
+
response = client.post(
|
|
39
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/queryScaleOut/sync"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if response.status_code == 200:
|
|
43
|
+
print(
|
|
44
|
+
f"{icons.green_dot} QSO sync initiated for the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
45
|
+
)
|
|
46
|
+
else:
|
|
47
|
+
print(
|
|
48
|
+
f"{icons.red_dot} QSO sync failed for the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def qso_sync_status(dataset: str, workspace: Optional[str] = None):
|
|
53
|
+
"""
|
|
54
|
+
Returns the query scale-out sync status for the specified dataset from the specified workspace.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
dataset : str
|
|
59
|
+
Name of the semantic model.
|
|
60
|
+
workspace : str, default=None
|
|
61
|
+
The Fabric workspace name.
|
|
62
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
63
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
# https://learn.microsoft.com/en-us/rest/api/power-bi/datasets/get-query-scale-out-sync-status-in-group
|
|
71
|
+
|
|
72
|
+
df = pd.DataFrame(
|
|
73
|
+
columns=[
|
|
74
|
+
"Scale Out Status",
|
|
75
|
+
"Sync Start Time",
|
|
76
|
+
"Sync End Time",
|
|
77
|
+
"Commit Version",
|
|
78
|
+
"Commit Timestamp",
|
|
79
|
+
"Target Sync Version",
|
|
80
|
+
"Target Sync Timestamp",
|
|
81
|
+
"Trigger Reason",
|
|
82
|
+
"Min Active Read Version",
|
|
83
|
+
"Min Active Read Timestamp",
|
|
84
|
+
]
|
|
85
|
+
)
|
|
86
|
+
dfRep = pd.DataFrame(
|
|
87
|
+
columns=["Replica ID", "Replica Type", "Replica Version", "Replica Timestamp"]
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if workspace is None:
|
|
91
|
+
workspace_id = fabric.get_workspace_id()
|
|
92
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
93
|
+
else:
|
|
94
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
95
|
+
|
|
96
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
97
|
+
|
|
98
|
+
client = fabric.PowerBIRestClient()
|
|
99
|
+
response = client.get(
|
|
100
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/queryScaleOut/syncStatus"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if response.status_code == 200:
|
|
104
|
+
o = response.json()
|
|
105
|
+
sos = o["scaleOutStatus"]
|
|
106
|
+
|
|
107
|
+
if sos == "Enabled":
|
|
108
|
+
new_data = {
|
|
109
|
+
"Scale Out Status": o["scaleOutStatus"],
|
|
110
|
+
"Sync Start Time": o["syncStartTime"],
|
|
111
|
+
"Sync End Time": o["syncEndTime"],
|
|
112
|
+
"Commit Version": o["commitVersion"],
|
|
113
|
+
"Commit Timestamp": o["commitTimestamp"],
|
|
114
|
+
"Target Sync Version": o["targetSyncVersion"],
|
|
115
|
+
"Target Sync Timestamp": o["targetSyncTimestamp"],
|
|
116
|
+
"Trigger Reason": o["triggerReason"],
|
|
117
|
+
"Min Active Read Version": o["minActiveReadVersion"],
|
|
118
|
+
"Min Active Read Timestamp": o["minActiveReadTimestamp"],
|
|
119
|
+
}
|
|
120
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
121
|
+
|
|
122
|
+
for r in o["scaleOutReplicas"]:
|
|
123
|
+
new_data = {
|
|
124
|
+
"Replica ID": r["replicaId"],
|
|
125
|
+
"Replica Type": r["replicaType"],
|
|
126
|
+
"Replica Version": str(r["replicaVersion"]),
|
|
127
|
+
"Replica Timestamp": r["replicaTimestamp"],
|
|
128
|
+
}
|
|
129
|
+
dfRep = pd.concat(
|
|
130
|
+
[dfRep, pd.DataFrame(new_data, index=[0])], ignore_index=True
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
df["Sync Start Time"] = pd.to_datetime(df["Sync Start Time"])
|
|
134
|
+
df["Sync End Time"] = pd.to_datetime(df["Sync End Time"])
|
|
135
|
+
df["Commit Timestamp"] = pd.to_datetime(df["Commit Timestamp"])
|
|
136
|
+
df["Target Sync Timestamp"] = pd.to_datetime(df["Target Sync Timestamp"])
|
|
137
|
+
df["Min Active Read Timestamp"] = pd.to_datetime(
|
|
138
|
+
df["Min Active Read Timestamp"]
|
|
139
|
+
)
|
|
140
|
+
dfRep["Replica Timestamp"] = pd.to_datetime(dfRep["Replica Timestamp"])
|
|
141
|
+
df["Commit Version"] = df["Commit Version"].astype("int")
|
|
142
|
+
df["Target Sync Version"] = df["Target Sync Version"].astype("int")
|
|
143
|
+
df["Min Active Read Version"] = df["Min Active Read Version"].astype("int")
|
|
144
|
+
|
|
145
|
+
return df, dfRep
|
|
146
|
+
else:
|
|
147
|
+
print(f"{sos}\n\n")
|
|
148
|
+
return df, dfRep
|
|
149
|
+
else:
|
|
150
|
+
return response.status_code
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def disable_qso(dataset: str, workspace: Optional[str] = None):
|
|
154
|
+
"""
|
|
155
|
+
Sets the max read-only replicas to 0, disabling query scale out.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
dataset : str
|
|
160
|
+
Name of the semantic model.
|
|
161
|
+
workspace : str, default=None
|
|
162
|
+
The Fabric workspace name.
|
|
163
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
164
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
if workspace is None:
|
|
172
|
+
workspace_id = fabric.get_workspace_id()
|
|
173
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
174
|
+
else:
|
|
175
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
176
|
+
|
|
177
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
178
|
+
|
|
179
|
+
request_body = {"queryScaleOutSettings": {"maxReadOnlyReplicas": "0"}}
|
|
180
|
+
|
|
181
|
+
client = fabric.PowerBIRestClient()
|
|
182
|
+
response = client.patch(
|
|
183
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}", json=request_body
|
|
184
|
+
)
|
|
185
|
+
if response.status_code == 200:
|
|
186
|
+
df = list_qso_settings(dataset=dataset, workspace=workspace)
|
|
187
|
+
print(
|
|
188
|
+
f"{icons.green_dot} Query scale out has been disabled for the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
189
|
+
)
|
|
190
|
+
return df
|
|
191
|
+
else:
|
|
192
|
+
return f"{icons.red_dot} {response.status_code}"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def set_qso(
|
|
196
|
+
dataset: str,
|
|
197
|
+
auto_sync: Optional[bool] = True,
|
|
198
|
+
max_read_only_replicas: Optional[int] = -1,
|
|
199
|
+
workspace: Optional[str] = None,
|
|
200
|
+
):
|
|
201
|
+
"""
|
|
202
|
+
Sets the query scale out settings for a semantic model.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
dataset : str
|
|
207
|
+
Name of the semantic model.
|
|
208
|
+
auto_sync : bool, default=True
|
|
209
|
+
Whether the semantic model automatically syncs read-only replicas.
|
|
210
|
+
max_read_only_replicas : int, default=-1
|
|
211
|
+
To enable semantic model scale-out, set max_read_only_replicas to -1, or any non-0 value. A value of -1 allows Power BI to create as many read-only replicas as your Power BI capacity supports. You can also explicitly set the replica count to a value lower than that of the capacity maximum. Setting max_read_only_replicas to -1 is recommended.
|
|
212
|
+
workspace : str, default=None
|
|
213
|
+
The Fabric workspace name.
|
|
214
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
215
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
# https://learn.microsoft.com/en-us/rest/api/power-bi/datasets/update-dataset-in-group
|
|
223
|
+
|
|
224
|
+
if workspace is None:
|
|
225
|
+
workspace_id = fabric.get_workspace_id()
|
|
226
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
227
|
+
else:
|
|
228
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
229
|
+
|
|
230
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
231
|
+
|
|
232
|
+
if max_read_only_replicas == 0:
|
|
233
|
+
disable_qso(dataset=dataset, workspace=workspace)
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
request_body = {
|
|
237
|
+
"queryScaleOutSettings": {
|
|
238
|
+
"autoSyncReadOnlyReplicas": auto_sync,
|
|
239
|
+
"maxReadOnlyReplicas": str(max_read_only_replicas),
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
ssm = set_semantic_model_storage_format(
|
|
244
|
+
dataset=dataset, storage_format="Large", workspace=workspace
|
|
245
|
+
)
|
|
246
|
+
if ssm == 200:
|
|
247
|
+
client = fabric.PowerBIRestClient()
|
|
248
|
+
response = client.patch(
|
|
249
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}",
|
|
250
|
+
json=request_body,
|
|
251
|
+
)
|
|
252
|
+
if response.status_code == 200:
|
|
253
|
+
df = list_qso_settings(dataset=dataset, workspace=workspace)
|
|
254
|
+
print(
|
|
255
|
+
f"{icons.green_dot} Query scale out has been set on the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
256
|
+
)
|
|
257
|
+
return df
|
|
258
|
+
else:
|
|
259
|
+
return f"{icons.red_dot} {response.status_code}"
|
|
260
|
+
else:
|
|
261
|
+
print(
|
|
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
|
+
|
|
269
|
+
|
|
270
|
+
def set_semantic_model_storage_format(
|
|
271
|
+
dataset: str, storage_format: str, workspace: Optional[str] = None
|
|
272
|
+
):
|
|
273
|
+
"""
|
|
274
|
+
Sets the semantic model storage format.
|
|
275
|
+
|
|
276
|
+
Parameters
|
|
277
|
+
----------
|
|
278
|
+
dataset : str
|
|
279
|
+
Name of the semantic model.
|
|
280
|
+
storage_format : str
|
|
281
|
+
The storage format for the semantic model. Valid options: 'Large', 'Small'.
|
|
282
|
+
workspace : str, default=None
|
|
283
|
+
The Fabric workspace name.
|
|
284
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
285
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
286
|
+
|
|
287
|
+
Returns
|
|
288
|
+
-------
|
|
289
|
+
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
if workspace is None:
|
|
293
|
+
workspace_id = fabric.get_workspace_id()
|
|
294
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
295
|
+
else:
|
|
296
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
297
|
+
|
|
298
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
299
|
+
|
|
300
|
+
storage_format = storage_format.capitalize()
|
|
301
|
+
|
|
302
|
+
if storage_format == "Abf":
|
|
303
|
+
storage_format = "Small"
|
|
304
|
+
elif storage_format.startswith("Premium"):
|
|
305
|
+
storage_format = "Large"
|
|
306
|
+
|
|
307
|
+
storageFormats = ["Small", "Large"]
|
|
308
|
+
|
|
309
|
+
if storage_format == "Large":
|
|
310
|
+
request_body = {"targetStorageMode": "PremiumFiles"}
|
|
311
|
+
elif storage_format == "Small":
|
|
312
|
+
request_body = {"targetStorageMode": "Abf"}
|
|
313
|
+
else:
|
|
314
|
+
print(
|
|
315
|
+
f"{icons.red_dot} Invalid storage format value. Valid options: {storageFormats}."
|
|
316
|
+
)
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
client = fabric.PowerBIRestClient()
|
|
320
|
+
response = client.patch(
|
|
321
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}", json=request_body
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if response.status_code == 200:
|
|
325
|
+
return print(
|
|
326
|
+
f"{icons.green_dot} Semantic model storage format set to '{storage_format}'."
|
|
327
|
+
)
|
|
328
|
+
else:
|
|
329
|
+
return f"{icons.red_dot} {response.status_code}"
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def list_qso_settings(dataset: Optional[str] = None, workspace: Optional[str] = None):
|
|
333
|
+
"""
|
|
334
|
+
Shows the query scale out settings for a semantic model (or all semantic models within a workspace).
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
dataset : str, default=None
|
|
339
|
+
Name of the semantic model.
|
|
340
|
+
workspace : str, default=None
|
|
341
|
+
The Fabric workspace name.
|
|
342
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
343
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
344
|
+
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
pandas.DataFrame
|
|
348
|
+
A pandas dataframe showing the query scale out settings.
|
|
349
|
+
"""
|
|
350
|
+
|
|
351
|
+
if workspace is None:
|
|
352
|
+
workspace_id = fabric.get_workspace_id()
|
|
353
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
354
|
+
else:
|
|
355
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
356
|
+
|
|
357
|
+
if dataset is not None:
|
|
358
|
+
dataset_id = resolve_dataset_id(dataset, workspace)
|
|
359
|
+
|
|
360
|
+
workspace_id = fabric.get_workspace_id()
|
|
361
|
+
df = pd.DataFrame(
|
|
362
|
+
columns=[
|
|
363
|
+
"Dataset Id",
|
|
364
|
+
"Dataset Name",
|
|
365
|
+
"Storage Mode",
|
|
366
|
+
"QSO Auto Sync Enabled",
|
|
367
|
+
"QSO Max Read Only Replicas",
|
|
368
|
+
]
|
|
369
|
+
)
|
|
370
|
+
client = fabric.PowerBIRestClient()
|
|
371
|
+
response = client.get(f"/v1.0/myorg/groups/{workspace_id}/datasets")
|
|
372
|
+
for v in response.json()["value"]:
|
|
373
|
+
tsm = v["targetStorageMode"]
|
|
374
|
+
if tsm == "Abf":
|
|
375
|
+
sm = "Small"
|
|
376
|
+
else:
|
|
377
|
+
sm = "Large"
|
|
378
|
+
new_data = {
|
|
379
|
+
"Dataset Id": v["id"],
|
|
380
|
+
"Dataset Name": v["name"],
|
|
381
|
+
"Storage Mode": sm,
|
|
382
|
+
"QSO Auto Sync Enabled": v["queryScaleOutSettings"][
|
|
383
|
+
"autoSyncReadOnlyReplicas"
|
|
384
|
+
],
|
|
385
|
+
"QSO Max Read Only Replicas": v["queryScaleOutSettings"][
|
|
386
|
+
"maxReadOnlyReplicas"
|
|
387
|
+
],
|
|
388
|
+
}
|
|
389
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
390
|
+
|
|
391
|
+
df["QSO Auto Sync Enabled"] = df["QSO Auto Sync Enabled"].astype("bool")
|
|
392
|
+
df["QSO Max Read Only Replicas"] = df["QSO Max Read Only Replicas"].astype("int")
|
|
393
|
+
|
|
394
|
+
if dataset is not None:
|
|
395
|
+
df = df[df["Dataset Id"] == dataset_id]
|
|
396
|
+
|
|
397
|
+
return df
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def set_workspace_default_storage_format(
|
|
401
|
+
storage_format: str, workspace: Optional[str] = None
|
|
402
|
+
):
|
|
403
|
+
"""
|
|
404
|
+
Sets the default storage format for semantic models within a workspace.
|
|
405
|
+
|
|
406
|
+
Parameters
|
|
407
|
+
----------
|
|
408
|
+
storage_format : str
|
|
409
|
+
The storage format for the semantic model. Valid options: 'Large', 'Small'.
|
|
410
|
+
workspace : str, default=None
|
|
411
|
+
The Fabric workspace name.
|
|
412
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
413
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
414
|
+
|
|
415
|
+
Returns
|
|
416
|
+
-------
|
|
417
|
+
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
# https://learn.microsoft.com/en-us/rest/api/power-bi/groups/update-group#defaultdatasetstorageformat
|
|
421
|
+
|
|
422
|
+
storageFormats = ["Small", "Large"]
|
|
423
|
+
|
|
424
|
+
storage_format = storage_format.capitalize()
|
|
425
|
+
|
|
426
|
+
if storage_format not in storageFormats:
|
|
427
|
+
print(
|
|
428
|
+
f"Invalid storage format. Please choose from these options: {storageFormats}."
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
if workspace is None:
|
|
432
|
+
workspace_id = fabric.get_workspace_id()
|
|
433
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
434
|
+
else:
|
|
435
|
+
workspace_id = fabric.resolve_workspace_id(workspace)
|
|
436
|
+
|
|
437
|
+
request_body = {"name": workspace, "defaultDatasetStorageFormat": storage_format}
|
|
438
|
+
|
|
439
|
+
client = fabric.PowerBIRestClient()
|
|
440
|
+
response = client.patch(f"/v1.0/myorg/groups/{workspace_id}", json=request_body)
|
|
441
|
+
|
|
442
|
+
if response.status_code == 200:
|
|
443
|
+
print(
|
|
444
|
+
f"{icons.green_dot} The default storage format for the '{workspace}' workspace has been updated to '{storage_format}."
|
|
445
|
+
)
|
|
446
|
+
else:
|
|
447
|
+
print(f"{icons.red_dot} {response.status_code}")
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import sempy
|
|
2
|
+
import sempy.fabric as fabric
|
|
3
|
+
import time
|
|
4
|
+
from sempy_labs._helper_functions import resolve_dataset_id
|
|
5
|
+
from typing import List, Optional, Union
|
|
6
|
+
from sempy._utils._log import log
|
|
7
|
+
import sempy_labs._icons as icons
|
|
8
|
+
from sempy_labs._helper_functions import resolve_workspace_name_and_id
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@log
|
|
12
|
+
def refresh_semantic_model(
|
|
13
|
+
dataset: str,
|
|
14
|
+
tables: Optional[Union[str, List[str]]] = None,
|
|
15
|
+
partitions: Optional[Union[str, List[str]]] = None,
|
|
16
|
+
refresh_type: Optional[str] = None,
|
|
17
|
+
retry_count: Optional[int] = 0,
|
|
18
|
+
apply_refresh_policy: Optional[bool] = True,
|
|
19
|
+
workspace: Optional[str] = None,
|
|
20
|
+
):
|
|
21
|
+
"""
|
|
22
|
+
Refreshes a semantic model.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
dataset : str
|
|
27
|
+
Name of the semantic model.
|
|
28
|
+
tables : str, List[str], default=None
|
|
29
|
+
A string or a list of tables to refresh.
|
|
30
|
+
partitions: str, List[str], default=None
|
|
31
|
+
A string or a list of partitions to refresh. Partitions must be formatted as such: 'Table Name'[Partition Name].
|
|
32
|
+
refresh_type : str, default='full'
|
|
33
|
+
The type of processing to perform. Types align with the TMSL refresh command types: full, clearValues, calculate, dataOnly, automatic, and defragment. The add type isn't supported. Defaults to "full".
|
|
34
|
+
retry_count : int, default=0
|
|
35
|
+
Number of times the operation retries before failing.
|
|
36
|
+
apply_refresh_policy : bool, default=True
|
|
37
|
+
If an incremental refresh policy is defined, determines whether to apply the policy. Modes are true or false. If the policy isn't applied, the full process leaves partition definitions unchanged, and fully refreshes all partitions in the table. If commitMode is transactional, applyRefreshPolicy can be true or false. If commitMode is partialBatch, applyRefreshPolicy of true isn't supported, and applyRefreshPolicy must be set to false.
|
|
38
|
+
workspace : str, default=None
|
|
39
|
+
The Fabric workspace name.
|
|
40
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
41
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
if workspace == None:
|
|
45
|
+
workspace_id = fabric.get_workspace_id()
|
|
46
|
+
workspace = fabric.resolve_workspace_name(workspace_id)
|
|
47
|
+
|
|
48
|
+
if refresh_type is None:
|
|
49
|
+
refresh_type = "full"
|
|
50
|
+
|
|
51
|
+
if isinstance(tables, str):
|
|
52
|
+
tables = [tables]
|
|
53
|
+
if isinstance(partitions, str):
|
|
54
|
+
partitions = [partitions]
|
|
55
|
+
|
|
56
|
+
objects = []
|
|
57
|
+
|
|
58
|
+
if tables is not None:
|
|
59
|
+
objects = objects + [{"table": table} for table in tables]
|
|
60
|
+
if partitions is not None:
|
|
61
|
+
|
|
62
|
+
def extract_names(partition):
|
|
63
|
+
parts = partition.split("[")
|
|
64
|
+
table_name = parts[0].strip("'")
|
|
65
|
+
partition_name = parts[1].strip("]")
|
|
66
|
+
return {"table": table_name, "partition": partition_name}
|
|
67
|
+
|
|
68
|
+
objects = objects + [extract_names(partition) for partition in partitions]
|
|
69
|
+
|
|
70
|
+
refresh_type = (
|
|
71
|
+
refresh_type.lower().replace("only", "Only").replace("values", "Values")
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
refreshTypes = [
|
|
75
|
+
"full",
|
|
76
|
+
"automatic",
|
|
77
|
+
"dataOnly",
|
|
78
|
+
"calculate",
|
|
79
|
+
"clearValues",
|
|
80
|
+
"defragment",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
if refresh_type not in refreshTypes:
|
|
84
|
+
print(
|
|
85
|
+
f"{icons.red_dot} Invalid refresh type. Refresh type must be one of these values: {refreshTypes}."
|
|
86
|
+
)
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
if len(objects) == 0:
|
|
90
|
+
requestID = fabric.refresh_dataset(
|
|
91
|
+
dataset=dataset,
|
|
92
|
+
workspace=workspace,
|
|
93
|
+
refresh_type=refresh_type,
|
|
94
|
+
retry_count=retry_count,
|
|
95
|
+
apply_refresh_policy=apply_refresh_policy,
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
requestID = fabric.refresh_dataset(
|
|
99
|
+
dataset=dataset,
|
|
100
|
+
workspace=workspace,
|
|
101
|
+
refresh_type=refresh_type,
|
|
102
|
+
retry_count=retry_count,
|
|
103
|
+
apply_refresh_policy=apply_refresh_policy,
|
|
104
|
+
objects=objects,
|
|
105
|
+
)
|
|
106
|
+
print(
|
|
107
|
+
f"{icons.in_progress} Refresh of the '{dataset}' semantic model within the '{workspace}' workspace is in progress..."
|
|
108
|
+
)
|
|
109
|
+
if len(objects) != 0:
|
|
110
|
+
print(objects)
|
|
111
|
+
|
|
112
|
+
while True:
|
|
113
|
+
requestDetails = fabric.get_refresh_execution_details(
|
|
114
|
+
dataset=dataset, refresh_request_id=requestID, workspace=workspace
|
|
115
|
+
)
|
|
116
|
+
status = requestDetails.status
|
|
117
|
+
|
|
118
|
+
# Check if the refresh has completed
|
|
119
|
+
if status == "Completed":
|
|
120
|
+
break
|
|
121
|
+
elif status == "Failed":
|
|
122
|
+
print(
|
|
123
|
+
f"{icons.red_dot} The refresh of the '{dataset}' semantic model within the '{workspace}' workspace has failed."
|
|
124
|
+
)
|
|
125
|
+
return
|
|
126
|
+
elif status == "Cancelled":
|
|
127
|
+
print(
|
|
128
|
+
f"{icons.yellow_dot} The refresh of the '{dataset}' semantic model within the '{workspace}' workspace has been cancelled."
|
|
129
|
+
)
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
time.sleep(3)
|
|
133
|
+
|
|
134
|
+
print(
|
|
135
|
+
f"{icons.green_dot} Refresh of the '{dataset}' semantic model within the '{workspace}' workspace is complete."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@log
|
|
140
|
+
def cancel_dataset_refresh(
|
|
141
|
+
dataset: str, request_id: Optional[str] = None, workspace: Optional[str] = None
|
|
142
|
+
):
|
|
143
|
+
"""
|
|
144
|
+
Cancels the refresh of a semantic model which was executed via the `Enhanced Refresh API <https://learn.microsoft.com/power-bi/connect-data/asynchronous-refresh>`_
|
|
145
|
+
|
|
146
|
+
Parameters
|
|
147
|
+
----------
|
|
148
|
+
dataset : str
|
|
149
|
+
Name of the semantic model.
|
|
150
|
+
request_id : str, default=None
|
|
151
|
+
The request id of a semantic model refresh.
|
|
152
|
+
Defaults to finding the latest active refresh of the semantic model.
|
|
153
|
+
workspace : str, default=None
|
|
154
|
+
The Fabric workspace name.
|
|
155
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
156
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
(workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
160
|
+
|
|
161
|
+
rr = fabric.list_refresh_requests(dataset=dataset, workspace=workspace)
|
|
162
|
+
rr_filt = rr[rr["Status"] == "Unknown"]
|
|
163
|
+
|
|
164
|
+
if request_id == None:
|
|
165
|
+
if len(rr_filt) == 0:
|
|
166
|
+
print(
|
|
167
|
+
f"{icons.red_dot} There are no active Enhanced API refreshes of the '{dataset}' semantic model within the '{workspace}' workspace."
|
|
168
|
+
)
|
|
169
|
+
return
|
|
170
|
+
request_id = rr_filt["Request Id"].iloc[0]
|
|
171
|
+
|
|
172
|
+
dataset_id = resolve_dataset_id(dataset=dataset, workspace=workspace)
|
|
173
|
+
|
|
174
|
+
client = fabric.PowerBIRestClient()
|
|
175
|
+
|
|
176
|
+
response = client.delete(
|
|
177
|
+
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/refreshes/{request_id}"
|
|
178
|
+
)
|
|
179
|
+
if response.status_code == 200:
|
|
180
|
+
print(
|
|
181
|
+
f"{icons.green_dot} The '{request_id}' refresh request for the '{dataset}' semantic model within the '{workspace}' workspace has been cancelled."
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
print(response.status_code)
|