semantic-link-labs 0.4.1__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.
- {semantic_link_labs-0.4.1.dist-info → semantic_link_labs-0.5.0.dist-info}/METADATA +1 -1
- semantic_link_labs-0.5.0.dist-info/RECORD +53 -0
- {semantic_link_labs-0.4.1.dist-info → semantic_link_labs-0.5.0.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +51 -27
- sempy_labs/_ai.py +32 -51
- sempy_labs/_clear_cache.py +2 -3
- sempy_labs/_connections.py +39 -38
- sempy_labs/_dax.py +5 -9
- sempy_labs/_generate_semantic_model.py +15 -21
- sempy_labs/_helper_functions.py +20 -25
- sempy_labs/_icons.py +6 -0
- sempy_labs/_list_functions.py +1172 -392
- sempy_labs/_model_auto_build.py +3 -5
- sempy_labs/_model_bpa.py +20 -24
- sempy_labs/_model_dependencies.py +7 -14
- sempy_labs/_one_lake_integration.py +14 -24
- sempy_labs/_query_scale_out.py +13 -31
- sempy_labs/_refresh_semantic_model.py +8 -18
- sempy_labs/_translations.py +5 -5
- sempy_labs/_vertipaq.py +11 -18
- sempy_labs/directlake/_directlake_schema_compare.py +11 -15
- sempy_labs/directlake/_directlake_schema_sync.py +35 -40
- sempy_labs/directlake/_fallback.py +3 -7
- sempy_labs/directlake/_get_directlake_lakehouse.py +3 -4
- sempy_labs/directlake/_get_shared_expression.py +5 -11
- sempy_labs/directlake/_guardrails.py +5 -7
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +28 -26
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +3 -4
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +11 -16
- sempy_labs/directlake/_update_directlake_partition_entity.py +25 -15
- sempy_labs/directlake/_warm_cache.py +10 -15
- sempy_labs/lakehouse/__init__.py +0 -2
- sempy_labs/lakehouse/_get_lakehouse_columns.py +4 -3
- sempy_labs/lakehouse/_get_lakehouse_tables.py +12 -11
- sempy_labs/lakehouse/_lakehouse.py +6 -7
- sempy_labs/lakehouse/_shortcuts.py +10 -111
- sempy_labs/migration/__init__.py +4 -2
- sempy_labs/migration/_create_pqt_file.py +5 -14
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +7 -7
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py +4 -4
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +3 -8
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +6 -6
- sempy_labs/migration/_migration_validation.py +5 -164
- sempy_labs/migration/_refresh_calc_tables.py +5 -5
- sempy_labs/report/__init__.py +2 -2
- sempy_labs/report/_generate_report.py +14 -19
- sempy_labs/report/_report_functions.py +41 -83
- sempy_labs/report/_report_rebind.py +43 -44
- sempy_labs/tom/__init__.py +6 -0
- sempy_labs/{_tom.py → tom/_model.py} +274 -337
- semantic_link_labs-0.4.1.dist-info/RECORD +0 -52
- {semantic_link_labs-0.4.1.dist-info → semantic_link_labs-0.5.0.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.4.1.dist-info → semantic_link_labs-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,7 @@ from sempy_labs._list_functions import list_relationships
|
|
|
8
8
|
from sempy_labs._refresh_semantic_model import refresh_semantic_model
|
|
9
9
|
from sempy_labs.directlake._fallback import check_fallback_reason
|
|
10
10
|
from contextlib import contextmanager
|
|
11
|
-
from typing import List, Optional, Union, TYPE_CHECKING
|
|
11
|
+
from typing import List, Iterator, Optional, Union, TYPE_CHECKING
|
|
12
12
|
from sempy._utils._log import log
|
|
13
13
|
import sempy_labs._icons as icons
|
|
14
14
|
|
|
@@ -17,32 +17,28 @@ if TYPE_CHECKING:
|
|
|
17
17
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
checked = "\u2611"
|
|
21
|
-
unchecked = "\u2610"
|
|
22
|
-
start_bold = "\033[1m"
|
|
23
|
-
end_bold = "\033[0m"
|
|
24
|
-
|
|
25
|
-
|
|
26
20
|
class TOMWrapper:
|
|
27
21
|
"""
|
|
28
|
-
Convenience wrapper around the TOM object model for a semantic model. Always use connect_semantic_model function to make sure the TOM object is initialized correctly.
|
|
22
|
+
Convenience wrapper around the TOM object model for a semantic model. Always use the connect_semantic_model function to make sure the TOM object is initialized correctly.
|
|
23
|
+
|
|
24
|
+
`XMLA read/write endpoints <https://learn.microsoft.com/power-bi/enterprise/service-premium-connect-tools#to-enable-read-write-for-a-premium-capacity>`_ must be enabled if setting the readonly parameter to False.
|
|
29
25
|
"""
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
_dataset: str
|
|
28
|
+
_workspace: str
|
|
29
|
+
_readonly: bool
|
|
30
|
+
_tables_added: List[str]
|
|
35
31
|
|
|
36
32
|
def __init__(self, dataset, workspace, readonly):
|
|
37
|
-
self.
|
|
38
|
-
self.
|
|
39
|
-
self.
|
|
40
|
-
self.
|
|
33
|
+
self._dataset = dataset
|
|
34
|
+
self._workspace = workspace
|
|
35
|
+
self._readonly = readonly
|
|
36
|
+
self._tables_added = []
|
|
41
37
|
|
|
42
|
-
self.
|
|
38
|
+
self._tom_server = fabric.create_tom_server(
|
|
43
39
|
readonly=readonly, workspace=workspace
|
|
44
40
|
)
|
|
45
|
-
self.model = self.
|
|
41
|
+
self.model = self._tom_server.Databases.GetByName(dataset).Model
|
|
46
42
|
|
|
47
43
|
def all_columns(self):
|
|
48
44
|
"""
|
|
@@ -97,7 +93,7 @@ class TOMWrapper:
|
|
|
97
93
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
98
94
|
|
|
99
95
|
for t in self.model.Tables:
|
|
100
|
-
if any(p.SourceType == TOM.
|
|
96
|
+
if any(p.SourceType == TOM.PartitionSourceType.Calculated for p in t.Partitions):
|
|
101
97
|
yield t
|
|
102
98
|
|
|
103
99
|
def all_calculation_groups(self):
|
|
@@ -181,10 +177,10 @@ class TOMWrapper:
|
|
|
181
177
|
All levels within the semantic model.
|
|
182
178
|
"""
|
|
183
179
|
|
|
184
|
-
for
|
|
185
|
-
for
|
|
186
|
-
for
|
|
187
|
-
yield
|
|
180
|
+
for table in self.model.Tables:
|
|
181
|
+
for hierarchy in table.Hierarchies:
|
|
182
|
+
for level in hierarchy.Levels:
|
|
183
|
+
yield level
|
|
188
184
|
|
|
189
185
|
def all_calculation_items(self):
|
|
190
186
|
"""
|
|
@@ -459,7 +455,7 @@ class TOMWrapper:
|
|
|
459
455
|
Marks the column as the primary key of the table.
|
|
460
456
|
summarize_by : str, default=None
|
|
461
457
|
Sets the value for the Summarize By property of the column.
|
|
462
|
-
Defaults to None resolves to 'Default'.
|
|
458
|
+
Defaults to None which resolves to 'Default'.
|
|
463
459
|
"""
|
|
464
460
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
465
461
|
import System
|
|
@@ -504,7 +500,7 @@ class TOMWrapper:
|
|
|
504
500
|
description: Optional[str] = None,
|
|
505
501
|
):
|
|
506
502
|
"""
|
|
507
|
-
Adds a calculation item to a calculation group within a semantic model.
|
|
503
|
+
Adds a `calculation item <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.calculationitem?view=analysisservices-dotnet>`_ to a `calculation group <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.calculationgroup?view=analysisservices-dotnet>`_ within a semantic model.
|
|
508
504
|
|
|
509
505
|
Parameters
|
|
510
506
|
----------
|
|
@@ -642,7 +638,7 @@ class TOMWrapper:
|
|
|
642
638
|
hierarchy_hidden: Optional[bool] = False,
|
|
643
639
|
):
|
|
644
640
|
"""
|
|
645
|
-
Adds a hierarchy to a table within a semantic model.
|
|
641
|
+
Adds a `hierarchy <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.hierarchy?view=analysisservices-dotnet>`_ to a table within a semantic model.
|
|
646
642
|
|
|
647
643
|
Parameters
|
|
648
644
|
----------
|
|
@@ -662,22 +658,16 @@ class TOMWrapper:
|
|
|
662
658
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
663
659
|
|
|
664
660
|
if isinstance(columns, str):
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
)
|
|
668
|
-
return
|
|
661
|
+
raise ValueError(f"{icons.red_dot} The 'levels' parameter must be a list. For example: ['Continent', 'Country', 'City']")
|
|
662
|
+
|
|
669
663
|
if len(columns) == 1:
|
|
670
|
-
|
|
671
|
-
return
|
|
664
|
+
raise ValueError(f"{icons.red_dot} There must be at least 2 levels in order to create a hierarchy.")
|
|
672
665
|
|
|
673
666
|
if levels is None:
|
|
674
667
|
levels = columns
|
|
675
668
|
|
|
676
669
|
if len(columns) != len(levels):
|
|
677
|
-
|
|
678
|
-
f"If specifying level names, you must specify a level for each column."
|
|
679
|
-
)
|
|
680
|
-
return
|
|
670
|
+
raise ValueError(f"{icons.red_dot} If specifying level names, you must specify a level for each column.")
|
|
681
671
|
|
|
682
672
|
obj = TOM.Hierarchy()
|
|
683
673
|
obj.Name = hierarchy_name
|
|
@@ -707,7 +697,7 @@ class TOMWrapper:
|
|
|
707
697
|
rely_on_referential_integrity: Optional[bool] = False,
|
|
708
698
|
):
|
|
709
699
|
"""
|
|
710
|
-
Adds a relationship to a semantic model.
|
|
700
|
+
Adds a `relationship <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.singlecolumnrelationship?view=analysisservices-dotnet>`_ to a semantic model.
|
|
711
701
|
|
|
712
702
|
Parameters
|
|
713
703
|
----------
|
|
@@ -779,7 +769,7 @@ class TOMWrapper:
|
|
|
779
769
|
hidden: Optional[bool] = False,
|
|
780
770
|
):
|
|
781
771
|
"""
|
|
782
|
-
Adds a calculation group to a semantic model.
|
|
772
|
+
Adds a `calculation group <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.calculationgroup?view=analysisservices-dotnet>`_ to a semantic model.
|
|
783
773
|
|
|
784
774
|
Parameters
|
|
785
775
|
----------
|
|
@@ -832,7 +822,7 @@ class TOMWrapper:
|
|
|
832
822
|
self, name: str, expression: str, description: Optional[str] = None
|
|
833
823
|
):
|
|
834
824
|
"""
|
|
835
|
-
Adds an expression to a semantic model.
|
|
825
|
+
Adds an `expression <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.namedexpression?view=analysisservices-dotnet>`_ to a semantic model.
|
|
836
826
|
|
|
837
827
|
Parameters
|
|
838
828
|
----------
|
|
@@ -856,7 +846,7 @@ class TOMWrapper:
|
|
|
856
846
|
|
|
857
847
|
def add_translation(self, language: str):
|
|
858
848
|
"""
|
|
859
|
-
Adds a translation language (culture) to a semantic model.
|
|
849
|
+
Adds a `translation language <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.culture?view=analysisservices-dotnet>`_ (culture) to a semantic model.
|
|
860
850
|
|
|
861
851
|
Parameters
|
|
862
852
|
----------
|
|
@@ -875,7 +865,7 @@ class TOMWrapper:
|
|
|
875
865
|
|
|
876
866
|
def add_perspective(self, perspective_name: str):
|
|
877
867
|
"""
|
|
878
|
-
Adds a perspective to a semantic model.
|
|
868
|
+
Adds a `perspective <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.perspective?view=analysisservices-dotnet>`_ to a semantic model.
|
|
879
869
|
|
|
880
870
|
Parameters
|
|
881
871
|
----------
|
|
@@ -910,18 +900,22 @@ class TOMWrapper:
|
|
|
910
900
|
mode : str, default=None
|
|
911
901
|
The query mode for the partition.
|
|
912
902
|
Defaults to None which resolves to 'Import'.
|
|
903
|
+
`Valid mode values <https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.modetype?view=analysisservices-dotnet>`_
|
|
913
904
|
description : str, default=None
|
|
914
905
|
A description for the partition.
|
|
915
906
|
"""
|
|
916
907
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
917
908
|
import System
|
|
918
909
|
|
|
919
|
-
mode
|
|
920
|
-
mode
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
910
|
+
if mode is None:
|
|
911
|
+
mode = "Default"
|
|
912
|
+
else:
|
|
913
|
+
mode = (
|
|
914
|
+
mode.title()
|
|
915
|
+
.replace("query", "Query")
|
|
916
|
+
.replace(" ", "")
|
|
917
|
+
.replace("lake", "Lake")
|
|
918
|
+
)
|
|
925
919
|
|
|
926
920
|
mp = TOM.MPartitionSource()
|
|
927
921
|
mp.Expression = expression
|
|
@@ -930,8 +924,6 @@ class TOMWrapper:
|
|
|
930
924
|
p.Source = mp
|
|
931
925
|
if description is not None:
|
|
932
926
|
p.Description = description
|
|
933
|
-
if mode is None:
|
|
934
|
-
mode = "Default"
|
|
935
927
|
p.Mode = System.Enum.Parse(TOM.ModeType, mode)
|
|
936
928
|
|
|
937
929
|
self.model.Tables[table_name].Partitions.Add(p)
|
|
@@ -966,7 +958,7 @@ class TOMWrapper:
|
|
|
966
958
|
if expression is None:
|
|
967
959
|
ep.ExpressionSource = self.model.Expressions["DatabaseQuery"]
|
|
968
960
|
else:
|
|
969
|
-
ep.ExpressionSource = expression
|
|
961
|
+
ep.ExpressionSource = self.model.Expressions[expression]
|
|
970
962
|
p = TOM.Partition()
|
|
971
963
|
p.Name = table_name
|
|
972
964
|
p.Source = ep
|
|
@@ -985,7 +977,7 @@ class TOMWrapper:
|
|
|
985
977
|
base_column: Optional[str] = None,
|
|
986
978
|
):
|
|
987
979
|
"""
|
|
988
|
-
Sets the
|
|
980
|
+
Sets the `alternate of <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.alternateof?view=analysisservices-dotnet>`_ property on a column.
|
|
989
981
|
|
|
990
982
|
Parameters
|
|
991
983
|
----------
|
|
@@ -1005,9 +997,7 @@ class TOMWrapper:
|
|
|
1005
997
|
import System
|
|
1006
998
|
|
|
1007
999
|
if base_column is not None and base_table is None:
|
|
1008
|
-
|
|
1009
|
-
f"ERROR: If you specify the base table you must also specify the base column"
|
|
1010
|
-
)
|
|
1000
|
+
raise ValueError(f"{icons.red_dot} If you specify the base table you must also specify the base column")
|
|
1011
1001
|
|
|
1012
1002
|
summarization_type = (
|
|
1013
1003
|
summarization_type.replace(" ", "")
|
|
@@ -1017,10 +1007,7 @@ class TOMWrapper:
|
|
|
1017
1007
|
|
|
1018
1008
|
summarizationTypes = ["Sum", "GroupBy", "Count", "Min", "Max"]
|
|
1019
1009
|
if summarization_type not in summarizationTypes:
|
|
1020
|
-
|
|
1021
|
-
f"The 'summarization_type' parameter must be one of the following valuse: {summarizationTypes}."
|
|
1022
|
-
)
|
|
1023
|
-
return
|
|
1010
|
+
raise ValueError(f"{icons.red_dot} The 'summarization_type' parameter must be one of the following valuse: {summarizationTypes}.")
|
|
1024
1011
|
|
|
1025
1012
|
ao = TOM.AlternateOf()
|
|
1026
1013
|
ao.Summarization = System.Enum.Parse(TOM.SummarizationType, summarization_type)
|
|
@@ -1039,7 +1026,7 @@ class TOMWrapper:
|
|
|
1039
1026
|
|
|
1040
1027
|
def remove_alternate_of(self, table_name: str, column_name: str):
|
|
1041
1028
|
"""
|
|
1042
|
-
Removes the
|
|
1029
|
+
Removes the `alternate of <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.alternateof?view=analysisservices-dotnet>`_ property on a column.
|
|
1043
1030
|
|
|
1044
1031
|
Parameters
|
|
1045
1032
|
----------
|
|
@@ -1059,7 +1046,7 @@ class TOMWrapper:
|
|
|
1059
1046
|
self, object
|
|
1060
1047
|
) -> "Microsoft.AnalysisServices.Tabular.Annotation":
|
|
1061
1048
|
"""
|
|
1062
|
-
Shows all annotations for a given object within a semantic model.
|
|
1049
|
+
Shows all `annotations <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.annotation?view=analysisservices-dotnet>`_ for a given object within a semantic model.
|
|
1063
1050
|
|
|
1064
1051
|
Parameters
|
|
1065
1052
|
----------
|
|
@@ -1081,7 +1068,7 @@ class TOMWrapper:
|
|
|
1081
1068
|
|
|
1082
1069
|
def set_annotation(self, object, name: str, value: str):
|
|
1083
1070
|
"""
|
|
1084
|
-
Sets an annotation on an object within the semantic model.
|
|
1071
|
+
Sets an `annotation <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.annotation?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1085
1072
|
|
|
1086
1073
|
Parameters
|
|
1087
1074
|
----------
|
|
@@ -1105,7 +1092,7 @@ class TOMWrapper:
|
|
|
1105
1092
|
|
|
1106
1093
|
def get_annotation_value(self, object, name: str):
|
|
1107
1094
|
"""
|
|
1108
|
-
Obtains the annotation value for a given annotation on an object within the semantic model.
|
|
1095
|
+
Obtains the `annotation <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.annotation?view=analysisservices-dotnet>`_ value for a given annotation on an object within the semantic model.
|
|
1109
1096
|
|
|
1110
1097
|
Parameters
|
|
1111
1098
|
----------
|
|
@@ -1124,7 +1111,7 @@ class TOMWrapper:
|
|
|
1124
1111
|
|
|
1125
1112
|
def remove_annotation(self, object, name: str):
|
|
1126
1113
|
"""
|
|
1127
|
-
Removes an annotation on an object within the semantic model.
|
|
1114
|
+
Removes an `annotation <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.annotation?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1128
1115
|
|
|
1129
1116
|
Parameters
|
|
1130
1117
|
----------
|
|
@@ -1138,7 +1125,7 @@ class TOMWrapper:
|
|
|
1138
1125
|
|
|
1139
1126
|
def clear_annotations(self, object):
|
|
1140
1127
|
"""
|
|
1141
|
-
Removes all annotations on an object within the semantic model.
|
|
1128
|
+
Removes all `annotations <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.annotation?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1142
1129
|
|
|
1143
1130
|
Parameters
|
|
1144
1131
|
----------
|
|
@@ -1152,7 +1139,7 @@ class TOMWrapper:
|
|
|
1152
1139
|
self, object
|
|
1153
1140
|
) -> "Microsoft.AnalysisServices.Tabular.ExtendedProperty":
|
|
1154
1141
|
"""
|
|
1155
|
-
Retrieves all extended properties on an object within the semantic model.
|
|
1142
|
+
Retrieves all `extended properties <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.extendedproperty?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1156
1143
|
|
|
1157
1144
|
Parameters
|
|
1158
1145
|
----------
|
|
@@ -1172,7 +1159,7 @@ class TOMWrapper:
|
|
|
1172
1159
|
self, object, extended_property_type: str, name: str, value: str
|
|
1173
1160
|
):
|
|
1174
1161
|
"""
|
|
1175
|
-
Sets an extended property on an object within the semantic model.
|
|
1162
|
+
Sets an `extended property <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.extendedproperty?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1176
1163
|
|
|
1177
1164
|
Parameters
|
|
1178
1165
|
----------
|
|
@@ -1205,7 +1192,7 @@ class TOMWrapper:
|
|
|
1205
1192
|
|
|
1206
1193
|
def get_extended_property_value(self, object, name: str):
|
|
1207
1194
|
"""
|
|
1208
|
-
Retrieves the value of an extended property for an object within the semantic model.
|
|
1195
|
+
Retrieves the value of an `extended property <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.extendedproperty?view=analysisservices-dotnet>`_ for an object within the semantic model.
|
|
1209
1196
|
|
|
1210
1197
|
Parameters
|
|
1211
1198
|
----------
|
|
@@ -1224,7 +1211,7 @@ class TOMWrapper:
|
|
|
1224
1211
|
|
|
1225
1212
|
def remove_extended_property(self, object, name: str):
|
|
1226
1213
|
"""
|
|
1227
|
-
Removes an extended property on an object within the semantic model.
|
|
1214
|
+
Removes an `extended property <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.extendedproperty?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1228
1215
|
|
|
1229
1216
|
Parameters
|
|
1230
1217
|
----------
|
|
@@ -1238,7 +1225,7 @@ class TOMWrapper:
|
|
|
1238
1225
|
|
|
1239
1226
|
def clear_extended_properties(self, object):
|
|
1240
1227
|
"""
|
|
1241
|
-
Removes all extended properties on an object within the semantic model.
|
|
1228
|
+
Removes all `extended properties <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.extendedproperty?view=analysisservices-dotnet>`_ on an object within the semantic model.
|
|
1242
1229
|
|
|
1243
1230
|
Parameters
|
|
1244
1231
|
----------
|
|
@@ -1254,7 +1241,7 @@ class TOMWrapper:
|
|
|
1254
1241
|
perspective_name: str,
|
|
1255
1242
|
):
|
|
1256
1243
|
"""
|
|
1257
|
-
Indicates whether an object is contained within a given perspective.
|
|
1244
|
+
Indicates whether an object is contained within a given `perspective <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.perspective?view=analysisservices-dotnet>`_.
|
|
1258
1245
|
|
|
1259
1246
|
Parameters
|
|
1260
1247
|
----------
|
|
@@ -1279,10 +1266,7 @@ class TOMWrapper:
|
|
|
1279
1266
|
objectType = object.ObjectType
|
|
1280
1267
|
|
|
1281
1268
|
if objectType not in validObjects:
|
|
1282
|
-
|
|
1283
|
-
f"Only the following object types are valid for perspectives: {validObjects}."
|
|
1284
|
-
)
|
|
1285
|
-
return
|
|
1269
|
+
raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
|
|
1286
1270
|
|
|
1287
1271
|
object.Model.Perspectives[perspective_name]
|
|
1288
1272
|
|
|
@@ -1313,7 +1297,7 @@ class TOMWrapper:
|
|
|
1313
1297
|
perspective_name: str,
|
|
1314
1298
|
):
|
|
1315
1299
|
"""
|
|
1316
|
-
Adds an object to a perspective.
|
|
1300
|
+
Adds an object to a `perspective <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.perspective?view=analysisservices-dotnet>`_.
|
|
1317
1301
|
|
|
1318
1302
|
Parameters
|
|
1319
1303
|
----------
|
|
@@ -1333,15 +1317,12 @@ class TOMWrapper:
|
|
|
1333
1317
|
objectType = object.ObjectType
|
|
1334
1318
|
|
|
1335
1319
|
if objectType not in validObjects:
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
)
|
|
1339
|
-
return
|
|
1320
|
+
raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
|
|
1321
|
+
|
|
1340
1322
|
try:
|
|
1341
1323
|
object.Model.Perspectives[perspective_name]
|
|
1342
1324
|
except:
|
|
1343
|
-
|
|
1344
|
-
return
|
|
1325
|
+
raise ValueError(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
|
|
1345
1326
|
|
|
1346
1327
|
# try:
|
|
1347
1328
|
if objectType == TOM.ObjectType.Table:
|
|
@@ -1375,7 +1356,7 @@ class TOMWrapper:
|
|
|
1375
1356
|
perspective_name: str,
|
|
1376
1357
|
):
|
|
1377
1358
|
"""
|
|
1378
|
-
Removes an object from a perspective.
|
|
1359
|
+
Removes an object from a `perspective <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.perspective?view=analysisservices-dotnet>`_.
|
|
1379
1360
|
|
|
1380
1361
|
Parameters
|
|
1381
1362
|
----------
|
|
@@ -1395,15 +1376,12 @@ class TOMWrapper:
|
|
|
1395
1376
|
objectType = object.ObjectType
|
|
1396
1377
|
|
|
1397
1378
|
if objectType not in validObjects:
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
)
|
|
1401
|
-
return
|
|
1379
|
+
raise ValueError(f"{icons.red_dot} Only the following object types are valid for perspectives: {validObjects}.")
|
|
1380
|
+
|
|
1402
1381
|
try:
|
|
1403
1382
|
object.Model.Perspectives[perspective_name]
|
|
1404
1383
|
except:
|
|
1405
|
-
|
|
1406
|
-
return
|
|
1384
|
+
raise ValueError(f"{icons.red_dot} The '{perspective_name}' perspective does not exist.")
|
|
1407
1385
|
|
|
1408
1386
|
# try:
|
|
1409
1387
|
if objectType == TOM.ObjectType.Table:
|
|
@@ -1449,7 +1427,7 @@ class TOMWrapper:
|
|
|
1449
1427
|
value: str,
|
|
1450
1428
|
):
|
|
1451
1429
|
"""
|
|
1452
|
-
Sets a translation value for an object's property.
|
|
1430
|
+
Sets a `translation <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.culture?view=analysisservices-dotnet>`_ value for an object's property.
|
|
1453
1431
|
|
|
1454
1432
|
Parameters
|
|
1455
1433
|
----------
|
|
@@ -1476,8 +1454,7 @@ class TOMWrapper:
|
|
|
1476
1454
|
] # , 'Level'
|
|
1477
1455
|
|
|
1478
1456
|
if object.ObjectType not in validObjects:
|
|
1479
|
-
|
|
1480
|
-
return
|
|
1457
|
+
raise ValueError(f"{icons.red_dot} Translations can only be set to {validObjects}.")
|
|
1481
1458
|
|
|
1482
1459
|
mapping = {
|
|
1483
1460
|
"Name": TOM.TranslatedProperty.Caption,
|
|
@@ -1486,14 +1463,13 @@ class TOMWrapper:
|
|
|
1486
1463
|
}
|
|
1487
1464
|
|
|
1488
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].")
|
|
1489
1468
|
|
|
1490
1469
|
try:
|
|
1491
1470
|
object.Model.Cultures[language]
|
|
1492
1471
|
except:
|
|
1493
|
-
|
|
1494
|
-
f"The '{language}' translation language does not exist in the semantic model."
|
|
1495
|
-
)
|
|
1496
|
-
return
|
|
1472
|
+
raise ValueError(f"{icons.red_dot} The '{language}' translation language does not exist in the semantic model.")
|
|
1497
1473
|
|
|
1498
1474
|
object.Model.Cultures[language].ObjectTranslations.SetTranslation(
|
|
1499
1475
|
object, prop, value
|
|
@@ -1505,7 +1481,7 @@ class TOMWrapper:
|
|
|
1505
1481
|
language: str,
|
|
1506
1482
|
):
|
|
1507
1483
|
"""
|
|
1508
|
-
Removes an object's translation value.
|
|
1484
|
+
Removes an object's `translation <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.culture?view=analysisservices-dotnet>`_ value.
|
|
1509
1485
|
|
|
1510
1486
|
Parameters
|
|
1511
1487
|
----------
|
|
@@ -1579,7 +1555,7 @@ class TOMWrapper:
|
|
|
1579
1555
|
|
|
1580
1556
|
def used_in_relationships(self, object: Union["TOM.Table", "TOM.Column"]):
|
|
1581
1557
|
"""
|
|
1582
|
-
Shows all relationships in which a table/column is used.
|
|
1558
|
+
Shows all `relationships <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.singlecolumnrelationship?view=analysisservices-dotnet>`_ in which a table/column is used.
|
|
1583
1559
|
|
|
1584
1560
|
Parameters
|
|
1585
1561
|
----------
|
|
@@ -1612,7 +1588,7 @@ class TOMWrapper:
|
|
|
1612
1588
|
|
|
1613
1589
|
def used_in_levels(self, column: "TOM.Column"):
|
|
1614
1590
|
"""
|
|
1615
|
-
Shows all levels in which a column is used.
|
|
1591
|
+
Shows all `levels <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.level?view=analysisservices-dotnet>`_ in which a column is used.
|
|
1616
1592
|
|
|
1617
1593
|
Parameters
|
|
1618
1594
|
----------
|
|
@@ -1629,16 +1605,16 @@ class TOMWrapper:
|
|
|
1629
1605
|
objType = column.ObjectType
|
|
1630
1606
|
|
|
1631
1607
|
if objType == TOM.ObjectType.Column:
|
|
1632
|
-
for
|
|
1608
|
+
for level in self.all_levels():
|
|
1633
1609
|
if (
|
|
1634
|
-
|
|
1635
|
-
and
|
|
1610
|
+
level.Parent.Table.Name == column.Parent.Name
|
|
1611
|
+
and level.Column.Name == column.Name
|
|
1636
1612
|
):
|
|
1637
|
-
yield
|
|
1613
|
+
yield level
|
|
1638
1614
|
|
|
1639
1615
|
def used_in_hierarchies(self, column: "TOM.Column"):
|
|
1640
1616
|
"""
|
|
1641
|
-
Shows all hierarchies in which a column is used.
|
|
1617
|
+
Shows all `hierarchies <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.hierarchy?view=analysisservices-dotnet>`_ in which a column is used.
|
|
1642
1618
|
|
|
1643
1619
|
Parameters
|
|
1644
1620
|
----------
|
|
@@ -1691,7 +1667,7 @@ class TOMWrapper:
|
|
|
1691
1667
|
dependencies: pd.DataFrame,
|
|
1692
1668
|
):
|
|
1693
1669
|
"""
|
|
1694
|
-
Identifies the filter expressions which reference a given object.
|
|
1670
|
+
Identifies the row level security `filter expressions <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.tablepermission.filterexpression?view=analysisservices-dotnet#microsoft-analysisservices-tabular-tablepermission-filterexpression>`_ which reference a given object.
|
|
1695
1671
|
|
|
1696
1672
|
Parameters
|
|
1697
1673
|
----------
|
|
@@ -1855,7 +1831,7 @@ class TOMWrapper:
|
|
|
1855
1831
|
|
|
1856
1832
|
def hybrid_tables(self):
|
|
1857
1833
|
"""
|
|
1858
|
-
Outputs the hybrid tables within a semantic model.
|
|
1834
|
+
Outputs the `hybrid tables <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_ within a semantic model.
|
|
1859
1835
|
|
|
1860
1836
|
Parameters
|
|
1861
1837
|
----------
|
|
@@ -1874,7 +1850,7 @@ class TOMWrapper:
|
|
|
1874
1850
|
|
|
1875
1851
|
def date_tables(self):
|
|
1876
1852
|
"""
|
|
1877
|
-
Outputs the tables which are marked as date tables within a semantic model.
|
|
1853
|
+
Outputs the tables which are marked as `date tables <https://learn.microsoft.com/power-bi/transform-model/desktop-date-tables>`_ within a semantic model.
|
|
1878
1854
|
|
|
1879
1855
|
Parameters
|
|
1880
1856
|
----------
|
|
@@ -1895,7 +1871,7 @@ class TOMWrapper:
|
|
|
1895
1871
|
|
|
1896
1872
|
def is_hybrid_table(self, table_name: str):
|
|
1897
1873
|
"""
|
|
1898
|
-
Identifies if a table is a hybrid table.
|
|
1874
|
+
Identifies if a table is a `hybrid table <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_.
|
|
1899
1875
|
|
|
1900
1876
|
Parameters
|
|
1901
1877
|
----------
|
|
@@ -1925,7 +1901,7 @@ class TOMWrapper:
|
|
|
1925
1901
|
|
|
1926
1902
|
def is_date_table(self, table_name: str):
|
|
1927
1903
|
"""
|
|
1928
|
-
Identifies if a table is marked as a date
|
|
1904
|
+
Identifies if a table is marked as a `date tables <https://learn.microsoft.com/power-bi/transform-model/desktop-date-tables>`_.
|
|
1929
1905
|
|
|
1930
1906
|
Parameters
|
|
1931
1907
|
----------
|
|
@@ -1939,18 +1915,11 @@ class TOMWrapper:
|
|
|
1939
1915
|
"""
|
|
1940
1916
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
1941
1917
|
|
|
1942
|
-
|
|
1943
|
-
t = self.model.Tables[table_name]
|
|
1944
|
-
|
|
1945
|
-
if t.DataCategory == "Time":
|
|
1946
|
-
if any(c.IsKey and c.DataType == TOM.DataType.DateTime for c in t.Columns):
|
|
1947
|
-
isDateTable = True
|
|
1948
|
-
|
|
1949
|
-
return isDateTable
|
|
1918
|
+
return any(c.IsKey and c.DataType == TOM.DataType.DateTime for c in self.all_columns() if c.Parent.Name == table_name and c.Parent.DataCategory == 'Time')
|
|
1950
1919
|
|
|
1951
1920
|
def mark_as_date_table(self, table_name: str, column_name: str):
|
|
1952
1921
|
"""
|
|
1953
|
-
Marks a table as a date table.
|
|
1922
|
+
Marks a table as a `date table <https://learn.microsoft.com/power-bi/transform-model/desktop-date-tables>`_.
|
|
1954
1923
|
|
|
1955
1924
|
Parameters
|
|
1956
1925
|
----------
|
|
@@ -1964,11 +1933,8 @@ class TOMWrapper:
|
|
|
1964
1933
|
t = self.model.Tables[table_name]
|
|
1965
1934
|
c = t.Columns[column_name]
|
|
1966
1935
|
if c.DataType != TOM.DataType.DateTime:
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
)
|
|
1970
|
-
return
|
|
1971
|
-
|
|
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
|
+
|
|
1972
1938
|
daxQuery = f"""
|
|
1973
1939
|
define measure '{table_name}'[test] =
|
|
1974
1940
|
var mn = MIN('{table_name}'[{column_name}])
|
|
@@ -1983,14 +1949,11 @@ class TOMWrapper:
|
|
|
1983
1949
|
)
|
|
1984
1950
|
"""
|
|
1985
1951
|
df = fabric.evaluate_dax(
|
|
1986
|
-
dataset=self.
|
|
1952
|
+
dataset=self._dataset, workspace=self._workspace, dax_string=daxQuery
|
|
1987
1953
|
)
|
|
1988
1954
|
value = df["1"].iloc[0]
|
|
1989
1955
|
if value != "1":
|
|
1990
|
-
|
|
1991
|
-
f"{icons.red_dot} The '{column_name}' within the '{table_name}' table does not contain contiguous date values."
|
|
1992
|
-
)
|
|
1993
|
-
return
|
|
1956
|
+
raise ValueError(f"{icons.red_dot} The '{column_name}' within the '{table_name}' table does not contain contiguous date values.")
|
|
1994
1957
|
|
|
1995
1958
|
# Mark as a date table
|
|
1996
1959
|
t.DataCategory = "Time"
|
|
@@ -2001,7 +1964,7 @@ class TOMWrapper:
|
|
|
2001
1964
|
|
|
2002
1965
|
def has_aggs(self):
|
|
2003
1966
|
"""
|
|
2004
|
-
Identifies if a semantic model has any aggregations.
|
|
1967
|
+
Identifies if a semantic model has any `aggregations <https://learn.microsoft.com/power-bi/transform-model/aggregations-advanced>`_.
|
|
2005
1968
|
|
|
2006
1969
|
Parameters
|
|
2007
1970
|
----------
|
|
@@ -2012,17 +1975,11 @@ class TOMWrapper:
|
|
|
2012
1975
|
Indicates if the semantic model has any aggregations.
|
|
2013
1976
|
"""
|
|
2014
1977
|
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
for c in self.all_columns():
|
|
2018
|
-
if c.AlterateOf is not None:
|
|
2019
|
-
hasAggs = True
|
|
2020
|
-
|
|
2021
|
-
return hasAggs
|
|
1978
|
+
return any(c.AlternateOf is not None for c in self.all_columns())
|
|
2022
1979
|
|
|
2023
1980
|
def is_agg_table(self, table_name: str):
|
|
2024
1981
|
"""
|
|
2025
|
-
Identifies if a table has aggregations.
|
|
1982
|
+
Identifies if a table has `aggregations <https://learn.microsoft.com/power-bi/transform-model/aggregations-advanced>`_.
|
|
2026
1983
|
|
|
2027
1984
|
Parameters
|
|
2028
1985
|
----------
|
|
@@ -2041,7 +1998,7 @@ class TOMWrapper:
|
|
|
2041
1998
|
|
|
2042
1999
|
def has_hybrid_table(self):
|
|
2043
2000
|
"""
|
|
2044
|
-
Identifies if a semantic model has a hybrid table.
|
|
2001
|
+
Identifies if a semantic model has a `hybrid table <https://learn.microsoft.com/power-bi/connect-data/service-dataset-modes-understand#hybrid-tables>`_.
|
|
2045
2002
|
|
|
2046
2003
|
Parameters
|
|
2047
2004
|
----------
|
|
@@ -2050,19 +2007,13 @@ class TOMWrapper:
|
|
|
2050
2007
|
-------
|
|
2051
2008
|
bool
|
|
2052
2009
|
Indicates if the semantic model has a hybrid table.
|
|
2053
|
-
"""
|
|
2010
|
+
"""
|
|
2054
2011
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
for t in self.model.Tables:
|
|
2058
|
-
if self.is_hybrid_table(table_name=t.Name):
|
|
2059
|
-
hasHybridTable = True
|
|
2060
|
-
|
|
2061
|
-
return hasHybridTable
|
|
2012
|
+
return any(self.is_hybrid_table(table_name=t.Name) for t in self.model.Tables)
|
|
2062
2013
|
|
|
2063
2014
|
def has_date_table(self):
|
|
2064
2015
|
"""
|
|
2065
|
-
Identifies if a semantic model has a table marked as a date table.
|
|
2016
|
+
Identifies if a semantic model has a table marked as a `date table <https://learn.microsoft.com/power-bi/transform-model/desktop-date-tables>`_.
|
|
2066
2017
|
|
|
2067
2018
|
Parameters
|
|
2068
2019
|
----------
|
|
@@ -2073,17 +2024,11 @@ class TOMWrapper:
|
|
|
2073
2024
|
Indicates if the semantic model has a table marked as a date table.
|
|
2074
2025
|
"""
|
|
2075
2026
|
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
for t in self.model.Tables:
|
|
2079
|
-
if self.is_date_table(table_name=t.Name):
|
|
2080
|
-
hasDateTable = True
|
|
2081
|
-
|
|
2082
|
-
return hasDateTable
|
|
2027
|
+
return any(self.is_date_table(table_name=t.Name) for t in self.model.Tables)
|
|
2083
2028
|
|
|
2084
2029
|
def is_direct_lake(self):
|
|
2085
2030
|
"""
|
|
2086
|
-
Identifies if a semantic model is in Direct Lake mode.
|
|
2031
|
+
Identifies if a semantic model is in `Direct Lake <https://learn.microsoft.com/fabric/get-started/direct-lake-overview>`_ mode.
|
|
2087
2032
|
|
|
2088
2033
|
Parameters
|
|
2089
2034
|
----------
|
|
@@ -2093,6 +2038,7 @@ class TOMWrapper:
|
|
|
2093
2038
|
bool
|
|
2094
2039
|
Indicates if the semantic model is in Direct Lake mode.
|
|
2095
2040
|
"""
|
|
2041
|
+
import Microsoft.AnalysisServices.Tabular as TOM
|
|
2096
2042
|
|
|
2097
2043
|
return any(
|
|
2098
2044
|
p.Mode == TOM.ModeType.DirectLake
|
|
@@ -2102,7 +2048,7 @@ class TOMWrapper:
|
|
|
2102
2048
|
|
|
2103
2049
|
def is_field_parameter(self, table_name: str):
|
|
2104
2050
|
"""
|
|
2105
|
-
Identifies if a table is a field parameter.
|
|
2051
|
+
Identifies if a table is a `field parameter <https://learn.microsoft.com/power-bi/create-reports/power-bi-field-parameters>`_.
|
|
2106
2052
|
|
|
2107
2053
|
Parameters
|
|
2108
2054
|
----------
|
|
@@ -2134,7 +2080,7 @@ class TOMWrapper:
|
|
|
2134
2080
|
|
|
2135
2081
|
def is_auto_date_table(self, table_name: str):
|
|
2136
2082
|
"""
|
|
2137
|
-
Identifies if a table is an auto
|
|
2083
|
+
Identifies if a table is an `auto date/time table <https://learn.microsoft.com/power-bi/transform-model/desktop-auto-date-time>`_.
|
|
2138
2084
|
|
|
2139
2085
|
Parameters
|
|
2140
2086
|
----------
|
|
@@ -2174,7 +2120,7 @@ class TOMWrapper:
|
|
|
2174
2120
|
status_graphic: Optional[str] = None,
|
|
2175
2121
|
):
|
|
2176
2122
|
"""
|
|
2177
|
-
Sets the properties to add/update a KPI for a measure.
|
|
2123
|
+
Sets the properties to add/update a `KPI <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.kpi?view=analysisservices-dotnet>`_ for a measure.
|
|
2178
2124
|
|
|
2179
2125
|
Parameters
|
|
2180
2126
|
----------
|
|
@@ -2202,58 +2148,44 @@ class TOMWrapper:
|
|
|
2202
2148
|
# https://github.com/m-kovalsky/Tabular/blob/master/KPI%20Graphics.md
|
|
2203
2149
|
|
|
2204
2150
|
if measure_name == target:
|
|
2205
|
-
|
|
2206
|
-
f"The 'target' parameter cannot be the same measure as the 'measure_name' parameter."
|
|
2207
|
-
)
|
|
2208
|
-
return
|
|
2151
|
+
raise ValueError(f"{icons.red_dot} The 'target' parameter cannot be the same measure as the 'measure_name' parameter.")
|
|
2209
2152
|
|
|
2210
2153
|
if status_graphic is None:
|
|
2211
2154
|
status_graphic = "Three Circles Colored"
|
|
2212
2155
|
|
|
2213
|
-
|
|
2214
|
-
status_type = status_type
|
|
2215
|
-
|
|
2156
|
+
valid_status_types = ["Linear", "LinearReversed", "Centered", "CenteredReversed"]
|
|
2157
|
+
status_type = status_type
|
|
2216
2158
|
if status_type is None:
|
|
2217
2159
|
status_type = "Linear"
|
|
2160
|
+
else:
|
|
2161
|
+
status_type = status_type.title().replace(" ", "")
|
|
2218
2162
|
|
|
2219
|
-
if status_type not in
|
|
2220
|
-
|
|
2221
|
-
f"'{status_type}' is an invalid status_type. Please choose from these options: {statusType}."
|
|
2222
|
-
)
|
|
2223
|
-
return
|
|
2163
|
+
if status_type not in valid_status_types:
|
|
2164
|
+
raise ValueError(f"{icons.red_dot} '{status_type}' is an invalid status_type. Please choose from these options: {valid_status_types}.")
|
|
2224
2165
|
|
|
2225
2166
|
if status_type in ["Linear", "LinearReversed"]:
|
|
2226
2167
|
if upper_bound is not None or lower_mid_bound is not None:
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
)
|
|
2230
|
-
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
|
+
|
|
2231
2170
|
elif upper_bound <= lower_bound:
|
|
2232
|
-
|
|
2233
|
-
return
|
|
2171
|
+
raise ValueError(f"{icons.red_dot} The upper_bound must be greater than the lower_bound.")
|
|
2234
2172
|
|
|
2235
2173
|
if status_type in ["Centered", "CenteredReversed"]:
|
|
2236
2174
|
if upper_mid_bound is None or lower_mid_bound is None:
|
|
2237
|
-
|
|
2238
|
-
f"The 'upper_mid_bound' and 'lower_mid_bound' parameters are necessary in the 'Centered' and 'CenteredReversed' status types."
|
|
2239
|
-
)
|
|
2240
|
-
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.")
|
|
2241
2176
|
elif upper_bound <= upper_mid_bound:
|
|
2242
|
-
|
|
2177
|
+
raise ValueError(f"{icons.red_dot} The upper_bound must be greater than the upper_mid_bound.")
|
|
2243
2178
|
elif upper_mid_bound <= lower_mid_bound:
|
|
2244
|
-
|
|
2179
|
+
raise ValueError(f"{icons.red_dot} The upper_mid_bound must be greater than the lower_mid_bound.")
|
|
2245
2180
|
elif lower_mid_bound <= lower_bound:
|
|
2246
|
-
|
|
2181
|
+
raise ValueError(f"{icons.red_dot} The lower_mid_bound must be greater than the lower_bound.")
|
|
2247
2182
|
|
|
2248
2183
|
try:
|
|
2249
2184
|
table_name = next(
|
|
2250
2185
|
m.Parent.Name for m in self.all_measures() if m.Name == measure_name
|
|
2251
2186
|
)
|
|
2252
2187
|
except:
|
|
2253
|
-
|
|
2254
|
-
f"The '{measure_name}' measure does not exist in the '{self.dataset}' semantic model within the '{self.workspace}'."
|
|
2255
|
-
)
|
|
2256
|
-
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}'.")
|
|
2257
2189
|
|
|
2258
2190
|
graphics = [
|
|
2259
2191
|
"Cylinder",
|
|
@@ -2276,10 +2208,7 @@ class TOMWrapper:
|
|
|
2276
2208
|
]
|
|
2277
2209
|
|
|
2278
2210
|
if status_graphic not in graphics:
|
|
2279
|
-
|
|
2280
|
-
f"The '{status_graphic}' status graphic is not valid. Please choose from these options: {graphics}."
|
|
2281
|
-
)
|
|
2282
|
-
return
|
|
2211
|
+
raise ValueError(f"{icons.red_dot} The '{status_graphic}' status graphic is not valid. Please choose from these options: {graphics}.")
|
|
2283
2212
|
|
|
2284
2213
|
measure_target = True
|
|
2285
2214
|
|
|
@@ -2295,10 +2224,8 @@ class TOMWrapper:
|
|
|
2295
2224
|
if m.Name == target
|
|
2296
2225
|
)
|
|
2297
2226
|
except:
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
)
|
|
2301
|
-
|
|
2227
|
+
raise ValueError(f"{icons.red_dot} The '{target}' measure does not exist in the '{self._dataset}' semantic model within the '{self._workspace}'.")
|
|
2228
|
+
|
|
2302
2229
|
if measure_target:
|
|
2303
2230
|
expr = f"var x = [{measure_name}]/[{target}]\nreturn"
|
|
2304
2231
|
else:
|
|
@@ -2328,7 +2255,7 @@ class TOMWrapper:
|
|
|
2328
2255
|
|
|
2329
2256
|
def set_aggregations(self, table_name: str, agg_table_name: str):
|
|
2330
2257
|
"""
|
|
2331
|
-
Sets the aggregations (alternate of) for all the columns in an aggregation table based on a base table.
|
|
2258
|
+
Sets the `aggregations <https://learn.microsoft.com/power-bi/transform-model/aggregations-advanced>`_ (alternate of) for all the columns in an aggregation table based on a base table.
|
|
2332
2259
|
|
|
2333
2260
|
Parameters
|
|
2334
2261
|
----------
|
|
@@ -2367,7 +2294,7 @@ class TOMWrapper:
|
|
|
2367
2294
|
self, table_name: str, column_name: str, value: Optional[bool] = False
|
|
2368
2295
|
):
|
|
2369
2296
|
"""
|
|
2370
|
-
Sets the
|
|
2297
|
+
Sets the `IsAvailableInMDX <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.column.isavailableinmdx?view=analysisservices-dotnet#microsoft-analysisservices-tabular-column-isavailableinmdx>`_ property on a column.
|
|
2371
2298
|
|
|
2372
2299
|
Parameters
|
|
2373
2300
|
----------
|
|
@@ -2385,7 +2312,7 @@ class TOMWrapper:
|
|
|
2385
2312
|
self, table_name: str, column_name: str, value: Optional[str] = None
|
|
2386
2313
|
):
|
|
2387
2314
|
"""
|
|
2388
|
-
Sets the SummarizeBy property on a column.
|
|
2315
|
+
Sets the `SummarizeBy <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.column.summarizeby?view=analysisservices-dotnet#microsoft-analysisservices-tabular-column-summarizeby>`_ property on a column.
|
|
2389
2316
|
|
|
2390
2317
|
Parameters
|
|
2391
2318
|
----------
|
|
@@ -2421,10 +2348,7 @@ class TOMWrapper:
|
|
|
2421
2348
|
)
|
|
2422
2349
|
|
|
2423
2350
|
if value not in values:
|
|
2424
|
-
|
|
2425
|
-
f"'{value}' is not a valid value for the SummarizeBy property. These are the valid values: {values}."
|
|
2426
|
-
)
|
|
2427
|
-
return
|
|
2351
|
+
raise ValueError(f"{icons.red_dot} '{value}' is not a valid value for the SummarizeBy property. These are the valid values: {values}.")
|
|
2428
2352
|
|
|
2429
2353
|
self.model.Tables[table_name].Columns[column_name].SummarizeBy = (
|
|
2430
2354
|
System.Enum.Parse(TOM.AggregateFunction, value)
|
|
@@ -2432,7 +2356,7 @@ class TOMWrapper:
|
|
|
2432
2356
|
|
|
2433
2357
|
def set_direct_lake_behavior(self, direct_lake_behavior: str):
|
|
2434
2358
|
"""
|
|
2435
|
-
Sets the Direct Lake Behavior property for a semantic model.
|
|
2359
|
+
Sets the `Direct Lake Behavior <https://learn.microsoft.com/fabric/get-started/direct-lake-overview#fallback-behavior>`_ property for a semantic model.
|
|
2436
2360
|
|
|
2437
2361
|
Parameters
|
|
2438
2362
|
----------
|
|
@@ -2453,10 +2377,7 @@ class TOMWrapper:
|
|
|
2453
2377
|
dlValues = ["Automatic", "DirectLakeOnly", "DirectQueryOnly"]
|
|
2454
2378
|
|
|
2455
2379
|
if direct_lake_behavior not in dlValues:
|
|
2456
|
-
|
|
2457
|
-
f"The 'direct_lake_behavior' parameter must be one of these values: {dlValues}."
|
|
2458
|
-
)
|
|
2459
|
-
return
|
|
2380
|
+
raise ValueError(f"{icons.red_dot} The 'direct_lake_behavior' parameter must be one of these values: {dlValues}.")
|
|
2460
2381
|
|
|
2461
2382
|
self.model.DirectLakeBehavior = System.Enum.Parse(
|
|
2462
2383
|
TOM.DirectLakeBehavior, direct_lake_behavior
|
|
@@ -2539,7 +2460,7 @@ class TOMWrapper:
|
|
|
2539
2460
|
|
|
2540
2461
|
def add_field_parameter(self, table_name: str, objects: List[str]):
|
|
2541
2462
|
"""
|
|
2542
|
-
Adds a
|
|
2463
|
+
Adds a `field parameter <https://learn.microsoft.com/power-bi/create-reports/power-bi-field-parameters>`_ to the semantic model.
|
|
2543
2464
|
|
|
2544
2465
|
Parameters
|
|
2545
2466
|
----------
|
|
@@ -2551,14 +2472,13 @@ class TOMWrapper:
|
|
|
2551
2472
|
Measures may be formatted as '[Measure Name]' or 'Measure Name'.
|
|
2552
2473
|
"""
|
|
2553
2474
|
|
|
2475
|
+
import Microsoft.AnalysisServices.Tabular as TOM
|
|
2476
|
+
|
|
2554
2477
|
if isinstance(objects, str):
|
|
2555
|
-
|
|
2556
|
-
|
|
2478
|
+
raise ValueError(f"{icons.red_dot} The 'objects' parameter must be a list of columns/measures.")
|
|
2479
|
+
|
|
2557
2480
|
if len(objects) == 1:
|
|
2558
|
-
|
|
2559
|
-
f"There must be more than one object (column/measure) within the objects parameter."
|
|
2560
|
-
)
|
|
2561
|
-
return
|
|
2481
|
+
raise ValueError(f"{icons.red_dot} There must be more than one object (column/measure) within the objects parameter.")
|
|
2562
2482
|
|
|
2563
2483
|
expr = ""
|
|
2564
2484
|
i = 0
|
|
@@ -2594,10 +2514,7 @@ class TOMWrapper:
|
|
|
2594
2514
|
)
|
|
2595
2515
|
success = True
|
|
2596
2516
|
if not success:
|
|
2597
|
-
|
|
2598
|
-
f"The '{obj}' object was not found in the '{self.dataset}' semantic model."
|
|
2599
|
-
)
|
|
2600
|
-
return
|
|
2517
|
+
raise ValueError(f"{icons.red_dot} The '{obj}' object was not found in the '{self._dataset}' semantic model.")
|
|
2601
2518
|
else:
|
|
2602
2519
|
i += 1
|
|
2603
2520
|
|
|
@@ -2631,7 +2548,6 @@ class TOMWrapper:
|
|
|
2631
2548
|
)
|
|
2632
2549
|
|
|
2633
2550
|
self.set_extended_property(
|
|
2634
|
-
self=self,
|
|
2635
2551
|
object=self.model.Tables[table_name].Columns[col2],
|
|
2636
2552
|
extended_property_type="Json",
|
|
2637
2553
|
name="ParameterMetadata",
|
|
@@ -2649,11 +2565,11 @@ class TOMWrapper:
|
|
|
2649
2565
|
].Columns[col3]
|
|
2650
2566
|
self.model.Tables[table_name].Columns[table_name].RelatedColumnDetails = rcd
|
|
2651
2567
|
|
|
2652
|
-
self.
|
|
2568
|
+
self._tables_added.append(table_name)
|
|
2653
2569
|
|
|
2654
2570
|
def remove_vertipaq_annotations(self):
|
|
2655
2571
|
"""
|
|
2656
|
-
Removes the annotations set using the
|
|
2572
|
+
Removes the annotations set using the set_vertipaq_annotations function.
|
|
2657
2573
|
"""
|
|
2658
2574
|
|
|
2659
2575
|
for t in self.model.Tables:
|
|
@@ -2683,10 +2599,10 @@ class TOMWrapper:
|
|
|
2683
2599
|
"""
|
|
2684
2600
|
|
|
2685
2601
|
dfT = fabric.list_tables(
|
|
2686
|
-
dataset=self.
|
|
2602
|
+
dataset=self._dataset, workspace=self._workspace, extended=True
|
|
2687
2603
|
)
|
|
2688
2604
|
dfC = fabric.list_columns(
|
|
2689
|
-
dataset=self.
|
|
2605
|
+
dataset=self._dataset, workspace=self._workspace, extended=True
|
|
2690
2606
|
)
|
|
2691
2607
|
# intList = ['Total Size']#, 'Data Size', 'Dictionary Size', 'Hierarchy Size']
|
|
2692
2608
|
dfCSum = dfC.groupby(["Table Name"])["Total Size"].sum().reset_index()
|
|
@@ -2698,16 +2614,16 @@ class TOMWrapper:
|
|
|
2698
2614
|
how="inner",
|
|
2699
2615
|
)
|
|
2700
2616
|
dfP = fabric.list_partitions(
|
|
2701
|
-
dataset=self.
|
|
2617
|
+
dataset=self._dataset, workspace=self._workspace, extended=True
|
|
2702
2618
|
)
|
|
2703
2619
|
dfP["Records per Segment"] = round(
|
|
2704
2620
|
dfP["Record Count"] / dfP["Segment Count"], 2
|
|
2705
2621
|
)
|
|
2706
2622
|
dfH = fabric.list_hierarchies(
|
|
2707
|
-
dataset=self.
|
|
2623
|
+
dataset=self._dataset, workspace=self._workspace, extended=True
|
|
2708
2624
|
)
|
|
2709
2625
|
dfR = list_relationships(
|
|
2710
|
-
dataset=self.
|
|
2626
|
+
dataset=self._dataset, workspace=self._workspace, extended=True
|
|
2711
2627
|
)
|
|
2712
2628
|
|
|
2713
2629
|
for t in self.model.Tables:
|
|
@@ -3100,7 +3016,7 @@ class TOMWrapper:
|
|
|
3100
3016
|
import Microsoft.AnalysisServices.Tabular as TOM
|
|
3101
3017
|
|
|
3102
3018
|
def create_pattern(a, b):
|
|
3103
|
-
return r"(?<!" + a + "\[)(?<!" + a + "'\[)" + b
|
|
3019
|
+
return r"(?<!" + re.escape(a) + r"\[)(?<!" + re.escape(a) + r"'\[)" + re.escape(b)
|
|
3104
3020
|
|
|
3105
3021
|
for obj in self.depends_on(object=object, dependencies=dependencies):
|
|
3106
3022
|
if obj.ObjectType == TOM.ObjectType.Column:
|
|
@@ -3128,7 +3044,7 @@ class TOMWrapper:
|
|
|
3128
3044
|
usingView = False
|
|
3129
3045
|
|
|
3130
3046
|
if self.is_direct_lake():
|
|
3131
|
-
df = check_fallback_reason(dataset=self.
|
|
3047
|
+
df = check_fallback_reason(dataset=self._dataset, workspace=self._workspace)
|
|
3132
3048
|
df_filt = df[df["FallbackReasonID"] == 2]
|
|
3133
3049
|
|
|
3134
3050
|
if len(df_filt) > 0:
|
|
@@ -3138,7 +3054,7 @@ class TOMWrapper:
|
|
|
3138
3054
|
|
|
3139
3055
|
def has_incremental_refresh_policy(self, table_name: str):
|
|
3140
3056
|
"""
|
|
3141
|
-
Identifies whether a table has an incremental refresh policy.
|
|
3057
|
+
Identifies whether a table has an `incremental refresh <https://learn.microsoft.com/power-bi/connect-data/incremental-refresh-overview>`_ policy.
|
|
3142
3058
|
|
|
3143
3059
|
Parameters
|
|
3144
3060
|
----------
|
|
@@ -3161,7 +3077,7 @@ class TOMWrapper:
|
|
|
3161
3077
|
|
|
3162
3078
|
def show_incremental_refresh_policy(self, table_name: str):
|
|
3163
3079
|
"""
|
|
3164
|
-
Prints the incremental refresh policy for a table.
|
|
3080
|
+
Prints the `incremental refresh <https://learn.microsoft.com/power-bi/connect-data/incremental-refresh-overview>`_ policy for a table.
|
|
3165
3081
|
|
|
3166
3082
|
Parameters
|
|
3167
3083
|
----------
|
|
@@ -3169,11 +3085,13 @@ class TOMWrapper:
|
|
|
3169
3085
|
Name of the table.
|
|
3170
3086
|
"""
|
|
3171
3087
|
|
|
3088
|
+
import Microsoft.AnalysisServices.Tabular as TOM
|
|
3089
|
+
|
|
3172
3090
|
rp = self.model.Tables[table_name].RefreshPolicy
|
|
3173
3091
|
|
|
3174
3092
|
if rp is None:
|
|
3175
3093
|
print(
|
|
3176
|
-
f"The '{table_name}' table in the '{self.
|
|
3094
|
+
f"{icons.yellow_dot} The '{table_name}' table in the '{self._dataset}' semantic model within the '{self._workspace}' workspace does not have an incremental refresh policy."
|
|
3177
3095
|
)
|
|
3178
3096
|
else:
|
|
3179
3097
|
print(f"Table Name: {table_name}")
|
|
@@ -3181,33 +3099,33 @@ class TOMWrapper:
|
|
|
3181
3099
|
icGran = str(rp.IncrementalGranularity).lower()
|
|
3182
3100
|
if rp.RollingWindowPeriods > 1:
|
|
3183
3101
|
print(
|
|
3184
|
-
f"Archive data starting {start_bold}{rp.RollingWindowPeriods} {rwGran}s{end_bold} before refresh date."
|
|
3102
|
+
f"Archive data starting {icons.start_bold}{rp.RollingWindowPeriods} {rwGran}s{icons.end_bold} before refresh date."
|
|
3185
3103
|
)
|
|
3186
3104
|
else:
|
|
3187
3105
|
print(
|
|
3188
|
-
f"Archive data starting {start_bold}{rp.RollingWindowPeriods} {rwGran}{end_bold} before refresh date."
|
|
3106
|
+
f"Archive data starting {icons.start_bold}{rp.RollingWindowPeriods} {rwGran}{icons.end_bold} before refresh date."
|
|
3189
3107
|
)
|
|
3190
3108
|
if rp.IncrementalPeriods > 1:
|
|
3191
3109
|
print(
|
|
3192
|
-
f"Incrementally refresh data {start_bold}{rp.IncrementalPeriods} {icGran}s{end_bold} before refresh date."
|
|
3110
|
+
f"Incrementally refresh data {icons.start_bold}{rp.IncrementalPeriods} {icGran}s{icons.end_bold} before refresh date."
|
|
3193
3111
|
)
|
|
3194
3112
|
else:
|
|
3195
3113
|
print(
|
|
3196
|
-
f"Incrementally refresh data {start_bold}{rp.IncrementalPeriods} {icGran}{end_bold} before refresh date."
|
|
3114
|
+
f"Incrementally refresh data {icons.start_bold}{rp.IncrementalPeriods} {icGran}{icons.end_bold} before refresh date."
|
|
3197
3115
|
)
|
|
3198
3116
|
|
|
3199
3117
|
if rp.Mode == TOM.RefreshPolicyMode.Hybrid:
|
|
3200
3118
|
print(
|
|
3201
|
-
f"{checked} Get the latest data in real time with DirectQuery (Premium only)"
|
|
3119
|
+
f"{icons.checked} Get the latest data in real time with DirectQuery (Premium only)"
|
|
3202
3120
|
)
|
|
3203
3121
|
else:
|
|
3204
3122
|
print(
|
|
3205
|
-
f"{unchecked} Get the latest data in real time with DirectQuery (Premium only)"
|
|
3123
|
+
f"{icons.unchecked} Get the latest data in real time with DirectQuery (Premium only)"
|
|
3206
3124
|
)
|
|
3207
3125
|
if rp.IncrementalPeriodsOffset == -1:
|
|
3208
|
-
print(f"{checked} Only refresh complete days")
|
|
3126
|
+
print(f"{icons.checked} Only refresh complete days")
|
|
3209
3127
|
else:
|
|
3210
|
-
print(f"{unchecked} Only refresh complete days")
|
|
3128
|
+
print(f"{icons.unchecked} Only refresh complete days")
|
|
3211
3129
|
if len(rp.PollingExpression) > 0:
|
|
3212
3130
|
pattern = r"\[([^\]]+)\]"
|
|
3213
3131
|
match = re.search(pattern, rp.PollingExpression)
|
|
@@ -3215,10 +3133,10 @@ class TOMWrapper:
|
|
|
3215
3133
|
col = match[0][1:-1]
|
|
3216
3134
|
fullCol = format_dax_object_name(table_name, col)
|
|
3217
3135
|
print(
|
|
3218
|
-
f"{checked} Detect data changes: {start_bold}{fullCol}{end_bold}"
|
|
3136
|
+
f"{icons.checked} Detect data changes: {icons.start_bold}{fullCol}{icons.end_bold}"
|
|
3219
3137
|
)
|
|
3220
3138
|
else:
|
|
3221
|
-
print(f"{unchecked} Detect data changes")
|
|
3139
|
+
print(f"{icons.unchecked} Detect data changes")
|
|
3222
3140
|
|
|
3223
3141
|
def update_incremental_refresh_policy(
|
|
3224
3142
|
self,
|
|
@@ -3231,7 +3149,7 @@ class TOMWrapper:
|
|
|
3231
3149
|
detect_data_changes_column: Optional[str] = None,
|
|
3232
3150
|
):
|
|
3233
3151
|
"""
|
|
3234
|
-
Updates the incremental refresh policy for a table within a semantic model.
|
|
3152
|
+
Updates the `incremental refresh <https://learn.microsoft.com/power-bi/connect-data/incremental-refresh-overview>`_ policy for a table within a semantic model.
|
|
3235
3153
|
|
|
3236
3154
|
Parameters
|
|
3237
3155
|
----------
|
|
@@ -3266,26 +3184,16 @@ class TOMWrapper:
|
|
|
3266
3184
|
rolling_window_granularity = rolling_window_granularity.capitalize()
|
|
3267
3185
|
|
|
3268
3186
|
if incremental_granularity not in incGran:
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
)
|
|
3272
|
-
return
|
|
3187
|
+
raise ValueError(f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}.")
|
|
3188
|
+
|
|
3273
3189
|
if rolling_window_granularity not in incGran:
|
|
3274
|
-
|
|
3275
|
-
f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}."
|
|
3276
|
-
)
|
|
3277
|
-
return
|
|
3190
|
+
raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}.")
|
|
3278
3191
|
|
|
3279
3192
|
if rolling_window_periods < 1:
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
)
|
|
3283
|
-
return
|
|
3193
|
+
raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0.")
|
|
3194
|
+
|
|
3284
3195
|
if incremental_periods < 1:
|
|
3285
|
-
|
|
3286
|
-
f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0."
|
|
3287
|
-
)
|
|
3288
|
-
return
|
|
3196
|
+
raise ValueError(f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0.")
|
|
3289
3197
|
|
|
3290
3198
|
t = self.model.Tables[table_name]
|
|
3291
3199
|
|
|
@@ -3293,10 +3201,7 @@ class TOMWrapper:
|
|
|
3293
3201
|
dc = t.Columns[detect_data_changes_column]
|
|
3294
3202
|
|
|
3295
3203
|
if dc.DataType != TOM.DataType.DateTime:
|
|
3296
|
-
|
|
3297
|
-
f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type."
|
|
3298
|
-
)
|
|
3299
|
-
return
|
|
3204
|
+
raise ValueError(f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type.")
|
|
3300
3205
|
|
|
3301
3206
|
rp = TOM.BasicRefreshPolicy()
|
|
3302
3207
|
rp.IncrementalPeriods = incremental_periods
|
|
@@ -3339,7 +3244,7 @@ class TOMWrapper:
|
|
|
3339
3244
|
detect_data_changes_column: Optional[str] = None,
|
|
3340
3245
|
):
|
|
3341
3246
|
"""
|
|
3342
|
-
Adds
|
|
3247
|
+
Adds an `incremental refresh <https://learn.microsoft.com/power-bi/connect-data/incremental-refresh-overview>`_ policy for a table within a semantic model.
|
|
3343
3248
|
|
|
3344
3249
|
Parameters
|
|
3345
3250
|
----------
|
|
@@ -3376,26 +3281,16 @@ class TOMWrapper:
|
|
|
3376
3281
|
rolling_window_granularity = rolling_window_granularity.capitalize()
|
|
3377
3282
|
|
|
3378
3283
|
if incremental_granularity not in incGran:
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
)
|
|
3382
|
-
return
|
|
3284
|
+
raise ValueError(f"{icons.red_dot} Invalid 'incremental_granularity' value. Please choose from the following options: {incGran}.")
|
|
3285
|
+
|
|
3383
3286
|
if rolling_window_granularity not in incGran:
|
|
3384
|
-
|
|
3385
|
-
f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}."
|
|
3386
|
-
)
|
|
3387
|
-
return
|
|
3287
|
+
raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_granularity' value. Please choose from the following options: {incGran}.")
|
|
3388
3288
|
|
|
3389
3289
|
if rolling_window_periods < 1:
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
)
|
|
3393
|
-
return
|
|
3290
|
+
raise ValueError(f"{icons.red_dot} Invalid 'rolling_window_periods' value. Must be a value greater than 0.")
|
|
3291
|
+
|
|
3394
3292
|
if incremental_periods < 1:
|
|
3395
|
-
|
|
3396
|
-
f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0."
|
|
3397
|
-
)
|
|
3398
|
-
return
|
|
3293
|
+
raise ValueError(f"{icons.red_dot} Invalid 'incremental_periods' value. Must be a value greater than 0.")
|
|
3399
3294
|
|
|
3400
3295
|
date_format = "%m/%d/%Y"
|
|
3401
3296
|
|
|
@@ -3410,10 +3305,7 @@ class TOMWrapper:
|
|
|
3410
3305
|
end_day = date_obj_end.day
|
|
3411
3306
|
|
|
3412
3307
|
if date_obj_end <= date_obj_start:
|
|
3413
|
-
|
|
3414
|
-
f"{icons.red_dot} Invalid 'start_date' or 'end_date'. The 'end_date' must be after the 'start_date'."
|
|
3415
|
-
)
|
|
3416
|
-
return
|
|
3308
|
+
raise ValueError(f"{icons.red_dot} Invalid 'start_date' or 'end_date'. The 'end_date' must be after the 'start_date'.")
|
|
3417
3309
|
|
|
3418
3310
|
t = self.model.Tables[table_name]
|
|
3419
3311
|
|
|
@@ -3422,20 +3314,14 @@ class TOMWrapper:
|
|
|
3422
3314
|
dType = c.DataType
|
|
3423
3315
|
|
|
3424
3316
|
if dType != TOM.DataType.DateTime:
|
|
3425
|
-
|
|
3426
|
-
f"{icons.red_dot} The {fcName} column is of '{dType}' data type. The column chosen must be of DateTime data type."
|
|
3427
|
-
)
|
|
3428
|
-
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.")
|
|
3429
3318
|
|
|
3430
3319
|
if detect_data_changes_column is not None:
|
|
3431
3320
|
dc = t.Columns[detect_data_changes_column]
|
|
3432
3321
|
dcType = dc.DataType
|
|
3433
3322
|
|
|
3434
3323
|
if dcType != TOM.DataType.DateTime:
|
|
3435
|
-
|
|
3436
|
-
f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type."
|
|
3437
|
-
)
|
|
3438
|
-
return
|
|
3324
|
+
raise ValueError(f"{icons.red_dot} Invalid 'detect_data_changes_column' parameter. This column must be of DateTime data type.")
|
|
3439
3325
|
|
|
3440
3326
|
# Start changes:
|
|
3441
3327
|
|
|
@@ -3443,10 +3329,8 @@ class TOMWrapper:
|
|
|
3443
3329
|
i = 0
|
|
3444
3330
|
for p in t.Partitions:
|
|
3445
3331
|
if p.SourceType != TOM.PartitionSourceType.M:
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
)
|
|
3449
|
-
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
|
+
|
|
3450
3334
|
elif i == 0:
|
|
3451
3335
|
text = p.Expression
|
|
3452
3336
|
text = text.rstrip()
|
|
@@ -3462,8 +3346,7 @@ class TOMWrapper:
|
|
|
3462
3346
|
|
|
3463
3347
|
print(text_before_last_match)
|
|
3464
3348
|
else:
|
|
3465
|
-
|
|
3466
|
-
return
|
|
3349
|
+
raise ValueError(f"{icons.red_dot} Invalid M-partition expression.")
|
|
3467
3350
|
|
|
3468
3351
|
endExpr = f'#"Filtered Rows IR" = Table.SelectRows({obj}, each [{column_name}] >= RangeStart and [{column_name}] <= RangeEnd)\n#"Filtered Rows IR"'
|
|
3469
3352
|
finalExpr = text_before_last_match + endExpr
|
|
@@ -3514,7 +3397,7 @@ class TOMWrapper:
|
|
|
3514
3397
|
max_parallelism: Optional[int] = 0,
|
|
3515
3398
|
):
|
|
3516
3399
|
"""
|
|
3517
|
-
Applies the incremental refresh policy for a table within a semantic model.
|
|
3400
|
+
`Applies the incremental refresh <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.table.applyrefreshpolicy?view=analysisservices-dotnet#microsoft-analysisservices-tabular-table-applyrefreshpolicy(system-boolean-system-int32)>`_ policy for a table within a semantic model.
|
|
3518
3401
|
|
|
3519
3402
|
Parameters
|
|
3520
3403
|
----------
|
|
@@ -3538,7 +3421,7 @@ class TOMWrapper:
|
|
|
3538
3421
|
self, table_name: str, partition_name: str, expression: str
|
|
3539
3422
|
):
|
|
3540
3423
|
"""
|
|
3541
|
-
Sets the data coverage definition for a partition.
|
|
3424
|
+
Sets the `data coverage definition <https://learn.microsoft.com/analysis-services/tom/table-partitions?view=asallproducts-allversions>`_ for a partition.
|
|
3542
3425
|
|
|
3543
3426
|
Parameters
|
|
3544
3427
|
----------
|
|
@@ -3559,15 +3442,9 @@ class TOMWrapper:
|
|
|
3559
3442
|
ht = self.is_hybrid_table(table_name=table_name)
|
|
3560
3443
|
|
|
3561
3444
|
if not ht:
|
|
3562
|
-
|
|
3563
|
-
f"The data coverage definition property is only applicable to hybrid tables. See the documentation: {doc}."
|
|
3564
|
-
)
|
|
3565
|
-
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}.")
|
|
3566
3446
|
if p.Mode != TOM.ModeType.DirectQuery:
|
|
3567
|
-
|
|
3568
|
-
f"The data coverage definition property is only applicable to the DirectQuery partition of a hybrid table. See the documentation: {doc}."
|
|
3569
|
-
)
|
|
3570
|
-
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}.")
|
|
3571
3448
|
|
|
3572
3449
|
dcd = TOM.DataCoverageDefinition()
|
|
3573
3450
|
dcd.Expression = expression
|
|
@@ -3575,7 +3452,7 @@ class TOMWrapper:
|
|
|
3575
3452
|
|
|
3576
3453
|
def set_encoding_hint(self, table_name: str, column_name: str, value: str):
|
|
3577
3454
|
"""
|
|
3578
|
-
Sets the encoding hint for a column.
|
|
3455
|
+
Sets the `encoding hint <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.tabular.encodinghinttype?view=analysisservices-dotnet>`_ for a column.
|
|
3579
3456
|
|
|
3580
3457
|
Parameters
|
|
3581
3458
|
----------
|
|
@@ -3594,10 +3471,7 @@ class TOMWrapper:
|
|
|
3594
3471
|
value = value.capitalize()
|
|
3595
3472
|
|
|
3596
3473
|
if value not in values:
|
|
3597
|
-
|
|
3598
|
-
f"{icons.red_dot} Invalid encoding hint value. Please choose from these options: {values}."
|
|
3599
|
-
)
|
|
3600
|
-
return
|
|
3474
|
+
raise ValueError(f"{icons.red_dot} Invalid encoding hint value. Please choose from these options: {values}.")
|
|
3601
3475
|
|
|
3602
3476
|
self.model.Tables[table_name].Columns[column_name].EncodingHint = (
|
|
3603
3477
|
System.Enum.Parse(TOM.EncodingHintType, value)
|
|
@@ -3605,7 +3479,7 @@ class TOMWrapper:
|
|
|
3605
3479
|
|
|
3606
3480
|
def set_data_type(self, table_name: str, column_name: str, value: str):
|
|
3607
3481
|
"""
|
|
3608
|
-
Sets the data type for a column.
|
|
3482
|
+
Sets the `data type <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.datatype?view=analysisservices-dotnet>`_ for a column.
|
|
3609
3483
|
|
|
3610
3484
|
Parameters
|
|
3611
3485
|
----------
|
|
@@ -3617,6 +3491,7 @@ class TOMWrapper:
|
|
|
3617
3491
|
The data type.
|
|
3618
3492
|
`Data type valid values <https://learn.microsoft.com/dotnet/api/microsoft.analysisservices.datatype?view=analysisservices-dotnet>`_
|
|
3619
3493
|
"""
|
|
3494
|
+
import Microsoft.AnalysisServices.Tabular as TOM
|
|
3620
3495
|
import System
|
|
3621
3496
|
|
|
3622
3497
|
values = [
|
|
@@ -3638,10 +3513,7 @@ class TOMWrapper:
|
|
|
3638
3513
|
value = "Boolean"
|
|
3639
3514
|
|
|
3640
3515
|
if value not in values:
|
|
3641
|
-
|
|
3642
|
-
f"{icons.red_dot} Invalid data type. Please choose from these options: {values}."
|
|
3643
|
-
)
|
|
3644
|
-
return
|
|
3516
|
+
raise ValueError(f"{icons.red_dot} Invalid data type. Please choose from these options: {values}.")
|
|
3645
3517
|
|
|
3646
3518
|
self.model.Tables[table_name].Columns[column_name].DataType = System.Enum.Parse(
|
|
3647
3519
|
TOM.DataType, value
|
|
@@ -3673,10 +3545,7 @@ class TOMWrapper:
|
|
|
3673
3545
|
for t in time_intel:
|
|
3674
3546
|
t = t.capitalize()
|
|
3675
3547
|
if t not in [time_intel_options]:
|
|
3676
|
-
|
|
3677
|
-
f"The '{t}' time intelligence variation is not supported. Valid options: {time_intel_options}."
|
|
3678
|
-
)
|
|
3679
|
-
return
|
|
3548
|
+
raise ValueError(f"{icons.red_dot} The '{t}' time intelligence variation is not supported. Valid options: {time_intel_options}.")
|
|
3680
3549
|
|
|
3681
3550
|
# Validate measure and extract table name
|
|
3682
3551
|
for m in self.all_measures():
|
|
@@ -3684,17 +3553,11 @@ class TOMWrapper:
|
|
|
3684
3553
|
table_name = m.Parent.Name
|
|
3685
3554
|
|
|
3686
3555
|
if table_name is None:
|
|
3687
|
-
|
|
3688
|
-
f"The '{measure_name}' is not a valid measure in the '{self.dataset}' semantic model within the '{self.workspace}' workspace."
|
|
3689
|
-
)
|
|
3690
|
-
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.")
|
|
3691
3557
|
|
|
3692
3558
|
# Validate date table
|
|
3693
3559
|
if not self.is_date_table(date_table):
|
|
3694
|
-
|
|
3695
|
-
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."
|
|
3696
|
-
)
|
|
3697
|
-
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.")
|
|
3698
3561
|
|
|
3699
3562
|
# Extract date key from date table
|
|
3700
3563
|
for c in self.all_columns():
|
|
@@ -3712,26 +3575,100 @@ class TOMWrapper:
|
|
|
3712
3575
|
expression=expr,
|
|
3713
3576
|
)
|
|
3714
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
|
+
|
|
3715
3652
|
def close(self):
|
|
3716
|
-
if not self.
|
|
3653
|
+
if not self._readonly and self.model is not None:
|
|
3717
3654
|
self.model.SaveChanges()
|
|
3718
3655
|
|
|
3719
|
-
if len(self.
|
|
3656
|
+
if len(self._tables_added) > 0:
|
|
3720
3657
|
refresh_semantic_model(
|
|
3721
|
-
dataset=self.
|
|
3722
|
-
tables=self.
|
|
3723
|
-
workspace=self.
|
|
3658
|
+
dataset=self._dataset,
|
|
3659
|
+
tables=self._tables_added,
|
|
3660
|
+
workspace=self._workspace,
|
|
3724
3661
|
)
|
|
3725
3662
|
self.model = None
|
|
3726
3663
|
|
|
3727
|
-
self.
|
|
3664
|
+
self._tom_server.Dispose()
|
|
3728
3665
|
|
|
3729
3666
|
|
|
3730
3667
|
@log
|
|
3731
3668
|
@contextmanager
|
|
3732
3669
|
def connect_semantic_model(
|
|
3733
3670
|
dataset: str, readonly: bool = True, workspace: Optional[str] = None
|
|
3734
|
-
):
|
|
3671
|
+
) -> Iterator[TOMWrapper]:
|
|
3735
3672
|
"""
|
|
3736
3673
|
Connects to the Tabular Object Model (TOM) within a semantic model.
|
|
3737
3674
|
|
|
@@ -3748,7 +3685,7 @@ def connect_semantic_model(
|
|
|
3748
3685
|
|
|
3749
3686
|
Returns
|
|
3750
3687
|
-------
|
|
3751
|
-
|
|
3688
|
+
typing.Iterator[TOMWrapper]
|
|
3752
3689
|
A connection to the semantic model's Tabular Object Model.
|
|
3753
3690
|
"""
|
|
3754
3691
|
|
|
@@ -3763,4 +3700,4 @@ def connect_semantic_model(
|
|
|
3763
3700
|
try:
|
|
3764
3701
|
yield tw
|
|
3765
3702
|
finally:
|
|
3766
|
-
tw.close()
|
|
3703
|
+
tw.close()
|