Skip to content

Commit

Permalink
Merge pull request #507 from tableau/development
Browse files Browse the repository at this point in the history
Release v0.9
## 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)
  • Loading branch information
Chris Shin authored Oct 4, 2019
2 parents 2c2ce91 + fe3ac07 commit b260ebc
Show file tree
Hide file tree
Showing 72 changed files with 2,771 additions and 71 deletions.
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

0 comments on commit b260ebc

Please sign in to comment.