semantic-link-labs 0.9.2__py3-none-any.whl → 0.9.4__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.9.2.dist-info → semantic_link_labs-0.9.4.dist-info}/METADATA +10 -6
- {semantic_link_labs-0.9.2.dist-info → semantic_link_labs-0.9.4.dist-info}/RECORD +54 -44
- {semantic_link_labs-0.9.2.dist-info → semantic_link_labs-0.9.4.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +27 -1
- sempy_labs/_ai.py +8 -5
- sempy_labs/_capacity_migration.py +3 -2
- sempy_labs/_connections.py +45 -9
- sempy_labs/_dax.py +17 -3
- sempy_labs/_delta_analyzer.py +308 -138
- sempy_labs/_eventhouses.py +70 -1
- sempy_labs/_gateways.py +56 -8
- sempy_labs/_generate_semantic_model.py +30 -9
- sempy_labs/_helper_functions.py +84 -9
- sempy_labs/_job_scheduler.py +226 -2
- sempy_labs/_list_functions.py +42 -19
- sempy_labs/_ml_experiments.py +1 -1
- sempy_labs/_model_bpa.py +17 -2
- sempy_labs/_model_bpa_rules.py +20 -8
- sempy_labs/_semantic_models.py +117 -0
- sempy_labs/_sql.py +73 -6
- sempy_labs/_sqldatabase.py +227 -0
- sempy_labs/_translations.py +2 -2
- sempy_labs/_vertipaq.py +3 -3
- sempy_labs/_warehouses.py +1 -1
- sempy_labs/admin/__init__.py +49 -8
- sempy_labs/admin/_activities.py +166 -0
- sempy_labs/admin/_apps.py +143 -0
- sempy_labs/admin/_basic_functions.py +32 -652
- sempy_labs/admin/_capacities.py +250 -0
- sempy_labs/admin/_datasets.py +184 -0
- sempy_labs/admin/_domains.py +1 -3
- sempy_labs/admin/_items.py +3 -1
- sempy_labs/admin/_reports.py +165 -0
- sempy_labs/admin/_scanner.py +53 -49
- sempy_labs/admin/_shared.py +74 -0
- sempy_labs/admin/_tenant.py +489 -0
- sempy_labs/directlake/_dl_helper.py +0 -1
- sempy_labs/directlake/_update_directlake_partition_entity.py +6 -0
- sempy_labs/graph/_teams.py +1 -1
- sempy_labs/graph/_users.py +9 -1
- sempy_labs/lakehouse/_get_lakehouse_columns.py +2 -2
- sempy_labs/lakehouse/_get_lakehouse_tables.py +2 -2
- sempy_labs/lakehouse/_lakehouse.py +3 -3
- sempy_labs/lakehouse/_shortcuts.py +29 -16
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +2 -2
- sempy_labs/migration/_refresh_calc_tables.py +2 -2
- sempy_labs/report/__init__.py +3 -1
- sempy_labs/report/_download_report.py +4 -1
- sempy_labs/report/_export_report.py +272 -0
- sempy_labs/report/_report_functions.py +11 -263
- sempy_labs/report/_report_rebind.py +1 -1
- sempy_labs/tom/_model.py +281 -29
- {semantic_link_labs-0.9.2.dist-info → semantic_link_labs-0.9.4.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.9.2.dist-info → semantic_link_labs-0.9.4.dist-info}/top_level.txt +0 -0
sempy_labs/_eventhouses.py
CHANGED
|
@@ -7,12 +7,18 @@ from sempy_labs._helper_functions import (
|
|
|
7
7
|
_print_success,
|
|
8
8
|
resolve_item_id,
|
|
9
9
|
_create_dataframe,
|
|
10
|
+
_conv_b64,
|
|
11
|
+
_decode_b64,
|
|
10
12
|
)
|
|
11
13
|
from uuid import UUID
|
|
14
|
+
import sempy_labs._icons as icons
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
def create_eventhouse(
|
|
15
|
-
name: str,
|
|
18
|
+
name: str,
|
|
19
|
+
definition: Optional[dict],
|
|
20
|
+
description: Optional[str] = None,
|
|
21
|
+
workspace: Optional[str | UUID] = None,
|
|
16
22
|
):
|
|
17
23
|
"""
|
|
18
24
|
Creates a Fabric eventhouse.
|
|
@@ -23,6 +29,8 @@ def create_eventhouse(
|
|
|
23
29
|
----------
|
|
24
30
|
name: str
|
|
25
31
|
Name of the eventhouse.
|
|
32
|
+
definition : dict
|
|
33
|
+
The definition (EventhouseProperties.json) of the eventhouse.
|
|
26
34
|
description : str, default=None
|
|
27
35
|
A description of the environment.
|
|
28
36
|
workspace : str | uuid.UUID, default=None
|
|
@@ -38,6 +46,20 @@ def create_eventhouse(
|
|
|
38
46
|
if description:
|
|
39
47
|
payload["description"] = description
|
|
40
48
|
|
|
49
|
+
if definition is not None:
|
|
50
|
+
if not isinstance(definition, dict):
|
|
51
|
+
raise ValueError(f"{icons.red_dot} The definition must be a dictionary.")
|
|
52
|
+
|
|
53
|
+
payload["definition"] = {
|
|
54
|
+
"parts": [
|
|
55
|
+
{
|
|
56
|
+
"path": "EventhouseProperties.json",
|
|
57
|
+
"payload": _conv_b64(definition),
|
|
58
|
+
"payloadType": "InlineBase64",
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
|
|
41
63
|
_base_api(
|
|
42
64
|
request=f"/v1/workspaces/{workspace_id}/eventhouses",
|
|
43
65
|
method="post",
|
|
@@ -123,3 +145,50 @@ def delete_eventhouse(name: str, workspace: Optional[str | UUID] = None):
|
|
|
123
145
|
workspace_name=workspace_name,
|
|
124
146
|
action="deleted",
|
|
125
147
|
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def get_eventhouse_definition(
|
|
151
|
+
eventhouse: str | UUID,
|
|
152
|
+
workspace: Optional[str | UUID] = None,
|
|
153
|
+
return_dataframe: bool = False,
|
|
154
|
+
) -> dict | pd.DataFrame:
|
|
155
|
+
"""
|
|
156
|
+
Gets the eventhouse definition.
|
|
157
|
+
|
|
158
|
+
This is a wrapper function for the following API: `Items - Get Eventhouse Definition <https://learn.microsoft.com/rest/api/fabric/eventhouse/items/get-eventhouse-definition>`_.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
eventhouse : str
|
|
163
|
+
Name of the eventhouse.
|
|
164
|
+
workspace : str | uuid.UUID, default=None
|
|
165
|
+
The Fabric workspace name or ID in which the eventhouse resides.
|
|
166
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
167
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
168
|
+
return_dataframe : bool, default=False
|
|
169
|
+
If True, returns a dataframe. If False, returns a json dictionary.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
dict | pandas.DataFrame
|
|
174
|
+
The eventhouse definition in .json format or as a pandas dataframe.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
178
|
+
item_id = resolve_item_id(item=eventhouse, type="Eventhouse", workspace=workspace)
|
|
179
|
+
|
|
180
|
+
result = _base_api(
|
|
181
|
+
request=f"/v1/workspaces/{workspace_id}/eventhouses/{item_id}/getDefinition",
|
|
182
|
+
method="post",
|
|
183
|
+
status_codes=None,
|
|
184
|
+
lro_return_json=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
df = pd.json_normalize(result["definition"]["parts"])
|
|
188
|
+
|
|
189
|
+
if return_dataframe:
|
|
190
|
+
return df
|
|
191
|
+
else:
|
|
192
|
+
df_filt = df[df["path"] == "EventhouseProperties.json"]
|
|
193
|
+
payload = df_filt["payload"].iloc[0]
|
|
194
|
+
return _decode_b64(payload)
|
sempy_labs/_gateways.py
CHANGED
|
@@ -21,6 +21,8 @@ def list_gateways() -> pd.DataFrame:
|
|
|
21
21
|
|
|
22
22
|
This is a wrapper function for the following API: `Gateways - List Gateways <https://learn.microsoft.com/rest/api/fabric/core/gateways/list-gateways>`_.
|
|
23
23
|
|
|
24
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
25
|
+
|
|
24
26
|
Returns
|
|
25
27
|
-------
|
|
26
28
|
pandas.DataFrame
|
|
@@ -41,7 +43,9 @@ def list_gateways() -> pd.DataFrame:
|
|
|
41
43
|
}
|
|
42
44
|
df = _create_dataframe(columns=columns)
|
|
43
45
|
|
|
44
|
-
responses = _base_api(
|
|
46
|
+
responses = _base_api(
|
|
47
|
+
request="/v1/gateways", client="fabric_sp", uses_pagination=True
|
|
48
|
+
)
|
|
45
49
|
|
|
46
50
|
for r in responses:
|
|
47
51
|
for v in r.get("value", []):
|
|
@@ -85,6 +89,8 @@ def delete_gateway(gateway: str | UUID):
|
|
|
85
89
|
|
|
86
90
|
This is a wrapper function for the following API: `Gateways - Delete Gateway <https://learn.microsoft.com/rest/api/fabric/core/gateways/delete-gateway>`_.
|
|
87
91
|
|
|
92
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
93
|
+
|
|
88
94
|
Parameters
|
|
89
95
|
----------
|
|
90
96
|
gateway : str | uuid.UUID
|
|
@@ -92,7 +98,7 @@ def delete_gateway(gateway: str | UUID):
|
|
|
92
98
|
"""
|
|
93
99
|
|
|
94
100
|
gateway_id = _resolve_gateway_id(gateway)
|
|
95
|
-
_base_api(request=f"/v1/gateways/{gateway_id}", method="delete")
|
|
101
|
+
_base_api(request=f"/v1/gateways/{gateway_id}", client="fabric_sp", method="delete")
|
|
96
102
|
print(f"{icons.green_dot} The '{gateway}' gateway has been deleted.")
|
|
97
103
|
|
|
98
104
|
|
|
@@ -102,6 +108,8 @@ def list_gateway_role_assigments(gateway: str | UUID) -> pd.DataFrame:
|
|
|
102
108
|
|
|
103
109
|
This is a wrapper function for the following API: `Gateways - List Gateway Role Assignments <https://learn.microsoft.com/rest/api/fabric/core/gateways/list-gateway-role-assignments>`_.
|
|
104
110
|
|
|
111
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
112
|
+
|
|
105
113
|
Parameters
|
|
106
114
|
----------
|
|
107
115
|
gateway : str | uuid.UUID
|
|
@@ -122,7 +130,9 @@ def list_gateway_role_assigments(gateway: str | UUID) -> pd.DataFrame:
|
|
|
122
130
|
df = _create_dataframe(columns=columns)
|
|
123
131
|
gateway_id = _resolve_gateway_id(gateway)
|
|
124
132
|
responses = _base_api(
|
|
125
|
-
request=f"/v1/gateways/{gateway_id}/roleAssignments",
|
|
133
|
+
request=f"/v1/gateways/{gateway_id}/roleAssignments",
|
|
134
|
+
client="fabric_sp",
|
|
135
|
+
uses_pagination=True,
|
|
126
136
|
)
|
|
127
137
|
|
|
128
138
|
for r in responses:
|
|
@@ -145,6 +155,8 @@ def delete_gateway_role_assignment(gateway: str | UUID, role_assignment_id: UUID
|
|
|
145
155
|
|
|
146
156
|
This is a wrapper function for the following API: `Gateways - Delete Gateway Role Assignment <https://learn.microsoft.com/rest/api/fabric/core/gateways/delete-gateway-role-assignment>`_.
|
|
147
157
|
|
|
158
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
159
|
+
|
|
148
160
|
Parameters
|
|
149
161
|
----------
|
|
150
162
|
gateway : str | uuid.UUID
|
|
@@ -156,6 +168,7 @@ def delete_gateway_role_assignment(gateway: str | UUID, role_assignment_id: UUID
|
|
|
156
168
|
gateway_id = _resolve_gateway_id(gateway)
|
|
157
169
|
_base_api(
|
|
158
170
|
request=f"/v1/gateways/{gateway_id}/roleAssignments/{role_assignment_id}",
|
|
171
|
+
client="fabric_sp",
|
|
159
172
|
method="delete",
|
|
160
173
|
)
|
|
161
174
|
|
|
@@ -187,6 +200,8 @@ def delete_gateway_member(gateway: str | UUID, gateway_member: str | UUID):
|
|
|
187
200
|
|
|
188
201
|
This is a wrapper function for the following API: `Gateways - Delete Gateway Member <https://learn.microsoft.com/rest/api/fabric/core/gateways/delete-gateway-member>`_.
|
|
189
202
|
|
|
203
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
204
|
+
|
|
190
205
|
Parameters
|
|
191
206
|
----------
|
|
192
207
|
gateway : str | uuid.UUID
|
|
@@ -200,7 +215,11 @@ def delete_gateway_member(gateway: str | UUID, gateway_member: str | UUID):
|
|
|
200
215
|
gateway=gateway_id, gateway_member=gateway_member
|
|
201
216
|
)
|
|
202
217
|
|
|
203
|
-
_base_api(
|
|
218
|
+
_base_api(
|
|
219
|
+
request=f"/v1/gateways/{gateway_id}/members/{member_id}",
|
|
220
|
+
client="fabric_sp",
|
|
221
|
+
method="delete",
|
|
222
|
+
)
|
|
204
223
|
print(
|
|
205
224
|
f"{icons.green_dot} The '{member_id}' member for the '{gateway}' gateway has been deleted."
|
|
206
225
|
)
|
|
@@ -212,6 +231,8 @@ def list_gateway_members(gateway: str | UUID) -> pd.DataFrame:
|
|
|
212
231
|
|
|
213
232
|
This is a wrapper function for the following API: `Gateways - List Gateway Members <https://learn.microsoft.com/rest/api/fabric/core/gateways/list-gateway-members>`_.
|
|
214
233
|
|
|
234
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
235
|
+
|
|
215
236
|
Parameters
|
|
216
237
|
----------
|
|
217
238
|
gateway : str | uuid.UUID
|
|
@@ -235,7 +256,9 @@ def list_gateway_members(gateway: str | UUID) -> pd.DataFrame:
|
|
|
235
256
|
}
|
|
236
257
|
df = _create_dataframe(columns=columns)
|
|
237
258
|
|
|
238
|
-
response = _base_api(
|
|
259
|
+
response = _base_api(
|
|
260
|
+
request=f"/v1/gateways/{gateway_id}/members", client="fabric_sp"
|
|
261
|
+
)
|
|
239
262
|
|
|
240
263
|
for v in response.json().get("value", []):
|
|
241
264
|
new_data = {
|
|
@@ -269,6 +292,8 @@ def create_vnet_gateway(
|
|
|
269
292
|
|
|
270
293
|
This is a wrapper function for the following API: `Gateways - Create Gateway <https://learn.microsoft.com/rest/api/fabric/core/gateways/create-gateway>`_.
|
|
271
294
|
|
|
295
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
296
|
+
|
|
272
297
|
Parameters
|
|
273
298
|
----------
|
|
274
299
|
name : str
|
|
@@ -304,7 +329,13 @@ def create_vnet_gateway(
|
|
|
304
329
|
"numberOfMemberGateways": number_of_member_gateways,
|
|
305
330
|
}
|
|
306
331
|
|
|
307
|
-
_base_api(
|
|
332
|
+
_base_api(
|
|
333
|
+
request="/v1/gateways",
|
|
334
|
+
client="fabric_sp",
|
|
335
|
+
method="post",
|
|
336
|
+
payload=payload,
|
|
337
|
+
status_codes=201,
|
|
338
|
+
)
|
|
308
339
|
|
|
309
340
|
print(
|
|
310
341
|
f"{icons.green_dot} The '{name}' gateway was created within the '{capacity}' capacity."
|
|
@@ -322,6 +353,8 @@ def update_on_premises_gateway(
|
|
|
322
353
|
|
|
323
354
|
This is a wrapper function for the following API: `Gateways - Update Gateway <https://learn.microsoft.com/rest/api/fabric/core/gateways/update-gateway>`_.
|
|
324
355
|
|
|
356
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
357
|
+
|
|
325
358
|
Parameters
|
|
326
359
|
----------
|
|
327
360
|
gateway : str | uuid.UUID
|
|
@@ -352,7 +385,12 @@ def update_on_premises_gateway(
|
|
|
352
385
|
|
|
353
386
|
payload["type"] = "OnPremises"
|
|
354
387
|
|
|
355
|
-
_base_api(
|
|
388
|
+
_base_api(
|
|
389
|
+
request=f"/v1/gateways/{gateway_id}",
|
|
390
|
+
client="fabric_sp",
|
|
391
|
+
method="patch",
|
|
392
|
+
payload=payload,
|
|
393
|
+
)
|
|
356
394
|
|
|
357
395
|
print(f"{icons.green_dot} The '{gateway}' has been updated accordingly.")
|
|
358
396
|
|
|
@@ -368,6 +406,8 @@ def update_vnet_gateway(
|
|
|
368
406
|
|
|
369
407
|
This is a wrapper function for the following API: `Gateways - Update Gateway <https://learn.microsoft.com/rest/api/fabric/core/gateways/update-gateway>`_.
|
|
370
408
|
|
|
409
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
410
|
+
|
|
371
411
|
Parameters
|
|
372
412
|
----------
|
|
373
413
|
gateway : str | uuid.UUID
|
|
@@ -399,7 +439,12 @@ def update_vnet_gateway(
|
|
|
399
439
|
|
|
400
440
|
payload["type"] = "VirtualNetwork"
|
|
401
441
|
|
|
402
|
-
_base_api(
|
|
442
|
+
_base_api(
|
|
443
|
+
request=f"/v1/gateways/{gateway_id}",
|
|
444
|
+
client="fabric_sp",
|
|
445
|
+
method="patch",
|
|
446
|
+
payload=payload,
|
|
447
|
+
)
|
|
403
448
|
print(f"{icons.green_dot} The '{gateway}' has been updated accordingly.")
|
|
404
449
|
|
|
405
450
|
|
|
@@ -411,6 +456,8 @@ def bind_semantic_model_to_gateway(
|
|
|
411
456
|
|
|
412
457
|
This is a wrapper function for the following API: `Datasets - Bind To Gateway In Group <https://learn.microsoft.com/rest/api/power-bi/datasets/bind-to-gateway-in-group>`_.
|
|
413
458
|
|
|
459
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
460
|
+
|
|
414
461
|
Parameters
|
|
415
462
|
----------
|
|
416
463
|
dataset : str | uuid.UUID
|
|
@@ -435,6 +482,7 @@ def bind_semantic_model_to_gateway(
|
|
|
435
482
|
|
|
436
483
|
_base_api(
|
|
437
484
|
request=f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/Default.BindToGateway",
|
|
485
|
+
client="fabric_sp",
|
|
438
486
|
method="post",
|
|
439
487
|
payload=payload,
|
|
440
488
|
)
|
|
@@ -11,6 +11,7 @@ from sempy_labs._helper_functions import (
|
|
|
11
11
|
_conv_b64,
|
|
12
12
|
_decode_b64,
|
|
13
13
|
_base_api,
|
|
14
|
+
_mount,
|
|
14
15
|
)
|
|
15
16
|
from sempy_labs.lakehouse._lakehouse import lakehouse_attached
|
|
16
17
|
import sempy_labs._icons as icons
|
|
@@ -252,6 +253,7 @@ def deploy_semantic_model(
|
|
|
252
253
|
target_workspace: Optional[str | UUID] = None,
|
|
253
254
|
refresh_target_dataset: bool = True,
|
|
254
255
|
overwrite: bool = False,
|
|
256
|
+
perspective: Optional[str] = None,
|
|
255
257
|
):
|
|
256
258
|
"""
|
|
257
259
|
Deploys a semantic model based on an existing semantic model.
|
|
@@ -274,6 +276,8 @@ def deploy_semantic_model(
|
|
|
274
276
|
If set to True, this will initiate a full refresh of the target semantic model in the target workspace.
|
|
275
277
|
overwrite : bool, default=False
|
|
276
278
|
If set to True, overwrites the existing semantic model in the workspace if it exists.
|
|
279
|
+
perspective : str, default=None
|
|
280
|
+
Set this to the name of a perspective in the model and it will reduce the deployed model down to the tables/columns/measures/hierarchies within that perspective.
|
|
277
281
|
"""
|
|
278
282
|
|
|
279
283
|
(source_workspace_name, source_workspace_id) = resolve_workspace_name_and_id(
|
|
@@ -307,7 +311,21 @@ def deploy_semantic_model(
|
|
|
307
311
|
f"{icons.warning} The '{target_dataset}' semantic model already exists within the '{target_workspace_name}' workspace. The 'overwrite' parameter is set to False so the source semantic model was not deployed to the target destination."
|
|
308
312
|
)
|
|
309
313
|
|
|
310
|
-
|
|
314
|
+
if perspective is not None:
|
|
315
|
+
|
|
316
|
+
from sempy_labs.tom import connect_semantic_model
|
|
317
|
+
|
|
318
|
+
with connect_semantic_model(
|
|
319
|
+
dataset=source_dataset, workspace=source_workspace, readonly=True
|
|
320
|
+
) as tom:
|
|
321
|
+
|
|
322
|
+
df_added = tom._reduce_model(perspective_name=perspective)
|
|
323
|
+
bim = tom.get_bim()
|
|
324
|
+
|
|
325
|
+
else:
|
|
326
|
+
bim = get_semantic_model_bim(
|
|
327
|
+
dataset=source_dataset, workspace=source_workspace_id
|
|
328
|
+
)
|
|
311
329
|
|
|
312
330
|
# Create the semantic model if the model does not exist
|
|
313
331
|
if dfD_filt.empty:
|
|
@@ -325,6 +343,9 @@ def deploy_semantic_model(
|
|
|
325
343
|
if refresh_target_dataset:
|
|
326
344
|
refresh_semantic_model(dataset=target_dataset, workspace=target_workspace_id)
|
|
327
345
|
|
|
346
|
+
if perspective is not None:
|
|
347
|
+
return df_added
|
|
348
|
+
|
|
328
349
|
|
|
329
350
|
@log
|
|
330
351
|
def get_semantic_model_bim(
|
|
@@ -368,16 +389,16 @@ def get_semantic_model_bim(
|
|
|
368
389
|
f"{icons.red_dot} In order to save the model.bim file, a lakehouse must be attached to the notebook. Please attach a lakehouse to this notebook."
|
|
369
390
|
)
|
|
370
391
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if not save_to_file_name.endswith(
|
|
375
|
-
save_to_file_name = f"{save_to_file_name}{
|
|
376
|
-
|
|
377
|
-
with open(
|
|
392
|
+
local_path = _mount()
|
|
393
|
+
save_folder = f"{local_path}/Files"
|
|
394
|
+
file_ext = ".bim"
|
|
395
|
+
if not save_to_file_name.endswith(file_ext):
|
|
396
|
+
save_to_file_name = f"{save_to_file_name}{file_ext}"
|
|
397
|
+
file_path = os.path.join(save_folder, save_to_file_name)
|
|
398
|
+
with open(file_path, "w") as json_file:
|
|
378
399
|
json.dump(bimJson, json_file, indent=4)
|
|
379
400
|
print(
|
|
380
|
-
f"{icons.green_dot} The {
|
|
401
|
+
f"{icons.green_dot} The {file_ext} file for the '{dataset_name}' semantic model has been saved to the lakehouse attached to the notebook within: 'Files/{save_to_file_name}'.\n\n"
|
|
381
402
|
)
|
|
382
403
|
|
|
383
404
|
return bimJson
|
sempy_labs/_helper_functions.py
CHANGED
|
@@ -31,7 +31,9 @@ def _build_url(url: str, params: dict) -> str:
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def create_abfss_path(
|
|
34
|
-
lakehouse_id: UUID,
|
|
34
|
+
lakehouse_id: UUID,
|
|
35
|
+
lakehouse_workspace_id: UUID,
|
|
36
|
+
delta_table_name: Optional[str] = None,
|
|
35
37
|
) -> str:
|
|
36
38
|
"""
|
|
37
39
|
Creates an abfss path for a delta table in a Fabric lakehouse.
|
|
@@ -42,18 +44,22 @@ def create_abfss_path(
|
|
|
42
44
|
ID of the Fabric lakehouse.
|
|
43
45
|
lakehouse_workspace_id : uuid.UUID
|
|
44
46
|
ID of the Fabric workspace.
|
|
45
|
-
delta_table_name : str
|
|
47
|
+
delta_table_name : str, default=None
|
|
46
48
|
Name of the delta table name.
|
|
47
49
|
|
|
48
50
|
Returns
|
|
49
51
|
-------
|
|
50
52
|
str
|
|
51
|
-
An abfss path which can be used to save/reference a delta table in a Fabric lakehouse.
|
|
53
|
+
An abfss path which can be used to save/reference a delta table in a Fabric lakehouse or lakehouse.
|
|
52
54
|
"""
|
|
53
55
|
|
|
54
56
|
fp = _get_default_file_path()
|
|
57
|
+
path = f"abfss://{lakehouse_workspace_id}@{fp}/{lakehouse_id}"
|
|
58
|
+
|
|
59
|
+
if delta_table_name is not None:
|
|
60
|
+
path += f"/Tables/{delta_table_name}"
|
|
55
61
|
|
|
56
|
-
return
|
|
62
|
+
return path
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
def _get_default_file_path() -> str:
|
|
@@ -506,7 +512,6 @@ def save_as_delta_table(
|
|
|
506
512
|
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
507
513
|
"""
|
|
508
514
|
|
|
509
|
-
from pyspark.sql import SparkSession
|
|
510
515
|
from pyspark.sql.types import (
|
|
511
516
|
StringType,
|
|
512
517
|
IntegerType,
|
|
@@ -538,8 +543,9 @@ def save_as_delta_table(
|
|
|
538
543
|
f"{icons.red_dot} Invalid 'delta_table_name'. Delta tables in the lakehouse cannot have spaces in their names."
|
|
539
544
|
)
|
|
540
545
|
|
|
541
|
-
dataframe.columns =
|
|
542
|
-
|
|
546
|
+
dataframe.columns = [col.replace(" ", "_") for col in dataframe.columns]
|
|
547
|
+
|
|
548
|
+
spark = _create_spark_session()
|
|
543
549
|
|
|
544
550
|
type_mapping = {
|
|
545
551
|
"string": StringType(),
|
|
@@ -1248,7 +1254,6 @@ def _get_column_aggregate(
|
|
|
1248
1254
|
default_value: int = 0,
|
|
1249
1255
|
) -> int:
|
|
1250
1256
|
|
|
1251
|
-
from pyspark.sql import SparkSession
|
|
1252
1257
|
from pyspark.sql.functions import approx_count_distinct
|
|
1253
1258
|
from pyspark.sql import functions as F
|
|
1254
1259
|
|
|
@@ -1257,7 +1262,7 @@ def _get_column_aggregate(
|
|
|
1257
1262
|
lakehouse_id = resolve_lakehouse_id(lakehouse, workspace)
|
|
1258
1263
|
path = create_abfss_path(lakehouse_id, workspace_id, table_name)
|
|
1259
1264
|
|
|
1260
|
-
spark =
|
|
1265
|
+
spark = _create_spark_session()
|
|
1261
1266
|
df = spark.read.format("delta").load(path)
|
|
1262
1267
|
|
|
1263
1268
|
if function in {"COUNTDISTINCT", "DISTINCTCOUNT"}:
|
|
@@ -1591,3 +1596,73 @@ def _print_success(item_name, item_type, workspace_name, action="created"):
|
|
|
1591
1596
|
)
|
|
1592
1597
|
else:
|
|
1593
1598
|
raise NotImplementedError
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
def _pure_python_notebook() -> bool:
|
|
1602
|
+
|
|
1603
|
+
from sempy.fabric._environment import _on_jupyter
|
|
1604
|
+
|
|
1605
|
+
return _on_jupyter()
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
def _create_spark_session():
|
|
1609
|
+
|
|
1610
|
+
if _pure_python_notebook():
|
|
1611
|
+
raise ValueError(
|
|
1612
|
+
f"{icons.red_dot} This function is only available in a PySpark notebook."
|
|
1613
|
+
)
|
|
1614
|
+
|
|
1615
|
+
from pyspark.sql import SparkSession
|
|
1616
|
+
|
|
1617
|
+
return SparkSession.builder.getOrCreate()
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
def _read_delta_table(path: str):
|
|
1621
|
+
|
|
1622
|
+
spark = _create_spark_session()
|
|
1623
|
+
|
|
1624
|
+
return spark.read.format("delta").load(path)
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
def _delta_table_row_count(table_name: str) -> int:
|
|
1628
|
+
|
|
1629
|
+
spark = _create_spark_session()
|
|
1630
|
+
|
|
1631
|
+
return spark.table(table_name).count()
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
def _run_spark_sql_query(query):
|
|
1635
|
+
|
|
1636
|
+
spark = _create_spark_session()
|
|
1637
|
+
|
|
1638
|
+
return spark.sql(query)
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
def _mount(lakehouse, workspace) -> str:
|
|
1642
|
+
"""
|
|
1643
|
+
Mounts a lakehouse to a notebook if it is not already mounted. Returns the local path to the lakehouse.
|
|
1644
|
+
"""
|
|
1645
|
+
|
|
1646
|
+
import notebookutils
|
|
1647
|
+
|
|
1648
|
+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace=workspace)
|
|
1649
|
+
(lakehouse_name, lakehouse_id) = resolve_lakehouse_name_and_id(
|
|
1650
|
+
lakehouse=lakehouse, workspace=workspace
|
|
1651
|
+
)
|
|
1652
|
+
|
|
1653
|
+
lake_path = create_abfss_path(lakehouse_id, workspace_id)
|
|
1654
|
+
mounts = notebookutils.fs.mounts()
|
|
1655
|
+
mount_point = f"/{workspace_name.replace(' ', '')}{lakehouse_name.replace(' ', '')}"
|
|
1656
|
+
if not any(i.get("source") == lake_path for i in mounts):
|
|
1657
|
+
# Mount lakehouse if not mounted
|
|
1658
|
+
notebookutils.fs.mount(lake_path, mount_point)
|
|
1659
|
+
print(
|
|
1660
|
+
f"{icons.green_dot} Mounted the '{lakehouse_name}' lakehouse within the '{workspace_name}' to the notebook."
|
|
1661
|
+
)
|
|
1662
|
+
|
|
1663
|
+
mounts = notebookutils.fs.mounts()
|
|
1664
|
+
local_path = next(
|
|
1665
|
+
i.get("localPath") for i in mounts if i.get("source") == lake_path
|
|
1666
|
+
)
|
|
1667
|
+
|
|
1668
|
+
return local_path
|