Skip to content

Commit

Permalink
Add Connection Credentials
Browse files Browse the repository at this point in the history
Allow users to add connection credentials to Datasources and workbook
publish requests. Should work for smaller requests and chunked requests
  • Loading branch information
geordielad committed Oct 27, 2016
1 parent 6544117 commit b6121d1
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 18 deletions.
4 changes: 2 additions & 2 deletions tableauserverclient/__init__.py
@@ -1,10 +1,10 @@
from .namespace import NAMESPACE
from .models import ConnectionItem, DatasourceItem,\
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
GroupItem, PaginationItem, ProjectItem, ScheduleItem, \
SiteItem, TableauAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError, \
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem
from .server import RequestOptions, Filter, Sort, Server, ServerResponseError,\
MissingRequiredFieldError, NotSignedInError

__version__ = '0.0.1'
__VERSION__ = __version__
__VERSION__ = __version__
1 change: 1 addition & 0 deletions tableauserverclient/models/__init__.py
@@ -1,3 +1,4 @@
from .connection_credentials import ConnectionCredentials
from .connection_item import ConnectionItem
from .datasource_item import DatasourceItem
from .exceptions import UnpopulatedPropertyError
Expand Down
5 changes: 5 additions & 0 deletions tableauserverclient/models/connection_credentials.py
@@ -0,0 +1,5 @@
class ConnectionCredentials(object):
def __init__(self, name, password, embed=True):
self.password = password
self.embed = embed
self.name = name
7 changes: 4 additions & 3 deletions tableauserverclient/server/endpoint/datasources_endpoint.py
Expand Up @@ -94,7 +94,7 @@ def update(self, datasource_item):
return updated_datasource._parse_common_tags(server_response.content)

# Publish datasource
def publish(self, datasource_item, file_path, mode):
def publish(self, datasource_item, file_path, mode, connection_credentials=None):
if not os.path.isfile(file_path):
error = "File path does not lead to an existing file."
raise IOError(error)
Expand Down Expand Up @@ -122,14 +122,15 @@ def publish(self, datasource_item, file_path, mode):
logger.info('Publishing {0} to server with chunking method (datasource over 64MB)'.format(filename))
upload_session_id = Fileuploads.upload_chunks(self.parent_srv, file_path)
url = "{0}&uploadSessionId={1}".format(url, upload_session_id)
xml_request, content_type = RequestFactory.Datasource.publish_req_chunked(datasource_item)
xml_request, content_type = RequestFactory.Datasource.publish_req_chunked(datasource_item, connection_credentials)
else:
logger.info('Publishing {0} to server'.format(filename))
with open(file_path, 'rb') as f:
file_contents = f.read()
xml_request, content_type = RequestFactory.Datasource.publish_req(datasource_item,
filename,
file_contents)
file_contents,
connection_credentials)
server_response = self.post_request(url, xml_request, content_type)
new_datasource = DatasourceItem.from_response(server_response.content)[0]
logger.info('Published {0} (ID: {1})'.format(filename, new_datasource.id))
Expand Down
7 changes: 4 additions & 3 deletions tableauserverclient/server/endpoint/workbooks_endpoint.py
Expand Up @@ -140,7 +140,7 @@ def populate_preview_image(self, workbook_item):
logger.info('Populated preview image for workbook (ID: {0})'.format(workbook_item.id))

# Publishes workbook. Chunking method if file over 64MB
def publish(self, workbook_item, file_path, mode):
def publish(self, workbook_item, file_path, mode, connection_credentials=None):
if not os.path.isfile(file_path):
error = "File path does not lead to an existing file."
raise IOError(error)
Expand Down Expand Up @@ -171,14 +171,15 @@ def publish(self, workbook_item, file_path, mode):
logger.info('Publishing {0} to server with chunking method (workbook over 64MB)'.format(filename))
upload_session_id = Fileuploads.upload_chunks(self.parent_srv, file_path)
url = "{0}&uploadSessionId={1}".format(url, upload_session_id)
xml_request, content_type = RequestFactory.Workbook.publish_req_chunked(workbook_item)
xml_request, content_type = RequestFactory.Workbook.publish_req_chunked(workbook_item, connection_credentials)
else:
logger.info('Publishing {0} to server'.format(filename))
with open(file_path, 'rb') as f:
file_contents = f.read()
xml_request, content_type = RequestFactory.Workbook.publish_req(workbook_item,
filename,
file_contents)
file_contents,
connection_credentials)
server_response = self.post_request(url, xml_request, content_type)
new_workbook = WorkbookItem.from_response(server_response.content)[0]
logger.info('Published {0} (ID: {1})'.format(filename, new_workbook.id))
Expand Down
30 changes: 20 additions & 10 deletions tableauserverclient/server/request_factory.py
Expand Up @@ -30,12 +30,17 @@ def signin_req(self, auth_item):


