semantic-link-labs 0.5.0__py3-none-any.whl → 0.7.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.7.0.dist-info/METADATA +148 -0
- semantic_link_labs-0.7.0.dist-info/RECORD +111 -0
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +45 -15
- sempy_labs/_ai.py +42 -85
- sempy_labs/_bpa_translation/_translations_am-ET.po +828 -0
- sempy_labs/_bpa_translation/_translations_ar-AE.po +860 -0
- sempy_labs/_bpa_translation/_translations_cs-CZ.po +894 -0
- sempy_labs/_bpa_translation/_translations_da-DK.po +894 -0
- sempy_labs/_bpa_translation/_translations_de-DE.po +933 -0
- sempy_labs/_bpa_translation/_translations_el-GR.po +936 -0
- sempy_labs/_bpa_translation/_translations_es-ES.po +915 -0
- sempy_labs/_bpa_translation/_translations_fa-IR.po +883 -0
- sempy_labs/_bpa_translation/_translations_fr-FR.po +938 -0
- sempy_labs/_bpa_translation/_translations_ga-IE.po +912 -0
- sempy_labs/_bpa_translation/_translations_he-IL.po +855 -0
- sempy_labs/_bpa_translation/_translations_hi-IN.po +892 -0
- sempy_labs/_bpa_translation/_translations_hu-HU.po +910 -0
- sempy_labs/_bpa_translation/_translations_is-IS.po +887 -0
- sempy_labs/_bpa_translation/_translations_it-IT.po +931 -0
- sempy_labs/_bpa_translation/_translations_ja-JP.po +805 -0
- sempy_labs/_bpa_translation/_translations_nl-NL.po +924 -0
- sempy_labs/_bpa_translation/_translations_pl-PL.po +913 -0
- sempy_labs/_bpa_translation/_translations_pt-BR.po +909 -0
- sempy_labs/_bpa_translation/_translations_pt-PT.po +904 -0
- sempy_labs/_bpa_translation/_translations_ru-RU.po +909 -0
- sempy_labs/_bpa_translation/_translations_ta-IN.po +922 -0
- sempy_labs/_bpa_translation/_translations_te-IN.po +896 -0
- sempy_labs/_bpa_translation/_translations_th-TH.po +873 -0
- sempy_labs/_bpa_translation/_translations_zh-CN.po +767 -0
- sempy_labs/_bpa_translation/_translations_zu-ZA.po +916 -0
- sempy_labs/_clear_cache.py +12 -8
- sempy_labs/_connections.py +77 -70
- sempy_labs/_dax.py +7 -9
- sempy_labs/_generate_semantic_model.py +75 -90
- sempy_labs/_helper_functions.py +371 -20
- sempy_labs/_icons.py +23 -0
- sempy_labs/_list_functions.py +855 -427
- sempy_labs/_model_auto_build.py +4 -3
- sempy_labs/_model_bpa.py +307 -1118
- sempy_labs/_model_bpa_bulk.py +363 -0
- sempy_labs/_model_bpa_rules.py +831 -0
- sempy_labs/_model_dependencies.py +20 -16
- sempy_labs/_one_lake_integration.py +18 -12
- sempy_labs/_query_scale_out.py +116 -129
- sempy_labs/_refresh_semantic_model.py +23 -10
- sempy_labs/_translations.py +367 -288
- sempy_labs/_vertipaq.py +152 -123
- sempy_labs/directlake/__init__.py +7 -1
- sempy_labs/directlake/_directlake_schema_compare.py +33 -30
- sempy_labs/directlake/_directlake_schema_sync.py +60 -77
- sempy_labs/directlake/_dl_helper.py +233 -0
- sempy_labs/directlake/_get_directlake_lakehouse.py +7 -8
- sempy_labs/directlake/_get_shared_expression.py +5 -3
- sempy_labs/directlake/_guardrails.py +20 -16
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +17 -10
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +3 -2
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +10 -5
- sempy_labs/directlake/_update_directlake_partition_entity.py +169 -22
- sempy_labs/directlake/_warm_cache.py +7 -4
- sempy_labs/lakehouse/_get_lakehouse_columns.py +1 -1
- sempy_labs/lakehouse/_get_lakehouse_tables.py +65 -71
- sempy_labs/lakehouse/_lakehouse.py +5 -3
- sempy_labs/lakehouse/_shortcuts.py +20 -13
- sempy_labs/migration/__init__.py +1 -1
- sempy_labs/migration/_create_pqt_file.py +184 -186
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +240 -269
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py +78 -77
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +444 -425
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +96 -102
- sempy_labs/migration/_migration_validation.py +2 -2
- sempy_labs/migration/_refresh_calc_tables.py +94 -100
- sempy_labs/report/_BPAReportTemplate.json +232 -0
- sempy_labs/report/__init__.py +6 -2
- sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
- sempy_labs/report/_bpareporttemplate/.platform +11 -0
- sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
- sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
- sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
- sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
- sempy_labs/report/_generate_report.py +260 -139
- sempy_labs/report/_report_functions.py +90 -59
- sempy_labs/report/_report_rebind.py +40 -34
- sempy_labs/tom/__init__.py +1 -4
- sempy_labs/tom/_model.py +601 -181
- semantic_link_labs-0.5.0.dist-info/METADATA +0 -22
- semantic_link_labs-0.5.0.dist-info/RECORD +0 -53
- sempy_labs/directlake/_fallback.py +0 -58
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.5.0.dist-info → semantic_link_labs-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import sempy
|
|
2
2
|
import sempy.fabric as fabric
|
|
3
|
-
import re
|
|
3
|
+
import re
|
|
4
4
|
from sempy_labs._list_functions import list_tables
|
|
5
|
-
from sempy_labs._helper_functions import
|
|
5
|
+
from sempy_labs._helper_functions import (
|
|
6
|
+
create_relationship_name,
|
|
7
|
+
retry,
|
|
8
|
+
format_dax_object_name,
|
|
9
|
+
)
|
|
6
10
|
from sempy_labs.tom import connect_semantic_model
|
|
7
11
|
from typing import Optional
|
|
8
12
|
from sempy._utils._log import log
|
|
9
13
|
import sempy_labs._icons as icons
|
|
10
14
|
|
|
15
|
+
|
|
11
16
|
@log
|
|
12
17
|
def migrate_model_objects_to_semantic_model(
|
|
13
18
|
dataset: str,
|
|
@@ -46,7 +51,6 @@ def migrate_model_objects_to_semantic_model(
|
|
|
46
51
|
dfT = list_tables(dataset, workspace)
|
|
47
52
|
dfC = fabric.list_columns(dataset=dataset, workspace=workspace)
|
|
48
53
|
dfM = fabric.list_measures(dataset=dataset, workspace=workspace)
|
|
49
|
-
dfR = fabric.list_relationships(dataset=dataset, workspace=workspace)
|
|
50
54
|
dfRole = fabric.get_roles(dataset=dataset, workspace=workspace)
|
|
51
55
|
dfRLS = fabric.get_row_level_security_permissions(
|
|
52
56
|
dataset=dataset, workspace=workspace
|
|
@@ -59,461 +63,476 @@ def migrate_model_objects_to_semantic_model(
|
|
|
59
63
|
|
|
60
64
|
dfP_cc = dfPar[(dfPar["Source Type"] == "Calculated")]
|
|
61
65
|
dfP_fp = dfP_cc[dfP_cc["Query"].str.contains("NAMEOF")]
|
|
62
|
-
dfC_fp = dfC[dfC["Table Name"].isin(dfP_fp["Table Name"].values)]
|
|
63
66
|
|
|
64
67
|
print(f"{icons.in_progress} Updating '{new_dataset}' based on '{dataset}'...")
|
|
65
|
-
start_time = datetime.datetime.now()
|
|
66
|
-
timeout = datetime.timedelta(minutes=1)
|
|
67
|
-
success = False
|
|
68
|
-
|
|
69
|
-
while not success:
|
|
70
|
-
try:
|
|
71
|
-
with connect_semantic_model(
|
|
72
|
-
dataset=new_dataset, readonly=False, workspace=new_dataset_workspace
|
|
73
|
-
) as tom:
|
|
74
|
-
success = True
|
|
75
|
-
|
|
76
|
-
isDirectLake = any(
|
|
77
|
-
str(p.Mode) == "DirectLake"
|
|
78
|
-
for t in tom.model.Tables
|
|
79
|
-
for p in t.Partitions
|
|
80
|
-
)
|
|
81
68
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
].iloc[0]
|
|
69
|
+
@retry(
|
|
70
|
+
sleep_time=1,
|
|
71
|
+
timeout_error_message=f"{icons.red_dot} Function timed out after 1 minute",
|
|
72
|
+
)
|
|
73
|
+
def dyn_connect():
|
|
74
|
+
with connect_semantic_model(
|
|
75
|
+
dataset=new_dataset, readonly=True, workspace=new_dataset_workspace
|
|
76
|
+
) as tom:
|
|
91
77
|
|
|
92
|
-
|
|
93
|
-
f"{icons.green_dot} The '{t.Name}' table's properties have been updated."
|
|
94
|
-
)
|
|
78
|
+
tom.model
|
|
95
79
|
|
|
96
|
-
|
|
97
|
-
for t in tom.model.Tables:
|
|
98
|
-
if (
|
|
99
|
-
t.Name not in dfP_fp["Table Name"].values
|
|
100
|
-
): # do not include field parameters
|
|
101
|
-
dfT_filtered = dfT[dfT["Name"] == t.Name]
|
|
102
|
-
tType = dfT_filtered["Type"].iloc[0]
|
|
103
|
-
for c in t.Columns:
|
|
104
|
-
if not c.Name.startswith("RowNumber-"):
|
|
105
|
-
dfC_filt = dfC[
|
|
106
|
-
(dfC["Table Name"] == t.Name)
|
|
107
|
-
& (dfC["Column Name"] == c.Name)
|
|
108
|
-
]
|
|
109
|
-
cName = dfC_filt["Column Name"].iloc[0]
|
|
110
|
-
c.Name = cName
|
|
111
|
-
if tType == "Table":
|
|
112
|
-
c.SourceColumn = cName.replace(" ", "_")
|
|
113
|
-
c.IsHidden = bool(dfC_filt["Hidden"].iloc[0])
|
|
114
|
-
c.DataType = System.Enum.Parse(
|
|
115
|
-
TOM.DataType, dfC_filt["Data Type"].iloc[0]
|
|
116
|
-
)
|
|
117
|
-
c.DisplayFolder = dfC_filt["Display Folder"].iloc[0]
|
|
118
|
-
c.FormatString = dfC_filt["Format String"].iloc[0]
|
|
119
|
-
c.SummarizeBy = System.Enum.Parse(
|
|
120
|
-
TOM.AggregateFunction,
|
|
121
|
-
dfC_filt["Summarize By"].iloc[0],
|
|
122
|
-
)
|
|
123
|
-
c.DataCategory = dfC_filt["Data Category"].iloc[0]
|
|
124
|
-
c.IsKey = bool(dfC_filt["Key"].iloc[0])
|
|
125
|
-
sbc = dfC_filt["Sort By Column"].iloc[0]
|
|
126
|
-
|
|
127
|
-
if sbc != None:
|
|
128
|
-
try:
|
|
129
|
-
c.SortByColumn = tom.model.Tables[
|
|
130
|
-
t.Name
|
|
131
|
-
].Columns[sbc]
|
|
132
|
-
except:
|
|
133
|
-
print(
|
|
134
|
-
f"{icons.red_dot} Failed to create '{sbc}' as a Sort By Column for the '{c.Name}' in the '{t.Name}' table."
|
|
135
|
-
)
|
|
136
|
-
print(
|
|
137
|
-
f"{icons.green_dot} The '{t.Name}'[{c.Name}] column's properties have been updated."
|
|
138
|
-
)
|
|
80
|
+
dyn_connect()
|
|
139
81
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
82
|
+
@retry(
|
|
83
|
+
sleep_time=1,
|
|
84
|
+
timeout_error_message=f"{icons.red_dot} Function timed out after 1 minute",
|
|
85
|
+
)
|
|
86
|
+
def dyn_connect2():
|
|
87
|
+
with connect_semantic_model(
|
|
88
|
+
dataset=dataset, readonly=True, workspace=workspace
|
|
89
|
+
) as tom:
|
|
90
|
+
|
|
91
|
+
tom.model
|
|
92
|
+
|
|
93
|
+
dyn_connect2()
|
|
94
|
+
|
|
95
|
+
with connect_semantic_model(
|
|
96
|
+
dataset=new_dataset, readonly=False, workspace=new_dataset_workspace
|
|
97
|
+
) as tom:
|
|
98
|
+
|
|
99
|
+
isDirectLake = tom.is_direct_lake()
|
|
100
|
+
|
|
101
|
+
print(f"\n{icons.in_progress} Updating table properties...")
|
|
102
|
+
for t in tom.model.Tables:
|
|
103
|
+
t.IsHidden = bool(dfT.loc[dfT["Name"] == t.Name, "Hidden"].iloc[0])
|
|
104
|
+
t.Description = dfT.loc[dfT["Name"] == t.Name, "Description"].iloc[0]
|
|
105
|
+
t.DataCategory = dfT.loc[dfT["Name"] == t.Name, "Data Category"].iloc[0]
|
|
106
|
+
|
|
107
|
+
print(
|
|
108
|
+
f"{icons.green_dot} The '{t.Name}' table's properties have been updated."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
print(f"\n{icons.in_progress} Updating column properties...")
|
|
112
|
+
for t in tom.model.Tables:
|
|
113
|
+
if (
|
|
114
|
+
t.Name not in dfP_fp["Table Name"].values
|
|
115
|
+
): # do not include field parameters
|
|
116
|
+
dfT_filtered = dfT[dfT["Name"] == t.Name]
|
|
117
|
+
tType = dfT_filtered["Type"].iloc[0]
|
|
118
|
+
for c in t.Columns:
|
|
119
|
+
if not c.Name.startswith("RowNumber-"):
|
|
120
|
+
dfC_filt = dfC[
|
|
121
|
+
(dfC["Table Name"] == t.Name)
|
|
122
|
+
& (dfC["Column Name"] == c.Name)
|
|
148
123
|
]
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
hName = r["Hierarchy Name"]
|
|
157
|
-
hDesc = r["Hierarchy Description"]
|
|
158
|
-
hHid = bool(r["Hierarchy Hidden"])
|
|
159
|
-
cols = r["Column Name"]
|
|
160
|
-
lvls = r["Level Name"]
|
|
161
|
-
|
|
162
|
-
try:
|
|
163
|
-
tom.model.Tables[tName].Hierarchies[hName]
|
|
164
|
-
except:
|
|
165
|
-
tom.add_hierarchy(
|
|
166
|
-
table_name=tName,
|
|
167
|
-
hierarchy_name=hName,
|
|
168
|
-
hierarchy_description=hDesc,
|
|
169
|
-
hierarchy_hidden=hHid,
|
|
170
|
-
columns=cols,
|
|
171
|
-
levels=lvls,
|
|
124
|
+
cName = dfC_filt["Column Name"].iloc[0]
|
|
125
|
+
c.Name = cName
|
|
126
|
+
# if tType == "Table":
|
|
127
|
+
# c.SourceColumn = cName.replace(" ", "_")
|
|
128
|
+
c.IsHidden = bool(dfC_filt["Hidden"].iloc[0])
|
|
129
|
+
c.DataType = System.Enum.Parse(
|
|
130
|
+
TOM.DataType, dfC_filt["Data Type"].iloc[0]
|
|
172
131
|
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for i, r in dfM.iterrows():
|
|
179
|
-
tName = r["Table Name"]
|
|
180
|
-
mName = r["Measure Name"]
|
|
181
|
-
mExpr = r["Measure Expression"]
|
|
182
|
-
mHidden = bool(r["Measure Hidden"])
|
|
183
|
-
mDF = r["Measure Display Folder"]
|
|
184
|
-
mDesc = r["Measure Description"]
|
|
185
|
-
mFS = r["Format String"]
|
|
186
|
-
|
|
187
|
-
try:
|
|
188
|
-
tom.model.Tables[tName].Measures[mName]
|
|
189
|
-
except:
|
|
190
|
-
tom.add_measure(
|
|
191
|
-
table_name=tName,
|
|
192
|
-
measure_name=mName,
|
|
193
|
-
expression=mExpr,
|
|
194
|
-
hidden=mHidden,
|
|
195
|
-
display_folder=mDF,
|
|
196
|
-
description=mDesc,
|
|
197
|
-
format_string=mFS,
|
|
132
|
+
c.DisplayFolder = dfC_filt["Display Folder"].iloc[0]
|
|
133
|
+
c.FormatString = dfC_filt["Format String"].iloc[0]
|
|
134
|
+
c.SummarizeBy = System.Enum.Parse(
|
|
135
|
+
TOM.AggregateFunction,
|
|
136
|
+
dfC_filt["Summarize By"].iloc[0],
|
|
198
137
|
)
|
|
138
|
+
c.DataCategory = dfC_filt["Data Category"].iloc[0]
|
|
139
|
+
c.IsKey = bool(dfC_filt["Key"].iloc[0])
|
|
140
|
+
sbc = dfC_filt["Sort By Column"].iloc[0]
|
|
141
|
+
|
|
142
|
+
if sbc is not None:
|
|
143
|
+
if any(
|
|
144
|
+
o.Name == sbc and o.Parent.Name == c.Parent.Name
|
|
145
|
+
for o in tom.all_columns()
|
|
146
|
+
):
|
|
147
|
+
c.SortByColumn = tom.model.Tables[t.Name].Columns[sbc]
|
|
148
|
+
else:
|
|
149
|
+
print(
|
|
150
|
+
f"{icons.red_dot} Failed to create '{sbc}' as a Sort By Column for the '{c.Name}' in the '{t.Name}' table."
|
|
151
|
+
)
|
|
199
152
|
print(
|
|
200
|
-
f"{icons.green_dot} The '{
|
|
153
|
+
f"{icons.green_dot} The '{t.Name}'[{c.Name}] column's properties have been updated."
|
|
201
154
|
)
|
|
202
155
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
156
|
+
print(f"\n{icons.in_progress} Creating hierarchies...")
|
|
157
|
+
dfH_grouped = (
|
|
158
|
+
dfH.groupby(
|
|
159
|
+
[
|
|
160
|
+
"Table Name",
|
|
161
|
+
"Hierarchy Name",
|
|
162
|
+
"Hierarchy Hidden",
|
|
163
|
+
"Hierarchy Description",
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
.agg({"Level Name": list, "Column Name": list})
|
|
167
|
+
.reset_index()
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
for i, r in dfH_grouped.iterrows():
|
|
171
|
+
tName = r["Table Name"]
|
|
172
|
+
hName = r["Hierarchy Name"]
|
|
173
|
+
hDesc = r["Hierarchy Description"]
|
|
174
|
+
hHid = bool(r["Hierarchy Hidden"])
|
|
175
|
+
cols = r["Column Name"]
|
|
176
|
+
lvls = r["Level Name"]
|
|
177
|
+
|
|
178
|
+
missing_columns = []
|
|
179
|
+
for col in cols:
|
|
180
|
+
if not any(
|
|
181
|
+
c.Name == col
|
|
182
|
+
for t in tom.model.Tables
|
|
183
|
+
if t.Name == tName
|
|
184
|
+
for c in t.Columns
|
|
185
|
+
):
|
|
186
|
+
missing_columns.append(col)
|
|
187
|
+
|
|
188
|
+
if any(
|
|
189
|
+
t.Name == tName and h.Name == hName
|
|
190
|
+
for t in tom.model.Tables
|
|
191
|
+
for h in t.Hierarchies
|
|
192
|
+
):
|
|
193
|
+
print(
|
|
194
|
+
f"{icons.warning} The '{hName}' hierarchy within the '{tName}' table already exists."
|
|
195
|
+
)
|
|
196
|
+
elif len(missing_columns) > 0:
|
|
197
|
+
print(
|
|
198
|
+
f"{icons.red_dot} The '{hName}' hierarchy within the '{tName}' table cannot be created as the {missing_columns} column)s) do not exist."
|
|
199
|
+
)
|
|
200
|
+
else:
|
|
201
|
+
tom.add_hierarchy(
|
|
202
|
+
table_name=tName,
|
|
203
|
+
hierarchy_name=hName,
|
|
204
|
+
hierarchy_description=hDesc,
|
|
205
|
+
hierarchy_hidden=hHid,
|
|
206
|
+
columns=cols,
|
|
207
|
+
levels=lvls,
|
|
208
|
+
)
|
|
209
|
+
print(f"{icons.green_dot} The '{hName}' hierarchy has been added.")
|
|
210
|
+
|
|
211
|
+
print(f"\n{icons.in_progress} Creating measures...")
|
|
212
|
+
for i, r in dfM.iterrows():
|
|
213
|
+
tName = r["Table Name"]
|
|
214
|
+
mName = r["Measure Name"]
|
|
215
|
+
mExpr = r["Measure Expression"]
|
|
216
|
+
mHidden = bool(r["Measure Hidden"])
|
|
217
|
+
mDF = r["Measure Display Folder"]
|
|
218
|
+
mDesc = r["Measure Description"]
|
|
219
|
+
mFS = r["Format String"]
|
|
220
|
+
|
|
221
|
+
if not any(m.Name == mName for m in tom.all_measures()):
|
|
222
|
+
tom.add_measure(
|
|
223
|
+
table_name=tName,
|
|
224
|
+
measure_name=mName,
|
|
225
|
+
expression=mExpr,
|
|
226
|
+
hidden=mHidden,
|
|
227
|
+
display_folder=mDF,
|
|
228
|
+
description=mDesc,
|
|
229
|
+
format_string=mFS,
|
|
230
|
+
)
|
|
231
|
+
print(f"{icons.green_dot} The '{mName}' measure has been added.")
|
|
232
|
+
print(f"\n{icons.in_progress} Creating calculation groups...")
|
|
233
|
+
for cgName in dfCI["Calculation Group Name"].unique():
|
|
234
|
+
|
|
235
|
+
isHidden = bool(
|
|
236
|
+
dfCI.loc[(dfCI["Calculation Group Name"] == cgName), "Hidden"].iloc[0]
|
|
237
|
+
)
|
|
238
|
+
prec = int(
|
|
239
|
+
dfCI.loc[(dfCI["Calculation Group Name"] == cgName), "Precedence"].iloc[
|
|
240
|
+
0
|
|
241
|
+
]
|
|
242
|
+
)
|
|
243
|
+
desc = dfCI.loc[
|
|
244
|
+
(dfCI["Calculation Group Name"] == cgName), "Description"
|
|
245
|
+
].iloc[0]
|
|
246
|
+
|
|
247
|
+
if not any(t.Name == cgName for t in tom.model.Tables):
|
|
248
|
+
tom.add_calculation_group(
|
|
249
|
+
name=cgName,
|
|
250
|
+
description=desc,
|
|
251
|
+
precedence=prec,
|
|
252
|
+
hidden=isHidden,
|
|
253
|
+
)
|
|
254
|
+
print(
|
|
255
|
+
f"{icons.green_dot} The '{cgName}' calculation group has been added."
|
|
256
|
+
)
|
|
257
|
+
tom.model.DiscourageImplicitMeasures = True
|
|
258
|
+
|
|
259
|
+
# print(
|
|
260
|
+
# f"\n{icons.in_progress} Updating calculation group column names..."
|
|
261
|
+
# )
|
|
262
|
+
dfC_filt = dfC[(dfC["Table Name"] == cgName) & (dfC["Hidden"] == False)]
|
|
263
|
+
colName = dfC_filt["Column Name"].iloc[0]
|
|
264
|
+
tom.model.Tables[cgName].Columns["Name"].Name = colName
|
|
265
|
+
|
|
266
|
+
calcItems = dfCI.loc[
|
|
267
|
+
dfCI["Calculation Group Name"] == cgName,
|
|
268
|
+
"Calculation Item Name",
|
|
269
|
+
].unique()
|
|
270
|
+
|
|
271
|
+
print(f"\n{icons.in_progress} Creating calculation items...")
|
|
272
|
+
for calcItem in calcItems:
|
|
273
|
+
ordinal = int(
|
|
274
|
+
dfCI.loc[
|
|
275
|
+
(dfCI["Calculation Group Name"] == cgName)
|
|
276
|
+
& (dfCI["Calculation Item Name"] == calcItem),
|
|
277
|
+
"Ordinal",
|
|
278
|
+
].iloc[0]
|
|
279
|
+
)
|
|
280
|
+
expr = dfCI.loc[
|
|
281
|
+
(dfCI["Calculation Group Name"] == cgName)
|
|
282
|
+
& (dfCI["Calculation Item Name"] == calcItem),
|
|
283
|
+
"Expression",
|
|
284
|
+
].iloc[0]
|
|
285
|
+
fse = dfCI.loc[
|
|
286
|
+
(dfCI["Calculation Group Name"] == cgName)
|
|
287
|
+
& (dfCI["Calculation Item Name"] == calcItem),
|
|
288
|
+
"Format String Expression",
|
|
289
|
+
].iloc[0]
|
|
290
|
+
|
|
291
|
+
if not any(
|
|
292
|
+
ci.CalculationGroup.Parent.Name == cgName and ci.Name == calcItem
|
|
293
|
+
for ci in tom.all_calculation_items()
|
|
294
|
+
):
|
|
295
|
+
tom.add_calculation_item(
|
|
296
|
+
table_name=cgName,
|
|
297
|
+
calculation_item_name=calcItem,
|
|
298
|
+
expression=expr,
|
|
299
|
+
format_string_expression=fse,
|
|
300
|
+
ordinal=ordinal,
|
|
209
301
|
)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
(dfCI["Calculation Group Name"] == cgName), "Precedence"
|
|
213
|
-
].iloc[0]
|
|
302
|
+
print(
|
|
303
|
+
f"{icons.green_dot} The '{calcItem}' has been added to the '{cgName}' calculation group."
|
|
214
304
|
)
|
|
215
|
-
desc = dfCI.loc[
|
|
216
|
-
(dfCI["Calculation Group Name"] == cgName), "Description"
|
|
217
|
-
].iloc[0]
|
|
218
305
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
name=cgName,
|
|
224
|
-
description=desc,
|
|
225
|
-
precedence=prec,
|
|
226
|
-
hidden=isHidden,
|
|
227
|
-
)
|
|
228
|
-
print(
|
|
229
|
-
f"{icons.green_dot} The '{cgName}' calculation group has been added."
|
|
230
|
-
)
|
|
231
|
-
tom.model.DiscourageImplicitMeasures = True
|
|
306
|
+
print(f"\n{icons.in_progress} Creating relationships...")
|
|
307
|
+
with connect_semantic_model(
|
|
308
|
+
dataset=dataset, readonly=True, workspace=workspace
|
|
309
|
+
) as tom_old:
|
|
232
310
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
for calcItem in calcItems:
|
|
249
|
-
ordinal = int(
|
|
250
|
-
dfCI.loc[
|
|
251
|
-
(dfCI["Calculation Group Name"] == cgName)
|
|
252
|
-
& (dfCI["Calculation Item Name"] == calcItem),
|
|
253
|
-
"Ordinal",
|
|
254
|
-
].iloc[0]
|
|
255
|
-
)
|
|
256
|
-
expr = dfCI.loc[
|
|
257
|
-
(dfCI["Calculation Group Name"] == cgName)
|
|
258
|
-
& (dfCI["Calculation Item Name"] == calcItem),
|
|
259
|
-
"Expression",
|
|
260
|
-
].iloc[0]
|
|
261
|
-
fse = dfCI.loc[
|
|
262
|
-
(dfCI["Calculation Group Name"] == cgName)
|
|
263
|
-
& (dfCI["Calculation Item Name"] == calcItem),
|
|
264
|
-
"Format String Expression",
|
|
265
|
-
].iloc[0]
|
|
266
|
-
try:
|
|
267
|
-
tom.model.Tables[cgName].CalculationGroup.CalculationItems[
|
|
268
|
-
calcItem
|
|
269
|
-
]
|
|
270
|
-
except:
|
|
271
|
-
tom.add_calculation_item(
|
|
272
|
-
table_name=cgName,
|
|
273
|
-
calculation_item_name=calcItem,
|
|
274
|
-
expression=expr,
|
|
275
|
-
format_string_expression=fse,
|
|
276
|
-
ordinal=ordinal,
|
|
277
|
-
)
|
|
278
|
-
print(
|
|
279
|
-
f"{icons.green_dot} The '{calcItem}' has been added to the '{cgName}' calculation group."
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
print(f"\n{icons.in_progress} Creating relationships...")
|
|
283
|
-
for index, row in dfR.iterrows():
|
|
284
|
-
fromTable = row["From Table"]
|
|
285
|
-
fromColumn = row["From Column"]
|
|
286
|
-
toTable = row["To Table"]
|
|
287
|
-
toColumn = row["To Column"]
|
|
288
|
-
isActive = row["Active"]
|
|
289
|
-
cfb = row["Cross Filtering Behavior"]
|
|
290
|
-
sfb = row["Security Filtering Behavior"]
|
|
291
|
-
rori = row["Rely On Referential Integrity"]
|
|
292
|
-
mult = row["Multiplicity"]
|
|
293
|
-
|
|
294
|
-
card_mapping = {"m": "Many", "1": "One", "0": "None"}
|
|
295
|
-
|
|
296
|
-
fromCard = card_mapping.get(mult[0])
|
|
297
|
-
toCard = card_mapping.get(mult[-1])
|
|
298
|
-
|
|
299
|
-
relName = create_relationship_name(
|
|
300
|
-
fromTable, fromColumn, toTable, toColumn
|
|
311
|
+
for r in tom_old.model.Relationships:
|
|
312
|
+
relName = create_relationship_name(
|
|
313
|
+
r.FromTable.Name, r.FromColumn.Name, r.ToTable.Name, r.ToColumn.Name
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
# Relationship already exists
|
|
317
|
+
if any(
|
|
318
|
+
rel.FromTable.Name == r.FromTable.Name
|
|
319
|
+
and rel.FromColumn.Name == r.FromColumn.Name
|
|
320
|
+
and rel.ToTable.Name == r.ToTable.Name
|
|
321
|
+
and rel.ToColumn.Name == r.ToColumn.Name
|
|
322
|
+
for rel in tom.model.Relationships
|
|
323
|
+
):
|
|
324
|
+
print(
|
|
325
|
+
f"{icons.warning} The {relName} relationship was not created as it already exists in the '{new_dataset}' semantic model within the '{new_dataset_workspace}' workspace."
|
|
301
326
|
)
|
|
302
327
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
328
|
+
# Direct Lake with incompatible column data types
|
|
329
|
+
elif isDirectLake and r.FromColumn.DataType != r.ToColumn.DataType:
|
|
330
|
+
print(
|
|
331
|
+
f"{icons.warning} The {relName} relationship was not created as Direct Lake does not support relationships based on columns with different data types."
|
|
332
|
+
)
|
|
333
|
+
# Direct Lake using DateTime columns
|
|
334
|
+
elif isDirectLake and (
|
|
335
|
+
r.FromColumn.DataType == TOM.DataType.DateTime
|
|
336
|
+
or r.ToColumn.DataType == TOM.DataType.DateTime
|
|
337
|
+
):
|
|
338
|
+
print(
|
|
339
|
+
f"{icons.red_dot} The {relName} relationship was not created as Direct Lake does not support relationships based on columns of DateTime data type."
|
|
340
|
+
)
|
|
341
|
+
# Columns do not exist in the new semantic model
|
|
342
|
+
elif not any(
|
|
343
|
+
c.Name == r.FromColumn.Name and c.Parent.Name == r.FromTable.Name
|
|
344
|
+
for c in tom.all_columns()
|
|
345
|
+
) or not any(
|
|
346
|
+
c.Name == r.ToColumn.Name and c.Parent.Name == r.ToTable.Name
|
|
347
|
+
for c in tom.all_columns()
|
|
348
|
+
):
|
|
349
|
+
# Direct lake and based on calculated column
|
|
350
|
+
if isDirectLake and (
|
|
351
|
+
any(
|
|
352
|
+
c.Name == r.FromColumn.Name
|
|
353
|
+
and c.Parent.Name == r.FromTable.Name
|
|
354
|
+
for c in tom_old.all_calculated_columns()
|
|
312
355
|
)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
and r.ToColumn.Name == toColumn
|
|
318
|
-
and (
|
|
319
|
-
r.FromColumn.DataType == "DateTime"
|
|
320
|
-
or r.ToColumn.DataType == "DateTime"
|
|
356
|
+
or any(
|
|
357
|
+
c.Name == r.ToColumn.Name
|
|
358
|
+
and c.Parent.Name == r.ToTable.Name
|
|
359
|
+
for c in tom_old.all_calculated_columns()
|
|
321
360
|
)
|
|
322
|
-
for r in tom.model.Relationships
|
|
323
361
|
):
|
|
324
362
|
print(
|
|
325
|
-
f"{icons.
|
|
363
|
+
f"{icons.red_dot} The {relName} relationship was not created as the necssary column(s) do not exist. This is due to Direct Lake not supporting calculated columns."
|
|
326
364
|
)
|
|
327
|
-
elif
|
|
328
|
-
|
|
329
|
-
and
|
|
330
|
-
|
|
331
|
-
and r.ToColumn.Name == toColumn
|
|
332
|
-
and (r.FromColumn.DataType != r.ToColumn.DataType)
|
|
333
|
-
for r in tom.model.Relationships
|
|
365
|
+
elif not any(
|
|
366
|
+
c.Name == r.FromColumn.Name
|
|
367
|
+
and c.Parent.Name == r.FromTable.Name
|
|
368
|
+
for c in tom.all_columns()
|
|
334
369
|
):
|
|
335
370
|
print(
|
|
336
|
-
f"{icons.
|
|
337
|
-
)
|
|
338
|
-
else:
|
|
339
|
-
try:
|
|
340
|
-
tom.add_relationship(
|
|
341
|
-
from_table=fromTable,
|
|
342
|
-
from_column=fromColumn,
|
|
343
|
-
to_table=toTable,
|
|
344
|
-
to_column=toColumn,
|
|
345
|
-
from_cardinality=fromCard,
|
|
346
|
-
to_cardinality=toCard,
|
|
347
|
-
cross_filtering_behavior=cfb,
|
|
348
|
-
security_filtering_behavior=sfb,
|
|
349
|
-
rely_on_referential_integrity=rori,
|
|
350
|
-
is_active=isActive,
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
print(
|
|
354
|
-
f"{icons.green_dot} The {relName} relationship has been added."
|
|
355
|
-
)
|
|
356
|
-
except:
|
|
357
|
-
print(
|
|
358
|
-
f"{icons.red_dot} The {relName} relationship was not added."
|
|
359
|
-
)
|
|
360
|
-
|
|
361
|
-
print(f"\n{icons.in_progress} Creating roles...")
|
|
362
|
-
for index, row in dfRole.iterrows():
|
|
363
|
-
roleName = row["Role"]
|
|
364
|
-
roleDesc = row["Description"]
|
|
365
|
-
modPerm = row["Model Permission"]
|
|
366
|
-
|
|
367
|
-
try:
|
|
368
|
-
tom.model.Roles[roleName]
|
|
369
|
-
except:
|
|
370
|
-
tom.add_role(
|
|
371
|
-
role_name=roleName,
|
|
372
|
-
model_permission=modPerm,
|
|
373
|
-
description=roleDesc,
|
|
371
|
+
f"{icons.red_dot} The {relName} relationship cannot be created because the {format_dax_object_name(r.FromTable.Name, r.FromColumn.Name)} column is not available in the '{new_dataset}' semantic model within the '{new_dataset_workspace}' workspace."
|
|
374
372
|
)
|
|
373
|
+
elif not any(
|
|
374
|
+
c.Name == r.ToColumn.Name and c.Parent.Name == r.ToTable.Name
|
|
375
|
+
for c in tom.all_columns()
|
|
376
|
+
):
|
|
375
377
|
print(
|
|
376
|
-
f"{icons.
|
|
377
|
-
)
|
|
378
|
-
|
|
379
|
-
print(f"\n{icons.in_progress} Creating row level security...")
|
|
380
|
-
for index, row in dfRLS.iterrows():
|
|
381
|
-
roleName = row["Role"]
|
|
382
|
-
tName = row["Table"]
|
|
383
|
-
expr = row["Filter Expression"]
|
|
384
|
-
|
|
385
|
-
try:
|
|
386
|
-
tom.set_rls(
|
|
387
|
-
role_name=roleName, table_name=tName, filter_expression=expr
|
|
388
|
-
)
|
|
389
|
-
print(
|
|
390
|
-
f"{icons.green_dot} Row level security for the '{tName}' table within the '{roleName}' role has been set."
|
|
391
|
-
)
|
|
392
|
-
except:
|
|
393
|
-
print(
|
|
394
|
-
f"{icons.red_dot} Row level security for the '{tName}' table within the '{roleName}' role was not set."
|
|
378
|
+
f"{icons.red_dot} The {relName} relationship cannot be created because the {format_dax_object_name(r.ToTable.Name, r.ToColumn.Name)} column is not available in the '{new_dataset}' semantic model within the '{new_dataset_workspace}' workspace."
|
|
395
379
|
)
|
|
380
|
+
else:
|
|
381
|
+
tom.add_relationship(
|
|
382
|
+
from_table=r.FromTable.Name,
|
|
383
|
+
from_column=r.FromColumn.Name,
|
|
384
|
+
to_table=r.ToTable.Name,
|
|
385
|
+
to_column=r.ToColumn.Name,
|
|
386
|
+
from_cardinality=str(r.FromCardinality),
|
|
387
|
+
to_cardinality=str(r.ToCardinality),
|
|
388
|
+
cross_filtering_behavior=str(r.CrossFilteringBehavior),
|
|
389
|
+
security_filtering_behavior=str(r.SecurityFilteringBehavior),
|
|
390
|
+
rely_on_referential_integrity=r.RelyOnReferentialIntegrity,
|
|
391
|
+
is_active=r.IsActive,
|
|
392
|
+
)
|
|
393
|
+
print(
|
|
394
|
+
f"{icons.green_dot} The {relName} relationship has been added."
|
|
395
|
+
)
|
|
396
396
|
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
print(f"\n{icons.in_progress} Creating roles...")
|
|
398
|
+
for index, row in dfRole.iterrows():
|
|
399
|
+
roleName = row["Role"]
|
|
400
|
+
roleDesc = row["Description"]
|
|
401
|
+
modPerm = row["Model Permission"]
|
|
402
|
+
|
|
403
|
+
if not any(r.Name == roleName for r in tom.model.Roles):
|
|
404
|
+
tom.add_role(
|
|
405
|
+
role_name=roleName,
|
|
406
|
+
model_permission=modPerm,
|
|
407
|
+
description=roleDesc,
|
|
408
|
+
)
|
|
409
|
+
print(f"{icons.green_dot} The '{roleName}' role has been added.")
|
|
399
410
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
f"{icons.green_dot} The '{pName}' perspective has been added."
|
|
406
|
-
)
|
|
411
|
+
print(f"\n{icons.in_progress} Creating row level security...")
|
|
412
|
+
for index, row in dfRLS.iterrows():
|
|
413
|
+
roleName = row["Role"]
|
|
414
|
+
tName = row["Table"]
|
|
415
|
+
expr = row["Filter Expression"]
|
|
407
416
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
object=tom.model.Tables[tName], perspective_name=pName
|
|
420
|
-
)
|
|
421
|
-
elif oType == "Column":
|
|
422
|
-
tom.add_to_perspective(
|
|
423
|
-
object=tom.model.Tables[tName].Columns[oName],
|
|
424
|
-
perspective_name=pName,
|
|
425
|
-
)
|
|
426
|
-
elif oType == "Measure":
|
|
427
|
-
tom.add_to_perspective(
|
|
428
|
-
object=tom.model.Tables[tName].Measures[oName],
|
|
429
|
-
perspective_name=pName,
|
|
430
|
-
)
|
|
431
|
-
elif oType == "Hierarchy":
|
|
432
|
-
tom.add_to_perspective(
|
|
433
|
-
object=tom.model.Tables[tName].Hierarchies[oName],
|
|
434
|
-
perspective_name=pName,
|
|
435
|
-
)
|
|
436
|
-
except:
|
|
437
|
-
pass
|
|
438
|
-
|
|
439
|
-
print(f"\n{icons.in_progress} Creating translation languages...")
|
|
440
|
-
for trName in dfTranslation["Culture Name"].unique():
|
|
441
|
-
try:
|
|
442
|
-
tom.model.Cultures[trName]
|
|
443
|
-
except:
|
|
444
|
-
tom.add_translation(trName)
|
|
445
|
-
print(
|
|
446
|
-
f"{icons.green_dot} The '{trName}' translation language has been added."
|
|
447
|
-
)
|
|
417
|
+
if any(t.Name == tName for t in tom.model.Tables):
|
|
418
|
+
tom.set_rls(
|
|
419
|
+
role_name=roleName, table_name=tName, filter_expression=expr
|
|
420
|
+
)
|
|
421
|
+
print(
|
|
422
|
+
f"{icons.green_dot} Row level security for the '{tName}' table within the '{roleName}' role has been set."
|
|
423
|
+
)
|
|
424
|
+
else:
|
|
425
|
+
print(
|
|
426
|
+
f"{icons.red_dot} Row level security for the '{tName}' table within the '{roleName}' role was not set."
|
|
427
|
+
)
|
|
448
428
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
tom.set_translation(
|
|
487
|
-
object=tom.model.Tables[tName].Hierarchies[oName],
|
|
488
|
-
language=trName,
|
|
489
|
-
property=prop,
|
|
490
|
-
value=translation,
|
|
491
|
-
)
|
|
492
|
-
elif oType == "Level":
|
|
493
|
-
|
|
494
|
-
pattern = r"\[([^]]+)\]"
|
|
495
|
-
matches = re.findall(pattern, oName)
|
|
496
|
-
lName = matches[0]
|
|
497
|
-
|
|
498
|
-
pattern = r"'([^']+)'"
|
|
499
|
-
matches = re.findall(pattern, oName)
|
|
500
|
-
hName = matches[0]
|
|
501
|
-
tom.set_translation(
|
|
502
|
-
object=tom.model.Tables[tName]
|
|
503
|
-
.Hierarchies[hName]
|
|
504
|
-
.Levels[lName],
|
|
505
|
-
language=trName,
|
|
506
|
-
property=prop,
|
|
507
|
-
value=translation,
|
|
508
|
-
)
|
|
509
|
-
except:
|
|
510
|
-
pass
|
|
429
|
+
print(f"\n{icons.in_progress} Creating perspectives...")
|
|
430
|
+
for pName in dfP["Perspective Name"].unique():
|
|
431
|
+
|
|
432
|
+
if not any(p.Name == pName for p in tom.model.Perspectives):
|
|
433
|
+
tom.add_perspective(perspective_name=pName)
|
|
434
|
+
print(f"{icons.green_dot} The '{pName}' perspective has been added.")
|
|
435
|
+
|
|
436
|
+
print(f"\n{icons.in_progress} Adding objects to perspectives...")
|
|
437
|
+
for index, row in dfP.iterrows():
|
|
438
|
+
pName = row["Perspective Name"]
|
|
439
|
+
tName = row["Table Name"]
|
|
440
|
+
oName = row["Object Name"]
|
|
441
|
+
oType = row["Object Type"]
|
|
442
|
+
tType = dfT.loc[(dfT["Name"] == tName), "Type"].iloc[0]
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
if oType == "Table":
|
|
446
|
+
tom.add_to_perspective(
|
|
447
|
+
object=tom.model.Tables[tName], perspective_name=pName
|
|
448
|
+
)
|
|
449
|
+
elif oType == "Column":
|
|
450
|
+
tom.add_to_perspective(
|
|
451
|
+
object=tom.model.Tables[tName].Columns[oName],
|
|
452
|
+
perspective_name=pName,
|
|
453
|
+
)
|
|
454
|
+
elif oType == "Measure":
|
|
455
|
+
tom.add_to_perspective(
|
|
456
|
+
object=tom.model.Tables[tName].Measures[oName],
|
|
457
|
+
perspective_name=pName,
|
|
458
|
+
)
|
|
459
|
+
elif oType == "Hierarchy":
|
|
460
|
+
tom.add_to_perspective(
|
|
461
|
+
object=tom.model.Tables[tName].Hierarchies[oName],
|
|
462
|
+
perspective_name=pName,
|
|
463
|
+
)
|
|
464
|
+
except Exception:
|
|
465
|
+
pass
|
|
511
466
|
|
|
467
|
+
print(f"\n{icons.in_progress} Creating translation languages...")
|
|
468
|
+
for trName in dfTranslation["Culture Name"].unique():
|
|
469
|
+
if not any(c.Name == trName for c in tom.model.Cultures):
|
|
470
|
+
tom.add_translation(trName)
|
|
512
471
|
print(
|
|
513
|
-
f"
|
|
472
|
+
f"{icons.green_dot} The '{trName}' translation language has been added."
|
|
514
473
|
)
|
|
515
474
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
475
|
+
print(f"\n{icons.in_progress} Creating translation values...")
|
|
476
|
+
for index, row in dfTranslation.iterrows():
|
|
477
|
+
trName = row["Culture Name"]
|
|
478
|
+
tName = row["Table Name"]
|
|
479
|
+
oName = row["Object Name"]
|
|
480
|
+
oType = row["Object Type"]
|
|
481
|
+
translation = row["Translation"]
|
|
482
|
+
prop = row["Property"]
|
|
483
|
+
|
|
484
|
+
if prop == "Caption":
|
|
485
|
+
prop = "Name"
|
|
486
|
+
elif prop == "DisplayFolder":
|
|
487
|
+
prop = "Display Folder"
|
|
488
|
+
|
|
489
|
+
try:
|
|
490
|
+
if oType == "Table":
|
|
491
|
+
tom.set_translation(
|
|
492
|
+
object=tom.model.Tables[tName],
|
|
493
|
+
language=trName,
|
|
494
|
+
property=prop,
|
|
495
|
+
value=translation,
|
|
496
|
+
)
|
|
497
|
+
elif oType == "Column":
|
|
498
|
+
tom.set_translation(
|
|
499
|
+
object=tom.model.Tables[tName].Columns[oName],
|
|
500
|
+
language=trName,
|
|
501
|
+
property=prop,
|
|
502
|
+
value=translation,
|
|
503
|
+
)
|
|
504
|
+
elif oType == "Measure":
|
|
505
|
+
tom.set_translation(
|
|
506
|
+
object=tom.model.Tables[tName].Measures[oName],
|
|
507
|
+
language=trName,
|
|
508
|
+
property=prop,
|
|
509
|
+
value=translation,
|
|
510
|
+
)
|
|
511
|
+
elif oType == "Hierarchy":
|
|
512
|
+
tom.set_translation(
|
|
513
|
+
object=tom.model.Tables[tName].Hierarchies[oName],
|
|
514
|
+
language=trName,
|
|
515
|
+
property=prop,
|
|
516
|
+
value=translation,
|
|
517
|
+
)
|
|
518
|
+
elif oType == "Level":
|
|
519
|
+
|
|
520
|
+
pattern = r"\[([^]]+)\]"
|
|
521
|
+
matches = re.findall(pattern, oName)
|
|
522
|
+
lName = matches[0]
|
|
523
|
+
|
|
524
|
+
pattern = r"'([^']+)'"
|
|
525
|
+
matches = re.findall(pattern, oName)
|
|
526
|
+
hName = matches[0]
|
|
527
|
+
tom.set_translation(
|
|
528
|
+
object=tom.model.Tables[tName].Hierarchies[hName].Levels[lName],
|
|
529
|
+
language=trName,
|
|
530
|
+
property=prop,
|
|
531
|
+
value=translation,
|
|
532
|
+
)
|
|
533
|
+
except Exception:
|
|
534
|
+
pass
|
|
535
|
+
|
|
536
|
+
print(
|
|
537
|
+
f"\n{icons.green_dot} Migration of objects from '{dataset}' -> '{new_dataset}' is complete."
|
|
538
|
+
)
|