Skip to content

Commit

Permalink
Enable filtering when an entire workbook is exported (#339)
Browse files Browse the repository at this point in the history
Fixes #233

example:
tabcmd export SampleWorkbook/Sheet1?Product%20Type=Tea --fullpdf --pagelayout landscape

OR (new command format option, same output)
tabcmd export SampleWorkbook/Sheet1 --filter" "Product Type=Tea" --fullpdf --pagelayout landscape
  • Loading branch information
jacalata authored Jan 10, 2025
2 parents 6230ccf + 1180703 commit dd10d39
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 53 deletions.
4 changes: 1 addition & 3 deletions tabcmd/commands/datasources_and_workbooks/export_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,12 @@ def apply_filters_from_args(request_options: TSC.PDFRequestOptions, args, logger
for value in params:
ExportCommand.apply_filter_value(logger, request_options, value)

# filtering isn't actually implemented for workbooks in REST
@staticmethod
def download_wb_pdf(server, workbook_item, args, logger):
logger.debug(args.url)
pdf_options = TSC.PDFRequestOptions(maxage=1)
if args.filter or args.url.find("?") > 0:
logger.info("warning: Filter values will not be applied when exporting a complete workbook")
ExportCommand.apply_values_from_url_params(logger, pdf_options, args.url)
ExportCommand.apply_filters_from_args(pdf_options, args, logger)
ExportCommand.apply_pdf_options(logger, pdf_options, args)
logger.debug(pdf_options.get_query_params())
server.workbooks.populate_pdf(workbook_item, pdf_options)
Expand Down
139 changes: 89 additions & 50 deletions tests/e2e/online_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@
debug_log = "--logging-level=DEBUG"
indexing_sleep_time = 1 # wait 1 second to confirm server has indexed updates

# object names
# object names: helpful if they are always unique
unique = str(time.gmtime().tm_sec)

default_project_name = "default-proj" + unique
group_name = "test-ing-group" + unique
workbook_name = "wb_1_" + unique

default_project_name = "Personal Work" # "default-proj" + unique
parent_location = "parent" + unique
project_name = "test-proj-" + unique

# Flags to let us skip tests if we know we don't have the required access
server_admin = False
site_admin = True
project_admin = True
site_admin = False
project_admin = False
extract_encryption_enabled = False
use_tabcmd_classic = False # toggle between testing using tabcmd 2 or tabcmd classic


def _test_command(test_args: list[str]):
# this will raise an exception if it gets a non-zero return code
# that should bubble up and fail the test?
# using tabcmd 2
# that will bubble up and fail the test

# default: run tests using tabcmd 2
calling_args = ["python", "-m", "tabcmd"] + test_args + [debug_log] + ["--no-certcheck"]

# call the executable directly: lets us drop in classic tabcmd
Expand Down Expand Up @@ -93,9 +93,11 @@ def _publish_samples(self, project_name):
arguments = [command, "--name", project_name]
_test_command(arguments)

def _publish_args(self, file, name):
def _publish_args(self, file, name, optional_args=None):
command = "publish"
arguments = [command, file, "--name", name, "--overwrite"]
arguments = [command, file, "--name", name, "--project", default_project_name, "--overwrite"]
if optional_args:
arguments.append(optional_args)
return arguments

def _publish_creds_args(
Expand All @@ -116,31 +118,52 @@ def _publish_creds_args(
arguments.append("--save-oauth")
return arguments

def _delete_wb(self, file):
def _delete_wb(self, name):
command = "delete"
arguments = [command, file]
arguments = [command, "--project", default_project_name, name]
_test_command(arguments)

def _delete_ds(self, file):
def _delete_ds(self, name):
command = "delete"
arguments = [command, "--datasource", file]
arguments = [command, "--project", default_project_name, "--datasource", name]
_test_command(arguments)

def _get_view(self, wb_name_on_server, sheet_name, filename=None):
def _get_view(self, wb_name_on_server, sheet_name, filename=None, additional_args=None):
server_file = "/views/" + wb_name_on_server + "/" + sheet_name
command = "get"
arguments = [command, server_file]
if filename:
arguments = arguments + ["--filename", filename]
if additional_args:
arguments = arguments + additional_args
_test_command(arguments)

def _get_custom_view(self):
# TODO
command = "get"

def _get_view_with_filters(self):
# TODO
command = "get"


def _export_wb(self, friendly_name, filename=None, additional_args=None):
command = "export"
arguments = [command, friendly_name, "--fullpdf"]

if filename:
arguments = arguments + ["--filename", filename]
if additional_args:
arguments = arguments + additional_args
_test_command(arguments)


def _export_view(self, wb_name_on_server, sheet_name, export_type, filename=None, additional_args=None):
server_file = "/" + wb_name_on_server + "/" + sheet_name
command = "export"
arguments = [command, server_file, export_type]
if filename:
arguments = arguments + ["--filename", filename]
if additional_args:
arguments = arguments + additional_args
_test_command(arguments)

def _get_workbook(self, server_file):
command = "get"
Expand All @@ -157,34 +180,40 @@ def _get_datasource(self, server_file):

def _create_extract(self, type, wb_name):
command = "createextracts"
arguments = [command, type, wb_name]
arguments = [command, type, wb_name, "--project", default_project_name]
if extract_encryption_enabled and not use_tabcmd_classic:
arguments.append("--encrypt")
_test_command(arguments)

# variation: url
def _refresh_extract(self, type, wb_name):
command = "refreshextracts"
arguments = [command, wb_name] # should not need -w
arguments = [command, "-w", wb_name, "--project", default_project_name] # bug: should not need -w
try:
_test_command(arguments)
except Exception as e:
print(e)
print("expected (tabcmd classic)")
print(" *** Unexpected response from the server: Bad request")
print("This refresh extracts operation is not allowed for workbook World Indicators (errorCode=80030)")
if use_tabcmd_classic:
print("expected (tabcmd classic)")
print(" *** Unexpected response from the server: Bad request")
print("This refresh extracts operation is not allowed for workbook World Indicators (errorCode=80030)")
else:
raise e

def _delete_extract(self, type, item_name):
command = "deleteextracts"
arguments = [command, type, item_name, "--include-all"]
arguments = [command, type, item_name, "--include-all", "--project", default_project_name]
try:
_test_command(arguments)
except Exception as e:
print(e)
print("Expected (tabcmd classic:")
print("*** Unexpected response from the server: Unable to load Data Source")
print("Remove extract operation failed. (errorCode=310028)")
print("8530479: Remove Extract is not supported for this Datasources (errorCode=310030)")
if use_tabcmd_classic:
print("Expected (tabcmd classic):")
print("*** Unexpected response from the server: Unable to load Data Source")
print("Remove extract operation failed. (errorCode=310028)")
print("8530479: Remove Extract is not supported for this Datasources (errorCode=310030)")
else:
raise e

def _list(self, item_type: str):
command = "list"
Expand Down Expand Up @@ -418,41 +447,51 @@ def test__delete_ds_live(self):
name_on_server = OnlineCommandTest.TDS_FILE_LIVE_NAME
self._delete_ds(name_on_server)

@pytest.mark.order(19)
def test_export_wb_filters(self):
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
friendly_name = wb_name_on_server +"/" + sheet_name
filters = ["--filter", "Product Type=Tea", "--fullpdf", "--pagelayout", "landscape"]
self._export_wb(friendly_name, "filter_a_wb_to_tea_and_two_pages.pdf", filters)
# NOTE: this test needs a visual check on the returned pdf to confirm the expected appearance

@pytest.mark.order(19)
def test_export_wb_pdf(self):
command = "export"
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
friendly_name = (
OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET + "?param1=3"
wb_name_on_server + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
)
arguments = [command, friendly_name, "--fullpdf", "-f", "exported_wb.pdf"]
_test_command(arguments)

filename = "exported_wb.pdf"
self._export_wb(friendly_name, filename)
@pytest.mark.order(19)
def test_export_data_csv(self):
command = "export"
friendly_name = (
OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET + "?param1=3"
)
arguments = [command, friendly_name, "--csv", "-f", "exported_data.csv"]
_test_command(arguments)
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
self._export_view(wb_name_on_server, sheet_name, "--csv", "exported_data.csv")

@pytest.mark.order(19)
def test_export_view_png(self):
command = "export"
friendly_name = (
OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET + "?param1=3"
)
arguments = [command, friendly_name, "--png", "-f", "exported_view.png"]
_test_command(arguments)
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
self._export_view(wb_name_on_server, sheet_name, "--png", "export_view.png")

@pytest.mark.order(19)
def test_export_view_pdf(self):
command = "export"
friendly_name = (
OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + "/" + OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET + "?param1=3"
)
arguments = [command, friendly_name, "--pdf", "-f", "exported_view.pdf"]
_test_command(arguments)
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
self._export_view(wb_name_on_server, sheet_name, "--pdf", "export_view_pdf.pdf")

@pytest.mark.order(19)
def test_export_view_filtered(self):
wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME
sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET
filename = "view_with_filters.pdf"

filters = ["--filter", "Product Type=Tea"]
self._export_view(wb_name_on_server, sheet_name, "--pdf", filename, filters)

@pytest.mark.order(20)
def test_delete_site_users(self):
Expand Down

0 comments on commit dd10d39

Please sign in to comment.