class DatasourceRequest(object):
def _generate_xml(self, datasource_item):
def _generate_xml(self, datasource_item, connection_credentials=None):
xml_request = ET.Element('tsRequest')
datasource_element = ET.SubElement(xml_request, 'datasource')
datasource_element.attrib['name'] = datasource_item.name
project_element = ET.SubElement(datasource_element, 'project')
project_element.attrib['id'] = datasource_item.project_id
if connection_credentials:
credentials_element = ET.SubElement(datasource_element,'connectionCredentials')
credentials_element.attrib['name'] = connection_credentials.name
credentials_element.attrib['password'] = connection_credentials.password
credentials_element.attrib['embed'] = str(connection_credentials.embed).lower()
return ET.tostring(xml_request)

def update_req(self, datasource_item):
Expand All @@ -49,15 +54,15 @@ def update_req(self, datasource_item):
owner_element.attrib['id'] = datasource_item.owner_id
return ET.tostring(xml_request)

def publish_req(self, datasource_item, filename, file_contents):
xml_request = self._generate_xml(datasource_item)
def publish_req(self, datasource_item, filename, file_contents, connection_credentials=None):
xml_request = self._generate_xml(datasource_item, connection_credentials)

parts = {'request_payload': ('', xml_request, 'text/xml'),
'tableau_datasource': (filename, file_contents, 'application/octet-stream')}
return _add_multipart(parts)

def publish_req_chunked(self, datasource_item):
xml_request = self._generate_xml(datasource_item)
def publish_req_chunked(self, datasource_item, connection_credentials=None):
xml_request = self._generate_xml(datasource_item, connection_credentials)

parts = {'request_payload': ('', xml_request, 'text/xml')}
return _add_multipart(parts)
Expand Down Expand Up @@ -260,14 +265,19 @@ def add_req(self, user_item):


class WorkbookRequest(object):
def _generate_xml(self, workbook_item):
def _generate_xml(self, workbook_item,connection_credentials=None):
xml_request = ET.Element('tsRequest')
workbook_element = ET.SubElement(xml_request, 'workbook')
workbook_element.attrib['name'] = workbook_item.name
if workbook_item.show_tabs:
workbook_element.attrib['showTabs'] = str(workbook_item.show_tabs).lower()
project_element = ET.SubElement(workbook_element, 'project')
project_element.attrib['id'] = workbook_item.project_id
if connection_credentials:
credentials_element = ET.SubElement(workbook_element,'connectionCredentials')
credentials_element.attrib['name'] = connection_credentials.name
credentials_element.attrib['password'] = connection_credentials.password
credentials_element.attrib['embed'] = str(connection_credentials.embed).lower()
return ET.tostring(xml_request)

def update_req(self, workbook_item):
Expand All @@ -283,15 +293,15 @@ def update_req(self, workbook_item):
owner_element.attrib['id'] = workbook_item.owner_id
return ET.tostring(xml_request)

def publish_req(self, workbook_item, filename, file_contents):
xml_request = self._generate_xml(workbook_item)
def publish_req(self, workbook_item, filename, file_contents, connection_credentials=None):
xml_request = self._generate_xml(workbook_item, connection_credentials)

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):
xml_request = self._generate_xml(workbook_item)
def publish_req_chunked(self, workbook_item, connection_credentials=None):
xml_request = self._generate_xml(workbook_item, connection_credentials)

parts = {'request_payload': ('', xml_request, 'text/xml')}
return _add_multipart(parts)
Expand Down

0 comments on commit b6121d1

Please sign in to comment.