Skip to content
Merged
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 0.12 (10 July 2020)

* Added hidden_views parameter to workbook publish method (#614)
* Added simple paging endpoint for GraphQL/Metadata API (#623)
* Added endpoints to Metadata API for retrieving backfill/eventing status (#626)
* Added maxage parameter to CSV and PDF export options (#635)
* Added support for querying, adding, and deleting favorites (#638)
* Added a sample for publishing datasources (#644)

## 0.11 (1 May 2020)

* Added more fields to Data Acceleration config (#588)
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The following people have contributed to this project to make it possible, and w
* [Geraldine Zanolli](https://github.com/illonage)
* [Jordan Woods](https://github.com/jorwoods)
* [Reba Magier](https://github.com/rmagier1)
* [Stephen Mitchell](https://github.com/scuml)

## Core Team

Expand Down
2 changes: 1 addition & 1 deletion samples/create_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This script demonstrates how to create groups using the Tableau
# Server Client.
#
# To run the script, you must have installed Python 2.7.9 or later.
# To run the script, you must have installed Python 3.5 or later.
####


Expand Down
2 changes: 1 addition & 1 deletion samples/create_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# parent_id.
#
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/create_schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This script demonstrates how to create schedules using the Tableau
# Server Client.
#
# To run the script, you must have installed Python 2.7.9 or later.
# To run the script, you must have installed Python 3.5 or later.
####


Expand Down
2 changes: 1 addition & 1 deletion samples/download_view_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# For more information, refer to the documentations on 'Query View Image'
# (https://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm)
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/filter_sort_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This script demonstrates how to filter groups using the Tableau
# Server Client.
#
# To run the script, you must have installed Python 2.7.9 or later.
# To run the script, you must have installed Python 3.5 or later.
####


Expand Down
2 changes: 1 addition & 1 deletion samples/filter_sort_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# to filter and sort on the name of the projects present on site.
#
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/kill_all_jobs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
####
# This script demonstrates how to kill all of the running jobs
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/list.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
####
# This script demonstrates how to list all of the workbooks or datasources
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/login.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
####
# This script demonstrates how to log in to Tableau Server Client.
#
# To run the script, you must have installed Python 2.7.9 or later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/move_workbook_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# a workbook that matches a given name and update it to be in
# the desired project.
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/move_workbook_sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# a workbook that matches a given name, download the workbook,
# and then publish it to the destination site.
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
85 changes: 85 additions & 0 deletions samples/publish_datasource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
####
# This script demonstrates how to use the Tableau Server Client
# to publish a datasource to a Tableau server. It will publish
# a specified datasource to the 'default' project of the provided site.
#
# Some optional arguments are provided to demonstrate async publishing,
# as well as providing connection credentials when publishing. If the
# provided datasource file is over 64MB in size, TSC will automatically
# publish the datasource using the chunking method.
#
# For more information, refer to the documentations:
# (https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_datasources.htm#publish_data_source)
#
# For signing into server, this script uses personal access tokens. For
# more information on personal access tokens, refer to the documentations:
# (https://help.tableau.com/current/server/en-us/security_personal_access_tokens.htm)
#
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
import logging

import tableauserverclient as TSC


def main():
parser = argparse.ArgumentParser(description='Publish a datasource to server.')
parser.add_argument('--server', '-s', required=True, help='server address')
parser.add_argument('--site', '-i', help='site name')
parser.add_argument('--token-name', '-p', required=True,
help='name of the personal access token used to sign into the server')
parser.add_argument('--token-value', '-v', required=True,
help='value of the personal access token used to sign into the server')
parser.add_argument('--filepath', '-f', required=True, help='filepath to the datasource to publish')
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
help='desired logging level (set to error by default)')
parser.add_argument('--async', '-a', help='Publishing asynchronously', dest='async_', action='store_true')
parser.add_argument('--conn-username', help='connection username')
parser.add_argument('--conn-password', help='connection password')
parser.add_argument('--conn-embed', help='embed connection password to datasource', action='store_true')
parser.add_argument('--conn-oauth', help='connection is configured to use oAuth', action='store_true')

args = parser.parse_args()

# Ensure that both the connection username and password are provided, or none at all
if (args.conn_username and not args.conn_password) or (not args.conn_username and args.conn_password):
parser.error("Both the connection username and password must be provided")

# Set logging level based on user input, or error by default
logging_level = getattr(logging, args.logging_level.upper())
logging.basicConfig(level=logging_level)

# Sign in to server
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):
# Create a new datasource item to publish - empty project_id field
# will default the publish to the site's default project
new_datasource = TSC.DatasourceItem(project_id="")

# Create a connection_credentials item if connection details are provided
new_conn_creds = None
if args.conn_username:
new_conn_creds = TSC.ConnectionCredentials(args.conn_username, args.conn_password,
embed=args.conn_embed, oauth=args.conn_oauth)

# Define publish mode - Overwrite, Append, or CreateNew
publish_mode = TSC.Server.PublishMode.Overwrite

# Publish datasource
if args.async_:
# Async publishing, returns a job_item
new_job = server.datasources.publish(new_datasource, args.filepath, publish_mode,
connection_credentials=new_conn_creds, as_job=True)
print("Datasource published asynchronously. Job ID: {0}".format(new_job.id))
else:
# Normal publishing, returns a datasource_item
new_datasource = server.datasources.publish(new_datasource, args.filepath, publish_mode,
connection_credentials=new_conn_creds)
print("Datasource published. Datasource ID: {0}".format(new_datasource.id))


if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion samples/publish_workbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# For more information, refer to the documentations on 'Publish Workbook'
# (https://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm)
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/refresh.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
####
# This script demonstrates how to use trigger a refresh on a datasource or workbook
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/refresh_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This script demonstrates how to use the Tableau Server Client
# to query extract refresh tasks and run them as needed.
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/set_http_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This script demonstrates how to set http options. It will set the option
# to not verify SSL certificate, and query all workbooks on site.
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
2 changes: 1 addition & 1 deletion samples/update_connection.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
####
# This script demonstrates how to update a connections credentials on a server to embed the credentials
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
# To run the script, you must have installed Python 3.5 or later.
####

import argparse
Expand Down
4 changes: 3 additions & 1 deletion tableauserverclient/datetime_helpers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import datetime

# This code below is from the python documentation for tzinfo: https://docs.python.org/2.3/lib/datetime-tzinfo.html
# This code below is from the python documentation for
# tzinfo: https://docs.python.org/2.3/lib/datetime-tzinfo.html

ZERO = datetime.timedelta(0)
HOUR = datetime.timedelta(hours=1)

Expand Down
1 change: 1 addition & 0 deletions tableauserverclient/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .datasource_item import DatasourceItem
from .database_item import DatabaseItem
from .exceptions import UnpopulatedPropertyError
from .favorites_item import FavoriteItem
from .group_item import GroupItem
from .flow_item import FlowItem
from .interval_item import IntervalItem, DailyInterval, WeeklyInterval, MonthlyInterval, HourlyInterval
Expand Down
3 changes: 1 addition & 2 deletions tableauserverclient/models/column_item.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import xml.etree.ElementTree as ET

from .property_decorators import property_is_enum, property_not_empty
from .exceptions import UnpopulatedPropertyError
from .property_decorators import property_not_empty


class ColumnItem(object):
Expand Down
12 changes: 8 additions & 4 deletions tableauserverclient/models/connection_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ def connection_type(self):
return self._connection_type

def __repr__(self):
return "<ConnectionItem#{_id} embed={embed_password} type={_connection_type} username={username}>"\
.format(**self.__dict__)
return (
"<ConnectionItem#{_id} embed={embed_password} "
"type={_connection_type} username={username}>".format(**self.__dict__)
)

@classmethod
def from_response(cls, resp, ns):
Expand Down Expand Up @@ -76,11 +78,13 @@ def from_xml_element(cls, parsed_response, ns):
connection_item.server_address = connection_xml.get('serverAddress', None)
connection_item.server_port = connection_xml.get('serverPort', None)

connection_credentials = connection_xml.find('.//t:connectionCredentials', namespaces=ns)
connection_credentials = connection_xml.find(
'.//t:connectionCredentials', namespaces=ns)

if connection_credentials is not None:

connection_item.connection_credentials = ConnectionCredentials.from_xml_element(connection_credentials)
connection_item.connection_credentials = ConnectionCredentials.from_xml_element(
connection_credentials)

return all_connection_items

Expand Down
4 changes: 0 additions & 4 deletions tableauserverclient/models/data_acceleration_report_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ def site(self):
def sheet_uri(self):
return self._sheet_uri

@property
def site(self):
return self._site

@property
def unaccelerated_session_count(self):
return self._unaccelerated_session_count
Expand Down
2 changes: 0 additions & 2 deletions tableauserverclient/models/database_item.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import xml.etree.ElementTree as ET

from .permissions_item import Permission

from .property_decorators import property_is_enum, property_not_empty, property_is_boolean
from .exceptions import UnpopulatedPropertyError

Expand Down
49 changes: 49 additions & 0 deletions tableauserverclient/models/favorites_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import xml.etree.ElementTree as ET
import logging
from .workbook_item import WorkbookItem
from .view_item import ViewItem
from .project_item import ProjectItem
from .datasource_item import DatasourceItem

logger = logging.getLogger('tableau.models.favorites_item')


class FavoriteItem:
class Type:
Workbook = 'workbook'
Datasource = 'datasource'
View = 'view'
Project = 'project'

@classmethod
def from_response(cls, xml, namespace):
favorites = {
'datasources': [],
'projects': [],
'views': [],
'workbooks': [],
}

parsed_response = ET.fromstring(xml)
for workbook in parsed_response.findall('.//t:favorite/t:workbook', namespace):
fav_workbook = WorkbookItem('')
fav_workbook._set_values(*fav_workbook._parse_element(workbook, namespace))
if fav_workbook:
favorites['workbooks'].append(fav_workbook)
for view in parsed_response.findall('.//t:favorite[t:view]', namespace):
fav_views = ViewItem.from_xml_element(view, namespace)
if fav_views:
for fav_view in fav_views:
favorites['views'].append(fav_view)
for datasource in parsed_response.findall('.//t:favorite/t:datasource', namespace):
fav_datasource = DatasourceItem('')
fav_datasource._set_values(*fav_datasource._parse_element(datasource, namespace))
if fav_datasource:
favorites['datasources'].append(fav_datasource)
for project in parsed_response.findall('.//t:favorite/t:project', namespace):
fav_project = ProjectItem('p')
fav_project._set_values(*fav_project._parse_element(project))
if fav_project:
favorites['projects'].append(fav_project)

return favorites
2 changes: 1 addition & 1 deletion tableauserverclient/models/flow_item.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import xml.etree.ElementTree as ET
from .exceptions import UnpopulatedPropertyError
from .property_decorators import property_not_nullable, property_is_boolean
from .property_decorators import property_not_nullable
from .tag_item import TagItem
from ..datetime_helpers import parse_datetime
import copy
Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/models/interval_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def interval(self, interval_value):
try:
if not (1 <= int(interval_value) <= 31):
raise ValueError(error)
except ValueError as e:
except ValueError:
if interval_value != "LastDay":
raise ValueError(error)

Expand Down
Loading