semantic-link-labs 0.4.2__py3-none-any.whl → 0.5.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 (44) hide show
  1. {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/METADATA +1 -1
  2. semantic_link_labs-0.5.0.dist-info/RECORD +53 -0
  3. {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/WHEEL +1 -1
  4. sempy_labs/__init__.py +27 -3
  5. sempy_labs/_ai.py +12 -32
  6. sempy_labs/_clear_cache.py +1 -3
  7. sempy_labs/_connections.py +39 -38
  8. sempy_labs/_generate_semantic_model.py +9 -14
  9. sempy_labs/_helper_functions.py +3 -12
  10. sempy_labs/_icons.py +1 -0
  11. sempy_labs/_list_functions.py +915 -391
  12. sempy_labs/_model_auto_build.py +2 -4
  13. sempy_labs/_model_bpa.py +26 -30
  14. sempy_labs/_model_dependencies.py +7 -13
  15. sempy_labs/_one_lake_integration.py +2 -5
  16. sempy_labs/_query_scale_out.py +12 -30
  17. sempy_labs/_refresh_semantic_model.py +5 -15
  18. sempy_labs/_translations.py +1 -1
  19. sempy_labs/_vertipaq.py +3 -10
  20. sempy_labs/directlake/_directlake_schema_compare.py +3 -9
  21. sempy_labs/directlake/_directlake_schema_sync.py +2 -6
  22. sempy_labs/directlake/_fallback.py +2 -6
  23. sempy_labs/directlake/_get_shared_expression.py +3 -9
  24. sempy_labs/directlake/_guardrails.py +3 -5
  25. sempy_labs/directlake/_list_directlake_model_calc_tables.py +3 -4
  26. sempy_labs/directlake/_show_unsupported_directlake_objects.py +1 -2
  27. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +3 -7
  28. sempy_labs/directlake/_update_directlake_partition_entity.py +2 -8
  29. sempy_labs/directlake/_warm_cache.py +5 -8
  30. sempy_labs/lakehouse/_get_lakehouse_columns.py +1 -1
  31. sempy_labs/lakehouse/_get_lakehouse_tables.py +3 -5
  32. sempy_labs/lakehouse/_lakehouse.py +1 -3
  33. sempy_labs/lakehouse/_shortcuts.py +2 -5
  34. sempy_labs/migration/_create_pqt_file.py +4 -13
  35. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +2 -6
  36. sempy_labs/migration/_migration_validation.py +4 -0
  37. sempy_labs/migration/_refresh_calc_tables.py +2 -0
  38. sempy_labs/report/_generate_report.py +2 -6
  39. sempy_labs/report/_report_functions.py +30 -73
  40. sempy_labs/report/_report_rebind.py +39 -39
  41. sempy_labs/tom/_model.py +141 -183
  42. semantic_link_labs-0.4.2.dist-info/RECORD +0 -53
  43. {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/LICENSE +0 -0
  44. {semantic_link_labs-0.4.2.dist-info → semantic_link_labs-0.5.0.dist-info}/top_level.txt +0 -0
sempy_labs/tom/_model.py CHANGED
@@ -93,7 +93,7 @@ class TOMWrapper:
93
93
  import Microsoft.AnalysisServices.Tabular as TOM
94
94
 
95
95
  for t in self.model.Tables:
96
- if any(p.SourceType == TOM.ColumnType.Calculated for p in t.Partitions):
96
+ if any(p.SourceType == TOM.PartitionSourceType.Calculated for p in t.Partitions):
97
97
  yield t
98
98
 
99
99
  def all_calculation_groups(self):
@@ -658,22 +658,16 @@ class TOMWrapper:
658
658
  import Microsoft.AnalysisServices.Tabular as TOM
659
659
 
660
660
  if isinstance(columns, str):
661
- print(
662
- f"{icons.red_dot} The 'levels' parameter must be a list. For example: ['Continent', 'Country', 'City']"
663
- )
664
- return
661
+ raise ValueError(f"{icons.red_dot} The 'levels' parameter must be a list. For example: ['Continent', 'Country', 'City']")
662
+
665
663
  if len(columns) == 1:
666
- print(f"{icons.red_dot} There must be at least 2 levels in order to create a hierarchy.")
667
- return
664
+ raise ValueError(f"{icons.red_dot} There must be at least 2 levels in order to create a hierarchy.")
668
665
 
669
666
  if levels is None:
670
667
  levels = columns
671
668
 
672
669
  if len(columns) != len(levels):
673
- print(
674
- f"{icons.red_dot} If specifying level names, you must specify a level for each column."
675
- )
676
- return
670
+ raise ValueError(f"{icons.red_dot} If specifying level names, you must specify a level for each column.")
677
671
 
678
672
  obj = TOM.Hierarchy()
679
673
  obj.Name = hierarchy_name
@@ -1003,9 +997,7 @@ class TOMWrapper:
1003
997
  import System
1004
998
 
1005
999
  if base_column is not None and base_table is None:
1006
- print(
1007
- f"{icons.red_dot} If you specify the base table you must also specify the base column"
1008
- )
1000
+ raise ValueError(f"{icons.red_dot} If you specify the base table you must also specify the base column")
1009
1001
 
1010
1002
  summarization_type = (
1011
1003
  summarization_type.replace(" ", "")
@@ -1015,10 +1007,7 @@ class TOMWrapper:
1015
1007
 
1016
1008
  summarizationTypes = ["Sum", "GroupBy", "Count", "Min", "Max"]
1017
1009
  if summarization_type not in summarizationTypes:
1018
- print(
1019
- f"{icons.red_dot} The 'summarization_type' parameter must be one of the following valuse: {summarizationTypes}."
1020
- )
1021
- return
1010
+ raise ValueError(f"{icons.red_dot} The 'summarization_type' parameter must be one of the following valuse: {summarizationTypes}.")
1022
1011
 
1023
1012
  ao = TOM.AlternateOf()
1024
1013
  ao.Summarization = System.Enum.Parse(TOM.SummarizationType, summarization_type)
@@ -1277,10 +1266,7 @@ class TOMWrapper:
1277
1266
  objectType = object.ObjectType
1278
1267
 
1279
1268
  if objectType not in validObjects:
1280
- print(
1281
- f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}."
1282
- )
1283
- return
1269
+ raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
1284
1270
 
1285
1271
  object.Model.Perspectives[perspective_name]
1286
1272
 
@@ -1331,15 +1317,12 @@ class TOMWrapper:
1331
1317
  objectType = object.ObjectType
1332
1318
 
1333
1319
  if objectType not in validObjects:
1334
- print(
1335
- f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}."
1336
- )
1337
- return
1320
+ raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
1321
+
1338
1322
  try:
1339
1323
  object.Model.Perspectives[perspective_name]
1340
1324
  except:
1341
- print(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
1342
- return
1325
+ raise ValueError(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
1343
1326
 
1344
1327
  # try:
1345
1328
  if objectType == TOM.ObjectType.Table:
@@ -1393,15 +1376,12 @@ class TOMWrapper:
1393
1376
  objectType = object.ObjectType
1394
1377
 
1395
1378
  if objectType not in validObjects:
1396
- print(
1397
- f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}."
1398
- )
1399
- return
1379
+ raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
1380
+
1400
1381
  try:
1401
1382
  object.Model.Perspectives[perspective_name]
1402
1383
  except:
1403
- print(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
1404
- return
1384
+ raise ValueError(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
1405
1385
 
1406
1386
  # try:
1407
1387
  if objectType == TOM.ObjectType.Table:
@@ -1474,8 +1454,7 @@ class TOMWrapper:
1474
1454
  ] # , 'Level'
1475
1455
 
1476
1456
  if object.ObjectType not in validObjects:
1477
- print(f"{icons.red_dot} Translations can only be set to {validObjects}.")
1478
- return
1457
+ raise ValueError(f"{icons.red_dot} Translations can only be set to {validObjects}.")
1479
1458
 
1480
1459
  mapping = {
1481
1460
  "Name": TOM.TranslatedProperty.Caption,
@@ -1484,14 +1463,13 @@ class TOMWrapper:
1484
1463
  }
1485
1464
 
1486
1465
  prop = mapping.get(property)
1466
+ if prop == None:
1467
+ raise ValueError(f"{icons.red_dot} Invalid property value. Please choose from the following: ['Name', 'Description', Display Folder].")
1487
1468
 
1488
1469
  try:
1489
1470
  object.Model.Cultures[language]
1490
1471
  except:
1491
- print(
1492
- f"{icons.red_dot} The '{language}' translation language does not exist in the semantic model."
1493
- )
1494
- return
1472
+ raise ValueError(f"{icons.red_dot} The '{language}' translation language does not exist in the semantic model.")
1495
1473
 
1496
1474
  object.Model.Cultures[language].ObjectTranslations.SetTranslation(
1497
1475
  object, prop, value
@@ -1955,11 +1933,8 @@ class TOMWrapper:
1955
1933
  t = self.model.Tables[table_name]
1956
1934
  c = t.Columns[column_name]
1957
1935
  if c.DataType != TOM.DataType.DateTime:
1958
- print(
1959
- f"{icons.red_dot} The column specified in the 'column_name' parameter in this function must be of DateTime data type."
1960
- )
1961
- return
1962
-
1936
+ raise ValueError(f"{icons.red_dot} The column specified in the 'column_name' parameter in this function must be of DateTime data type.")
1937
+
1963
1938
  daxQuery = f"""
1964
1939
  define measure '{table_name}'[test] =
1965
1940
  var mn = MIN('{table_name}'[{column_name}])
@@ -1978,10 +1953,7 @@ class TOMWrapper:
1978
1953
  )
1979
1954
  value = df["1"].iloc[0]
1980
1955
  if value != "1":
1981
- print(
1982
- f"{icons.red_dot} The '{column_name}' within the '{table_name}' table does not contain contiguous date values."
1983
- )
1984
- return
1956
+ raise ValueError(f"{icons.red_dot} The '{column_name}' within the '{table_name}' table does not contain contiguous date values.")
1985
1957
 
1986
1958
  # Mark as a date table
1987
1959
  t.DataCategory = "Time"
@@ -2176,10 +2148,7 @@ class TOMWrapper:
2176
2148
  # https://github.com/m-kovalsky/Tabular/blob/master/KPI%20Graphics.md
2177
2149
 
2178
2150
  if measure_name == target:
2179
- print(
2180
- f"{icons.red_dot} The 'target' parameter cannot be the same measure as the 'measure_name' parameter."
2181
- )
2182
- return
2151
+ raise ValueError(f"{icons.red_dot} The 'target' parameter cannot be the same measure as the 'measure_name' parameter.")
2183
2152
 
2184
2153
  if status_graphic is None:
2185
2154
  status_graphic = "Three Circles Colored"
@@ -2192,43 +2161,31 @@ class TOMWrapper:
2192
2161
  status_type = status_type.title().replace(" ", "")
2193
2162
 
2194
2163
  if status_type not in valid_status_types:
2195
- print(
2196
- f"{icons.red_dot} '{status_type}' is an invalid status_type. Please choose from these options: {valid_status_types}."
2197
- )
2198
- return
2164
+ raise ValueError(f"{icons.red_dot} '{status_type}' is an invalid status_type. Please choose from these options: {valid_status_types}.")
2199
2165
 
2200
2166
  if status_type in ["Linear", "LinearReversed"]:
2201
2167
  if upper_bound is not None or lower_mid_bound is not None:
2202
- print(
2203
- f"{icons.red_dot} The 'upper_mid_bound' and 'lower_mid_bound' parameters are not used in the 'Linear' and 'LinearReversed' status types. Make sure these parameters are set to None."
2204
- )
2205
- return
2168
+ raise ValueError(f"{icons.red_dot} The 'upper_mid_bound' and 'lower_mid_bound' parameters are not used in the 'Linear' and 'LinearReversed' status types. Make sure these parameters are set to None.")
2169
+
2206
2170
  elif upper_bound <= lower_bound:
2207
- print(f"{icons.red_dot} The upper_bound must be greater than the lower_bound.")
2208
- return
2171
+ raise ValueError(f"{icons.red_dot} The upper_bound must be greater than the lower_bound.")
2209
2172
 
2210
2173
  if status_type in ["Centered", "CenteredReversed"]:
2211
2174
  if upper_mid_bound is None or lower_mid_bound is None:
2212
- print(
2213
- f"{icons.red_dot} The 'upper_mid_bound' and 'lower_mid_bound' parameters are necessary in the 'Centered' and 'CenteredReversed' status types."
2214
- )
2215
- return
2175
+ raise ValueError(f"{icons.red_dot} The 'upper_mid_bound' and 'lower_mid_bound' parameters are necessary in the 'Centered' and 'CenteredReversed' status types.")
2216
2176
  elif upper_bound <= upper_mid_bound:
2217
- print(f"{icons.red_dot} The upper_bound must be greater than the upper_mid_bound.")
2177
+ raise ValueError(f"{icons.red_dot} The upper_bound must be greater than the upper_mid_bound.")
2218
2178
  elif upper_mid_bound <= lower_mid_bound:
2219
- print(f"{icons.red_dot} The upper_mid_bound must be greater than the lower_mid_bound.")
2179
+ raise ValueError(f"{icons.red_dot} The upper_mid_bound must be greater than the lower_mid_bound.")
2220
2180
  elif lower_mid_bound <= lower_bound:
2221
- print(f"{icons.red_dot} The lower_mid_bound must be greater than the lower_bound.")
2181
+ raise ValueError(f"{icons.red_dot} The lower_mid_bound must be greater than the lower_bound.")
2222
2182
 
2223
2183
  try:
2224
2184
  table_name = next(
2225
2185
  m.Parent.Name for m in self.all_measures() if m.Name == measure_name
2226
2186
  )
2227
2187
  except:
2228
- print(
2229
- f"{icons.red_dot} The '{measure_name}' measure does not exist in the '{self._dataset}' semantic model within the '{self._workspace}'."
2230
- )
2231
- return
2188
+ raise ValueError(f"{icons.red_dot} The '{measure_name}' measure does not exist in the '{self._dataset}' semantic model within the '{self._workspace}'.")
2232
2189
 
2233
2190
  graphics = [
2234
2191
  "Cylinder",
@@ -2251,10 +2208,7 @@ class TOMWrapper:
2251
2208
  ]
2252
2209
 
2253
2210
  if status_graphic not in graphics:
2254
- print(
2255
- f"{icons.red_dot} The '{status_graphic}' status graphic is not valid. Please choose from these options: {graphics}."
2256
- )
2257
- return
2211
+ raise ValueError(f"{icons.red_dot} The '{status_graphic}' status graphic is not valid. Please choose from these options: {graphics}.")
2258
2212
 
2259
2213
  measure_target = True
2260
2214
 
@@ -2270,10 +2224,8 @@ class TOMWrapper:
2270
2224
  if m.Name == target
2271
2225
  )
2272
2226
  except:
2273
- print(
2274
- f"{icons.red_dot} The '{target}' measure does not exist in the '{self._dataset}' semantic model within the '{self._workspace}'."
2275
- )
2276
-
2227
+ raise ValueError(f"{icons.red_dot} The '{target}' measure does not exist in the '{self._dataset}' semantic model within the '{self._workspace}'.")
2228
+
2277
2229
  if measure_target:
2278
2230
  expr = f"var x = [{measure_name}]/[{target}]\nreturn"
2279
2231
  else:
@@ -2396,10 +2348,7 @@ class TOMWrapper:
2396
2348
  )
2397
2349
 
2398
2350
  if value not in values:
2399
- print(
2400
- f"{icons.red_dot} '{value}' is not a valid value for the SummarizeBy property. These are the valid values: {values}."
2401
- )
2402
- return
2351
+ raise ValueError(f"{icons.red_dot} '{value}' is not a valid value for the SummarizeBy property. These are the valid values: {values}.")
2403
2352
 
2404
2353
  self.model.Tables[table_name].Columns[column_name].SummarizeBy = (
2405
2354
  System.Enum.Parse(TOM.AggregateFunction, value)
@@ -2428,10 +2377,7 @@ class TOMWrapper:
2428
2377
  dlValues = ["Automatic", "DirectLakeOnly", "DirectQueryOnly"]
2429
2378
 
2430
2379
  if direct_lake_behavior not in dlValues:
2431
- print(
2432
- f"{icons.red_dot} The 'direct_lake_behavior' parameter must be one of these values: {dlValues}."
2433
- )
2434
- return
2380
+ raise ValueError(f"{icons.red_dot} The 'direct_lake_behavior' parameter must be one of these values: {dlValues}.")
2435
2381
 
2436
2382
  self.model.DirectLakeBehavior = System.Enum.Parse(
2437
2383
  TOM.DirectLakeBehavior, direct_lake_behavior
@@ -2529,13 +2475,10 @@ class TOMWrapper:
2529
2475
  import Microsoft.AnalysisServices.Tabular as TOM
2530
2476
 
2531
2477
  if isinstance(objects, str):
2532
- print(f"{icons.red_dot} The 'objects' parameter must be a list of columns/measures.")
2533
- return
2478
+ raise ValueError(f"{icons.red_dot} The 'objects' parameter must be a list of columns/measures.")
2479
+
2534
2480
  if len(objects) == 1:
2535
- print(
2536
- f"{icons.red_dot} There must be more than one object (column/measure) within the objects parameter."
2537
- )
2538
- return
2481
+ raise ValueError(f"{icons.red_dot} There must be more than one object (column/measure) within the objects parameter.")
2539
2482
 
2540
2483
  expr = ""
2541
2484
  i = 0
@@ -2571,10 +2514,7 @@ class TOMWrapper:
2571
2514
  )
2572
2515
  success = True
2573
2516
  if not success:
2574
- print(
2575
- f"{icons.red_dot} The '{obj}' object was not found in the '{self._dataset}' semantic model."
2576
- )
2577
- return
2517
+ raise ValueError(f"{icons.red_dot} The '{obj}' object was not found in the '{self._dataset}' semantic model.")
2578
2518
  else:
2579
2519
  i += 1
2580
2520
 
@@ -3244,26 +3184,16 @@ class TOMWrapper:
3244
3184
  rolling_window_granularity = rolling_window_granularity.capitalize()
3245
3185
 
3246
3186
  if incremental_granularity not in incGran:
3247
- print(
3248
- f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}."
3249
- )
3250
- return
3187
+ raise ValueError(f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}.")
3188
+
3251
3189
  if rolling_window_granularity not in incGran:
3252
- print(
3253
- f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}."
3254
- )
3255
- return
3190
+ raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}.")
3256
3191
 
3257
3192
  if rolling_window_periods < 1:
3258
- print(
3259
- f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0."
3260
- )
3261
- return
3193
+ raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0.")
3194
+
3262
3195
  if incremental_periods < 1:
3263
- print(
3264
- f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0."
3265
- )
3266
- return
3196
+ raise ValueError(f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0.")
3267
3197
 
3268
3198
  t = self.model.Tables[table_name]
3269
3199
 
@@ -3271,10 +3201,7 @@ class TOMWrapper:
3271
3201
  dc = t.Columns[detect_data_changes_column]
3272
3202
 
3273
3203
  if dc.DataType != TOM.DataType.DateTime:
3274
- print(
3275
- f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type."
3276
- )
3277
- return
3204
+ raise ValueError(f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type.")
3278
3205
 
3279
3206
  rp = TOM.BasicRefreshPolicy()
3280
3207
  rp.IncrementalPeriods = incremental_periods
@@ -3354,26 +3281,16 @@ class TOMWrapper:
3354
3281
  rolling_window_granularity = rolling_window_granularity.capitalize()
3355
3282
 
3356
3283
  if incremental_granularity not in incGran:
3357
- print(
3358
- f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}."
3359
- )
3360
- return
3284
+ raise ValueError(f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}.")
3285
+
3361
3286
  if rolling_window_granularity not in incGran:
3362
- print(
3363
- f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}."
3364
- )
3365
- return
3287
+ raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}.")
3366
3288
 
3367
3289
  if rolling_window_periods < 1:
3368
- print(
3369
- f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0."
3370
- )
3371
- return
3290
+ raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0.")
3291
+
3372
3292
  if incremental_periods < 1:
3373
- print(
3374
- f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0."
3375
- )
3376
- return
3293
+ raise ValueError(f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0.")
3377
3294
 
3378
3295
  date_format = "%m/%d/%Y"
3379
3296
 
@@ -3388,10 +3305,7 @@ class TOMWrapper:
3388
3305
  end_day = date_obj_end.day
3389
3306
 
3390
3307
  if date_obj_end <= date_obj_start:
3391
- print(
3392
- f"{icons.red_dot} Invalid 'start_date' or 'end_date'. The 'end_date' must be after the 'start_date'."
3393
- )
3394
- return
3308
+ raise ValueError(f"{icons.red_dot} Invalid 'start_date' or 'end_date'. The 'end_date' must be after the 'start_date'.")
3395
3309
 
3396
3310
  t = self.model.Tables[table_name]
3397
3311
 
@@ -3400,20 +3314,14 @@ class TOMWrapper:
3400
3314
  dType = c.DataType
3401
3315
 
3402
3316
  if dType != TOM.DataType.DateTime:
3403
- print(
3404
- f"{icons.red_dot} The {fcName} column is of '{dType}' data type. The column chosen must be of DateTime data type."
3405
- )
3406
- return
3317
+ raise ValueError(f"{icons.red_dot} The {fcName} column is of '{dType}' data type. The column chosen must be of DateTime data type.")
3407
3318
 
3408
3319
  if detect_data_changes_column is not None:
3409
3320
  dc = t.Columns[detect_data_changes_column]
3410
3321
  dcType = dc.DataType
3411
3322
 
3412
3323
  if dcType != TOM.DataType.DateTime:
3413
- print(
3414
- f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type."
3415
- )
3416
- return
3324
+ raise ValueError(f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type.")
3417
3325
 
3418
3326
  # Start changes:
3419
3327
 
@@ -3421,10 +3329,8 @@ class TOMWrapper:
3421
3329
  i = 0
3422
3330
  for p in t.Partitions:
3423
3331
  if p.SourceType != TOM.PartitionSourceType.M:
3424
- print(
3425
- f"{icons.red_dot} Invalid partition source type. Incremental refresh can only be set up if the table's partition is an M-partition."
3426
- )
3427
- return
3332
+ raise ValueError(f"{icons.red_dot} Invalid partition source type. Incremental refresh can only be set up if the table's partition is an M-partition.")
3333
+
3428
3334
  elif i == 0:
3429
3335
  text = p.Expression
3430
3336
  text = text.rstrip()
@@ -3440,8 +3346,7 @@ class TOMWrapper:
3440
3346
 
3441
3347
  print(text_before_last_match)
3442
3348
  else:
3443
- print(f"{icons.red_dot} Invalid M-partition expression.")
3444
- return
3349
+ raise ValueError(f"{icons.red_dot} Invalid M-partition expression.")
3445
3350
 
3446
3351
  endExpr = f'#"Filtered Rows IR" = Table.SelectRows({obj}, each [{column_name}] >= RangeStart and [{column_name}] <= RangeEnd)\n#"Filtered Rows IR"'
3447
3352
  finalExpr = text_before_last_match + endExpr
@@ -3537,15 +3442,9 @@ class TOMWrapper:
3537
3442
  ht = self.is_hybrid_table(table_name=table_name)
3538
3443
 
3539
3444
  if not ht:
3540
- print(
3541
- f"{icons.red_dot} The `data coverage definition <https://learn.microsoft.com/analysis-services/tom/table-partitions?view=asallproducts-allversions>`_ property is only applicable to `hybrid tables <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_. See the documentation: {doc}."
3542
- )
3543
- return
3445
+ raise ValueError(f"{icons.red_dot} The `data coverage definition <https://learn.microsoft.com/analysis-services/tom/table-partitions?view=asallproducts-allversions>`_ property is only applicable to `hybrid tables <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_. See the documentation: {doc}.")
3544
3446
  if p.Mode != TOM.ModeType.DirectQuery:
3545
- print(
3546
- f"{icons.red_dot} The `data coverage definition <https://learn.microsoft.com/analysis-services/tom/table-partitions?view=asallproducts-allversions>`_ property is only applicable to the DirectQuery partition of a `hybrid table <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_. See the documentation: {doc}."
3547
- )
3548
- return
3447
+ raise ValueError(f"{icons.red_dot} The `data coverage definition <https://learn.microsoft.com/analysis-services/tom/table-partitions?view=asallproducts-allversions>`_ property is only applicable to the DirectQuery partition of a `hybrid table <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_. See the documentation: {doc}.")
3549
3448
 
3550
3449
  dcd = TOM.DataCoverageDefinition()
3551
3450
  dcd.Expression = expression
@@ -3572,10 +3471,7 @@ class TOMWrapper:
3572
3471
  value = value.capitalize()
3573
3472
 
3574
3473
  if value not in values:
3575
- print(
3576
- f"{icons.red_dot} Invalid encoding hint value. Please choose from these options: {values}."
3577
- )
3578
- return
3474
+ raise ValueError(f"{icons.red_dot} Invalid encoding hint value. Please choose from these options: {values}.")
3579
3475
 
3580
3476
  self.model.Tables[table_name].Columns[column_name].EncodingHint = (
3581
3477
  System.Enum.Parse(TOM.EncodingHintType, value)
@@ -3617,10 +3513,7 @@ class TOMWrapper:
3617
3513
  value = "Boolean"
3618
3514
 
3619
3515
  if value not in values:
3620
- print(
3621
- f"{icons.red_dot} Invalid data type. Please choose from these options: {values}."
3622
- )
3623
- return
3516
+ raise ValueError(f"{icons.red_dot} Invalid data type. Please choose from these options: {values}.")
3624
3517
 
3625
3518
  self.model.Tables[table_name].Columns[column_name].DataType = System.Enum.Parse(
3626
3519
  TOM.DataType, value
@@ -3652,10 +3545,7 @@ class TOMWrapper:
3652
3545
  for t in time_intel:
3653
3546
  t = t.capitalize()
3654
3547
  if t not in [time_intel_options]:
3655
- print(
3656
- f"{icons.red_dot} The '{t}' time intelligence variation is not supported. Valid options: {time_intel_options}."
3657
- )
3658
- return
3548
+ raise ValueError(f"{icons.red_dot} The '{t}' time intelligence variation is not supported. Valid options: {time_intel_options}.")
3659
3549
 
3660
3550
  # Validate measure and extract table name
3661
3551
  for m in self.all_measures():
@@ -3663,17 +3553,11 @@ class TOMWrapper:
3663
3553
  table_name = m.Parent.Name
3664
3554
 
3665
3555
  if table_name is None:
3666
- print(
3667
- f"{icons.red_dot} The '{measure_name}' is not a valid measure in the '{self._dataset}' semantic model within the '{self._workspace}' workspace."
3668
- )
3669
- return
3556
+ raise ValueError(f"{icons.red_dot} The '{measure_name}' is not a valid measure in the '{self._dataset}' semantic model within the '{self._workspace}' workspace.")
3670
3557
 
3671
3558
  # Validate date table
3672
3559
  if not self.is_date_table(date_table):
3673
- print(
3674
- f"{icons.red_dot} The '{date_table}' table is not a valid date table in the '{self._dataset}' wemantic model within the '{self._workspace}' workspace."
3675
- )
3676
- return
3560
+ raise ValueError(f"{icons.red_dot} The '{date_table}' table is not a valid date table in the '{self._dataset}' wemantic model within the '{self._workspace}' workspace.")
3677
3561
 
3678
3562
  # Extract date key from date table
3679
3563
  for c in self.all_columns():
@@ -3691,6 +3575,80 @@ class TOMWrapper:
3691
3575
  expression=expr,
3692
3576
  )
3693
3577
 
3578
+ def update_m_partition(self, table_name: str, partition_name: str, expression: Optional[str | None] = None, mode: Optional[str | None] = None, description: Optional[str | None] = None):
3579
+
3580
+ """
3581
+ Updates an M partition for a table within a semantic model.
3582
+
3583
+ Parameters
3584
+ ----------
3585
+ table_name : str
3586
+ Name of the table.
3587
+ partition_name : str
3588
+ Name of the partition.
3589
+ expression : str, default=None
3590
+ The `M expression <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.mpartitionsource.expression?view=analysisservices-dotnet>`_ containing the logic for the partition.
3591
+ Defaults to None which keeps the existing setting.
3592
+ mode : str, default=None
3593
+ The query `mode <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.modetype?view=analysisservices-dotnet>`_ of the partition.
3594
+ Defaults to None which keeps the existing setting.
3595
+ description : str, default=None
3596
+ The description of the partition.
3597
+ Defaults to None which keeps the existing setting.
3598
+ """
3599
+
3600
+ import Microsoft.AnalysisServices.Tabular as TOM
3601
+ import System
3602
+
3603
+ p = self.model.Tables[table_name].Partitions[partition_name]
3604
+ if p.SourceType != TOM.PartitionSourceType.M:
3605
+ raise ValueError(f"Invalid partition source type. This function is only for M partitions.")
3606
+ if expression is not None:
3607
+ p.Source.Expression = expression
3608
+ if mode is not None:
3609
+ p.Mode = System.Enum.Parse(TOM.ModeType, mode)
3610
+ if description is not None:
3611
+ p.Description = description
3612
+
3613
+ def set_sort_by_column(self, table_name: str, column_name: str, sort_by_column: str):
3614
+
3615
+ """
3616
+ Sets the sort by column for a column in a semantic model.
3617
+
3618
+ Parameters
3619
+ ----------
3620
+ table_name : str
3621
+ Name of the table.
3622
+ column_name : str
3623
+ Name of the column.
3624
+ sort_by_column : str
3625
+ Name of the column to use for sorting. Must be of integer (Int64) data type.
3626
+ """
3627
+
3628
+ import Microsoft.AnalysisServices.Tabular as TOM
3629
+
3630
+ sbc = self.model.Tables[table_name].Columns[sort_by_column]
3631
+
3632
+ if sbc.DataType != TOM.DataType.Int64:
3633
+ raise ValueError(f"Invalid sort by column data type. The sort by column must be of 'Int64' data type.")
3634
+
3635
+ self.model.Tables[table_name].Columns[column_name].SortByColumn = sbc
3636
+
3637
+ def remove_sort_by_column(self, table_name: str, column_name: str):
3638
+
3639
+ """
3640
+ Removes the sort by column for a column in a semantic model.
3641
+
3642
+ Parameters
3643
+ ----------
3644
+ table_name : str
3645
+ Name of the table.
3646
+ column_name : str
3647
+ Name of the column.
3648
+ """
3649
+
3650
+ self.model.Tables[table_name].Columns[column_name].SortByColumn = None
3651
+
3694
3652
  def close(self):
3695
3653
  if not self._readonly and self.model is not None:
3696
3654
  self.model.SaveChanges()
@@ -3742,4 +3700,4 @@ def connect_semantic_model(
3742
3700
  try:
3743
3701
  yield tw
3744
3702
  finally:
3745
- tw.close()
3703
+ tw.close()
@@ -1,53 +0,0 @@
1
- sempy_labs/__init__.py,sha256=aKnIa8tgtzqT939USn5rjCYnMNRu-Aku4mJSEFG75mc,4126
2
- sempy_labs/_ai.py,sha256=WXWnVJ9g5Xq5ctiMWFNXbrv2WdAhKv5EsO6tCBy8ceE,17930
3
- sempy_labs/_clear_cache.py,sha256=yahzQ-QojCtAReFT3zK9lrr5LJhkONUr49GC1qXf6Uw,1476
4
- sempy_labs/_connections.py,sha256=DNgiMbswZM-vv6qnEnZ2RhIuo1HhGobh47X2UYh2br8,7396
5
- sempy_labs/_dax.py,sha256=u4qVxsu2dVaOJmso-ErScNZ5yI4lGQTlon_jmrAzvGs,2148
6
- sempy_labs/_generate_semantic_model.py,sha256=PgqqAk3ptVTXHlW6lU5dqGNZUAOjA3xrqmvZX2GlXx8,9273
7
- sempy_labs/_helper_functions.py,sha256=mzzMFv6SKottNGBXjBe2-cCTgTQXDf6fXT7MmQ05DLA,14313
8
- sempy_labs/_icons.py,sha256=mREeT-3eJCAbuKwaYf1IZGWYssy6WQ-mBCZ6nFnKGPU,196
9
- sempy_labs/_list_functions.py,sha256=mxacAOu2MwBBLqOTbwb_Zqmx6liSItbc8fhQgkxkgqQ,53459
10
- sempy_labs/_model_auto_build.py,sha256=xv4n4pjBAFAxz9Otu0ggx9QJsgRHzOFf_h4Fyou9p8E,5149
11
- sempy_labs/_model_bpa.py,sha256=6fvUeZ0isLpmeTF4XC6lK9C5NreIJhoAgWpYIoD236s,63250
12
- sempy_labs/_model_dependencies.py,sha256=e0QhwQs4KuWllbrYdGQnqQ5YwbbC-KKYxvsqT5x7Y6I,13194
13
- sempy_labs/_one_lake_integration.py,sha256=RRjyDFitYzsC9vvovlYmvame9lRlV0myABAcFZxYffw,6210
14
- sempy_labs/_query_scale_out.py,sha256=5X6Q8-hskf6VY_VY02VdyMlmBuV77bHWTTKqMdbGLBg,15296
15
- sempy_labs/_refresh_semantic_model.py,sha256=YUtSnMyln7_8iPY3owG5uwfm8RqRdCPIKh0fTChuiIM,6805
16
- sempy_labs/_translations.py,sha256=zW2HmJPqDs5p0Mj-1dTIlgee1rSmfZYMcQoPdNsZCmM,18044
17
- sempy_labs/_vertipaq.py,sha256=18YT-3zDZnsY9DhPh9iQIjuCW8T91zZjliW8cUtbEAY,33385
18
- sempy_labs/directlake/__init__.py,sha256=HbfHvDvGE4H-xSbV6JO7TUb4HoLGJf2AeuqeQxIuuJ4,1689
19
- sempy_labs/directlake/_directlake_schema_compare.py,sha256=1N2NHL9XwjdLz-SPFpGAGkGGFsaEAqAfEdNzfUgli-E,4748
20
- sempy_labs/directlake/_directlake_schema_sync.py,sha256=Fkg8qJdiPF4ppgG2ED9lN40MbobIleT_W5wCTv190rw,5166
21
- sempy_labs/directlake/_fallback.py,sha256=StqIL9WS6NWHMIBkgqM14my37Foz_zzkCryZtn_Qjj4,2091
22
- sempy_labs/directlake/_get_directlake_lakehouse.py,sha256=vEY1QBU7gAdoVQIGl59T_1TTYuXbHgk3pZA41EkVkl8,2358
23
- sempy_labs/directlake/_get_shared_expression.py,sha256=IyjBSIvmhb5Nri1Xf8QoK8owGFQ2znKP60N0U1VDLg0,2012
24
- sempy_labs/directlake/_guardrails.py,sha256=NJxT4AStorzNimYIRkLW2iu3T2f_QfGZOhIRdW4glVI,2330
25
- sempy_labs/directlake/_list_directlake_model_calc_tables.py,sha256=a5YOj3FrMj6DGmnNi9iSriredtti8_802L_Da3pBmrI,2079
26
- sempy_labs/directlake/_show_unsupported_directlake_objects.py,sha256=9e5RSge91Cg_9qGCUqRlIhq2xvPA_ut_bE20SwZHk50,3386
27
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py,sha256=Qq6iYTvMnimNNa67y3Q_Qpigpez49euK2fNXc05Xg4w,3224
28
- sempy_labs/directlake/_update_directlake_partition_entity.py,sha256=Egr_NH7XoDDEDc8tz2e3JJ5UKXU0H0EgxTAIcpGr5_M,3207
29
- sempy_labs/directlake/_warm_cache.py,sha256=fkAw7Lpnoh6dnkdFqtKUeH4fhi6Qzk4ydzHQI-KTqEM,8204
30
- sempy_labs/lakehouse/__init__.py,sha256=i6VRx4dR1SIN-1GxioiNwhC4FxbozRCIz5TfXjb9rKc,587
31
- sempy_labs/lakehouse/_get_lakehouse_columns.py,sha256=Ot49AuYtoNwsp-gHWqBplclrSD2rscudwXf_PyFU0mY,2578
32
- sempy_labs/lakehouse/_get_lakehouse_tables.py,sha256=eUeRloAXC5DUEiPNIwcjyRQRnJID_iDzMqIGZM5QJT0,9094
33
- sempy_labs/lakehouse/_lakehouse.py,sha256=gkLBpxizTAm-ti8OXqbI9VUgurIG4VjxljxKO3xTtE0,2856
34
- sempy_labs/lakehouse/_shortcuts.py,sha256=k6p4FMW-tLjGR9vRql7vBQf_bDmNYlax6sf47TUIb34,6910
35
- sempy_labs/migration/__init__.py,sha256=l5v8pC2INdNwbAKVmvWpuVxs6lpb6omim_4BPOmNo4E,1042
36
- sempy_labs/migration/_create_pqt_file.py,sha256=MNFxF7XVQBT_-iklsvgm41vG2fyZ0WS42jJ9iFrZVRc,9195
37
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py,sha256=ajFvHauFdEsbgxvn9JXj2kiXaRtJLEjwX4hWQG7FQy0,20609
38
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py,sha256=Co2f579vSwkWZ95SlBStS-XJ73YwgcdfAMlJbUv_pkk,6343
39
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py,sha256=iCfbyJuharFnHvwviuoRM_caQX8AKmaX47HYafI6Wtg,23955
40
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py,sha256=qohJC6ARjM8NiMH7nZEKqUEXMrh-IqhdeUzgrBNZ1DQ,7028
41
- sempy_labs/migration/_migration_validation.py,sha256=IdSNuK2EVz-egX7glvcocvRlWZrnKj5_nOz-l20yZdk,2370
42
- sempy_labs/migration/_refresh_calc_tables.py,sha256=MjtBBoDA8W6J-6HPD736Voocp5AK2E1glXCy79C57ts,5985
43
- sempy_labs/report/__init__.py,sha256=fkjbkAXZuH7VnAn-k3iB4dngWZKaX-k0bxS6mBa9iAs,846
44
- sempy_labs/report/_generate_report.py,sha256=D1u_XzbvgYzUO4NXU5k9huMNh0n7bEjreW4SSoaa2vE,8532
45
- sempy_labs/report/_report_functions.py,sha256=Ctx9kCTOC40ibBvkzGt2DAZG9GNa_iE8_T4ruERsk7A,30016
46
- sempy_labs/report/_report_rebind.py,sha256=sWaj6aw8sh0njZ0__ULeGD4CZrg7oPLKtOlv4ETKGOk,4635
47
- sempy_labs/tom/__init__.py,sha256=hFwkmWk5AZ7GK1LWqoqaK1g4gDmu9mZMkfLQvLsR_eE,130
48
- sempy_labs/tom/_model.py,sha256=hRnIL1rkdYBTFt3hg2zcsEmvsoMhUCAeepmFyzyfzhA,135257
49
- semantic_link_labs-0.4.2.dist-info/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141
50
- semantic_link_labs-0.4.2.dist-info/METADATA,sha256=d4DjYbKoZum30lR9bqhV-X1CHR5DZCfsdnay1UOz-w4,764
51
- semantic_link_labs-0.4.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
52
- semantic_link_labs-0.4.2.dist-info/top_level.txt,sha256=kiQX1y42Dbein1l3Q8jMUYyRulDjdlc2tMepvtrvixQ,11
53
- semantic_link_labs-0.4.2.dist-info/RECORD,,