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.

Files changed (52) hide show
  1. semantic_link_labs-0.4.1.dist-info/LICENSE +21 -0
  2. semantic_link_labs-0.4.1.dist-info/METADATA +22 -0
  3. semantic_link_labs-0.4.1.dist-info/RECORD +52 -0
  4. semantic_link_labs-0.4.1.dist-info/WHEEL +5 -0
  5. semantic_link_labs-0.4.1.dist-info/top_level.txt +1 -0
  6. sempy_labs/__init__.py +154 -0
  7. sempy_labs/_ai.py +496 -0
  8. sempy_labs/_clear_cache.py +39 -0
  9. sempy_labs/_connections.py +234 -0
  10. sempy_labs/_dax.py +70 -0
  11. sempy_labs/_generate_semantic_model.py +280 -0
  12. sempy_labs/_helper_functions.py +506 -0
  13. sempy_labs/_icons.py +4 -0
  14. sempy_labs/_list_functions.py +1372 -0
  15. sempy_labs/_model_auto_build.py +143 -0
  16. sempy_labs/_model_bpa.py +1354 -0
  17. sempy_labs/_model_dependencies.py +341 -0
  18. sempy_labs/_one_lake_integration.py +155 -0
  19. sempy_labs/_query_scale_out.py +447 -0
  20. sempy_labs/_refresh_semantic_model.py +184 -0
  21. sempy_labs/_tom.py +3766 -0
  22. sempy_labs/_translations.py +378 -0
  23. sempy_labs/_vertipaq.py +893 -0
  24. sempy_labs/directlake/__init__.py +45 -0
  25. sempy_labs/directlake/_directlake_schema_compare.py +110 -0
  26. sempy_labs/directlake/_directlake_schema_sync.py +128 -0
  27. sempy_labs/directlake/_fallback.py +62 -0
  28. sempy_labs/directlake/_get_directlake_lakehouse.py +69 -0
  29. sempy_labs/directlake/_get_shared_expression.py +59 -0
  30. sempy_labs/directlake/_guardrails.py +84 -0
  31. sempy_labs/directlake/_list_directlake_model_calc_tables.py +54 -0
  32. sempy_labs/directlake/_show_unsupported_directlake_objects.py +89 -0
  33. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +81 -0
  34. sempy_labs/directlake/_update_directlake_partition_entity.py +64 -0
  35. sempy_labs/directlake/_warm_cache.py +210 -0
  36. sempy_labs/lakehouse/__init__.py +24 -0
  37. sempy_labs/lakehouse/_get_lakehouse_columns.py +81 -0
  38. sempy_labs/lakehouse/_get_lakehouse_tables.py +250 -0
  39. sempy_labs/lakehouse/_lakehouse.py +85 -0
  40. sempy_labs/lakehouse/_shortcuts.py +296 -0
  41. sempy_labs/migration/__init__.py +29 -0
  42. sempy_labs/migration/_create_pqt_file.py +239 -0
  43. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +429 -0
  44. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +150 -0
  45. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +524 -0
  46. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +165 -0
  47. sempy_labs/migration/_migration_validation.py +227 -0
  48. sempy_labs/migration/_refresh_calc_tables.py +129 -0
  49. sempy_labs/report/__init__.py +35 -0
  50. sempy_labs/report/_generate_report.py +253 -0
  51. sempy_labs/report/_report_functions.py +855 -0
  52. sempy_labs/report/_report_rebind.py +131 -0
