From 1fbd2c6bb5b86156509d4461374c0cc0ee857e06 Mon Sep 17 00:00:00 2001 From: Andy O'Neal Date: Sat, 20 Aug 2022 21:59:09 +0000 Subject: [PATCH 01/11] add datasources to the get command --- tabcmd/commands/datasources_and_workbooks/get_url_command.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index 302283c1..eee706ae 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -92,13 +92,13 @@ def get_file_type_from_filename(logger, file_name, url): type_of_file = GetUrl.get_file_extension(file_name) if not type_of_file: - Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) + Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) #TODO else: logger.debug("filetype: {}".format(type_of_file)) if type_of_file in ["pdf", "csv", "png", "twb", "twbx", "tdsx"]: return type_of_file - Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) + Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) #TODO @staticmethod def get_file_extension(filename): @@ -121,6 +121,7 @@ def get_name_without_possible_extension(filename): filename = filename.split(".")[0] return filename + # TODO rename to get_resource_name because it works for ds as well @staticmethod def get_resource_name(url, logger): # workbooks/wb-name" -> "wb-name", datasource/ds-name -> ds-name name_parts = url.split("/") From b0d9512e5ea51455ace80ed18e525172641b04e4 Mon Sep 17 00:00:00 2001 From: Andy O'Neal Date: Sat, 20 Aug 2022 22:11:59 +0000 Subject: [PATCH 02/11] remove TODOs --- tabcmd/commands/datasources_and_workbooks/get_url_command.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index eee706ae..3d405f0b 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -92,13 +92,13 @@ def get_file_type_from_filename(logger, file_name, url): type_of_file = GetUrl.get_file_extension(file_name) if not type_of_file: - Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) #TODO + Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) else: logger.debug("filetype: {}".format(type_of_file)) if type_of_file in ["pdf", "csv", "png", "twb", "twbx", "tdsx"]: return type_of_file - Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) #TODO + Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name)) @staticmethod def get_file_extension(filename): From 4185b830385f3b9d3d86dbc66d135ce01d29d9fb Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 30 Nov 2022 18:14:54 -0800 Subject: [PATCH 03/11] merge fixes, better error message --- tabcmd/commands/datasources_and_workbooks/get_url_command.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index 3d405f0b..302283c1 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -121,7 +121,6 @@ def get_name_without_possible_extension(filename): filename = filename.split(".")[0] return filename - # TODO rename to get_resource_name because it works for ds as well @staticmethod def get_resource_name(url, logger): # workbooks/wb-name" -> "wb-name", datasource/ds-name -> ds-name name_parts = url.split("/") From 03a3858542050b7e0df39376f3462779244a527b Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 6 Dec 2022 19:30:53 -0800 Subject: [PATCH 04/11] make db-auth/oauth mutually exclusive --- tabcmd/execution/global_options.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tabcmd/execution/global_options.py b/tabcmd/execution/global_options.py index 61467455..3aa6e7b4 100644 --- a/tabcmd/execution/global_options.py +++ b/tabcmd/execution/global_options.py @@ -285,10 +285,15 @@ def set_publish_args(parser): parser.add_argument("-n", "--name", help="Name to publish the new datasource or workbook by.") set_overwrite_option(parser) - parser.add_argument( + + creds = parser.add_mutually_exclusive_group() + creds.add_argument("--oauth-username", help="The email address of a preconfigured OAuth connection") + creds.add_argument( "--db-username", help="Use this option to publish a database user name with the workbook, data source, or data extract.", ) + parser.add_argument("--save-oauth", action="store_true", help="Save embedded OAuth credentials in the datasource") + parser.add_argument( "--db-password", help="publish a database password with the workbook, data source, or extract", @@ -298,6 +303,7 @@ def set_publish_args(parser): action="store_true", help="Stores the provided database password on the server.", ) + parser.add_argument( "--tabbed", action="store_true", @@ -314,9 +320,6 @@ def set_publish_args(parser): action="store_true", help="Encrypt extracts in the workbook, datasource, or extract being published to the server", ) - parser.add_argument("--oauth-username", help="The email address of a preconfigured OAuth connection") - parser.add_argument("--save-oauth", action="store_true", help="Save embedded OAuth credentials in the datasource") - thumbnails = parser.add_mutually_exclusive_group() thumbnails.add_argument("--thumbnail-username", help="Not yet implemented") thumbnails.add_argument("--thumbnail-group", help="Not yet implemented") # not implemented in the REST API From bb5e1aa37f4528dedf0454714dc8683bf6d05ff7 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 6 Dec 2022 21:08:57 -0800 Subject: [PATCH 05/11] Create a db credentials item for publishing Start using the --db-username, etc arguments --- .../publish_command.py | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 59432ee1..3abb6c29 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -28,6 +28,7 @@ def define_args(publish_parser): set_publish_args(publish_parser) set_project_r_arg(publish_parser) set_parent_project_arg(publish_parser) + # --disable-uploader and --restart don't do anything @staticmethod def run_command(args): @@ -50,15 +51,30 @@ def run_command(args): args.project_name = "default" args.parent_project_path = "" - publish_mode = PublishCommand.get_publish_mode(args) + publish_mode = PublishCommand.get_publish_mode(args) # --overwrite, --replace logger.info("Publishing as " + publish_mode) + if args.db_username: + creds = TSC.models.ConnectionCredentials(args.db_username, + args.db_password, + embed=args.save_db_password) + elif args.oauth_username: + creds = TSC.models.ConnectionCredentials(args.oauth_username, + None, + embed=False, + oauth=args.save_oauth) + else: + logger.debug("No db-username or oauth-username found in command") + creds = None + source = PublishCommand.get_filename_extension_if_tableau_type(logger, args.filename) logger.info(_("publish.status").format(args.filename)) if source in ["twbx", "twb"]: new_workbook = TSC.WorkbookItem(project_id, name=args.name, show_tabs=args.tabbed) try: - new_workbook = server.workbooks.publish(new_workbook, args.filename, publish_mode) + new_workbook = server.workbooks.publish(new_workbook, args.filename, publish_mode, + connection_credentials=creds, as_job=False, skip_connection_check=False) + except IOError as ioe: Errors.exit_with_error(logger, ioe) logger.info(_("publish.success") + "\n{}".format(new_workbook.webpage_url)) @@ -67,7 +83,8 @@ def run_command(args): new_datasource = TSC.DatasourceItem(project_id, name=args.name) new_datasource.use_remote_query_agent = args.use_tableau_bridge try: - new_datasource = server.datasources.publish(new_datasource, args.filename, publish_mode) + new_datasource = server.datasources.publish(new_datasource, args.filename, publish_mode, + connection_credentials=creds) except IOError as ioe: Errors.exit_with_error(logger, exc) logger.info(_("publish.success") + "\n{}".format(new_datasource.webpage_url)) From 6ad25241d163d4ff1ba731218dcd40ca635bed3c Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 02:52:29 -0800 Subject: [PATCH 06/11] improve debugging logs --- tabcmd/commands/constants.py | 8 +++-- .../datasources_and_workbooks_command.py | 33 +++++++++++-------- tabcmd/commands/server.py | 6 ++-- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/tabcmd/commands/constants.py b/tabcmd/commands/constants.py index 0eaa9b3c..ba4e6288 100644 --- a/tabcmd/commands/constants.py +++ b/tabcmd/commands/constants.py @@ -44,10 +44,11 @@ def log_stack(logger): start = 0 n_lines = 5 logger.trace(HEADER_FMT % (file, func)) - for frame in stack[start + 1 : n_lines]: + + for frame in stack[start + 2 : n_lines]: file, line, func = frame[1:4] logger.trace(STACK_FMT % (file, line, func)) - except BaseException as e: + except Exception as e: logger.info("Error printing stack trace:", e) @staticmethod @@ -64,10 +65,11 @@ def exit_with_error(logger, message=None, exception=None): # "session.session_expired_login")) # session.renew_session() if message: - logger.debug(message) + logger.debug("Error message: " + message) Errors.check_common_error_codes_and_explain(logger, exception) except Exception as exc: print("Error during log call from exception - {} {}".format(exc.__class__, message)) + print("Exiting...") sys.exit(1) @staticmethod diff --git a/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py b/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py index 2c2d421d..1159a04c 100644 --- a/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py +++ b/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py @@ -23,6 +23,7 @@ def get_view_by_content_url(logger, server, view_content_url) -> TSC.ViewItem: try: req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, view_content_url)) + logger.trace(req_option.get_query_params()) matching_views, paging = server.views.get(req_option) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, _("publish.errors.unexpected_server_response").format(e)) @@ -36,6 +37,7 @@ def get_wb_by_content_url(logger, server, workbook_content_url) -> TSC.WorkbookI try: req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, workbook_content_url)) + logger.trace(req_option.get_query_params()) matching_workbooks, paging = server.workbooks.get(req_option) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, _("publish.errors.unexpected_server_response").format("")) @@ -43,6 +45,21 @@ def get_wb_by_content_url(logger, server, workbook_content_url) -> TSC.WorkbookI Errors.exit_with_error(logger, message=_("dataalerts.failure.error.workbookNotFound")) return matching_workbooks[0] + @staticmethod + def get_ds_by_content_url(logger, server, datasource_content_url) -> TSC.DatasourceItem: + logger.debug(_("export.status").format(datasource_content_url)) + try: + req_option = TSC.RequestOptions() + req_option.filter.add(TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, datasource_content_url)) + logger.trace(req_option.get_query_params()) + matching_datasources, paging = server.datasources.get(req_option) + except TSC.ServerResponseError as e: + Errors.exit_with_error(logger, _("publish.errors.unexpected_server_response").format("")) + if len(matching_datasources) < 1: + Errors.exit_with_error(logger, message=_("dataalerts.failure.error.datasourceNotFound")) + return matching_datasources[0] + + @staticmethod def apply_values_from_url_params(request_options: TSC.PDFRequestOptions, url, logger) -> None: # should be able to replace this with request_options._append_view_filters(params) @@ -63,7 +80,7 @@ def apply_values_from_url_params(request_options: TSC.PDFRequestOptions, url, lo else: # it must be a filter DatasourcesAndWorkbooks.apply_filter_value(request_options, value, logger) - except BaseException as e: + except Exception as e: logger.warn("Error building filter params", e) # ExportCommand.log_stack(logger) # type: ignore @@ -86,7 +103,7 @@ def apply_option_value(request_options: TSC.PDFRequestOptions, value: str, logge logger.debug("Set max age to {} from {}".format(request_options.max_age, value)) elif ":size" == setting[0]: height, width = setting[1].split(",") - logger.warn("Height/weight parameters not yet implemented ({})".format(value)) + logger.warn("Height/width parameters not yet implemented ({})".format(value)) else: logger.debug("Parameter[s] not recognized: {}".format(value)) @@ -123,15 +140,3 @@ def save_to_file(logger, output, filename): f.write(output) logger.info(_("export.success").format("", filename)) - @staticmethod - def get_ds_by_content_url(logger, server, datasource_content_url) -> TSC.DatasourceItem: - logger.debug(_("export.status").format(datasource_content_url)) - try: - req_option = TSC.RequestOptions() - req_option.filter.add(TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, datasource_content_url)) - matching_datasources, paging = server.datasources.get(req_option) - except TSC.ServerResponseError as e: - Errors.exit_with_error(logger, _("publish.errors.unexpected_server_response").format("")) - if len(matching_datasources) < 1: - Errors.exit_with_error(logger, message=_("dataalerts.failure.error.datasourceNotFound")) - return matching_datasources[0] diff --git a/tabcmd/commands/server.py b/tabcmd/commands/server.py index bde8c624..f215e3a8 100644 --- a/tabcmd/commands/server.py +++ b/tabcmd/commands/server.py @@ -45,10 +45,10 @@ def find_user(logger, server, username): @staticmethod def get_items_by_name(logger, item_endpoint, item_name: str, container: Optional[TSC.ProjectItem] = None) -> List: # TODO: typing should reflect that this returns TSC.TableauItem and item_endpoint is of type TSC.QuerysetEndpoint[same] - item_type = type(item_endpoint).__name__ - item_log_name: str = "[" + item_type + "] " + item_name + item_log_name: str = "[{0}] {1}".format(type(item_endpoint).__name__, item_name) if container: - item_log_name = str(container) + "/" + item_log_name + container_name: str = "({0}) {1}".format(container.__class__, container.name) + item_log_name = "{0}/{1}".format(container_name, item_log_name) logger.debug(_("export.status").format(item_log_name)) req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, item_name)) From ffdf100d1537bf28c8589e80d7934d72cd11425a Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 02:53:37 -0800 Subject: [PATCH 07/11] strip opening slash for consistency also add some trace statements showing when we begin the export, fixed some switched arguments --- .../get_url_command.py | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index 302283c1..621d9179 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -1,3 +1,5 @@ +import inspect + import tableauserverclient as TSC from tableauserverclient import ServerResponseError @@ -59,7 +61,7 @@ def run_command(args): GetUrl.get_content_as_file(file_type, content_type, logger, args, server, url) except ServerResponseError as e: Errors.exit_with_error(logger, e) - except BaseException as be: + except Exception as be: Errors.exit_with_error(logger, be, "Error during file download") ## this first set of methods is all parsing the url and file input from the user @@ -76,11 +78,13 @@ def evaluate_content_type(logger, url): Errors.exit_with_error(logger, message=_("get.errors.invalid_content_type").format(url)) @staticmethod - def explain_expected_url(logger, url): + def explain_expected_url(logger, url: str): view_example = "/views//[.ext]" wb_example = "/workbooks/[.ext]" ds_example = "/datasources/ "wb-name", datasource/ds-name -> ds-name + def get_resource_name(url: str, logger): # workbooks/wb-name" -> "wb-name", datasource/ds-name -> ds-name + url = url.lstrip("/") # strip opening / if present name_parts = url.split("/") if len(name_parts) != 2: GetUrl.explain_expected_url(logger, url) @@ -170,6 +175,7 @@ def get_content_as_file(file_type, content_type, logger, args, server, url): @staticmethod def generate_pdf(logger, server, args, view_url): + logger.trace("Entered method " + inspect.stack()[0].function) try: view_item: TSC.ViewItem = GetUrl.get_view_by_content_url(logger, server, view_url) logger.debug(_("content_type.view") + ": {}".format(view_item.name)) @@ -183,6 +189,7 @@ def generate_pdf(logger, server, args, view_url): @staticmethod def generate_png(logger, server, args, view_url): + logger.trace("Entered method " + inspect.stack()[0].function) try: view_item: TSC.ViewItem = GetUrl.get_view_by_content_url(logger, server, view_url) logger.debug(_("content_type.view") + ": {}".format(view_item.name)) @@ -196,6 +203,7 @@ def generate_png(logger, server, args, view_url): @staticmethod def generate_csv(logger, server, args, view_url): + logger.trace("Entered method " + inspect.stack()[0].function) try: view_item: TSC.ViewItem = GetUrl.get_view_by_content_url(logger, server, view_url) logger.debug(_("content_type.view") + ": {}".format(view_item.name)) @@ -211,6 +219,7 @@ def generate_csv(logger, server, args, view_url): @staticmethod def generate_twb(logger, server, args, file_extension, url): + logger.trace("Entered method " + inspect.stack()[0].function) workbook_name = GetUrl.get_resource_name(url, logger) try: target_workbook = GetUrl.get_wb_by_content_url(logger, server, workbook_name) @@ -224,7 +233,8 @@ def generate_twb(logger, server, args, file_extension, url): @staticmethod def generate_tds(logger, server, args, file_extension): - datasource_name = GetUrl.get_resource_name(logger, args.url) + logger.trace("Entered method " + inspect.stack()[0].function) + datasource_name = GetUrl.get_resource_name(args.url, logger) try: target_datasource = GetUrl.get_ds_by_content_url(logger, server, datasource_name) logger.debug(_("content_type.datasource") + ": {}".format(datasource_name)) From 3cb8a18d7e81e4cc56b5c0b76b13368b6c6a4104 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 02:54:02 -0800 Subject: [PATCH 08/11] dont catch BaseException This will also catch a system exit --- tabcmd/commands/site/delete_site_command.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabcmd/commands/site/delete_site_command.py b/tabcmd/commands/site/delete_site_command.py index babc5f41..b5537b46 100644 --- a/tabcmd/commands/site/delete_site_command.py +++ b/tabcmd/commands/site/delete_site_command.py @@ -32,7 +32,7 @@ def run_command(args): server.sites.delete(target_site_id) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, strings[1], e) - except BaseException as e: + except Exception as e: Errors.exit_with_error(logger, strings[4], e) logger.info(strings[0].format(args.site_name_to_delete)) From 4a9d3f3596ec85de3bcfc7a449471185aa627916 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 02:54:22 -0800 Subject: [PATCH 09/11] Add credentials to publish call --- .../publish_command.py | 24 +++++---- tabcmd/execution/global_options.py | 4 +- tests/commands/test_run_commands.py | 2 + tests/e2e/online_tests.py | 53 ++++++++++++++----- 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 3abb6c29..e7daf450 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -55,14 +55,9 @@ def run_command(args): logger.info("Publishing as " + publish_mode) if args.db_username: - creds = TSC.models.ConnectionCredentials(args.db_username, - args.db_password, - embed=args.save_db_password) + creds = TSC.models.ConnectionCredentials(args.db_username, args.db_password, embed=args.save_db_password) elif args.oauth_username: - creds = TSC.models.ConnectionCredentials(args.oauth_username, - None, - embed=False, - oauth=args.save_oauth) + creds = TSC.models.ConnectionCredentials(args.oauth_username, None, embed=False, oauth=args.save_oauth) else: logger.debug("No db-username or oauth-username found in command") creds = None @@ -72,8 +67,14 @@ def run_command(args): if source in ["twbx", "twb"]: new_workbook = TSC.WorkbookItem(project_id, name=args.name, show_tabs=args.tabbed) try: - new_workbook = server.workbooks.publish(new_workbook, args.filename, publish_mode, - connection_credentials=creds, as_job=False, skip_connection_check=False) + new_workbook = server.workbooks.publish( + new_workbook, + args.filename, + publish_mode, + connection_credentials=creds, + as_job=False, + skip_connection_check=False, + ) except IOError as ioe: Errors.exit_with_error(logger, ioe) @@ -83,8 +84,9 @@ def run_command(args): new_datasource = TSC.DatasourceItem(project_id, name=args.name) new_datasource.use_remote_query_agent = args.use_tableau_bridge try: - new_datasource = server.datasources.publish(new_datasource, args.filename, publish_mode, - connection_credentials=creds) + new_datasource = server.datasources.publish( + new_datasource, args.filename, publish_mode, connection_credentials=creds + ) except IOError as ioe: Errors.exit_with_error(logger, exc) logger.info(_("publish.success") + "\n{}".format(new_datasource.webpage_url)) diff --git a/tabcmd/execution/global_options.py b/tabcmd/execution/global_options.py index 3aa6e7b4..7b7159b2 100644 --- a/tabcmd/execution/global_options.py +++ b/tabcmd/execution/global_options.py @@ -324,7 +324,9 @@ def set_publish_args(parser): thumbnails.add_argument("--thumbnail-username", help="Not yet implemented") thumbnails.add_argument("--thumbnail-group", help="Not yet implemented") # not implemented in the REST API - parser.add_argument("--use-tableau-bridge", help="Refresh datasource through Tableau Bridge") + parser.add_argument("--use-tableau-bridge", + action="store_true", + help="Refresh datasource through Tableau Bridge") def set_overwrite_option(parser): diff --git a/tests/commands/test_run_commands.py b/tests/commands/test_run_commands.py index 22b9dda0..00eda114 100644 --- a/tests/commands/test_run_commands.py +++ b/tests/commands/test_run_commands.py @@ -139,6 +139,8 @@ def test_publish(self, mock_session, mock_server): mock_args.parent_project_path = "projects" mock_args.name = "" mock_args.tabbed = True + mock_args.db_username = None + mock_args.oauth_username = None mock_server.projects = getter publish_command.PublishCommand.run_command(mock_args) mock_session.assert_called() diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index 236820f5..4e4255f8 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -4,6 +4,7 @@ import time import unittest +from credentials import waremart_password, waremart_user from tests.e2e import setup_e2e debug_log = "--logging-level=DEBUG" @@ -70,15 +71,26 @@ def _publish_samples(self, project_name): arguments = [command, "--name", project_name] _test_command(arguments) - def _publish_wb(self, file, name): + def _publish_args(self, file, name, tabbed=None): command = "publish" arguments = [command, file, "--name", name, "--overwrite"] - return _test_command(arguments) - - def _publish_ds(self, file, name): - command = "publish" - arguments = [command, file, "--name", name, "--overwrite"] - return _test_command(arguments) + return arguments + + def _publish_creds_args(self, arguments, db_user=None, db_pass=None, db_save=None, oauth_user=None, oauth_save=None): + if db_user: + arguments.append("--db-username") + arguments.append(db_user) + if db_pass: + arguments.append("--db-password") + arguments.append(db_pass) + if db_save: + arguments.append("--save-db-password") + if oauth_user: + arguments.append("--oauth-username") + arguments.append(oauth_user) + if oauth_save: + arguments.append("--save-oauth") + return arguments def _delete_wb(self, file): command = "delete" @@ -144,6 +156,7 @@ def _list(self, item_type: str): TWBX_WITHOUT_EXTRACT_SHEET = "Testsheet1" TDSX_WITH_EXTRACT_NAME = "WorldIndicators" TDSX_FILE_WITH_EXTRACT = "World Indicators.tdsx" + TWB_WITH_EMBEDDED_CONNECTION = "embedded_connection_waremart.twb" @pytest.mark.order(1) def test_login(self): @@ -250,7 +263,8 @@ def test_delete_projects(self): def test_wb_publish(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) - self._publish_wb(file, name_on_server) + arguments = self._publish_args(file, name_on_server) + _test_command(arguments) @pytest.mark.order(10) def test_wb_get(self): @@ -279,11 +293,20 @@ def test_wb_delete(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME self._delete_wb(name_on_server) + @pytest.mark.order(11) + def test_wb_publish_embedded(self): + name_on_server = OnlineCommandTest.TWB_WITH_EMBEDDED_CONNECTION + file = os.path.join("tests", "assets", OnlineCommandTest.TWB_WITH_EMBEDDED_CONNECTION) + arguments = self._publish_args(file, name_on_server) + arguments = self._publish_creds_args(arguments, waremart_user, waremart_password, True) + _test_command(arguments) + @pytest.mark.order(12) def test_publish_ds(self): name_on_server = OnlineCommandTest.TDSX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TDSX_FILE_WITH_EXTRACT) - self._publish_ds(file, name_on_server) + arguments = self._publish_args(file, name_on_server) + _test_command(arguments) @pytest.mark.order(13) def test__get_ds(self): @@ -300,7 +323,7 @@ def test_delete_extract(self): # fails because the extract has a bad data connection :/ name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) - self._publish_wb(file, name_on_server) + self._publish_args(file, name_on_server) self._delete_extract(name_on_server) @pytest.mark.order(16) @@ -314,7 +337,8 @@ def test_refresh_extract(self): # must be a datasource owned by the test user name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) - self._publish_wb(file, name_on_server) + arguments = self._publish_args(file, name_on_server) + _test_command(arguments) name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME self._refresh_extract(name_on_server) @@ -324,7 +348,9 @@ def test_refresh_extract(self): def test_export_wb_pdf(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) - self._publish_wb(file, name_on_server) + arguments = self._publish_args(file, name_on_server) + _test_command(arguments) + command = "export" friendly_name = name_on_server + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET arguments = [command, friendly_name, "--fullpdf", "-f", "exported_wb.pdf"] @@ -334,7 +360,8 @@ def test_export_wb_pdf(self): def test_export_view_pdf(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) - self._publish_wb(file, name_on_server) + arguments = self._publish_args(file, name_on_server) + _test_command(arguments) command = "export" friendly_name = name_on_server + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET + "?param1=3" arguments = [command, friendly_name, "--pdf", "-f", "exported_view.pdf"] From 94803ed8b971dc993d082bc8ead384b1b1d47b58 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 11:56:53 -0800 Subject: [PATCH 10/11] fix __class__ ref in static method --- .../commands/datasources_and_workbooks/get_url_command.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index 621d9179..4daacae5 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -78,14 +78,14 @@ def evaluate_content_type(logger, url): Errors.exit_with_error(logger, message=_("get.errors.invalid_content_type").format(url)) @staticmethod - def explain_expected_url(logger, url: str): + def explain_expected_url(logger, url: str, command: str): view_example = "/views//[.ext]" wb_example = "/workbooks/[.ext]" ds_example = "/datasources/ "wb-name", dat url = url.lstrip("/") # strip opening / if present name_parts = url.split("/") if len(name_parts) != 2: - GetUrl.explain_expected_url(logger, url) + GetUrl.explain_expected_url(logger, url, "GetURl") resource_name_with_params = name_parts[::-1][0] # last part resource_name_with_ext = GetUrl.strip_query_params(resource_name_with_params) resource_name = GetUrl.get_name_without_possible_extension(resource_name_with_ext) @@ -140,7 +140,7 @@ def get_resource_name(url: str, logger): # workbooks/wb-name" -> "wb-name", dat def get_view_url(url, logger): # "views/wb-name/view-name" -> wb-name/sheets/view-name name_parts = url.split("/") # ['views', 'wb-name', 'view-name'] if len(name_parts) != 3: - GetUrl.explain_expected_url(logger, url) + GetUrl.explain_expected_url(logger, url, "GetURl") workbook_name = name_parts[1] view_name = name_parts[::-1][0] view_name = GetUrl.strip_query_params(view_name) From 4f5c8199ec5b3836f1dc5d2dd274755ee4620f0e Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 7 Dec 2022 11:59:33 -0800 Subject: [PATCH 11/11] format --- .../datasources_and_workbooks_command.py | 2 -- .../commands/datasources_and_workbooks/get_url_command.py | 6 +++--- tabcmd/execution/global_options.py | 4 +--- tests/e2e/online_tests.py | 4 +++- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py b/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py index 1159a04c..e59851ab 100644 --- a/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py +++ b/tabcmd/commands/datasources_and_workbooks/datasources_and_workbooks_command.py @@ -59,7 +59,6 @@ def get_ds_by_content_url(logger, server, datasource_content_url) -> TSC.Datasou Errors.exit_with_error(logger, message=_("dataalerts.failure.error.datasourceNotFound")) return matching_datasources[0] - @staticmethod def apply_values_from_url_params(request_options: TSC.PDFRequestOptions, url, logger) -> None: # should be able to replace this with request_options._append_view_filters(params) @@ -139,4 +138,3 @@ def save_to_file(logger, output, filename): with open(filename, "wb") as f: f.write(output) logger.info(_("export.success").format("", filename)) - diff --git a/tabcmd/commands/datasources_and_workbooks/get_url_command.py b/tabcmd/commands/datasources_and_workbooks/get_url_command.py index 4daacae5..afecd1f3 100644 --- a/tabcmd/commands/datasources_and_workbooks/get_url_command.py +++ b/tabcmd/commands/datasources_and_workbooks/get_url_command.py @@ -83,9 +83,9 @@ def explain_expected_url(logger, url: str, command: str): wb_example = "/workbooks/[.ext]" ds_example = "/datasources/