Publishing Extracts from a Template Data Source using tableau_tools

With the release of tableau_tools 4.0.0 and Tableau Server 10.5, most of the pieces are in place in the library and in the product itself to allow for an efficient path for publishing unique extracts for different customers all from a single original data source (or workbook) template.

The basics steps of the technique are:

  1. Create a template live connection to a database table, Custom SQL or a Stored Procedure in Tableau Desktop. This does not need to be the final table/custom SQL or Stored Proc; you can use a test or QA data source and switch it programmatically to the final source
    1. Optional: Set up your the appropriate filtering for a single customer / user / etc. — whatever the main filtering field will be. You can instead add this later programmatically.
  2. Save that file (TDS or TWB)
  3. Use the tableau_tools.tableau_documents sub-module to programmatically add any additional filters or modify the filters / parameters you set
  4. Use tableau_tools to alter the actual table / SP / Custom SQL to the final version of that customer
  5. Add an extract to that data source in tableau_tools. This will use the Extract API / SDK to generate an empty extract with the bare minimum of requirements to allow it to publish and refresh
  6. Save the new file. It will be saved as a TWBX or TDSX, based on the input file type
  7. Publish the file to Tableau Server
  8. Send an Extract Refresh command to Tableau Server using the REST API (using the tableau_tools.tableau_rest_api sub-module).
  9. Extract will refresh based on the information in the TDS and be filled out with information just for the specified customer/user/whatever you filtered



tableau_tools 4.4.0 released!

I haven’t been announcing the minor point releases of tableau_tools lately, but 4.4.0 is out with a lot of good new stuff:

  • Updated to work with the Extract API 2.0, so you can add the necessary Hyper extracts to 10.5 data sources and workbooks
  • Fully updated and documented mechanism for altering the main table of existing data sources. Change the table name or Custom SQL or…
  • Stored Procedure Parameters can be accessed and set
  • Tableau Parameters can now be added, removed or modified

As always, preferred install is from PyPi using pip install tableau_tools –upgrade or you can see the source at the Releases on GitHub. See the full documentation in the README .

tableau_tools 4.3.0 released!

tableau_tools 4.3.0 is now up and available on PyPi and GitHub!

If you’ve installed before, just run

pip install tableau_tools --upgrade

There’s lots of good stuff in this release:

  • 100% implementation of the spec. If it is in the Reference Guide, it’s possible through tableau_tools. There are even a few things that aren’t in the reference guide 😉
  • 10.5 / API 2.8 compatibility
  • Vastly improved README file, covering almost all topics
  • Code refactoring broke up some of the larger library files into easier to understand pieces
  • So much more!

As always, please let me know through GitHub if there are any issues.

Using tableau_tools to change Permissions

In tableau_tools 4.2.3, there is a new example called . The examples and show how to set permissions when you are working with a new site or to look at the permissions that exist on an existing site, but there was not previously an example of updating an existing site, where you might have existing permissions of any sort. The script itself is decently commented, but here I want to explore some of the things I had to think about when putting the script together, to help people doing other variations of this task. Read through the script, which is reasonably well commented, then come back and read more to gain a more full understanding.


Republishing Extracts from One Site (or Server) to Another with tableau_tools

Imagine you have a Data Source (in a workbook or outside of one) which is an extract, refreshing on a schedule. But that same data could be used on a different site, or a different server. There are lots of reasons to have logical partitions that basically need a copy of data, particularly related to security. You might have an internal server that connects to data sources allowing the refresh, but want to push that content to a server that eventually connects to the public Internet.

The REST API allow for this fairly easily — you simply download the first workbook, then republish to a different site with the Save Credentials options set to “False”. No credentials means the extract can’t update, but that’s exactly the idea behind this exercise — you want no way to access the database.

Note: The Tableau workbook and data source files will still contain some information about the original live data source that the extract was created from, but no passwords (no credentials are passed to the second site/server). If you need complete lock-down security, I can try and explore how much you can blank out of the XML while still publishing successfully.

This is very easily accomplished via tableau_tools:

# -*- coding: utf-8 -*-

from tableau_tools.tableau_rest_api import *
from tableau_tools import *
import time

o_server = u'http://'
o_username = u''
o_password = u''
o_site_content_url = u''

logger = Logger(u'move.log')

d_server = u'http://'
d_username = u''
d_password = u''
d_site_content_url = u''

t = TableauRestApiConnection26(o_server, o_username, o_password, o_site_content_url)
downloaded_filename = u'File Name'
wb_name_on_server = u'WB Name on Server'
proj_name = u'Default'
t.download_workbook(wb_name_on_server, downloaded_filename, proj_name_or_luid=proj_name)

d = TableauRestApiConnection26(d_server, d_username, d_password, d_site_content_url)
proj = d.query_project(u'Default')
d.publish_workbook(u'{}.twbx'.format(downloaded_filename), wb_name_on_server, proj, save_credentials=False, overwrite=True)



Killing a Tableau Server Session

Within an embedded application, it can be difficult to make sure that sign-out is achieved in both the application and Tableau Server. Tableau Server supports SAML signout commands, but for all sorts of reasons, this might not always work.

Luckily, it is possible to use the REST API to kill any session programmatically, but you need the session identifier from the Tableau Repository. The question is, how do you know what session belongs to a user? There is a sessions view, but you need a little bit more to get filtering down to the username level:

sessions.shared_vizql_write, AS user_name,
FROM sessions
JOIN users ON sessions.user_id =
JOIN system_users ON users.system_user_id =
WHERE = '{username}'

Once you have the session ID, you can send a REST API sign out command.

tableau_tools has both of these commands wrapped in a simple interface.

server = ''
username = ''
password = ''
readonly_user_password = ""
d = TableauRestApiConnection25(server, username, password)
tab_rep = TableauRepository(server, readonly_user_password)
uname = 'some_username'
sessions_cur = tab_rep.query_sessions(username=uname)
for row in sessions_cur:
    d.token = row[0]

The token property of the TableauRestApiConnection uses the REST API session token on when you do the signin() method, but you can replace the token with any session ID from the repository and then the signout() method will be sending the correct method to sign-out.

tableau_tools version 4.2.0 released – now Python 3 compatible!

Update: Hot on the heels of 4.1.0, tableau_tools 4.2.0 is now available with full Python 3 compatibility!

The version 4.0 series of tableau_tools was always intended to allow for Python 3 compatibility, and with version 4.2.0, installing from PyPi (or invokes automatic 2to3 conversion that should work without any additional changes. The short lived 4.1.0 release moved from urllib2 to requests as the library for making the actual HTTP calls in the backend, and 4.2.0 finishes off the work by moving everything to Unicode internally, while writing all text files out in UTF-8 encoding.

This means there is now a requirement for the requests library, but since every other Python package in the world now uses requests, I don’t think it should cause anyone any harm. Please do report any bugs that you see, as there might be a few quirky corner cases where something that was necessary before requests is causing an issue.

The Tableau SDK itself is only Python 2.7 compatible, so the TDE Extract Generation / Conversion from TDS to TDSX functionality won’t work in Python 3, but everything else should be completely compatible.