1
1
"""Import a list of assets from a yaml file and create them in the superset assets folder."""
2
+
2
3
import os
4
+
3
5
from superset .app import create_app
4
6
5
7
app = create_app ()
6
8
app .app_context ().push ()
7
9
8
10
import logging
9
11
import uuid
10
- import yaml
12
+ from collections import defaultdict
11
13
from copy import deepcopy
12
14
from pathlib import Path
15
+
16
+ import yaml
17
+ from openedx .create_assets_utils import load_configs_from_directory
18
+ from openedx .create_row_level_security import create_rls_filters
19
+ from openedx .delete_assets import delete_assets
20
+ from openedx .localization import get_translation
13
21
from sqlfmt .api import format_string
14
22
from sqlfmt .mode import Mode
15
- from collections import defaultdict
16
-
17
23
from superset import security_manager
24
+ from superset .commands .utils import update_tags
25
+ from superset .connectors .sqla .models import SqlaTable
18
26
from superset .extensions import db
19
27
from superset .models .dashboard import Dashboard
20
- from superset .models .slice import Slice
21
- from superset .connectors .sqla .models import SqlaTable
22
28
from superset .models .embedded_dashboard import EmbeddedDashboard
23
-
24
-
25
- from superset .tags .models import TagType , get_tag
26
- from superset .commands .utils import update_tags
27
- from superset .tags .models import ObjectType
28
- from openedx .delete_assets import delete_assets
29
- from openedx .create_assets_utils import load_configs_from_directory
30
- from openedx .localization import get_translation
31
- from openedx .create_row_level_security import create_rls_filters
32
-
29
+ from superset .models .slice import Slice
30
+ from superset .tags .models import ObjectType , TagType , get_tag
33
31
34
32
logger = logging .getLogger ("create_assets" )
35
33
# Supress output from black (sqlfmt) formatting
36
- blib2to3_logger = logging .getLogger (' blib2to3.pgen2.driver' )
34
+ blib2to3_logger = logging .getLogger (" blib2to3.pgen2.driver" )
37
35
blib2to3_logger .setLevel (logging .WARN )
38
36
39
37
BASE_DIR = "/app/assets/superset"
@@ -77,7 +75,7 @@ def create_assets():
77
75
process_asset (asset , roles , translated_asset_uuids )
78
76
79
77
# Get extra assets
80
- with open (os .path .join (PYTHONPATH ,"assets.yaml" ), "r" ) as file :
78
+ with open (os .path .join (PYTHONPATH , "assets.yaml" ), "r" ) as file :
81
79
extra_assets = yaml .safe_load_all (file )
82
80
83
81
if extra_assets :
@@ -92,11 +90,14 @@ def create_assets():
92
90
create_rls_filters ()
93
91
94
92
# Delete unused assets
95
- with open (os .path .join (PYTHONPATH ,"aspects_asset_list.yaml" ), "r" , encoding = "utf-8" ) as file :
93
+ with open (
94
+ os .path .join (PYTHONPATH , "aspects_asset_list.yaml" ), "r" , encoding = "utf-8"
95
+ ) as file :
96
96
assets = yaml .safe_load (file )
97
- unused_aspect_uuids = assets [' unused_uuids' ]
97
+ unused_aspect_uuids = assets [" unused_uuids" ]
98
98
delete_assets (unused_aspect_uuids , translated_asset_uuids )
99
99
100
+
100
101
def process_asset (asset , roles , translated_asset_uuids ):
101
102
if FILE_NAME_ATTRIBUTE not in asset :
102
103
raise Exception (f"Asset { asset } has no { FILE_NAME_ATTRIBUTE } " )
@@ -105,7 +106,9 @@ def process_asset(asset, roles, translated_asset_uuids):
105
106
# Find the right folder to create the asset in
106
107
for asset_name , folder in ASSET_FOLDER_MAPPING .items ():
107
108
if asset_name in asset :
108
- write_asset_to_file (asset , asset_name , folder , file_name , roles , translated_asset_uuids )
109
+ write_asset_to_file (
110
+ asset , asset_name , folder , file_name , roles , translated_asset_uuids
111
+ )
109
112
return
110
113
111
114
@@ -117,16 +120,21 @@ def get_localized_uuid(base_uuid, language):
117
120
base_namespace = uuid .uuid5 (base_uuid , "superset" )
118
121
normalized_language = language .lower ().replace ("-" , "_" )
119
122
return str (uuid .uuid5 (base_namespace , normalized_language ))
120
-
121
- def write_asset_to_file (asset , asset_name , folder , file_name , roles , translated_asset_uuids ):
123
+
124
+
125
+ def write_asset_to_file (
126
+ asset , asset_name , folder , file_name , roles , translated_asset_uuids
127
+ ):
122
128
"""Write an asset to a file and generated translated assets"""
123
129
if folder == "databases" :
124
130
# Update the sqlalchery_uri from the asset override pre-generated values
125
131
asset ["sqlalchemy_uri" ] = DATABASES .get (asset ["database_name" ])
126
132
if folder in ["charts" , "dashboards" , "datasets" ]:
127
133
for locale in DASHBOARD_LOCALES :
128
134
if folder == "datasets" :
129
- asset ["sql" ] = format_string (asset ["sql" ], mode = Mode (dialect_name = "clickhouse" ))
135
+ asset ["sql" ] = format_string (
136
+ asset ["sql" ], mode = Mode (dialect_name = "clickhouse" )
137
+ )
130
138
131
139
updated_asset = generate_translated_asset (
132
140
asset , asset_name , folder , locale , roles , translated_asset_uuids
@@ -135,7 +143,9 @@ def write_asset_to_file(asset, asset_name, folder, file_name, roles, translated_
135
143
# Clean up old localized dashboards
136
144
if folder == "dashboards" :
137
145
dashboard_slug = updated_asset ["slug" ]
138
- dashboard = db .session .query (Dashboard ).filter_by (slug = dashboard_slug ).first ()
146
+ dashboard = (
147
+ db .session .query (Dashboard ).filter_by (slug = dashboard_slug ).first ()
148
+ )
139
149
if dashboard :
140
150
db .session .delete (dashboard )
141
151
path = f"{ BASE_DIR } /{ folder } /{ file_name .split ('.' )[0 ]} -{ locale } .yaml"
@@ -146,7 +156,7 @@ def write_asset_to_file(asset, asset_name, folder, file_name, roles, translated_
146
156
# access the original dashboards.
147
157
dashboard_roles = asset .pop ("_roles" , None )
148
158
if dashboard_roles :
149
- roles [asset ["uuid" ]] = ([security_manager .find_role ("Admin" )], ' original' )
159
+ roles [asset ["uuid" ]] = ([security_manager .find_role ("Admin" )], " original" )
150
160
151
161
# Clean up old un-localized dashboard
152
162
dashboard_slug = asset .get ("slug" )
@@ -162,15 +172,17 @@ def write_asset_to_file(asset, asset_name, folder, file_name, roles, translated_
162
172
db .session .commit ()
163
173
164
174
165
- def generate_translated_asset (asset , asset_name , folder , language , roles , translated_asset_uuids ):
175
+ def generate_translated_asset (
176
+ asset , asset_name , folder , language , roles , translated_asset_uuids
177
+ ):
166
178
"""Generate a translated asset with their elements updated"""
167
179
copy = deepcopy (asset )
168
- parent_uuid = copy [' uuid' ]
180
+ parent_uuid = copy [" uuid" ]
169
181
copy ["uuid" ] = str (get_localized_uuid (copy ["uuid" ], language ))
170
182
copy [asset_name ] = get_translation (copy [asset_name ], language )
171
183
172
184
# Save parent & translated uuids in yaml file
173
- translated_asset_uuids [parent_uuid ].add (copy [' uuid' ])
185
+ translated_asset_uuids [parent_uuid ].add (copy [" uuid" ])
174
186
if folder == "dashboards" :
175
187
copy ["slug" ] = f"{ copy ['slug' ]} -{ language } "
176
188
copy ["description" ] = get_translation (copy ["description" ], language )
@@ -181,9 +193,10 @@ def generate_translated_asset(asset, asset_name, folder, language, roles, transl
181
193
for role in dashboard_roles :
182
194
translated_dashboard_roles .append (f"{ role } - { language } " )
183
195
184
- roles [copy ["uuid" ]] = ([
185
- (security_manager .find_role (role )) for role in translated_dashboard_roles
186
- ], language )
196
+ roles [copy ["uuid" ]] = (
197
+ [(security_manager .find_role (role )) for role in translated_dashboard_roles ],
198
+ language ,
199
+ )
187
200
188
201
generate_translated_dashboard_elements (copy , language )
189
202
generate_translated_dashboard_filters (copy , language )
@@ -284,6 +297,7 @@ def update_dashboard_roles(roles):
284
297
285
298
db .session .commit ()
286
299
300
+
287
301
def get_owners ():
288
302
owners_username = {{SUPERSET_OWNERS }}
289
303
owners = []
@@ -293,6 +307,7 @@ def get_owners():
293
307
owners .append (user )
294
308
return owners
295
309
310
+
296
311
def update_embeddable_uuids ():
297
312
"""Update the uuids of the embeddable dashboards"""
298
313
for dashboard_slug , embeddable_uuid in EMBEDDABLE_DASHBOARDS .items ():
@@ -313,7 +328,9 @@ def create_embeddable_dashboard_by_slug(dashboard_slug, embeddable_uuid):
313
328
logger .info (f"WARNING: Dashboard { dashboard_slug } not found" )
314
329
return
315
330
316
- embedded_dashboard = db .session .query (EmbeddedDashboard ).filter_by (dashboard_id = dashboard .id ).first ()
331
+ embedded_dashboard = (
332
+ db .session .query (EmbeddedDashboard ).filter_by (dashboard_id = dashboard .id ).first ()
333
+ )
317
334
if embedded_dashboard is None :
318
335
embedded_dashboard = EmbeddedDashboard ()
319
336
embedded_dashboard .dashboard_id = dashboard .id
@@ -322,13 +339,12 @@ def create_embeddable_dashboard_by_slug(dashboard_slug, embeddable_uuid):
322
339
db .session .add (embedded_dashboard )
323
340
db .session .commit ()
324
341
342
+
325
343
def update_datasets ():
326
344
"""Update the datasets"""
327
345
logger .info ("Refreshing datasets" )
328
346
if {{SUPERSET_REFRESH_DATASETS }}:
329
- datasets = (
330
- db .session .query (SqlaTable ).all ()
331
- )
347
+ datasets = db .session .query (SqlaTable ).all ()
332
348
for dataset in datasets :
333
349
logger .info (f"Refreshing dataset { dataset .table_name } " )
334
350
dataset .fetch_metadata (commit = True )
0 commit comments