semantic-link-labs 0.5.0__py3-none-any.whl → 0.7.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.7.0.dist-info/METADATA +148 -0
- semantic_link_labs-0.7.0.dist-info/RECORD +111 -0
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +45 -15
- sempy_labs/_ai.py +42 -85
- sempy_labs/_bpa_translation/_translations_am-ET.po +828 -0
- sempy_labs/_bpa_translation/_translations_ar-AE.po +860 -0
- sempy_labs/_bpa_translation/_translations_cs-CZ.po +894 -0
- sempy_labs/_bpa_translation/_translations_da-DK.po +894 -0
- sempy_labs/_bpa_translation/_translations_de-DE.po +933 -0
- sempy_labs/_bpa_translation/_translations_el-GR.po +936 -0
- sempy_labs/_bpa_translation/_translations_es-ES.po +915 -0
- sempy_labs/_bpa_translation/_translations_fa-IR.po +883 -0
- sempy_labs/_bpa_translation/_translations_fr-FR.po +938 -0
- sempy_labs/_bpa_translation/_translations_ga-IE.po +912 -0
- sempy_labs/_bpa_translation/_translations_he-IL.po +855 -0
- sempy_labs/_bpa_translation/_translations_hi-IN.po +892 -0
- sempy_labs/_bpa_translation/_translations_hu-HU.po +910 -0
- sempy_labs/_bpa_translation/_translations_is-IS.po +887 -0
- sempy_labs/_bpa_translation/_translations_it-IT.po +931 -0
- sempy_labs/_bpa_translation/_translations_ja-JP.po +805 -0
- sempy_labs/_bpa_translation/_translations_nl-NL.po +924 -0
- sempy_labs/_bpa_translation/_translations_pl-PL.po +913 -0
- sempy_labs/_bpa_translation/_translations_pt-BR.po +909 -0
- sempy_labs/_bpa_translation/_translations_pt-PT.po +904 -0
- sempy_labs/_bpa_translation/_translations_ru-RU.po +909 -0
- sempy_labs/_bpa_translation/_translations_ta-IN.po +922 -0
- sempy_labs/_bpa_translation/_translations_te-IN.po +896 -0
- sempy_labs/_bpa_translation/_translations_th-TH.po +873 -0
- sempy_labs/_bpa_translation/_translations_zh-CN.po +767 -0
- sempy_labs/_bpa_translation/_translations_zu-ZA.po +916 -0
- sempy_labs/_clear_cache.py +12 -8
- sempy_labs/_connections.py +77 -70
- sempy_labs/_dax.py +7 -9
- sempy_labs/_generate_semantic_model.py +75 -90
- sempy_labs/_helper_functions.py +371 -20
- sempy_labs/_icons.py +23 -0
- sempy_labs/_list_functions.py +855 -427
- sempy_labs/_model_auto_build.py +4 -3
- sempy_labs/_model_bpa.py +307 -1118
- sempy_labs/_model_bpa_bulk.py +363 -0
- sempy_labs/_model_bpa_rules.py +831 -0
- sempy_labs/_model_dependencies.py +20 -16
- sempy_labs/_one_lake_integration.py +18 -12
- sempy_labs/_query_scale_out.py +116 -129
- sempy_labs/_refresh_semantic_model.py +23 -10
- sempy_labs/_translations.py +367 -288
- sempy_labs/_vertipaq.py +152 -123
- sempy_labs/directlake/__init__.py +7 -1
- sempy_labs/directlake/_directlake_schema_compare.py +33 -30
- sempy_labs/directlake/_directlake_schema_sync.py +60 -77
- sempy_labs/directlake/_dl_helper.py +233 -0
- sempy_labs/directlake/_get_directlake_lakehouse.py +7 -8
- sempy_labs/directlake/_get_shared_expression.py +5 -3
- sempy_labs/directlake/_guardrails.py +20 -16
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +17 -10
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +3 -2
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +10 -5
- sempy_labs/directlake/_update_directlake_partition_entity.py +169 -22
- sempy_labs/directlake/_warm_cache.py +7 -4
- sempy_labs/lakehouse/_get_lakehouse_columns.py +1 -1
- sempy_labs/lakehouse/_get_lakehouse_tables.py +65 -71
- sempy_labs/lakehouse/_lakehouse.py +5 -3
- sempy_labs/lakehouse/_shortcuts.py +20 -13
- sempy_labs/migration/__init__.py +1 -1
- sempy_labs/migration/_create_pqt_file.py +184 -186
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +240 -269
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py +78 -77
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +444 -425
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +96 -102
- sempy_labs/migration/_migration_validation.py +2 -2
- sempy_labs/migration/_refresh_calc_tables.py +94 -100
- sempy_labs/report/_BPAReportTemplate.json +232 -0
- sempy_labs/report/__init__.py +6 -2
- sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
- sempy_labs/report/_bpareporttemplate/.platform +11 -0
- sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
- sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
- sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
- sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
- sempy_labs/report/_generate_report.py +260 -139
- sempy_labs/report/_report_functions.py +90 -59
- sempy_labs/report/_report_rebind.py +40 -34
- sempy_labs/tom/__init__.py +1 -4
- sempy_labs/tom/_model.py +601 -181
- semantic_link_labs-0.5.0.dist-info/METADATA +0 -22
- semantic_link_labs-0.5.0.dist-info/RECORD +0 -53
- sempy_labs/directlake/_fallback.py +0 -58
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import sempy
|
|
2
1
|
import sempy.fabric as fabric
|
|
3
2
|
import pandas as pd
|
|
4
|
-
import json
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
5
6
|
from typing import Optional
|
|
6
|
-
from sempy_labs._helper_functions import
|
|
7
|
+
from sempy_labs._helper_functions import (
|
|
8
|
+
resolve_workspace_name_and_id,
|
|
9
|
+
_conv_b64,
|
|
10
|
+
resolve_report_id,
|
|
11
|
+
lro,
|
|
12
|
+
)
|
|
7
13
|
import sempy_labs._icons as icons
|
|
14
|
+
from sempy._utils._log import log
|
|
15
|
+
from sempy.fabric.exceptions import FabricHTTPException
|
|
8
16
|
|
|
9
17
|
|
|
10
18
|
def create_report_from_reportjson(
|
|
@@ -35,18 +43,18 @@ def create_report_from_reportjson(
|
|
|
35
43
|
|
|
36
44
|
(workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
37
45
|
|
|
38
|
-
|
|
46
|
+
dfI = fabric.list_items(workspace=workspace)
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
dfI_model = dfI_m[(dfI_m["Display Name"] == dataset)]
|
|
48
|
+
dfI_model = dfI[(dfI["Display Name"] == dataset) & (dfI["Type"] == "SemanticModel")]
|
|
42
49
|
|
|
43
50
|
if len(dfI_model) == 0:
|
|
44
|
-
raise ValueError(
|
|
51
|
+
raise ValueError(
|
|
52
|
+
f"{icons.red_dot} The '{dataset}' semantic model does not exist in the '{workspace}' workspace."
|
|
53
|
+
)
|
|
45
54
|
|
|
46
55
|
datasetId = dfI_model["Id"].iloc[0]
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
dfI_rpt = dfI_r[(dfI_r["Display Name"] == report)]
|
|
57
|
+
dfI_rpt = dfI[(dfI["Display Name"] == report) & (dfI["Type"] == "Report")]
|
|
50
58
|
|
|
51
59
|
if len(dfI_rpt) > 0:
|
|
52
60
|
print(
|
|
@@ -70,83 +78,50 @@ def create_report_from_reportjson(
|
|
|
70
78
|
},
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
payloadThemeJson = conv_b64(theme_json)
|
|
104
|
-
themeID = theme_json["payload"]["blob"]["displayName"]
|
|
105
|
-
themePath = "StaticResources/SharedResources/BaseThemes/" + themeID + ".json"
|
|
106
|
-
request_body = {
|
|
107
|
-
"displayName": report,
|
|
108
|
-
"type": objectType,
|
|
109
|
-
"definition": {
|
|
110
|
-
"parts": [
|
|
111
|
-
{
|
|
112
|
-
"path": "report.json",
|
|
113
|
-
"payload": payloadReportJson,
|
|
114
|
-
"payloadType": "InlineBase64",
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"path": themePath,
|
|
118
|
-
"payload": payloadThemeJson,
|
|
119
|
-
"payloadType": "InlineBase64",
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"path": "definition.pbir",
|
|
123
|
-
"payload": definitionPBIR,
|
|
124
|
-
"payloadType": "InlineBase64",
|
|
125
|
-
},
|
|
126
|
-
]
|
|
127
|
-
},
|
|
81
|
+
definitionPBIR = _conv_b64(defPBIR)
|
|
82
|
+
payloadReportJson = _conv_b64(report_json)
|
|
83
|
+
|
|
84
|
+
request_body = {
|
|
85
|
+
"displayName": report,
|
|
86
|
+
"definition": {
|
|
87
|
+
"parts": [
|
|
88
|
+
{
|
|
89
|
+
"path": "report.json",
|
|
90
|
+
"payload": payloadReportJson,
|
|
91
|
+
"payloadType": "InlineBase64",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"path": "definition.pbir",
|
|
95
|
+
"payload": definitionPBIR,
|
|
96
|
+
"payloadType": "InlineBase64",
|
|
97
|
+
},
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if theme_json is not None:
|
|
103
|
+
theme_payload = _conv_b64(theme_json)
|
|
104
|
+
theme_id = theme_json["payload"]["blob"]["displayName"]
|
|
105
|
+
theme_path = f"StaticResources/SharedResources/BaseThemes/{theme_id}.json"
|
|
106
|
+
|
|
107
|
+
part = {
|
|
108
|
+
"path": theme_path,
|
|
109
|
+
"payload": theme_payload,
|
|
110
|
+
"payloadType": "InlineBase64",
|
|
128
111
|
}
|
|
112
|
+
request_body["definition"]["parts"].append(part)
|
|
113
|
+
|
|
114
|
+
response = client.post(f"/v1/workspaces/{workspace_id}/reports", json=request_body)
|
|
129
115
|
|
|
130
|
-
response =
|
|
116
|
+
lro(client, response, status_codes=[201, 202])
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
elif response.status_code == 202:
|
|
136
|
-
operationId = response.headers["x-ms-operation-id"]
|
|
137
|
-
response = client.get(f"/v1/operations/{operationId}")
|
|
138
|
-
response_body = json.loads(response.content)
|
|
139
|
-
while response_body["status"] != "Succeeded":
|
|
140
|
-
time.sleep(3)
|
|
141
|
-
response = client.get(f"/v1/operations/{operationId}")
|
|
142
|
-
response_body = json.loads(response.content)
|
|
143
|
-
response = client.get(f"/v1/operations/{operationId}/result")
|
|
144
|
-
print(f"{icons.green_dot} Report creation succeeded")
|
|
145
|
-
print(response.json())
|
|
118
|
+
print(
|
|
119
|
+
f"{icons.green_dot} Succesfully created the '{report}' report within the '{workspace}' workspace."
|
|
120
|
+
)
|
|
146
121
|
|
|
147
122
|
|
|
148
123
|
def update_report_from_reportjson(
|
|
149
|
-
report: str, report_json:
|
|
124
|
+
report: str, report_json: dict, workspace: Optional[str] = None
|
|
150
125
|
):
|
|
151
126
|
"""
|
|
152
127
|
Updates a report based on a report.json file.
|
|
@@ -155,7 +130,7 @@ def update_report_from_reportjson(
|
|
|
155
130
|
----------
|
|
156
131
|
report : str
|
|
157
132
|
Name of the report.
|
|
158
|
-
report_json :
|
|
133
|
+
report_json : dict
|
|
159
134
|
The report.json file to be used to update the report.
|
|
160
135
|
workspace : str, default=None
|
|
161
136
|
The Fabric workspace name in which the report resides.
|
|
@@ -164,53 +139,15 @@ def update_report_from_reportjson(
|
|
|
164
139
|
"""
|
|
165
140
|
|
|
166
141
|
(workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
142
|
+
report_id = resolve_report_id(report=report, workspace=workspace)
|
|
167
143
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if len(dfR_filt) == 0:
|
|
172
|
-
raise ValueError(f"{icons.red_dot} The '{report}' report does not exist in the '{workspace}' workspace.")
|
|
173
|
-
|
|
174
|
-
reportId = dfR_filt["Id"].iloc[0]
|
|
175
|
-
client = fabric.FabricRestClient()
|
|
176
|
-
|
|
177
|
-
response = client.post(
|
|
178
|
-
f"/v1/workspaces/{workspace_id}/items/{reportId}/getDefinition"
|
|
179
|
-
)
|
|
180
|
-
df_items = pd.json_normalize(response.json()["definition"]["parts"])
|
|
144
|
+
# Get the existing PBIR file
|
|
145
|
+
df_items = get_report_definition(report=report, workspace=workspace)
|
|
181
146
|
df_items_filt = df_items[df_items["path"] == "definition.pbir"]
|
|
182
147
|
rptDefFile = df_items_filt["payload"].iloc[0]
|
|
183
|
-
|
|
184
|
-
# datasetWorkspaceId = dfR_filt['Dataset Workspace Id'].iloc[0]
|
|
185
|
-
|
|
186
|
-
# defPBIR = {
|
|
187
|
-
# "version": "1.0",
|
|
188
|
-
# "datasetReference": {
|
|
189
|
-
# "byPath": None,
|
|
190
|
-
# "byConnection": {
|
|
191
|
-
# "connectionString": None,
|
|
192
|
-
# "pbiServiceModelId": None,
|
|
193
|
-
# "pbiModelVirtualServerName": "sobe_wowvirtualserver",
|
|
194
|
-
# "pbiModelDatabaseName": datasetId,
|
|
195
|
-
# "name": "EntityDataSource",
|
|
196
|
-
# "connectionType": "pbiServiceXmlaStyleLive"
|
|
197
|
-
# }
|
|
198
|
-
# }
|
|
199
|
-
# }
|
|
200
|
-
|
|
201
|
-
def conv_b64(file):
|
|
202
|
-
|
|
203
|
-
loadJson = json.dumps(file)
|
|
204
|
-
f = base64.b64encode(loadJson.encode("utf-8")).decode("utf-8")
|
|
205
|
-
|
|
206
|
-
return f
|
|
207
|
-
|
|
208
|
-
# definitionPBIR = conv_b64(defPBIR)
|
|
209
|
-
payloadReportJson = conv_b64(report_json)
|
|
148
|
+
payloadReportJson = _conv_b64(report_json)
|
|
210
149
|
|
|
211
150
|
request_body = {
|
|
212
|
-
"displayName": report,
|
|
213
|
-
"type": 'Report',
|
|
214
151
|
"definition": {
|
|
215
152
|
"parts": [
|
|
216
153
|
{
|
|
@@ -224,25 +161,209 @@ def update_report_from_reportjson(
|
|
|
224
161
|
"payloadType": "InlineBase64",
|
|
225
162
|
},
|
|
226
163
|
]
|
|
227
|
-
}
|
|
164
|
+
}
|
|
228
165
|
}
|
|
229
166
|
|
|
167
|
+
client = fabric.FabricRestClient()
|
|
230
168
|
response = client.post(
|
|
231
|
-
f"/v1/workspaces/{workspace_id}/reports/{
|
|
169
|
+
f"/v1/workspaces/{workspace_id}/reports/{report_id}/updateDefinition",
|
|
232
170
|
json=request_body,
|
|
233
171
|
)
|
|
234
172
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
173
|
+
lro(client, response, return_status_code=True)
|
|
174
|
+
|
|
175
|
+
print(
|
|
176
|
+
f"{icons.green_dot} The '{report}' report within the '{workspace}' workspace has been successfully updated."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def get_report_definition(report: str, workspace: Optional[str] = None) -> pd.DataFrame:
|
|
181
|
+
"""
|
|
182
|
+
Gets the collection of definition files of a report.
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
report : str
|
|
187
|
+
Name of the report.
|
|
188
|
+
workspace : str, default=None
|
|
189
|
+
The Fabric workspace name in which the report resides.
|
|
190
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
191
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
pandas.DataFrame
|
|
196
|
+
The collection of report definition files within a pandas dataframe.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
(workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
200
|
+
|
|
201
|
+
report_id = resolve_report_id(report=report, workspace=workspace)
|
|
202
|
+
client = fabric.FabricRestClient()
|
|
203
|
+
response = client.post(
|
|
204
|
+
f"/v1/workspaces/{workspace_id}/reports/{report_id}/getDefinition",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
result = lro(client, response).json()
|
|
208
|
+
rdef = pd.json_normalize(result["definition"]["parts"])
|
|
209
|
+
|
|
210
|
+
return rdef
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@log
|
|
214
|
+
def create_model_bpa_report(
|
|
215
|
+
report: Optional[str] = icons.model_bpa_name,
|
|
216
|
+
dataset: Optional[str] = icons.model_bpa_name,
|
|
217
|
+
dataset_workspace: Optional[str] = None,
|
|
218
|
+
):
|
|
219
|
+
"""
|
|
220
|
+
Dynamically generates a Best Practice Analyzer report for analyzing semantic models.
|
|
221
|
+
|
|
222
|
+
Parameters
|
|
223
|
+
----------
|
|
224
|
+
report : str, default='ModelBPA'
|
|
225
|
+
Name of the report.
|
|
226
|
+
Defaults to 'ModelBPA'.
|
|
227
|
+
dataset : str, default='ModelBPA'
|
|
228
|
+
Name of the semantic model which feeds this report.
|
|
229
|
+
Defaults to 'ModelBPA'
|
|
230
|
+
dataset_workspace : str, default=None
|
|
231
|
+
The Fabric workspace name in which the semantic model resides.
|
|
232
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
233
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
234
|
+
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
# from sempy_labs._helper_functions import resolve_dataset_id
|
|
238
|
+
|
|
239
|
+
dfI = fabric.list_items(workspace=dataset_workspace, type="SemanticModel")
|
|
240
|
+
dfI_filt = dfI[dfI["Display Name"] == dataset]
|
|
241
|
+
|
|
242
|
+
if len(dfI_filt) == 0:
|
|
243
|
+
raise ValueError(
|
|
244
|
+
f"The '{dataset}' semantic model does not exist within the '{dataset_workspace}' workspace."
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
dfR = fabric.list_reports(workspace=dataset_workspace)
|
|
248
|
+
dfR_filt = dfR[dfR["Name"] == report]
|
|
249
|
+
# dataset_id = resolve_dataset_id(dataset=dataset, workspace=dataset_workspace)
|
|
250
|
+
|
|
251
|
+
current_dir = os.path.dirname(__file__)
|
|
252
|
+
# directory_path = os.path.join(current_dir, "_bpareporttemplate")
|
|
253
|
+
# len_dir_path = len(directory_path) + 1
|
|
254
|
+
|
|
255
|
+
# request_body = {"displayName": report, "definition": {"parts": []}}
|
|
256
|
+
|
|
257
|
+
# def get_all_file_paths(directory):
|
|
258
|
+
# file_paths = []
|
|
259
|
+
|
|
260
|
+
# for root, directories, files in os.walk(directory):
|
|
261
|
+
# for filename in files:
|
|
262
|
+
# full_path = os.path.join(root, filename)
|
|
263
|
+
# file_paths.append(full_path)
|
|
264
|
+
|
|
265
|
+
# return file_paths
|
|
266
|
+
|
|
267
|
+
# all_files = get_all_file_paths(directory_path)
|
|
268
|
+
|
|
269
|
+
# for file_path in all_files:
|
|
270
|
+
# fp = file_path[len_dir_path:]
|
|
271
|
+
# with open(file_path, "r") as file:
|
|
272
|
+
# json_file = json.load(file)
|
|
273
|
+
# if fp == 'definition.pbir':
|
|
274
|
+
# conn_string = f"Data Source=powerbi://api.powerbi.com/v1.0/myorg/{dataset_workspace};Initial Catalog={dataset};Integrated Security=ClaimsToken"
|
|
275
|
+
# json_file['datasetReference']['byConnection']['connectionString'] = conn_string
|
|
276
|
+
# json_file['datasetReference']['byConnection']['pbiModelDatabaseName'] = dataset_id
|
|
277
|
+
# part = {
|
|
278
|
+
# "path": fp,
|
|
279
|
+
# "payload": _conv_b64(json_file),
|
|
280
|
+
# "payloadType": "InlineBase64",
|
|
281
|
+
# }
|
|
282
|
+
|
|
283
|
+
# request_body["definition"]["parts"].append(part)
|
|
284
|
+
|
|
285
|
+
# _create_report(
|
|
286
|
+
# report=report,
|
|
287
|
+
# request_body=request_body,
|
|
288
|
+
# dataset=dataset,
|
|
289
|
+
# report_workspace=dataset_workspace,
|
|
290
|
+
# dataset_workspace=dataset_workspace,
|
|
291
|
+
# )
|
|
292
|
+
|
|
293
|
+
json_file_path = os.path.join(current_dir, "_BPAReportTemplate.json")
|
|
294
|
+
with open(json_file_path, "r") as file:
|
|
295
|
+
report_json = json.load(file)
|
|
296
|
+
|
|
297
|
+
if len(dfR_filt) > 0:
|
|
298
|
+
update_report_from_reportjson(
|
|
299
|
+
report=report, report_json=report_json, workspace=dataset_workspace
|
|
300
|
+
)
|
|
301
|
+
else:
|
|
302
|
+
create_report_from_reportjson(
|
|
303
|
+
report=report,
|
|
304
|
+
dataset=dataset,
|
|
305
|
+
report_json=report_json,
|
|
306
|
+
workspace=dataset_workspace,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _create_report(
|
|
311
|
+
report: str,
|
|
312
|
+
request_body: dict,
|
|
313
|
+
dataset: str,
|
|
314
|
+
dataset_workspace: Optional[str] = None,
|
|
315
|
+
report_workspace: Optional[str] = None,
|
|
316
|
+
update_if_exists: Optional[bool] = False,
|
|
317
|
+
):
|
|
318
|
+
|
|
319
|
+
from sempy_labs.report import report_rebind
|
|
320
|
+
|
|
321
|
+
report_workspace = fabric.resolve_workspace_name(report_workspace)
|
|
322
|
+
report_workspace_id = fabric.resolve_workspace_id(report_workspace)
|
|
323
|
+
client = fabric.FabricRestClient()
|
|
324
|
+
|
|
325
|
+
dfR = fabric.list_reports(workspace=report_workspace)
|
|
326
|
+
dfR_filt = dfR[dfR["Name"] == report]
|
|
327
|
+
|
|
328
|
+
updated_report = False
|
|
329
|
+
|
|
330
|
+
# Create report if it does not exist
|
|
331
|
+
if len(dfR_filt) == 0:
|
|
332
|
+
response = client.post(
|
|
333
|
+
f"/v1/workspaces/{report_workspace_id}/reports",
|
|
334
|
+
json=request_body,
|
|
335
|
+
lro_wait=True,
|
|
336
|
+
)
|
|
337
|
+
if response.status_code not in [200, 201]:
|
|
338
|
+
raise FabricHTTPException(response)
|
|
339
|
+
print(
|
|
340
|
+
f"{icons.green_dot} The '{report}' report has been created within the '{report_workspace}'"
|
|
341
|
+
)
|
|
342
|
+
updated_report = True
|
|
343
|
+
# Update the report if it exists
|
|
344
|
+
elif len(dfR_filt) > 0 and update_if_exists:
|
|
345
|
+
report_id = dfR_filt["Id"].iloc[0]
|
|
346
|
+
response = client.post(
|
|
347
|
+
f"/v1/workspaces/{report_workspace_id}/reports/{report_id}/updateDefinition",
|
|
348
|
+
json=request_body,
|
|
349
|
+
lro_wait=True,
|
|
350
|
+
)
|
|
351
|
+
if response.status_code not in [200, 201]:
|
|
352
|
+
raise FabricHTTPException(response)
|
|
353
|
+
print(
|
|
354
|
+
f"{icons.green_dot} The '{report}' report has been updated within the '{report_workspace}'"
|
|
355
|
+
)
|
|
356
|
+
updated_report = True
|
|
357
|
+
else:
|
|
358
|
+
raise ValueError(
|
|
359
|
+
f"{icons.red_dot} The '{report}' report within the '{report_workspace}' workspace already exists and it was selected not to update it if the report already exists."
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# Rebind the report to the semantic model to make sure it is pointed at the correct semantic model
|
|
363
|
+
if updated_report:
|
|
364
|
+
report_rebind(
|
|
365
|
+
report=report,
|
|
366
|
+
dataset=dataset,
|
|
367
|
+
report_workspace=report_workspace,
|
|
368
|
+
dataset_workspace=dataset_workspace,
|
|
369
|
+
)
|