Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
44581c4
add fields to ViewItem model
opus-42 Aug 22, 2018
d27993d
update test assets and unit tests with new fields
opus-42 Aug 22, 2018
2216d43
add new fields to docs
opus-42 Aug 25, 2018
2c7e538
remove favoritesTotal only available from api 3.1
opus-42 Aug 25, 2018
f05d1c1
remove favorite total from docs
opus-42 Aug 25, 2018
07030af
Initial support for Tableau Metadata API
t8y8 May 7, 2019
395598f
fix encoding error
t8y8 May 7, 2019
4c0bbeb
stop doing weird things
t8y8 May 7, 2019
9377d91
Just use built in json parsing
t8y8 May 7, 2019
c0670f2
last one
t8y8 May 7, 2019
e971d78
Can only test on CI
t8y8 May 7, 2019
7e02635
Merge pull request #431 from t8y8/metadata-api
gaoang2148 May 7, 2019
d8bdeae
Update .travis.yml (#432)
t8y8 May 7, 2019
e4ec849
Add support for Cataloging and Prep Conductor to TSC. (#434)
t8y8 May 10, 2019
ea437a2
Change server_info endpoint error message to be verbose (#439)
jacobj10 May 29, 2019
fa818d5
Fix serialization error in WB request generation (#449)
jacobj10 Jun 19, 2019
d87600b
Update Pager to take and pass arguments to underlying callable (#451)
t8y8 Jun 25, 2019
bdddf97
Fix update_workbook endpoint to address #454 (#461)
Jul 17, 2019
4a279ad
Merge pull request #331 from opus-42/xx-feature-add-viewitem-metafields
jacalata Jul 25, 2019
11d47ef
Personal Access Token Authentication (#465)
fpagliar Jul 26, 2019
122fe1a
Permissions Support 2.0 (#429)
t8y8 Jul 27, 2019
c5afbd6
Fix support for tags in ViewItem (#470)
toomyem Jul 30, 2019
942dbd7
Make it so the test-runner is only downloaded when running tests (#485)
t8y8 Aug 9, 2019
869ae40
Pin to urllib3 to fix encoding issue (#487)
t8y8 Aug 14, 2019
19c6322
External Content Support (Databases and Tables) (#445)
t8y8 Aug 26, 2019
f3cf843
embedded fix (#492)
t8y8 Aug 26, 2019
fa6d444
Prep Flow Support (#494)
t8y8 Sep 3, 2019
903fa97
Add topLevelProject filter to projects (#497)
Sep 3, 2019
d87eaa2
renamed PAT fields (#490)
fpagliar Sep 10, 2019
234011b
Add variable support to GraphQL Endpoint (#498)
t8y8 Sep 13, 2019
533aeb1
Changelog and contributors for v0.9 (#506)
Oct 4, 2019
26a4445
Fixes merge conflicts
Oct 4, 2019
fe3ac07
Fixes CI error and includes more contributors
Oct 4, 2019
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
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
dist: xenial
language: python
python:
- "2.7"
- "3.5"
- "3.6"
- "pypy"
- "3.7"
# command to install dependencies
install:
- "pip install -e ."
Expand All @@ -12,5 +13,4 @@ install:
script:
# Tests
- python setup.py test
# pep8 - disabled for now until we can scrub the files to make sure we pass before turning it on
- pycodestyle tableauserverclient test samples
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## 0.9 (4 Oct 2019)

* Added Metadata API endpoints (#431)
* Added site settings for Data Catalog and Prep Conductor (#434)
* Added new fields to ViewItem (#331)
* Added support and samples for Tableau Server Personal Access Tokens (#465)
* Added Permissions endpoints (#429)
* Added tags to ViewItem (#470)
* Added Databases and Tables endpoints (#445)
* Added Flow endpoints (#494)
* Added ability to filter projects by topLevelProject attribute (#497)
* Improved server_info endpoint error handling (#439)
* Improved Pager to take in keyword arguments (#451)
* Fixed UUID serialization error while publishing workbook (#449)
* Fixed materalized views in request body for update_workbook (#461)

## 0.8.1 (17 July 2019)

* Fixed update_workbook endpoint (#454)
Expand All @@ -13,7 +29,6 @@
* Fixed checked upload (#309, #319, #326, #329)
* Fixed embed_password field on publish (#416)


## 0.7 (2 Jul 2018)

* Added cancel job (#299)
Expand Down
18 changes: 14 additions & 4 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,26 @@ The following people have contributed to this project to make it possible, and w
* [Bruce Zhang](https://github.com/baixin137)
* [Bumsoo Kim](https://github.com/bskim45)
* [daniel1608](https://github.com/daniel1608)
* [Joshua Jacob](https://github.com/jacobj10)
* [Francisco Pagliaricci](https://github.com/fpagliar)
* [Tomasz Machalski](https://github.com/toomyem)
* [Jared Dominguez](https://github.com/jdomingu)
* [Brendan Lee](https://github.com/lbrendanl)
* [Martin Dertz](https://github.com/martydertz)
* [Christian Oliff](https://github.com/coliff)
* [Albin Antony](https://github.com/user9747)
* [prae04](https://github.com/prae04)

## Core Team

* [Shin Chris](https://github.com/shinchris)
* [Chris Shin](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)
* [Brendan Lee](https://github.com/lbrendanl)
* [Ang Gao](https://github.com/gaoang2148)
* [Priya R](https://github.com/preguraman)
* [Priya Reguraman](https://github.com/preguraman)
* [Jac Fitzgerald](https://github.com/jacalata)
* [Dan Zucker](https://github.com/dzucker-tab)
* [Irwin Dolobowsky](https://github.com/irwando)
52 changes: 52 additions & 0 deletions samples/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
####
# 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.
####

import argparse
import getpass
import logging

import tableauserverclient as TSC


def main():
parser = argparse.ArgumentParser(description='Logs in to the 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('--server', '-s', required=True, help='server address')

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--username', '-u', help='username to sign into the server')
group.add_argument('--token-name', '-n', help='name of the personal access token used to sign into the server')

args = parser.parse_args()

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

# Make sure we use an updated version of the rest apis.
server = TSC.Server(args.server, use_server_version=True)

if args.username:
# Trying to authenticate using username and password.
password = getpass.getpass("Password: ")
tableau_auth = TSC.TableauAuth(args.username, password)
with server.auth.sign_in(tableau_auth):
print('Logged in successfully')

else:
# Trying to authenticate using personal access tokens.
personal_access_token = getpass.getpass("Personal Access Token: ")
tableau_auth = TSC.PersonalAccessTokenAuth(token_name=args.token_name,
personal_access_token=personal_access_token)
with server.auth.sign_in_with_personal_access_token(tableau_auth):
print('Logged in successfully')


if __name__ == '__main__':
main()
14 changes: 10 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import sys
import versioneer

try:
from setuptools import setup
except ImportError:
from distutils.core import setup

# Only install pytest and runner when test command is run
# This makes work easier for offline installs or low bandwidth machines
needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv)
pytest_runner = ['pytest-runner'] if needs_pytest else []

setup(
name='tableauserverclient',
version=versioneer.get_version(),
Expand All @@ -16,11 +23,10 @@
license='MIT',
description='A Python module for working with the Tableau Server REST API.',
test_suite='test',
setup_requires=[
'pytest-runner'
],
setup_requires=pytest_runner,
install_requires=[
'requests>=2.11,<3.0'
'requests>=2.11,<3.0',
'urllib3==1.24.3'
],
tests_require=[
'requests-mock>=1.0,<2.0',
Expand Down
8 changes: 4 additions & 4 deletions tableauserverclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
GroupItem, JobItem, BackgroundJobItem, PaginationItem, ProjectItem, ScheduleItem, \
SiteItem, TableauAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError, \
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem, \
SubscriptionItem, Target
GroupItem, JobItem, BackgroundJobItem, PaginationItem, ProjectItem, ScheduleItem,\
SiteItem, TableauAuth, PersonalAccessTokenAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError,\
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem,\
SubscriptionItem, Target, PermissionsRule, Permission, DatabaseItem, TableItem, ColumnItem, FlowItem
from .server import RequestOptions, CSVRequestOptions, ImageRequestOptions, PDFRequestOptions, Filter, Sort, \
Server, ServerResponseError, MissingRequiredFieldError, NotSignedInError, Pager
from ._version import get_versions
Expand Down
6 changes: 6 additions & 0 deletions tableauserverclient/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from .connection_credentials import ConnectionCredentials
from .connection_item import ConnectionItem
from .column_item import ColumnItem
from .datasource_item import DatasourceItem
from .database_item import DatabaseItem
from .exceptions import UnpopulatedPropertyError
from .group_item import GroupItem
from .flow_item import FlowItem
from .interval_item import IntervalItem, DailyInterval, WeeklyInterval, MonthlyInterval, HourlyInterval
from .job_item import JobItem, BackgroundJobItem
from .pagination_item import PaginationItem
Expand All @@ -11,9 +14,12 @@
from .server_info_item import ServerInfoItem
from .site_item import SiteItem
from .tableau_auth import TableauAuth
from .personal_access_token_auth import PersonalAccessTokenAuth
from .target import Target
from .table_item import TableItem
from .task_item import TaskItem
from .user_item import UserItem
from .view_item import ViewItem
from .workbook_item import WorkbookItem
from .subscription_item import SubscriptionItem
from .permissions_item import PermissionsRule, Permission
69 changes: 69 additions & 0 deletions tableauserverclient/models/column_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import xml.etree.ElementTree as ET

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


class ColumnItem(object):
def __init__(self, name, description=None):
self._id = None
self.description = description
self.name = name

@property
def id(self):
return self._id

@property
def name(self):
return self._name

@name.setter
@property_not_empty
def name(self, value):
self._name = value

@property
def description(self):
return self._description

@description.setter
def description(self, value):
self._description = value

@property
def remote_type(self):
return self._remote_type

def _set_values(self, id, name, description, remote_type):
if id is not None:
self._id = id
if name:
self._name = name
if description:
self.description = description
if remote_type:
self._remote_type = remote_type

@classmethod
def from_response(cls, resp, ns):
all_column_items = list()
parsed_response = ET.fromstring(resp)
all_column_xml = parsed_response.findall('.//t:column', namespaces=ns)

for column_xml in all_column_xml:
(id, name, description, remote_type) = cls._parse_element(column_xml, ns)
column_item = cls(name)
column_item._set_values(id, name, description, remote_type)
all_column_items.append(column_item)

return all_column_items

@staticmethod
def _parse_element(column_xml, ns):
id = column_xml.get('id', None)
name = column_xml.get('name', None)
description = column_xml.get('description', None)
remote_type = column_xml.get('remoteType', None)

return id, name, description, remote_type
Loading