semantic-link-labs 0.5.0__py3-none-any.whl → 0.6.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.

Files changed (54) hide show
  1. {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.6.0.dist-info}/METADATA +2 -2
  2. semantic_link_labs-0.6.0.dist-info/RECORD +54 -0
  3. {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.6.0.dist-info}/WHEEL +1 -1
  4. sempy_labs/__init__.py +19 -13
  5. sempy_labs/_ai.py +43 -24
  6. sempy_labs/_clear_cache.py +4 -5
  7. sempy_labs/_connections.py +77 -70
  8. sempy_labs/_dax.py +7 -9
  9. sempy_labs/_generate_semantic_model.py +55 -44
  10. sempy_labs/_helper_functions.py +13 -6
  11. sempy_labs/_icons.py +14 -0
  12. sempy_labs/_list_functions.py +491 -304
  13. sempy_labs/_model_auto_build.py +4 -3
  14. sempy_labs/_model_bpa.py +131 -1118
  15. sempy_labs/_model_bpa_rules.py +831 -0
  16. sempy_labs/_model_dependencies.py +14 -12
  17. sempy_labs/_one_lake_integration.py +11 -5
  18. sempy_labs/_query_scale_out.py +89 -81
  19. sempy_labs/_refresh_semantic_model.py +16 -10
  20. sempy_labs/_translations.py +213 -287
  21. sempy_labs/_vertipaq.py +53 -37
  22. sempy_labs/directlake/__init__.py +2 -0
  23. sempy_labs/directlake/_directlake_schema_compare.py +12 -5
  24. sempy_labs/directlake/_directlake_schema_sync.py +13 -19
  25. sempy_labs/directlake/_fallback.py +5 -3
  26. sempy_labs/directlake/_get_directlake_lakehouse.py +1 -1
  27. sempy_labs/directlake/_get_shared_expression.py +4 -2
  28. sempy_labs/directlake/_guardrails.py +3 -3
  29. sempy_labs/directlake/_list_directlake_model_calc_tables.py +17 -10
  30. sempy_labs/directlake/_show_unsupported_directlake_objects.py +3 -2
  31. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +10 -5
  32. sempy_labs/directlake/_update_directlake_partition_entity.py +132 -9
  33. sempy_labs/directlake/_warm_cache.py +6 -3
  34. sempy_labs/lakehouse/_get_lakehouse_columns.py +1 -1
  35. sempy_labs/lakehouse/_get_lakehouse_tables.py +5 -3
  36. sempy_labs/lakehouse/_lakehouse.py +2 -1
  37. sempy_labs/lakehouse/_shortcuts.py +19 -12
  38. sempy_labs/migration/__init__.py +1 -1
  39. sempy_labs/migration/_create_pqt_file.py +21 -15
  40. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +16 -13
  41. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +17 -18
  42. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +43 -40
  43. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +14 -14
  44. sempy_labs/migration/_migration_validation.py +2 -2
  45. sempy_labs/migration/_refresh_calc_tables.py +8 -5
  46. sempy_labs/report/__init__.py +2 -2
  47. sempy_labs/report/_generate_report.py +10 -5
  48. sempy_labs/report/_report_functions.py +67 -29
  49. sempy_labs/report/_report_rebind.py +9 -8
  50. sempy_labs/tom/__init__.py +1 -4
  51. sempy_labs/tom/_model.py +555 -152
  52. semantic_link_labs-0.5.0.dist-info/RECORD +0 -53
  53. {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.6.0.dist-info}/LICENSE +0 -0
  54. {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.6.0.dist-info}/top_level.txt +0 -0