@@ -0,0 +1,506 @@
1
+ import sempy.fabric as fabric
2
+ import re
3
+ import pandas as pd
4
+ from pyspark.sql import SparkSession
5
+ from typing import Optional, Tuple
6
+ from uuid import UUID
7
+ import sempy_labs._icons as icons
8
+
9
+
10
+ def create_abfss_path(
11
+ lakehouse_id: UUID, lakehouse_workspace_id: UUID, delta_table_name: str
12
+ ):
13
+ """
14
+ Creates an abfss path for a delta table in a Fabric lakehouse.
15
+
16
+ Parameters
17
+ ----------
18
+ lakehouse_id : UUID
19
+ ID of the Fabric lakehouse.
20
+ lakehouse_workspace_id : UUID
21
+ ID of the Fabric workspace.
22
+ delta_table_name : str
23
+ Name of the delta table name.
24
+
25
+ Returns
26
+ -------
27
+ str
28
+ An abfss path which can be used to save/reference a delta table in a Fabric lakehouse.
29
+ """
30
+
31
+ return f"abfss://{lakehouse_workspace_id}@onelake.dfs.fabric.microsoft.com/{lakehouse_id}/Tables/{delta_table_name}"
32
+
33
+
34
+ def format_dax_object_name(table: str, column: str):
35
+ """
36
+ Formats a table/column combination to the 'Table Name'[Column Name] format.
37
+
38
+ Parameters
39
+ ----------
40
+ table : str
41
+ The name of the table.
42
+ column : str
43
+ The name of the column.
44
+
45
+ Returns
46
+ -------
47
+ str
48
+ The fully qualified object name.
49
+ """
50
+
51
+ return "'" + table + "'[" + column + "]"
52
+
53
+
54
+ def create_relationship_name(
55
+ from_table: str, from_column: str, to_table: str, to_column: str
56
+ ):
57
+ """
58
+ Formats a relationship's table/columns into a fully qualified name.
59
+
60
+ Parameters
61
+ ----------
62
+ from_table : str
63
+ The name of the table on the 'from' side of the relationship.
64
+ from_column : str
65
+ The name of the column on the 'from' side of the relationship.
66
+ to_table : str
67
+ The name of the table on the 'to' side of the relationship.
68
+ to_column : str
69
+ The name of the column on the 'to' side of the relationship.
70
+
71
+ Returns
72
+ -------
73
+ str
74
+ The fully qualified relationship name.
75
+ """
76
+
77
+ return (
78
+ format_dax_object_name(from_table, from_column)
79
+ + " -> "
80
+ + format_dax_object_name(to_table, to_column)
81
+ )
82
+
83
+
84
+ def resolve_report_id(report: str, workspace: Optional[str] = None):
85
+ """
86
+ Obtains the ID of the Power BI report.
87
+
88
+ Parameters
89
+ ----------
90
+ report : str
91
+ The name of the Power BI report.
92
+ workspace : str, default=None
93
+ The Fabric workspace name.
94
+ Defaults to None which resolves to the workspace of the attached lakehouse
95
+ or if no lakehouse attached, resolves to the workspace of the notebook.
96
+
97
+ Returns
98
+ -------
99
+ UUID
100
+ The ID of the Power BI report.
101
+ """
102
+
103
+ if workspace == None:
104
+ workspace_id = fabric.get_workspace_id()
105
+ workspace = fabric.resolve_workspace_name(workspace_id)
106
+
107
+ obj = fabric.resolve_item_id(item_name=report, type="Report", workspace=workspace)
108
+
109
+ return obj
110
+
111
+
112
+ def resolve_report_name(report_id: UUID, workspace: Optional[str] = None):
113
+ """
114
+ Obtains the name of the Power BI report.
115
+
116
+ Parameters
117
+ ----------
118
+ report_id : UUID
119
+ The name of the Power BI report.
120
+ workspace : str, default=None
121
+ The Fabric workspace name.
122
+ Defaults to None which resolves to the workspace of the attached lakehouse
123
+ or if no lakehouse attached, resolves to the workspace of the notebook.
124
+
125
+ Returns
126
+ -------
127
+ str
128
+ The name of the Power BI report.
129
+ """
130
+
131
+ if workspace == None:
132
+ workspace_id = fabric.get_workspace_id()
133
+ workspace = fabric.resolve_workspace_name(workspace_id)
134
+
135
+ obj = fabric.resolve_item_name(
136
+ item_id=report_id, type="Report", workspace=workspace
137
+ )
138
+
139
+ return obj
140
+
141
+
142
+ def resolve_dataset_id(dataset: str, workspace: Optional[str] = None):
143
+ """
144
+ Obtains the ID of the semantic model.
145
+
146
+ Parameters
147
+ ----------
148
+ dataset : str
149
+ The name of the semantic model.
150
+ workspace : str, default=None
151
+ The Fabric workspace name.
152
+ Defaults to None which resolves to the workspace of the attached lakehouse
153
+ or if no lakehouse attached, resolves to the workspace of the notebook.
154
+
155
+ Returns
156
+ -------
157
+ UUID
158
+ The ID of the semantic model.
159
+ """
160
+
161
+ if workspace == None:
162
+ workspace_id = fabric.get_workspace_id()
163
+ workspace = fabric.resolve_workspace_name(workspace_id)
164
+
165
+ obj = fabric.resolve_item_id(
166
+ item_name=dataset, type="SemanticModel", workspace=workspace
167
+ )
168
+
169
+ return obj
170
+
171
+
172
+ def resolve_dataset_name(dataset_id: UUID, workspace: Optional[str] = None):
173
+ """
174
+ Obtains the name of the semantic model.
175
+
176
+ Parameters
177
+ ----------
178
+ dataset_id : UUID
179
+ The name of the semantic model.
180
+ workspace : str, default=None
181
+ The Fabric workspace name.
182
+ Defaults to None which resolves to the workspace of the attached lakehouse
183
+ or if no lakehouse attached, resolves to the workspace of the notebook.
184
+
185
+ Returns
186
+ -------
187
+ str
188
+ The name of the semantic model.
189
+ """
190
+
191
+ if workspace == None:
192
+ workspace_id = fabric.get_workspace_id()
193
+ workspace = fabric.resolve_workspace_name(workspace_id)
194
+
195
+ obj = fabric.resolve_item_name(
196
+ item_id=dataset_id, type="SemanticModel", workspace=workspace
197
+ )
198
+
199
+ return obj
200
+
201
+
202
+ def resolve_lakehouse_name(lakehouse_id: UUID, workspace: Optional[str] = None):
203
+ """
204
+ Obtains the name of the Fabric lakehouse.
205
+
206
+ Parameters
207
+ ----------
208
+ lakehouse_id : UUID
209
+ The name of the Fabric lakehouse.
210
+ workspace : str, default=None
211
+ The Fabric workspace name.
212
+ Defaults to None which resolves to the workspace of the attached lakehouse
213
+ or if no lakehouse attached, resolves to the workspace of the notebook.
214
+
215
+ Returns
216
+ -------
217
+ str
218
+ The name of the Fabric lakehouse.
219
+ """
220
+
221
+ if workspace == None:
222
+ workspace_id = fabric.get_workspace_id()
223
+ workspace = fabric.resolve_workspace_name(workspace_id)
224
+
225
+ obj = fabric.resolve_item_name(
226
+ item_id=lakehouse_id, type="Lakehouse", workspace=workspace
227
+ )
228
+
229
+ return obj
230
+
231
+
232
+ def resolve_lakehouse_id(lakehouse: str, workspace: Optional[str] = None):
233
+ """
234
+ Obtains the ID of the Fabric lakehouse.
235
+
236
+ Parameters
237
+ ----------
238
+ lakehouse : str
239
+ The name of the Fabric lakehouse.
240
+ workspace : str, default=None
241
+ The Fabric workspace name.
242
+ Defaults to None which resolves to the workspace of the attached lakehouse
243
+ or if no lakehouse attached, resolves to the workspace of the notebook.
244
+
245
+ Returns
246
+ -------
247
+ UUID
248
+ The ID of the Fabric lakehouse.
249
+ """
250
+
251
+ if workspace == None:
252
+ workspace_id = fabric.get_workspace_id()
253
+ workspace = fabric.resolve_workspace_name(workspace_id)
254
+
255
+ obj = fabric.resolve_item_id(
256
+ item_name=lakehouse, type="Lakehouse", workspace=workspace
257
+ )
258
+
259
+ return obj
260
+
261
+
262
+ def get_direct_lake_sql_endpoint(dataset: str, workspace: Optional[str] = None) -> UUID:
263
+ """
264
+ Obtains the SQL Endpoint ID of the semantic model.
265
+
266
+ Parameters
267
+ ----------
268
+ dataset : str
269
+ The name of the semantic model.
270
+ workspace : str, default=None
271
+ The Fabric workspace name.
272
+ Defaults to None which resolves to the workspace of the attached lakehouse
273
+ or if no lakehouse attached, resolves to the workspace of the notebook.
274
+
275
+ Returns
276
+ -------
277
+ uuid.UUID
278
+ The ID of SQL Endpoint.
279
+ """
280
+
281
+ if workspace == None:
282
+ workspace_id = fabric.get_workspace_id()
283
+ workspace = fabric.resolve_workspace_name(workspace_id)
284
+
285
+ dfP = fabric.list_partitions(dataset=dataset, workspace=workspace)
286
+ dfP_filt = dfP[dfP["Mode"] == "DirectLake"]
287
+
288
+ if len(dfP_filt) == 0:
289
+ print(
290
+ f"The '{dataset}' semantic model in the '{workspace}' workspace is not in Direct Lake mode."
291
+ )
292
+ return
293
+
294
+ dfE = fabric.list_expressions(dataset=dataset, workspace=workspace)
295
+ dfE_filt = dfE[dfE["Name"] == "DatabaseQuery"]
296
+ expr = dfE_filt["Expression"].iloc[0]
297
+
298
+ matches = re.findall(r'"([^"]*)"', expr)
299
+ sqlEndpointId = matches[1]
300
+
301
+ return sqlEndpointId
302
+
303
+
304
+ def generate_embedded_filter(filter: str):
305
+ """
306
+ Converts the filter expression to a filter expression which can be used by a Power BI embedded URL.
307
+
308
+ Parameters
309
+ ----------
310
+ filter : str
311
+ The filter expression for an embedded Power BI report.
312
+
313
+ Returns
314
+ -------
315
+ str
316
+ A filter expression usable by a Power BI embedded URL.
317
+ """
318
+
319
+ pattern = r"'[^']+'\[[^\[]+\]"
320
+ matches = re.findall(pattern, filter)
321
+ for match in matches:
322
+ matchReplace = (
323
+ match.replace("'", "")
324
+ .replace("[", "/")
325
+ .replace("]", "")
326
+ .replace(" ", "_x0020_")
327
+ .replace("@", "_00x40_")
328
+ .replace("+", "_0x2B_")
329
+ .replace("{", "_007B_")
330
+ .replace("}", "_007D_")
331
+ )
332
+ filter = filter.replace(match, matchReplace)
333
+
334
+ pattern = r"\[[^\[]+\]"
335
+ matches = re.findall(pattern, filter)
336
+ for match in matches:
337
+ matchReplace = (
338
+ match.replace("'", "")
339
+ .replace("[", "/")
340
+ .replace("]", "")
341
+ .replace(" ", "_x0020_")
342
+ .replace("@", "_00x40_")
343
+ .replace("+", "_0x2B_")
344
+ .replace("{", "_007B_")
345
+ .replace("}", "_007D_")
346
+ )
347
+ filter = filter.replace(match, matchReplace)
348
+
349
+ revised_filter = (
350
+ filter.replace("<=", "le")
351
+ .replace(">=", "ge")
352
+ .replace("<>", "ne")
353
+ .replace("!=", "ne")
354
+ .replace("==", "eq")
355
+ .replace("=", "eq")
356
+ .replace("<", "lt")
357
+ .replace(">", "gt")
358
+ .replace(" && ", " and ")
359
+ .replace(" & ", " and ")
360
+ .replace(" || ", " or ")
361
+ .replace(" | ", " or ")
362
+ .replace("{", "(")
363
+ .replace("}", ")")
364
+ )
365
+
366
+ return revised_filter
367
+
368
+
369
+ def save_as_delta_table(
370
+ dataframe,
371
+ delta_table_name: str,
372
+ write_mode: str,
373
+ lakehouse: Optional[str] = None,
374
+ workspace: Optional[str] = None,
375
+ ):
376
+ """
377
+ Saves a pandas dataframe as a delta table in a Fabric lakehouse.
378
+
379
+ Parameters
380
+ ----------
381
+ dataframe : pandas.DataFrame
382
+ The dataframe to be saved as a delta table.
383
+ delta_table_name : str
384
+ The name of the delta table.
385
+ write_mode : str
386
+ The write mode for the save operation. Options: 'append', 'overwrite'.
387
+ lakehouse : str, default=None
388
+ The Fabric lakehouse used by the Direct Lake semantic model.
389
+ Defaults to None which resolves to the lakehouse attached to the notebook.
390
+ workspace : str, default=None
391
+ The Fabric workspace name.
392
+ Defaults to None which resolves to the workspace of the attached lakehouse
393
+ or if no lakehouse attached, resolves to the workspace of the notebook.
394
+
395
+ Returns
396
+ -------
397
+ UUID
398
+ The ID of the Power BI report.
399
+ """
400
+
401
+ if workspace is None:
402
+ workspace_id = fabric.get_workspace_id()
403
+ workspace = fabric.resolve_workspace_name(workspace_id)
404
+ else:
405
+ workspace_id = fabric.resolve_workspace_id(workspace)
406
+
407
+ if lakehouse is None:
408
+ lakehouse_id = fabric.get_lakehouse_id()
409
+ lakehouse = resolve_lakehouse_name(
410
+ lakehouse_id=lakehouse_id, workspace=workspace
411
+ )
412
+ else:
413
+ lakehouse_id = resolve_lakehouse_id(lakehouse, workspace)
414
+
415
+ writeModes = ["append", "overwrite"]
416
+ write_mode = write_mode.lower()
417
+
418
+ if write_mode not in writeModes:
419
+ print(
420
+ f"{icons.red_dot} Invalid 'write_type' parameter. Choose from one of the following values: {writeModes}."
421
+ )
422
+ return
423
+
424
+ if " " in delta_table_name:
425
+ print(
426
+ f"{icons.red_dot} Invalid 'delta_table_name'. Delta tables in the lakehouse cannot have spaces in their names."
427
+ )
428
+ return
429
+
430
+ dataframe.columns = dataframe.columns.str.replace(" ", "_")
431
+
432
+ spark = SparkSession.builder.getOrCreate()
433
+ spark_df = spark.createDataFrame(dataframe)
434
+
435
+ filePath = create_abfss_path(
436
+ lakehouse_id=lakehouse_id,
437
+ lakehouse_workspace_id=workspace_id,
438
+ delta_table_name=delta_table_name,
439
+ )
440
+ spark_df.write.mode(write_mode).format("delta").save(filePath)
441
+ print(
442
+ f"{icons.green_dot} The dataframe has been saved as the '{delta_table_name}' table in the '{lakehouse}' lakehouse within the '{workspace}' workspace."
443
+ )
444
+
445
+
446
+ def language_validate(language: str):
447
+ """
448
+ Validateds that the language specified exists within the supported langauges.
449
+
450
+ Parameters
451
+ ----------
452
+ language : str
453
+ The language code.
454
+
455
+ Returns
456
+ -------
457
+ bool
458
+ A True/False indication as to whether the language code is supported.
459
+ """
460
+
461
+ url = "https://learn.microsoft.com/azure/ai-services/translator/language-support"
462
+
463
+ tables = pd.read_html(url)
464
+ df = tables[0]
465
+
466
+ df_filt = df[df["Language code"] == language]
467
+
468
+ df_filt2 = df[df["Language"] == language.capitalize()]
469
+
470
+ if len(df_filt) == 1:
471
+ lang = df_filt["Language"].iloc[0]
472
+ elif len(df_filt2) == 1:
473
+ lang = df_filt2["Language"].iloc[0]
474
+ else:
475
+ print(
476
+ f"The '{language}' language is not a valid language code. Please refer to this link for a list of valid language codes: {url}."
477
+ )
478
+ return
479
+
480
+ return lang
481
+
482
+
483
+ def resolve_workspace_name_and_id(workspace: Optional[str] = None) -> Tuple[str, str]:
484
+ """
485
+ Obtains the name and ID of the Fabric workspace.
486
+
487
+ Parameters
488
+ ----------
489
+ workspace : str, default=None
490
+ The Fabric workspace name.
491
+ Defaults to None which resolves to the workspace of the attached lakehouse
492
+ or if no lakehouse attached, resolves to the workspace of the notebook.
493
+
494
+ Returns
495
+ -------
496
+ str, str
497
+ The name and ID of the Fabric workspace.
498
+ """
499
+
500
+ if workspace == None:
501
+ workspace_id = fabric.get_workspace_id()
502
+ workspace = fabric.resolve_workspace_name(workspace_id)
503
+ else:
504
+ workspace_id = fabric.resolve_workspace_id(workspace)
505
+
506
+ return workspace, workspace_id
sempy_labs/_icons.py ADDED
@@ -0,0 +1,4 @@
1
+ green_dot = "\U0001F7E2"
2
+ yellow_dot = "\U0001F7E1"
3
+ red_dot = "\U0001F534"
4
+ in_progress = "⌛"