Skip to content

Commit

Permalink
Adding support for thumbnail related options in workbook publish (#1542)
Browse files Browse the repository at this point in the history
* Adding support for thumbnail related options in workbook publish
  • Loading branch information
renoyjohnm authored Dec 4, 2024
1 parent 9d4e43e commit e3f1e22
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 8 deletions.
38 changes: 31 additions & 7 deletions samples/publish_workbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@ def main():
help="desired logging level (set to error by default)",
)
# Options specific to this sample
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument("--thumbnails-user-id", "-u", help="User ID to use for thumbnails")
group.add_argument("--thumbnails-group-id", "-g", help="Group ID to use for thumbnails")

parser.add_argument("--workbook-name", "-n", help="Name with which to publish the workbook")
parser.add_argument("--file", "-f", help="local filepath of the workbook to publish")
parser.add_argument("--as-job", "-a", help="Publishing asynchronously", action="store_true")
parser.add_argument("--skip-connection-check", "-c", help="Skip live connection check", action="store_true")
parser.add_argument("--project", help="Project within which to publish the workbook")
parser.add_argument("--show-tabs", help="Publish workbooks with tabs displayed", action="store_true")

args = parser.parse_args()

Expand All @@ -50,9 +57,20 @@ def main():
tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site)
server = TSC.Server(args.server, use_server_version=True)
with server.auth.sign_in(tableau_auth):
# Step 2: Get all the projects on server, then look for the default one.
all_projects, pagination_item = server.projects.get()
default_project = next((project for project in all_projects if project.is_default()), None)
# Step2: Retrieve the project id, if a project name was passed
if args.project is not None:
req_options = TSC.RequestOptions()
req_options.filter.add(
TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, args.project)
)
projects = list(TSC.Pager(server.projects, req_options))
if len(projects) > 1:
raise ValueError("The project name is not unique")
project_id = projects[0].id
else:
# Get all the projects on server, then look for the default one.
all_projects, pagination_item = server.projects.get()
project_id = next((project for project in all_projects if project.is_default()), None).id

connection1 = ConnectionItem()
connection1.server_address = "mssql.test.com"
Expand All @@ -67,10 +85,16 @@ def main():
all_connections.append(connection1)
all_connections.append(connection2)

# Step 3: If default project is found, form a new workbook item and publish.
# Step 3: Form a new workbook item and publish.
overwrite_true = TSC.Server.PublishMode.Overwrite
if default_project is not None:
new_workbook = TSC.WorkbookItem(default_project.id)
if project_id is not None:
new_workbook = TSC.WorkbookItem(
project_id=project_id,
name=args.workbook_name,
show_tabs=args.show_tabs,
thumbnails_user_id=args.thumbnails_user_id,
thumbnails_group_id=args.thumbnails_group_id,
)
if args.as_job:
new_job = server.workbooks.publish(
new_workbook,
Expand All @@ -92,7 +116,7 @@ def main():
)
print(f"Workbook published. ID: {new_workbook.id}")
else:
error = "The default project could not be found."
error = "The destination project could not be found."
raise LookupError(error)


Expand Down
27 changes: 26 additions & 1 deletion tableauserverclient/models/workbook_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,14 @@ class as arguments. The workbook item specifies the project.
>>> new_workbook = TSC.WorkbookItem('3a8b6148-493c-11e6-a621-6f3499394a39')
"""

def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None, show_tabs: bool = False) -> None:
def __init__(
self,
project_id: Optional[str] = None,
name: Optional[str] = None,
show_tabs: bool = False,
thumbnails_user_id: Optional[str] = None,
thumbnails_group_id: Optional[str] = None,
) -> None:
self._connections = None
self._content_url = None
self._webpage_url = None
Expand Down Expand Up @@ -130,6 +137,8 @@ def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None,
}
self.data_freshness_policy = None
self._permissions = None
self.thumbnails_user_id = thumbnails_user_id
self.thumbnails_group_id = thumbnails_group_id

return None

Expand Down Expand Up @@ -275,6 +284,22 @@ def revisions(self) -> list[RevisionItem]:
raise UnpopulatedPropertyError(error)
return self._revisions()

@property
def thumbnails_user_id(self) -> Optional[str]:
return self._thumbnails_user_id

@thumbnails_user_id.setter
def thumbnails_user_id(self, value: str):
self._thumbnails_user_id = value

@property
def thumbnails_group_id(self) -> Optional[str]:
return self._thumbnails_group_id

@thumbnails_group_id.setter
def thumbnails_group_id(self, value: str):
self._thumbnails_group_id = value

def _set_connections(self, connections):
self._connections = connections

Expand Down
6 changes: 6 additions & 0 deletions tableauserverclient/server/request_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,12 @@ def _generate_xml(
views_element = ET.SubElement(workbook_element, "views")
for view_name in workbook_item.hidden_views:
_add_hiddenview_element(views_element, view_name)

if workbook_item.thumbnails_user_id is not None:
workbook_element.attrib["thumbnailsUserId"] = workbook_item.thumbnails_user_id
elif workbook_item.thumbnails_group_id is not None:
workbook_element.attrib["thumbnailsGroupId"] = workbook_item.thumbnails_group_id

return ET.tostring(xml_request)

def update_req(self, workbook_item, parent_srv: Optional["Server"] = None):
Expand Down
39 changes: 39 additions & 0 deletions test/test_workbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,45 @@ def test_publish_with_hidden_views_on_workbook(self) -> None:
self.assertTrue(re.search(rb"<views><view.*?hidden=\"true\".*?\/><\/views>", request_body))
self.assertTrue(re.search(rb"<views><view.*?name=\"GDP per capita\".*?\/><\/views>", request_body))

def test_publish_with_thumbnails_user_id(self) -> None:
with open(PUBLISH_XML, "rb") as f:
response_xml = f.read().decode("utf-8")
with requests_mock.mock() as m:
m.post(self.baseurl, text=response_xml)

new_workbook = TSC.WorkbookItem(
name="Sample",
show_tabs=False,
project_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760",
thumbnails_user_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20761",
)

sample_workbook = os.path.join(TEST_ASSET_DIR, "SampleWB.twbx")
publish_mode = self.server.PublishMode.CreateNew
new_workbook = self.server.workbooks.publish(new_workbook, sample_workbook, publish_mode)
request_body = m._adapter.request_history[0]._request.body
# order of attributes in xml is unspecified
self.assertTrue(re.search(rb"thumbnailsUserId=\"ee8c6e70-43b6-11e6-af4f-f7b0d8e20761\"", request_body))

def test_publish_with_thumbnails_group_id(self) -> None:
with open(PUBLISH_XML, "rb") as f:
response_xml = f.read().decode("utf-8")
with requests_mock.mock() as m:
m.post(self.baseurl, text=response_xml)

new_workbook = TSC.WorkbookItem(
name="Sample",
show_tabs=False,
project_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760",
thumbnails_group_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20762",
)

sample_workbook = os.path.join(TEST_ASSET_DIR, "SampleWB.twbx")
publish_mode = self.server.PublishMode.CreateNew
new_workbook = self.server.workbooks.publish(new_workbook, sample_workbook, publish_mode)
request_body = m._adapter.request_history[0]._request.body
self.assertTrue(re.search(rb"thumbnailsGroupId=\"ee8c6e70-43b6-11e6-af4f-f7b0d8e20762\"", request_body))

@pytest.mark.filterwarnings("ignore:'as_job' not available")
def test_publish_with_query_params(self) -> None:
with open(PUBLISH_ASYNC_XML, "rb") as f:
Expand Down

0 comments on commit e3f1e22

Please sign in to comment.