diff --git a/tableauserverclient/server/endpoint/workbooks_endpoint.py b/tableauserverclient/server/endpoint/workbooks_endpoint.py index 1559bc41b..c7c1000bd 100644 --- a/tableauserverclient/server/endpoint/workbooks_endpoint.py +++ b/tableauserverclient/server/endpoint/workbooks_endpoint.py @@ -234,7 +234,11 @@ def delete_permission(self, item, capability_item): @api(version="2.0") @parameter_added_in(as_job='3.0') @parameter_added_in(connections='2.8') - def publish(self, workbook_item, file_path, mode, connection_credentials=None, connections=None, as_job=False): + def publish( + self, workbook_item, file_path, mode, + connection_credentials=None, connections=None, as_job=False, + hidden_views=None + ): if connection_credentials is not None: import warnings @@ -277,7 +281,8 @@ def publish(self, workbook_item, file_path, mode, connection_credentials=None, c conn_creds = connection_credentials xml_request, content_type = RequestFactory.Workbook.publish_req_chunked(workbook_item, connection_credentials=conn_creds, - connections=connections) + connections=connections, + hidden_views=hidden_views) else: logger.info('Publishing {0} to server'.format(filename)) with open(file_path, 'rb') as f: @@ -287,7 +292,8 @@ def publish(self, workbook_item, file_path, mode, connection_credentials=None, c filename, file_contents, connection_credentials=conn_creds, - connections=connections) + connections=connections, + hidden_views=hidden_views) logger.debug('Request xml: {0} '.format(xml_request[:1000])) # Send the publishing request to server diff --git a/tableauserverclient/server/request_factory.py b/tableauserverclient/server/request_factory.py index 87529b84f..fbb09fc27 100644 --- a/tableauserverclient/server/request_factory.py +++ b/tableauserverclient/server/request_factory.py @@ -38,6 +38,12 @@ def _add_connections_element(connections_element, connection): _add_credentials_element(connection_element, connection_credentials) +def _add_hiddenview_element(views_element, view_name): + view_element = ET.SubElement(views_element, 'view') + view_element.attrib['name'] = view_name + view_element.attrib['hidden'] = "true" + + def _add_credentials_element(parent_element, connection_credentials): credentials_element = ET.SubElement(parent_element, 'connectionCredentials') credentials_element.attrib['name'] = connection_credentials.name @@ -448,7 +454,11 @@ def add_req(self, user_item): class WorkbookRequest(object): - def _generate_xml(self, workbook_item, connection_credentials=None, connections=None): + def _generate_xml( + self, workbook_item, + connection_credentials=None, connections=None, + hidden_views=None + ): xml_request = ET.Element('tsRequest') workbook_element = ET.SubElement(xml_request, 'workbook') workbook_element.attrib['name'] = workbook_item.name @@ -467,6 +477,12 @@ def _generate_xml(self, workbook_item, connection_credentials=None, connections= connections_element = ET.SubElement(workbook_element, 'connections') for connection in connections: _add_connections_element(connections_element, connection) + + if hidden_views is not None: + views_element = ET.SubElement(workbook_element, 'views') + for view_name in hidden_views: + _add_hiddenview_element(views_element, view_name) + return ET.tostring(xml_request) def update_req(self, workbook_item): @@ -494,19 +510,27 @@ def update_req(self, workbook_item): return ET.tostring(xml_request) - def publish_req(self, workbook_item, filename, file_contents, connection_credentials=None, connections=None): + def publish_req( + self, workbook_item, filename, file_contents, + connection_credentials=None, connections=None, hidden_views=None + ): xml_request = self._generate_xml(workbook_item, connection_credentials=connection_credentials, - connections=connections) + connections=connections, + hidden_views=hidden_views) parts = {'request_payload': ('', xml_request, 'text/xml'), 'tableau_workbook': (filename, file_contents, 'application/octet-stream')} return _add_multipart(parts) - def publish_req_chunked(self, workbook_item, connection_credentials=None, connections=None): + def publish_req_chunked( + self, workbook_item, connection_credentials=None, connections=None, + hidden_views=None + ): xml_request = self._generate_xml(workbook_item, connection_credentials=connection_credentials, - connections=connections) + connections=connections, + hidden_views=hidden_views) parts = {'request_payload': ('', xml_request, 'text/xml')} return _add_multipart(parts) diff --git a/test/test_workbook.py b/test/test_workbook.py index 1a62f4fc5..f1d9df9e0 100644 --- a/test/test_workbook.py +++ b/test/test_workbook.py @@ -4,6 +4,7 @@ import tableauserverclient as TSC import xml.etree.ElementTree as ET + from tableauserverclient.datetime_helpers import format_datetime from tableauserverclient.server.endpoint.exceptions import InternalServerError from tableauserverclient.server.request_factory import RequestFactory @@ -436,6 +437,28 @@ def test_publish(self): self.assertEqual('GDP per capita', new_workbook.views[0].name) self.assertEqual('RESTAPISample_0/sheets/GDPpercapita', new_workbook.views[0].content_url) + def test_publish_with_hidden_view(self): + 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') + + 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, + hidden_views=['GDP per capita']) + + request_body = m._adapter.request_history[0]._request.body + self.assertIn( + b'', request_body) + def test_publish_async(self): self.server.version = '3.0' baseurl = self.server.workbooks.baseurl