@@ -37,10 +37,16 @@ def translate_semantic_model(
37
37
  from pyspark.sql import SparkSession
38
38
  from sempy_labs.tom import connect_semantic_model
39
39
 
40
+ def clean_text(text, exclude_chars):
41
+ if exclude_chars:
42
+ for char in exclude_chars:
43
+ text = text.replace(char, " ")
44
+ return text
45
+
40
46
  if isinstance(languages, str):
41
47
  languages = [languages]
42
48
 
43
- dfPrep = pd.DataFrame(
49
+ df_prep = pd.DataFrame(
44
50
  columns=["Object Type", "Name", "Description", "Display Folder"]
45
51
  )
46
52
 
@@ -48,141 +54,87 @@ def translate_semantic_model(
48
54
  dataset=dataset, readonly=False, workspace=workspace
49
55
  ) as tom:
50
56
 
51
- if exclude_characters is None:
52
- for o in tom.model.Tables:
53
- new_data = {
54
- "Object Type": "Table",
55
- "Name": o.Name,
56
- "TName": o.Name,
57
- "Description": o.Description,
58
- "TDescription": o.Description,
59
- "Display Folder": None,
60
- "TDisplay Folder": None,
61
- }
62
- dfPrep = pd.concat(
63
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
64
- )
65
- for o in tom.all_columns():
66
- new_data = {
67
- "Object Type": "Column",
68
- "Name": o.Name,
69
- "TName": o.Name,
70
- "Description": o.Description,
71
- "TDescription": o.Description,
72
- "Display Folder": o.DisplayFolder,
73
- "TDisplay Folder": o.DisplayFolder,
74
- }
75
- dfPrep = pd.concat(
76
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
77
- )
78
- for o in tom.all_measures():
79
- new_data = {
80
- "Object Type": "Measure",
81
- "Name": o.Name,
82
- "TName": o.Name,
83
- "Description": o.Description,
84
- "TDescription": o.Description,
85
- "Display Folder": o.DisplayFolder,
86
- "TDisplay Folder": o.DisplayFolder,
87
- }
88
- dfPrep = pd.concat(
89
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
90
- )
91
- for o in tom.all_hierarchies():
92
- new_data = {
93
- "Object Type": "Hierarchy",
94
- "Name": o.Name,
95
- "TName": o.Name,
96
- "Description": o.Description,
97
- "TDescription": o.Description,
98
- "Display Folder": o.DisplayFolder,
99
- "TDisplay Folder": o.DisplayFolder,
100
- }
101
- dfPrep = pd.concat(
102
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
103
- )
104
- else:
105
- for o in tom.model.Tables:
106
- oName = o.Name
107
- oDescription = o.Description
108
- for s in exclude_characters:
109
- oName = oName.replace(s, " ")
110
- oDescription = oDescription.replace(s, " ")
111
- new_data = {
112
- "Object Type": "Table",
113
- "Name": o.Name,
114
- "TName": oName,
115
- "Description": o.Description,
116
- "TDescription": oDescription,
117
- "Display Folder": None,
118
- "TDisplay Folder": None,
119
- }
120
- dfPrep = pd.concat(
121
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
122
- )
123
- for o in tom.all_columns():
124
- oName = o.Name
125
- oDescription = o.Description
126
- oDisplayFolder = o.DisplayFolder
127
- for s in exclude_characters:
128
- oName = oName.replace(s, " ")
129
- oDescription = oDescription.replace(s, " ")
130
- oDisplayFolder = oDisplayFolder.replace(s, " ")
131
- new_data = {
132
- "Object Type": "Column",
133
- "Name": o.Name,
134
- "TName": oName,
135
- "Description": o.Description,
136
- "TDescription": oDescription,
137
- "Display Folder": o.DisplayFolder,
138
- "TDisplay Folder": oDisplayFolder,
139
- }
140
- dfPrep = pd.concat(
141
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
142
- )
143
- for o in tom.all_measures():
144
- oName = o.Name
145
- oDescription = o.Description
146
- oDisplayFolder = o.DisplayFolder
147
- for s in exclude_characters:
148
- oName = oName.replace(s, " ")
149
- oDescription = oDescription.replace(s, " ")
150
- oDisplayFolder = oDisplayFolder.replace(s, " ")
151
- new_data = {
152
- "Object Type": "Measure",
153
- "Name": o.Name,
154
- "TName": oName,
155
- "Description": o.Description,
156
- "TDescription": oDescription,
157
- "Display Folder": o.DisplayFolder,
158
- "TDisplay Folder": oDisplayFolder,
159
- }
160
- dfPrep = pd.concat(
161
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
162
- )
163
- for o in tom.all_hierarchies():
164
- oName = o.Name
165
- oDescription = o.Description
166
- oDisplayFolder = o.DisplayFolder
167
- for s in exclude_characters:
168
- oName = oName.replace(s, " ")
169
- oDescription = oDescription.replace(s, " ")
170
- oDisplayFolder = oDisplayFolder.replace(s, " ")
171
- new_data = {
172
- "Object Type": "Hierarchy",
173
- "Name": o.Name,
174
- "TName": oName,
175
- "Description": o.Description,
176
- "TDescription": oDescription,
177
- "Display Folder": o.DisplayFolder,
178
- "TDisplay Folder": oDisplayFolder,
179
- }
180
- dfPrep = pd.concat(
181
- [dfPrep, pd.DataFrame(new_data, index=[0])], ignore_index=True
182
- )
57
+ for o in tom.model.Tables:
58
+ oName = clean_text(o.Name, exclude_characters)
59
+ oDescription = clean_text(o.Description, exclude_characters)
60
+ new_data = {
61
+ "Object Type": "Table",
62
+ "Name": o.Name,
63
+ "TName": oName,
64
+ "Description": o.Description,
65
+ "TDescription": oDescription,
66
+ "Display Folder": None,
67
+ "TDisplay Folder": None,
68
+ }
69
+ df_prep = pd.concat(
70
+ [df_prep, pd.DataFrame(new_data, index=[0])], ignore_index=True
71
+ )
72
+ for o in tom.all_columns():
73
+ oName = clean_text(o.Name, exclude_characters)
74
+ oDescription = clean_text(o.Description, exclude_characters)
75
+ oDisplayFolder = clean_text(o.DisplayFolder, exclude_characters)
76
+ new_data = {
77
+ "Object Type": "Column",
78
+ "Name": o.Name,
79
+ "TName": oName,
80
+ "Description": o.Description,
81
+ "TDescription": oDescription,
82
+ "Display Folder": o.DisplayFolder,
83
+ "TDisplay Folder": oDisplayFolder,
84
+ }
85
+ df_prep = pd.concat(
86
+ [df_prep, pd.DataFrame(new_data, index=[0])], ignore_index=True
87
+ )
88
+ for o in tom.all_measures():
89
+ oName = clean_text(o.Name, exclude_characters)
90
+ oDescription = clean_text(o.Description, exclude_characters)
91
+ oDisplayFolder = clean_text(o.DisplayFolder, exclude_characters)
92
+ new_data = {
93
+ "Object Type": "Measure",
94
+ "Name": o.Name,
95
+ "TName": oName,
96
+ "Description": o.Description,
97
+ "TDescription": oDescription,
98
+ "Display Folder": o.DisplayFolder,
99
+ "TDisplay Folder": oDisplayFolder,
100
+ }
101
+ df_prep = pd.concat(
102
+ [df_prep, pd.DataFrame(new_data, index=[0])], ignore_index=True
103
+ )
104
+ for o in tom.all_hierarchies():
105
+ oName = clean_text(o.Name, exclude_characters)
106
+ oDescription = clean_text(o.Description, exclude_characters)
107
+ oDisplayFolder = clean_text(o.DisplayFolder, exclude_characters)
108
+ new_data = {
109
+ "Object Type": "Hierarchy",
110
+ "Name": o.Name,
111
+ "TName": oName,
112
+ "Description": o.Description,
113
+ "TDescription": oDescription,
114
+ "Display Folder": o.DisplayFolder,
115
+ "TDisplay Folder": oDisplayFolder,
116
+ }
117
+ df_prep = pd.concat(
118
+ [df_prep, pd.DataFrame(new_data, index=[0])], ignore_index=True
119
+ )
120
+ for o in tom.all_levels():
121
+ oName = clean_text(o.Name, exclude_characters)
122
+ oDescription = clean_text(o.Description, exclude_characters)
123
+ new_data = {
124
+ "Object Type": "Level",
125
+ "Name": o.Name,
126
+ "TName": oName,
127
+ "Description": o.Description,
128
+ "TDescription": oDescription,
129
+ "Display Folder": None,
130
+ "TDisplay Folder": None,
131
+ }
132
+ df_prep = pd.concat(
133
+ [df_prep, pd.DataFrame(new_data, index=[0])], ignore_index=True
134
+ )
183
135
 
184
136
  spark = SparkSession.builder.getOrCreate()
185
- df = spark.createDataFrame(dfPrep)
137
+ df = spark.createDataFrame(df_prep)
186
138
 
187
139
  columns = ["Name", "Description", "Display Folder"]
188
140
 
@@ -204,175 +156,149 @@ def translate_semantic_model(
204
156
  )
205
157
 
206
158
  df_panda = transDF.toPandas()
207
- print(f"{icons.in_progress} Translating {clm}s...")
159
+
160
+ def set_translation_if_exists(
161
+ obj, obj_type, property_name, property_value, df, lang, index
162
+ ):
163
+ if property_name in df.columns and len(property_value) > 0:
164
+ df_filt = df[
165
+ (df["Object Type"] == obj_type)
166
+ & (df[property_name] == property_value)
167
+ ]
168
+ if len(df_filt) == 1:
169
+ translation = df_filt["translation"].str[index].iloc[0]
170
+ tom.set_translation(
171
+ object=obj,
172
+ language=lang,
173
+ property=property_name,
174
+ value=translation,
175
+ )
208
176
 
209
177
  for lang in languages:
210
178
  i = languages.index(lang)
211
179
  tom.add_translation(language=lang)
212
- print(f"{icons.in_progress} Translating into the '{lang}' language...")
180
+ print(
181
+ f"{icons.in_progress} Translating {clm.lower()}s into the '{lang}' language..."
182
+ )
213
183
 
214
184
  for t in tom.model.Tables:
215
185
  if t.IsHidden is False:
216
186
  if clm == "Name":
217
- df_filt = df_panda[
218
- (df_panda["Object Type"] == "Table")
219
- & (df_panda["Name"] == t.Name)
220
- ]
221
- if len(df_filt) == 1:
222
- tr = df_filt["translation"].str[i].iloc[0]
223
- tom.set_translation(
224
- object=t, language=lang, property="Name", value=tr
225
- )
226
- print(
227
- f"{icons.green_dot} Translation '{tr}' set for the '{lang}' language on the '{t.Name}' table."
228
- )
229
- elif clm == "Description" and t.Description is not None:
230
- df_filt = df_panda[
231
- (df_panda["Object Type"] == "Table")
232
- & (df_panda["Description"] == t.Description)
233
- ]
234
- if len(df_filt) == 1:
235
- tr = df_filt["translation"].str[i].iloc[0]
236
- tom.set_translation(
237
- object=t,
238
- language=lang,
239
- property="Description",
240
- value=tr,
241
- )
187
+ set_translation_if_exists(
188
+ t, "Table", "Name", t.Name, df_panda, lang, i
189
+ )
190
+ elif clm == "Description":
191
+ set_translation_if_exists(
192
+ t,
193
+ "Table",
194
+ "Description",
195
+ t.Description,
196
+ df_panda,
197
+ lang,
198
+ i,
199
+ )
242
200
  for c in t.Columns:
243
201
  if c.IsHidden is False:
244
202
  if clm == "Name":
245
- df_filt = df_panda[
246
- (df_panda["Object Type"] == "Column")
247
- & (df_panda["Name"] == c.Name)
248
- ]
249
- if len(df_filt) == 1:
250
- tr = df_filt["translation"].str[i].iloc[0]
251
- tom.set_translation(
252
- object=c,
253
- language=lang,
254
- property="Name",
255
- value=tr,
256
- )
257
- print(
258
- f"{icons.green_dot} Translation '{tr}' set on the '{c.Name}' column within the {t.Name}' table."
259
- )
260
- elif clm == "Description" and c.Description is not None:
261
- df_filt = df_panda[
262
- (df_panda["Object Type"] == "Column")
263
- & (df_panda["Description"] == c.Description)
264
- ]
265
- if len(df_filt) == 1:
266
- tr = df_filt["translation"].str[i].iloc[0]
267
- tom.set_translation(
268
- object=c,
269
- language=lang,
270
- property="Description",
271
- value=tr,
272
- )
273
- elif (
274
- clm == "Display Folder"
275
- and c.DisplayFolder is not None
276
- ):
277
- df_filt = df_panda[
278
- (df_panda["Object Type"] == "Column")
279
- & (df_panda["Display Folder"] == c.Description)
280
- ]
281
- if len(df_filt) == 1:
282
- tr = df_filt["translation"].str[i].iloc[0]
283
- tom.set_translation(
284
- object=c,
285
- language=lang,
286
- property="Display Folder",
287
- value=tr,
288
- )
203
+ set_translation_if_exists(
204
+ c, "Column", "Name", c.Name, df_panda, lang, i
205
+ )
206
+ elif clm == "Description":
207
+ set_translation_if_exists(
208
+ c,
209
+ "Column",
210
+ "Description",
211
+ c.Description,
212
+ df_panda,
213
+ lang,
214
+ i,
215
+ )
216
+ elif clm == "Display Folder":
217
+ set_translation_if_exists(
218
+ c,
219
+ "Column",
220
+ "Display Folder",
221
+ c.DisplayFolder,
222
+ df_panda,
223
+ lang,
224
+ i,
225
+ )
289
226
  for h in t.Hierarchies:
290
227
  if h.IsHidden is False:
291
228
  if clm == "Name":
292
- df_filt = df_panda[
293
- (df_panda["Object Type"] == "Hierarchy")
294
- & (df_panda["Name"] == h.Name)
295
- ]
296
- if len(df_filt) == 1:
297
- tr = df_filt["translation"].str[i].iloc[0]
298
- tom.set_translation(
299
- object=h,
300
- language=lang,
301
- property="Name",
302
- value=tr,
303
- )
304
- elif clm == "Description" and h.Description is not None:
305
- df_filt = df_panda[
306
- (df_panda["Object Type"] == "Hierarchy")
307
- & (df_panda["Description"] == h.Description)
308
- ]
309
- if len(df_filt) == 1:
310
- tr = df_filt["translation"].str[i].iloc[0]
311
- tom.set_translation(
312
- object=h,
313
- language=lang,
314
- property="Description",
315
- value=tr,
229
+ set_translation_if_exists(
230
+ h,
231
+ "Hierarchy",
232
+ "Name",
233
+ h.Name,
234
+ df_panda,
235
+ lang,
236
+ i,
237
+ )
238
+ elif clm == "Description":
239
+ set_translation_if_exists(
240
+ h,
241
+ "Hierarchy",
242
+ "Description",
243
+ h.Description,
244
+ df_panda,
245
+ lang,
246
+ i,
247
+ )
248
+ elif clm == "Display Folder":
249
+ set_translation_if_exists(
250
+ h,
251
+ "Hierarchy",
252
+ "Display Folder",
253
+ h.DisplayFolder,
254
+ df_panda,
255
+ lang,
256
+ i,
257
+ )
258
+ for lev in h.Levels:
259
+ if clm == "Name":
260
+ set_translation_if_exists(
261
+ lev,
262
+ "Level",
263
+ "Name",
264
+ lev.Name,
265
+ df_panda,
266
+ lang,
267
+ i,
316
268
  )
317
- elif (
318
- clm == "Display Folder"
319
- and h.DisplayFolder is not None
320
- ):
321
- df_filt = df_panda[
322
- (df_panda["Object Type"] == "Hierarchy")
323
- & (df_panda["Display Folder"] == h.Description)
324
- ]
325
- if len(df_filt) == 1:
326
- tr = df_filt["translation"].str[i].iloc[0]
327
- tom.set_translation(
328
- object=h,
329
- language=lang,
330
- property="Display Folder",
331
- value=tr,
269
+ elif clm == "Description":
270
+ set_translation_if_exists(
271
+ lev,
272
+ "Level",
273
+ "Description",
274
+ lev.Description,
275
+ df_panda,
276
+ lang,
277
+ i,
332
278
  )
333
279
  for ms in t.Measures:
334
280
  if ms.IsHidden is False:
335
281
  if clm == "Name":
336
- df_filt = df_panda[
337
- (df_panda["Object Type"] == "Measure")
338
- & (df_panda["Name"] == ms.Name)
339
- ]
340
- if len(df_filt) == 1:
341
- tr = df_filt["translation"].str[i].iloc[0]
342
- tom.set_translation(
343
- object=ms,
344
- language=lang,
345
- property="Name",
346
- value=tr,
347
- )
348
- print(
349
- f"{icons.green_dot} Translation '{tr}' set on the '{ms.Name}' column within the {t.Name}' table."
350
- )
351
- elif clm == "Description" and ms.Description is not None:
352
- df_filt = df_panda[
353
- (df_panda["Object Type"] == "Measure")
354
- & (df_panda["Description"] == ms.Description)
355
- ]
356
- if len(df_filt) == 1:
357
- tr = df_filt["translation"].str[i].iloc[0]
358
- tom.set_translation(
359
- object=ms,
360
- language=lang,
361
- property="Description",
362
- value=tr,
363
- )
364
- elif (
365
- clm == "Display Folder" and ms.DisplayFolder is not None
366
- ):
367
- df_filt = df_panda[
368
- (df_panda["Object Type"] == "Measure")
369
- & (df_panda["Display Folder"] == ms.Description)
370
- ]
371
- if len(df_filt) == 1:
372
- tr = df_filt["translation"].str[i].iloc[0]
373
- tom.set_translation(
374
- object=ms,
375
- language=lang,
376
- property="Display Folder",
377
- value=tr,
378
- )
282
+ set_translation_if_exists(
283
+ ms, "Measure", "Name", ms.Name, df_panda, lang, i
284
+ )
285
+ elif clm == "Description":
286
+ set_translation_if_exists(
287
+ ms,
288
+ "Measure",
289
+ "Description",
290
+ ms.Description,
291
+ df_panda,
292
+ lang,
293
+ i,
294
+ )
295
+ elif clm == "Display Folder":
296
+ set_translation_if_exists(
297
+ ms,
298
+ "Measure",
299
+ "Display Folder",
300
+ ms.DisplayFolder,
301
+ df_panda,
302
+ lang,
303
+ i,
304
+ )