8000 Merge pull request #394 from baixin137/materialize-workbooks · srqway/server-client-python@fc75870 · GitHub
[go: up one dir, main page]

10000 Skip to content

Commit fc75870

Browse files
authored
Merge pull request tableau#394 from baixin137/materialize-workbooks
Added more options for materialized views feature
2 parents 0a099f4 + ad83f80 commit fc75870

File tree

9 files changed

+195
-66
lines changed

9 files changed

+195
-66
lines changed

samples/materialize_workbooks.py

Lines changed: 103 additions & 29 deletions
38
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,22 @@ def main():
1010
parser.add_argument('--server', '-s', required=True, help='Tableau server address')
1111
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
1212
parser.add_argument('--password', '-p', required=False, help='password to sign into server')
13-
parser.add_argument('--mode', '-m', required=False, choices=['enable', 'disable'],
13+
parser.add_argument('--mode', '-m', required=False, choices=['disable', 'enable', 'enable_all', 'enable_selective'],
1414
help='enable/disable materialized views for sites/workbooks')
1515
parser.add_argument('--status', '-st', required=False, action='store_true',
1616
help='show materialized views enabled sites/workbooks')
1717
parser.add_argument('--site-id', '-si', required=False,
1818
help='set to Default site by default')
1919
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
2020
help='desired logging level (set to error by default)')
21-
parser.add_argument('--type', '-t', required=False, choices=['site', 'workbook', 'project_name',
22-
'project_id', 'project_path'],
21+
parser.add_argument('--type', '-t', required=False, choices=['site', 'workbook', 'project_name', 'project_path'],
2322
help='type of content you want to update materialized views settings on')
2423
parser.add_argument('--path-list', '-pl', required=False, help='path to a list of workbook paths')
2524
parser.add_argument('--name-list', '-nl', required=False, help='path to a list of workbook names')
2625
parser.add_argument('--project-name', '-pn', required=False, help='name of the project')
2726
parser.add_argument('--project-path', '-pp', required=False, help="path of the project")
27+
parser.add_argument('--materialize-now', '-mn', required=False, action='store_true',
28+
help='create materialized views for workbooks immediately')
2829

2930
args = parser.parse_args()
3031

@@ -38,32 +39,32 @@ def main():
39

3940
# site content url is the TSC term for site id
4041
site_content_url = args.site_id if args.site_id is not None else ""
41-
enable_materialized_views = args.mode == "enable"
4242

43-
if (args.type is None) != (args.mode is None):
44-
print("Use '--type <content type> --mode <enable/disable>' to update materialized views settings.")
43+
if not assert_options_valid(args):
4544
return
4645

46+
materialized_views_config = create_materialized_views_config(args)
47+
4748
# enable/disable materialized views for site
4849
if args.type == 'site':
49-
if not update_site(args, enable_materialized_views, password, site_content_url):
50+
if not update_site(args, password, site_content_url):
5051
return
5152

5253
# enable/disable materialized views for workbook
5354
# works only when the site the workbooks belong to are enabled too
5455
elif args.type == 'workbook':
55-
if not update_workbook(args, enable_materialized_views, password, site_content_url):
56+
if not update_workbook(args, materialized_views_config, password, site_content_url):
5657
return
5758

5859
# enable/disable materialized views for project by project name
5960
# will show possible projects when project name is not unique
6061
elif args.type == 'project_name':
61-
if not update_project_by_name(args, enable_materialized_views, password, site_content_url):
62+
if not update_project_by_name(args, materialized_views_config, password, site_content_url):
6263
return
6364

64-
# enable/disable materialized views for proejct by project path, for example: project1/project2
65+
# enable/disable materialized views for project by project path, for example: project1/project2
6566
elif args.type == 'project_path':
66-
if not update_project_by_path(args, enable_materialized_views, password, site_content_url):
67+
if not update_project_by_path(args, materialized_views_config, password, site_content_url):
6768
return
6869

6970
# show enabled sites and workbooks
@@ -108,7 +109,7 @@ def show_materialized_views_status(args, password, site_content_url):
108109
# only server admins can get all the sites in the server
109110
# other users can only get the site they are in
110111
for site in TSC.Pager(server.sites):
111-
if site.materialized_views_enabled:
112+
if site.materialized_views_mode != "disable":
112113
enabled_sites.add(site)
113114
print("Site name: {}".format(site.name))
114115
print('\n')
@@ -119,34 +120,42 @@ def show_materialized_views_status(args, password, site_content_url):
119120
site_auth = TSC.TableauAuth(args.username, password, site.content_url)
120121
with server.auth.sign_in(site_auth):
121122
for workbook in TSC.Pager(server.workbooks):
122-
if workbook.materialized_views_enabled:
123+
if workbook.materialized_views_config['materialized_views_enabled']:
123124
print("Workbook: {} from site: {}".format(workbook.name, site.name))
124125

125126

126-
def update_project_by_path(args, enable_materialized_views, password, site_content_url):
127+
def update_project_by_path(args, materialized_views_mode, password, site_content_url):
127128
if args.project_path is None:
128129
print("Use --project_path <project path> to specify the path of the project")
129130
return False
130131
tableau_auth = TSC.TableauAuth(args.username, password, site_content_url)
131132
server = TSC.Server(args.server, use_server_version=True)
132133
project_name = args.project_path.split('/')[-1]
133134
with server.auth.sign_in(tableau_auth):
135+
if not assert_site_enabled_for_materialized_views(server, site_content_url):
136+
return False
134137
projects = [project for project in TSC.Pager(server.projects) if project.name == project_name]
138+
if not assert_project_valid(args.project_path, projects):
139+
return False
135140

136141
possible_paths = get_project_paths(server, projects)
137-
update_project(possible_paths[args.project_path], server, enable_materialized_views)
142+
update_project(possible_paths[args.project_path], server, materialized_views_mode)
138143
return True
139144

140145

141-
def update_project_by_name(args, enable_materialized_views, password, site_content_url):
146+
def update_project_by_name(args, materialized_views_config, password, site_content_url):
142147
if args.project_name is None:
143148
print("Use --project-name <project name> to specify the name of the project")
144149
return False
145150
tableau_auth = TSC.TableauAuth(args.username, password, site_content_url)
146151
server = TSC.Server(args.server, use_server_version=True)
147152
with server.auth.sign_in(tableau_auth):
153+
if not assert_site_enabled_for_materialized_views(server, site_content_url):
154+
return False
148155
# get all projects with given name
149156
projects = [project for project in TSC.Pager(server.projects) if project.name == args.project_name]
157+
if not assert_project_valid(args.project_name, projects):
158+
return False
150159

151160
if len(projects) > 1:
152161
possible_paths = get_project_paths(server, projects)
@@ -156,20 +165,28 @@ def update_project_by_name(args, enable_materialized_views, password, site_conte
156165
print('\n')
157166
return False
158167
else:
159-
update_project(projects[0], server, enable_materialized_views)
168+
update_project(projects[0], server, materialized_views_config)
160169
return True
161170

162171

163-
def update_project(project, server, enable_materialized_views):
172+
def update_project(project, server, materialized_views_config):
173+
all_projects = list(TSC.Pager(server.projects))
174+
project_ids = find_project_ids_to_update(all_projects, project, server)
164175
for workbook in TSC.Pager(server.workbooks):
165-
if workbook.project_id == project.id:
166-
workbook.materialized_views_enabled = enable_materialized_views
176+
if workbook.project_id in project_ids:
177+
workbook.materialized_views_config = materialized_views_config
167178
server.workbooks.update(workbook)
168179

169180
print("Updated materialized views settings for project: {}".format(project.name))
170181
print('\n')
171182

172183

184+
def find_project_ids_to_update(all_projects, project, server):
185+
projects_to_update = []
186+
find_projects_to_update(project, server, all_projects, projects_to_update)
187+
return set([project_to_update.id for project_to_update in projects_to_update])
188+
189+
173190
def parse_workbook_path(file_path):
174191
# parse the list of project path of workbooks
175192
workbook_paths = open(file_path, 'r')
@@ -180,24 +197,26 @@ def parse_workbook_path(file_path):
180197
return workbook_path_mapping
181198

182199

183-
def update_workbook(args, enable_materialized_views, password, site_content_url):
200+
def update_workbook(args, materialized_views_config, password, site_content_url):
184201
if args.path_list is None and args.name_list is None:
185202
print("Use '--path-list <filename>' or '--name-list <filename>' to specify the path of a list of workbooks")
186203
print('\n')
187204
return False
188205
tableau_auth = TSC.TableauAuth(args.username, password, site_id=site_content_url)
189206
server = TSC.Server(args.server, use_server_version=True)
190207
with server.auth.sign_in(tableau_auth):
208+
if not assert_site_enabled_for_materialized_views(server, site_content_url):
209+
return False
191210
if args.path_list is not None:
192211
workbook_path_mapping = parse_workbook_path(args.path_list)
193212
all_projects = {project.id: project for project in TSC.Pager(server.projects)}
194-
update_workbooks_by_paths(all_projects, enable_materialized_views, server, workbook_path_mapping)
213+
update_workbooks_by_paths(all_projects, materialized_views_config, server, workbook_path_mapping)
195214
elif args.name_list is not None:
196-
update_workbooks_by_names(args.name_list, server, enable_materialized_views)
215+
update_workbooks_by_names(args.name_list, server, materialized_views_config)
197216
return True
198217

199218

200-
def update_workbooks_by_paths(all_projects, enable_materialized_views, server, workbook_path_mapping):
219+
def update_workbooks_by_paths(all_projects, materialized_views_config, server, workbook_path_mapping):
201220
for workbook_name, workbook_paths in workbook_path_mapping.items():
202221
req_option = TSC.RequestOptions()
203222
req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
@@ -207,13 +226,13 @@ def update_workbooks_by_paths(all_projects, enable_materialized_views, server, w
207226
for workbook in workbooks:
208227
path = find_project_path(all_projects[workbook.project_id], all_projects, "")
209228
if path in workbook_paths:
210-
workbook.materialized_views_enabled = enable_materialized_views
229+
workbook.materialized_views_config = materialized_views_config
211230
server.workbooks.update(workbook)
212231
print("Updated materialized views settings for workbook: {}".format(path + '/' + workbook.name))
213232
print('\n')
214233

215234

216-
def update_workbooks_by_names(name_list, server, enable_materialized_views):
235+
def update_workbooks_by_names(name_list, server, materialized_views_config):
217236
workbook_names = open(name_list, 'r')
218237
for workbook_name in workbook_names:
219238
req_option = TSC.RequestOptions()
@@ -222,24 +241,79 @@ def update_workbooks_by_names(name_list, server, enable_materialized_views):
222241
workbook_name.rstrip()))
223242
workbooks = list(TSC.Pager(server.workbooks, req_option))
224243
for workbook in workbooks:
225-
workbook.materialized_views_enabled = enable_materialized_views
244+
workbook.materialized_views_config = materialized_views_config
226245
server.workbooks.update(workbook)
227246
print("Updated materialized views settings for workbook: {}".format(workbook.name))
228247
print('\n')
229248

230249

231-
def update_site(args, enable_materialized_views, password, site_content_url):
250+
def update_site(args, password, site_content_url):
251+
if not assert_site_options_valid(args):
252+
return False
232253
tableau_auth = TSC.TableauAuth(args.username, password, site_id=site_content_url)
233254
server = TSC.Server(args.server, use_server_version=True)
234255
with server.auth.sign_in(tableau_auth):
235256
site_to_update = server.sites.get_by_content_url(site_content_url)
236-
site_to_update.materialized_views_enabled = enable_materialized_views
257+
site_to_update.materialized_views_mode = args.mode
237258

238259
server.sites.update(site_to_update)
239260
print("Updated materialized views settings for site: {}".format(site_to_update.name))
240261
print('\n')
241262
return True
242263

243264

265+
def create_materialized_views_config(args):
266+
materialized_views_config = dict()
267+
materialized_views_config['materialized_views_enabled'] = args.mode == "enable"
268+
materialized_views_config['run_materialization_now'] = True if args.materialize_now else False
269+
return materialized_views_config
270+
271+
272+
def assert_site_options_valid(args):
273+
if args.materialize_now:
274+
print('"--materialize-now" only applies to workbook/project type')
275+
return False
276+
if args.mode == 'enable':
277+
print('For site type please choose from "disable", "enable_all", or "enable_selective"')
278+
return False
279+
return True
280+
281+
282+
def assert_options_valid(args):
283+
if args.type != "site" and args.mode in ("enable_all", "enable_selective"):
284+
print('"enable_all" and "enable_selective" do not apply to workbook/project type')
285+
return False
286+
if (args.type is None) != (args.mode is None):
287+
print("Use '--type <content type> --mode <mode>' to update materialized views settings.")
288+
return False
289+
return True
290+
291+
292+
def assert_site_enabled_for_materialized_views(server, site_content_url):
293+
parent_site = server.sites.get_by_content_url(site_content_url)
294+
if parent_site.materialized_views_mode == "disable":
295+
print('Cannot update workbook/project because site is disabled for materialized views')
296+
return False
297+
return True
298+
299+
300+
def assert_project_valid(project_name, projects):
301+
if len(projects) == 0:
302+
print("Cannot find project: {}".format(project_name))
303+
return False
304+
return True
305+
306+
307+
def find_projects_to_update(project, server, all_projects, projects_to_update):
308+
# Use recursion to find all the sub-projects and enable/disable the workbooks in them
309+
projects_to_update.append(project)
310+
children_projects = [child for child in all_projects if child.parent_id == project.id]
311+
if len(children_projects) == 0:
312+
return
313+
314+
for child in children_projects:
315+
find_projects_to_update(child, server, all_projects, projects_to_update)
316+
317+
244318
if __name__ == "__main__":
245319
main()

samples/name.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
92 08 23
2+
Book2

tableauserverclient/models/property_decorators.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,19 @@ def wrapper(self, value):
136136
dt = parse_datetime(value)
137137
return func(self, dt)
138138
return wrapper
139+
140+
141+
def property_is_materialized_views_config(func):
142+
@wraps(func)
143+
def wrapper(self, value):
144+
if not isinstance(value, dict):
145+
raise ValueError("{} is not type 'dict', cannot update {})".format(value.__class__.__name__,
146+
func.__name__))
147+
if len(value) != 2 or not all(attr in value.keys() for attr in ('materialized_views_enabled',
148+
'run_materialization_now')):
149+
error = "{} should have 2 keys ".format(func.__name__)
150+
error += "'materialized_views_enabled' and 'run_materialization_now'"
151+
error += "instead you have {}".format(value.keys())
152+
raise ValueError(error)
153+
return func(self, value)
154+
return wrapper

0 commit comments

Comments
 (0)
0