Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

list content with attributes #332

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 58 additions & 10 deletions tabcmd/commands/site/list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class ListCommand(Server):
# strings to move to string files
local_strings = {
"tabcmd_content_listing": "===== Listing {0} content for user {1}...",
"tabcmd_listing_label_name": "\tNAME: {}",
"tabcmd_listing_label_name": "NAME: {}",
"tabcmd_listing_label_id": "ID: {}",
"tabcmd_listing_label_owner": "OWNER: {}",
"tabcmd_content_none": "No content found.",
}

Expand All @@ -27,7 +28,17 @@ def define_args(list_parser):
args_group.add_argument(
"content", choices=["projects", "workbooks", "datasources", "flows"], help="View content"
)
args_group.add_argument("-d", "--details", action="store_true", help="Show object details")

format_group = list_parser.add_mutually_exclusive_group()
# TODO: should this be saved directly to csv?
format_group.add_argument("--machine", action="store_true", help="Format output as csv for machine reading")

data_group = list_parser.add_argument_group(title="Attributes to include")
# data_group.add_argument("-i", "--id", action="store_true", help="Show item id") # default true
data_group.add_argument("-n", "--name", action="store_true", help="Show item name") # default true
data_group.add_argument("-o", "--owner", action="store_true", help="Show item owner")
data_group.add_argument("-d", "--details", action="store_true", help="Show children of the item")
data_group.add_argument("-a", "--address", action="store_true", help="Show web address of the item")

@staticmethod
def run_command(args):
Expand All @@ -51,16 +62,53 @@ def run_command(args):

if not items or len(items) == 0:
logger.info(ListCommand.local_strings["tabcmd_content_none"])
exit(0)


logger.info(ListCommand.show_header(args, content_type))
for item in items:
if args.details:
logger.info("\t{}".format(item))
if content_type == "workbooks":
server.workbooks.populate_views(item)
for v in item.views:
logger.info(v)
if args.machine:
id = item.id
name = ", " + item.name if args.name else ""
owner =", " + item.owner_id if args.owner else ""
url = ""
if args.address and content_type in ["workbooks, datasources"]:
url = item.content_url
children = ListCommand.format_children_listing(args, server, content_type, item) if args.details else ""

else:
logger.info(ListCommand.local_strings["tabcmd_listing_label_id"].format(item.id))
logger.info(ListCommand.local_strings["tabcmd_listing_label_name"].format(item.name))
id = ListCommand.local_strings["tabcmd_listing_label_id"].format(item.id)
name = ", " + ListCommand.local_strings["tabcmd_listing_label_name"].format(item.name) if args.name else ""
owner = ", " + ListCommand.local_strings["tabcmd_listing_label_owner"].format(item.owner_id) if args.owner else ""

url = ""
if args.address and content_type == "workbooks":
url = item.content_url
children = ListCommand.format_children_listing(args, server, content_type, item) if args.details else ""

logger.info("{0}{1}{2}{3}".format(id, name, owner, url, children))

# TODO: do we want this line if it is csv output?
logger.info("{} total {}".format(len(items), content_type))
except Exception as e:
Errors.exit_with_error(logger, e)

@staticmethod
def format_children_listing(args, server, content_type, item):
if args.details:
if content_type == "workbooks":
server.workbooks.populate_views(item)
child_items = item.views[:10]
children = ", VIEWS: [" + ", ".join(map(lambda x: x.name, child_items)) + "]"
return children
return ""

@staticmethod
def show_header(args, content_type):
id = "ID"
name = ", NAME" if args.name else ""
owner = ", OWNER" if args.owner else ""
url = ", URL" if args.address and content_type in ["workbooks, datasources"] else ""
children = ", CHILDREN" if args.details and content_type == "workbooks" else ""
return "{0}{1}{2}{3}".format(id, name, owner, children)

36 changes: 29 additions & 7 deletions tests/commands/test_listing_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,62 @@
getter = MagicMock()
getter.get = MagicMock("get", return_value=([fake_item], 1))

mock_args = argparse.Namespace()
mock_args.logging_level = "INFO"


@mock.patch("tabcmd.commands.auth.session.Session.create_session")
@mock.patch("tableauserverclient.Server")
class ListingTests(unittest.TestCase):


@staticmethod
def _set_up_session(mock_session, mock_server):
mock_session.return_value = mock_server
assert mock_session is not None
mock_session.assert_not_called()
global mock_args
mock_args = argparse.Namespace(logging_level="DEBUG")
# set values for things that should always have a default
# should refactor so this can be automated
mock_args.continue_if_exists = False
mock_args.project_name = None
mock_args.parent_project_path = None
mock_args.parent_path = None
mock_args.timeout = None
mock_args.username = None
mock_args.name = True
mock_args.owner = None
mock_args.address = None
mock_args.get_extract_encryption_mode = False
mock_args.details = False


def test_list_sites(self, mock_server, mock_session):
ListingTests._set_up_session(mock_session, mock_server)
mock_server.sites = getter
mock_args.get_extract_encryption_mode = False
mock_session.return_value = mock_server
out_value = ListSiteCommand.run_command(mock_args)

def test_list_content(self, mock_server, mock_session):
ListingTests._set_up_session(mock_session, mock_server)
mock_server.flows = getter
mock_args.content = "flows"
mock_session.return_value = mock_server
out_value = ListCommand.run_command(mock_args)

def test_list_wb_details(self, mock_server, mock_session):
ListingTests._set_up_session(mock_session, mock_server)
mock_server.workbooks = getter
mock_args.content = "workbooks"
mock_session.return_value = mock_server
mock_args.details = True
out_value = ListCommand.run_command(mock_args)

def test_list_datasources(self, mock_server, mock_session):
ListingTests._set_up_session(mock_session, mock_server)
mock_server.datasources = getter
mock_args.content = "datasources"
mock_session.return_value = mock_server
mock_args.details = True
out_value = ListCommand.run_command(mock_args)

def test_list_projects(self, mock_server, mock_session):
ListingTests._set_up_session(mock_session, mock_server)
mock_server.projects = getter
mock_args.content = "projects"
mock_session.return_value = mock_server
Expand Down
7 changes: 1 addition & 6 deletions tests/commands/test_publish_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
from unittest.mock import *
import tableauserverclient as TSC

from tabcmd.commands.auth import login_command
from tabcmd.commands.datasources_and_workbooks import delete_command, export_command, get_url_command, publish_command


from typing import List, NamedTuple, TextIO, Union
import io
from tabcmd.commands.datasources_and_workbooks import publish_command

mock_args = argparse.Namespace()

Expand Down
7 changes: 6 additions & 1 deletion tests/commands/test_run_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,16 @@ def test_create_user(self, mock_session, mock_server):
mock_session.assert_called()

def test_list_content(self, mock_session, mock_server):

RunCommandsTest._set_up_session(mock_session, mock_server)
mock_args.name = False
mock_args.owner = None
mock_args.address = None
mock_args.get_extract_encryption_mode = False
mock_args.details = False
mock_args.content = "workbooks"
list_command.ListCommand.run_command(mock_args)
mock_args.content = "projects"
list_command.ListCommand.run_command(mock_args)
mock_args.content = "flows"
list_command.ListCommand.run_command(mock_args)
# todo: details, filters
Loading