Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__pycache__/
*.py[cod]
*$py.class
test.junit.xml

# C extensions
*.so
Expand Down Expand Up @@ -145,4 +146,4 @@ $RECYCLE.BIN/

# Documentation
docs/_site/
docs/.jekyll-metadata
docs/.jekyll-metadata
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.5 (11 Sept 2017)

* Added revision settings to update site (#187)
* Added support for certified data sources (#189)
* Added support for include/exclude extract (#203)
* Added auto-paging for group users (#204)
* Added ability to add workbooks to a schedule (#206)
* Added the ability to create nested projects (#208)
* Fixed sort order when using pager (#192)
* Docs Updates and new samples (#196, #199, #200, #201)

## 0.4.1 (18 April 2017)

* Fix #177 to remove left in debugging print
Expand Down
14 changes: 8 additions & 6 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ The following people have contributed to this project to make it possible, and w
## Contributors

* [geordielad](https://github.com/geordielad)
* [Hugo Stijns)(https://github.com/hugoboos)
* [Hugo Stijns](https://github.com/hugoboos)
* [kovner](https://github.com/kovner)
* [Talvalin](https://github.com/Talvalin)
* [Chris Toomey](https://github.com/cmtoomey)
* [Vathsala Achar](https://github.com/VathsalaAchar)
* [Graeme Britz](https://github.com/grbritz)

* [Russ Goldin](https://github.com/tagyoureit)
* [William Lang](https://github.com/williamlang)
* [Jim Morris](https://github.com/jimbodriven)

## Core Team

* [shinchris](https://github.com/shinchris)
* [lgraber](https://github.com/lgraber)
* [t8y8](https://github.com/t8y8)
* [RussTheAerialist](https://github.com/RussTheAerialist)
* [Shin Chris](https://github.com/shinchris)
* [Lee Graber](https://github.com/lgraber)
* [Tyler Doyle](https://github.com/t8y8)
* [Russell Hay](https://github.com/RussTheAerialist)
* [Ben Lower](https://github.com/benlower)
* [Jared Dominguez](https://github.com/jdomingu)
* [Jackson Huang](https://github.com/jz-huang)
Expand Down
7 changes: 7 additions & 0 deletions LICENSE.versioneer
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## License

To make Versioneer easier to embed, all its code is dedicated to the public
domain. The `_version.py` that it creates is also in the public domain.
Specifically, both are released under the Creative Commons "Public Domain
Dedication" license (CC0-1.0), as described in
https://creativecommons.org/publicdomain/zero/1.0/ .
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
include versioneer.py
include tableauserverclient/_version.py
include LICENSE
include LICENSE.versioneer
3 changes: 2 additions & 1 deletion docs/docs/samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ The following list describes the samples available in the repository:

* `create_group.py`. Create a user group.

* `create_project.py`. Create new projects at the top level as well as nested projects.

* `create_schedules.py`. Create schedules for extract refreshes and subscriptions.

* `explore_datasource.py`. Queries datasources, selects a datasource, populates connections for the datasource, then updates the datasource.
Expand All @@ -54,4 +56,3 @@ The following list describes the samples available in the repository:

**Note**: For all of the samples, ensure that your Tableau Server user account has permission to access the resources
requested by the samples.

2 changes: 1 addition & 1 deletion docs/docs/versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import tableauserverclient as TSC

server = TSC.Server('http://SERVER_URL')

server.version = 2.4
server.version = '2.4'
```

## Supported versions
Expand Down
68 changes: 68 additions & 0 deletions samples/create_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
####
# This script demonstrates how to use the Tableau Server Client
# to create new projects, both at the root level and how to nest them using
# parent_id.
#
#
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
####

import argparse
import getpass
import logging
import sys

import tableauserverclient as TSC


def create_project(server, project_item):
try:
project_item = server.projects.create(project_item)
print('Created a new project called: %s' % project_item.name)
return project_item
except TSC.ServerResponseError:
print('We have already created this project: %s' % project_item.name)
sys.exit(1)

def main():
parser = argparse.ArgumentParser(description='Get all of the refresh tasks available on a server')
parser.add_argument('--server', '-s', required=True, help='server address')
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
parser.add_argument('--site', '-S', default=None)
parser.add_argument('-p', default=None, help='password')

parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
help='desired logging level (set to error by default)')

args = parser.parse_args()

if args.p is None:
password = getpass.getpass("Password: ")
else:
password = args.p

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

tableau_auth = TSC.TableauAuth(args.username, password)
server = TSC.Server(args.server)

with server.auth.sign_in(tableau_auth):
# Use highest Server REST API version available
server.use_server_version()

# Without parent_id specified, projects are created at the top level.
top_level_project = TSC.ProjectItem(name='Top Level Project')
top_level_project = create_project(server, top_level_project)

# Specifying parent_id creates a nested projects.
child_project = TSC.ProjectItem(name='Child Project', parent_id=top_level_project.id)
child_project = create_project(server, child_project)

# Projects can be nested at any level.
grand_child_project = TSC.ProjectItem(name='Grand Child Project', parent_id=child_project.id)
grand_child_project = create_project(server, grand_child_project)

if __name__ == '__main__':
main()
91 changes: 91 additions & 0 deletions samples/filter_sort_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
####
# 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.
####


import argparse
import getpass
import logging

import tableauserverclient as TSC


def create_example_group(group_name='Example Group', server=None):
new_group = TSC.GroupItem(group_name)
try:
new_group = server.groups.create(new_group)
print('Created a new project called: \'%s\'' % group_name)
print(new_group)
except TSC.ServerResponseError:
print('Group \'%s\' already existed' % group_name)


def main():
parser = argparse.ArgumentParser(description='Filter on groups')
parser.add_argument('--server', '-s', required=True, help='server address')
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
help='desired logging level (set to error by default)')
parser.add_argument('-p', default=None)
args = parser.parse_args()

if args.p is None:
password = getpass.getpass("Password: ")
else:
password = args.p

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

tableau_auth = TSC.TableauAuth(args.username, password)
server = TSC.Server(args.server)

with server.auth.sign_in(tableau_auth):

# Determine and use the highest api version for the server
server.use_server_version()

group_name = 'SALES NORTHWEST'
# Try to create a group named "SALES NORTHWEST"
create_example_group(group_name, server)

group_name = 'SALES ROMANIA'
# Try to create a group named "SALES ROMANIA"
create_example_group(group_name, server)

# URL Encode the name of the group that we want to filter on
# i.e. turn spaces into plus signs
filter_group_name = 'SALES+ROMANIA'
options = TSC.RequestOptions()
options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Operator.Equals,
filter_group_name))

filtered_groups, _ = server.groups.get(req_options=options)
# Result can either be a matching group or an empty list
if filtered_groups:
group_name = filtered_groups.pop().name
print(group_name)
else:
error = "No project named '{}' found".format(filter_group_name)
print(error)

options = TSC.RequestOptions()
options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Operator.In,
['SALES+NORTHWEST', 'SALES+ROMANIA', 'this_group']))

options.sort.add(TSC.Sort(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Direction.Desc))

matching_groups, pagination_item = server.groups.get(req_options=options)
print('Filtered groups are:')
for group in matching_groups:
print(group.name)

if __name__ == '__main__':
main()
94 changes: 94 additions & 0 deletions samples/filter_sort_projects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
####
# This script demonstrates how to use the Tableau Server Client
# 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.
####

import argparse
import getpass
import logging

import tableauserverclient as TSC


def create_example_project(name='Example Project', content_permissions='LockedToProject',
description='Project created for testing', server=None):

new_project = TSC.ProjectItem(name=name, content_permissions=content_permissions,
description=description)
try:
server.projects.create(new_project)
print('Created a new project called: %s' % name)
except TSC.ServerResponseError:
print('We have already created this resource: %s' % name)


def main():
parser = argparse.ArgumentParser(description='Get all of the refresh tasks available on a server')
parser.add_argument('--server', '-s', required=True, help='server address')
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
parser.add_argument('--site', '-S', default=None)
parser.add_argument('-p', default=None)

parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
help='desired logging level (set to error by default)')

args = parser.parse_args()

if args.p is None:
password = getpass.getpass("Password: ")
else:
password = args.p

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

tableau_auth = TSC.TableauAuth(args.username, password)
server = TSC.Server(args.server)

with server.auth.sign_in(tableau_auth):
# Use highest Server REST API version available
server.use_server_version()

filter_project_name = 'default'
options = TSC.RequestOptions()

options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Operator.Equals,
filter_project_name))

filtered_projects, _ = server.projects.get(req_options=options)
# Result can either be a matching project or an empty list
if filtered_projects:
project_name = filtered_projects.pop().name
print(project_name)
else:
error = "No project named '{}' found".format(filter_project_name)
print(error)

create_example_project(name='Example 1', server=server)
create_example_project(name='Example 2', server=server)
create_example_project(name='Example 3', server=server)
create_example_project(name='Proiect ca Exemplu', server=server)

options = TSC.RequestOptions()

# don't forget to URL encode the query names
options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Operator.In,
['Example+1', 'Example+2', 'Example+3']))

options.sort.add(TSC.Sort(TSC.RequestOptions.Field.Name,
TSC.RequestOptions.Direction.Desc))

matching_projects, pagination_item = server.projects.get(req_options=options)
print('Filtered projects are:')
for project in matching_projects:
print(project.name, project.id)


if __name__ == '__main__':
main()
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ versionfile_build = tableauserverclient/_version.py
tag_prefix = v
#parentdir_prefix =

[aliases]
smoke=pytest

[tool:pytest]
testpaths = test smoke
addopts = --junitxml=./test.junit.xml
8 changes: 6 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
license='MIT',
description='A Python module for working with the Tableau Server REST API.',
test_suite='test',
setup_requires=[
'pytest-runner'
],
install_requires=[
'requests>=2.11,<2.12.0a0'
'requests>=2.11,<3.0'
],
tests_require=[
'requests-mock>=1.0,<1.1a0'
'requests-mock>=1.0,<2.0',
'pytest'
]
)
Empty file added smoke/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion tableauserverclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .namespace import NAMESPACE
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
GroupItem, PaginationItem, ProjectItem, ScheduleItem, \
SiteItem, TableauAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError, \
Expand Down
Loading