Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d2b72e0
Jac/publish samples (#918)
jacalata Oct 23, 2021
2f28642
Clean up hidden_views by making it an attribute of WorkbookItem (#617)
scuml Nov 9, 2021
64e9bb7
Jorwoods/type hint revisions (#956)
jorwoods Nov 11, 2021
5c5b311
WIP: Enable Black for CI and add as dependency (#935)
bcantoni Jan 28, 2022
3dad933
Jorwoods/type hint data alert (#934)
jorwoods Jan 28, 2022
c5cb6a1
Jorwoods/type hint favorites (#936)
jorwoods Jan 28, 2022
c53f08a
Jorwoods/type hint flows (#937)
jorwoods Jan 28, 2022
86c5edf
make tests run even if code style fails (#980)
jacalata Jan 28, 2022
5b7ae58
Jorwoods/type hint groups (#938)
jorwoods Jan 28, 2022
aee7605
Jorwoods/type hint permissions (#940)
jorwoods Jan 28, 2022
01fa902
Jorwoods/type hint projects (#941)
jorwoods Jan 28, 2022
7598f6c
Jorwoods/type hint flow runs (#950)
jorwoods Jan 28, 2022
e3f3a4b
Type hint site (#942)
jorwoods Jan 28, 2022
0251ac8
Type hint subscriptions (#943)
jorwoods Jan 28, 2022
519a5c8
Jorwoods/type hint user (#944)
jorwoods Jan 28, 2022
0d879b3
Type hint webhooks (#945)
jorwoods Jan 28, 2022
797344a
Add back old format for setting hidden views on publish (#955)
jacalata Mar 17, 2022
9ee828d
add get_by_id method and test for schedules (#1011)
jacalata Mar 24, 2022
c4735fd
Jorwoods/quota tiers allow null (#1015)
jorwoods Mar 30, 2022
2cf198d
fix workbook.delete_extract (#1013)
jacalata Apr 2, 2022
6f08b48
add publish to pypi action (#1017)
jacalata Apr 5, 2022
d0e5acc
Update publish.sh
jacalata Apr 8, 2022
b102a4c
Jac/createextracts bug (#1026)
jacalata May 4, 2022
63eab28
Add Status and StartedAt filters for jobs endpoint (#1023)
jorwoods May 5, 2022
332315e
Workbook item nullable project (#1028)
bcmyguest1 May 7, 2022
5edd179
create single Credentials class (#1032)
jacalata May 15, 2022
fdf3992
Reassign content on user removal (#1036)
jorwoods May 15, 2022
4d90e8a
Jac/export sample fix (#1034)
jacalata May 23, 2022
26e9948
Add black and mypy configurations to pyproject.toml (#1040)
jorwoods May 23, 2022
7607e5f
Jac/redact embedded creds (#1035)
jacalata May 26, 2022
6714721
Extract refreshable item IDs from job XML response (#1048)
jorwoods May 31, 2022
ec70791
jorwood: Do not eagerly fetch content when a stream was requested
jacalata Jun 1, 2022
2dce2ef
Fix QuerySet slicing logic (#1047)
jorwoods Jun 2, 2022
f41aa09
default permissions (#1054)
jacalata Jun 4, 2022
5d13d1a
Merge branch 'master' into development
jacalata Jun 6, 2022
c0d3bf7
Remove vf support from populate_excel (#1060)
jorwoods Jun 26, 2022
5a7ea97
Jorwoods/add len to queryset (#1061)
jorwoods Jun 26, 2022
620d43f
Log RequestOptions params (#1070)
jorwoods Jul 28, 2022
91c25b2
Jac/git actions (#1077)
jacalata Jul 28, 2022
a5a2f04
black and mypy only in the metadata workflow (#1082)
jacalata Jul 29, 2022
d6bc008
change initialization defaults (#1081)
jacalata Jul 29, 2022
88473b1
Add version awareness to site create/update methods (#1068)
jacalata Aug 5, 2022
89514df
Jac/user import (#1086)
jacalata Aug 27, 2022
c1c38fa
Jac/client version header (#1075)
jacalata Aug 31, 2022
00f55bb
Use explicit None identity check for datasource updates (#1099)
jorwoods Sep 1, 2022
1e14554
consolidate config files into pyproject.toml (#1074)
jacalata Sep 10, 2022
e8ef61d
Merge branch 'master' into development
jacalata Sep 10, 2022
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
9 changes: 5 additions & 4 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ name: Publish to PyPi
on:
workflow_dispatch:
push:
branches:
- master
tags:
- 'v*.*.*'

jobs:
build-n-publish:
Expand All @@ -19,12 +19,13 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.7
- name: Build dist files
run: |
python -m pip install --upgrade pip
pip install -e .[test]
python setup.py sdist --formats=gztar
python setup.py sdist --formats=gztar bdist_wheel
git describe --tag --dirty --always
- name: Publish distribution 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1 # license BSD-2
with:
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,3 @@ jobs:
if: always()
run: |
pytest test

- name: Run Mypy tests
run: |
mypy --show-error-codes --disable-error-code misc --disable-error-code import tableauserverclient test
12 changes: 7 additions & 5 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
include versioneer.py
include tableauserverclient/_version.py
include CHANGELOG.md
include contributing.md
include CONTRIBUTORS.md
include LICENSE
include LICENSE.versioneer
include README.md
include CHANGELOG.md
include tableauserverclient/_version.py
include versioneer.py
recursive-include docs *.md
recursive-include samples *.py
recursive-include samples *.txt
recursive-include smoke *.py
recursive-include test *.csv
recursive-include test *.dict
recursive-include test *.hyper
Expand All @@ -16,5 +17,6 @@ recursive-include test *.pdf
recursive-include test *.png
recursive-include test *.py
recursive-include test *.xml
recursive-include test *.tde
global-include *.pyi
global-include *.typed
global-include *.typed
5 changes: 2 additions & 3 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ somewhere.
## Getting Started

```shell
pip install versioneer
python setup.py build
python setup.py test
python -m build
pytest
```

### To use your locally built version
Expand Down
42 changes: 37 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
[build-system]
requires = ["setuptools>=45.0", "versioneer-518", "wheel"]
requires = ["setuptools>=45.0", "versioneer>=0.24", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name="tableauserverclient"

dynamic = ["version"]
description='A Python module for working with the Tableau Server REST API.'
authors = [{name="Tableau", email="github@tableau.com"}]
license = {file = "LICENSE"}
readme = "README.md"

dependencies = [
'defusedxml>=0.7.1',
'packaging~=21.3',
'requests>=2.28',
'urllib3~=1.26.8',
]
requires-python = ">=3.7"
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10"
]
[project.urls]
repository = "https://github.com/tableau/server-client-python"

[project.optional-dependencies]
test = ["argparse", "black", "mock", "mypy", "pytest>=7.0", "requests-mock>=1.0,<2.0"]

[tool.black]
line-length = 120
target-version = ['py37', 'py38', 'py39', 'py310']
Expand All @@ -11,8 +41,10 @@ disable_error_code = [
'misc',
'import'
]
files = [
"tableauserverclient",
"test"
]
files = ["tableauserverclient", "test"]
show_error_codes = true
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["test"]
addopts = "--junitxml=./test.junit.xml"
48 changes: 45 additions & 3 deletions samples/create_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@

import argparse
import logging
import os

from datetime import time
from typing import List

import tableauserverclient as TSC
from tableauserverclient import ServerResponseError


def main():
Expand All @@ -35,7 +38,7 @@ def main():
)
# Options specific to this sample
# This sample has no additional options, yet. If you add some, please add them here

parser.add_argument("--file", help="csv file containing user info", required=False)
args = parser.parse_args()

# Set logging level based on user input, or error by default
Expand All @@ -45,9 +48,48 @@ def main():
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):
# this code shows 3 different error codes that mean "resource is already in collection"
# 409009: group already exists on server
# 409107: user is already on site
# 409011: user is already in group

group = TSC.GroupItem("test")
group = server.groups.create(group)
print(group)
try:
group = server.groups.create(group)
except TSC.server.endpoint.exceptions.ServerResponseError as rError:
if rError.code == "409009":
print("Group already exists")
group = server.groups.filter(name=group.name)[0]
else:
raise rError
server.groups.populate_users(group)
for user in group.users:
print(user.name)

if args.file:
filepath = os.path.abspath(args.file)
print("Add users to site from file {}:".format(filepath))
added: List[TSC.UserItem]
failed: List[TSC.UserItem, TSC.ServerResponseError]
added, failed = server.users.create_from_file(filepath)
for user, error in failed:
print(user, error.code)
if error.code == "409017":
user = server.users.filter(name=user.name)[0]
added.append(user)
print("Adding users to group:{}".format(added))
for user in added:
print("Adding user {}".format(user))
try:
server.groups.add_user(group, user.id)
except ServerResponseError as serverError:
if serverError.code == "409011":
print("user {} is already a member of group {}".format(user.name, group.name))
else:
raise rError

for user in group.users:
print(user.name)


if __name__ == "__main__":
Expand Down
83 changes: 83 additions & 0 deletions samples/explore_site.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
####
# This script demonstrates how to use the Tableau Server Client
# to interact with sites.
####

import argparse
import logging
import os.path
import sys

import tableauserverclient as TSC


def main():

parser = argparse.ArgumentParser(description="Explore site updates by the Server API.")
# Common options; please keep those in sync across all samples
parser.add_argument("--server", "-s", required=True, help="server address")
parser.add_argument("--site", "-S", 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(
"--logging-level",
"-l",
choices=["debug", "info", "error"],
default="error",
help="desired logging level (set to error by default)",
)

parser.add_argument("--delete")
parser.add_argument("--create")
parser.add_argument("--url")
parser.add_argument("--new_site_name")
parser.add_argument("--user_quota")
parser.add_argument("--storage_quota")
parser.add_argument("--status")

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)

# SIGN IN
tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site)
server = TSC.Server(args.server, use_server_version=True)
new_site = None
with server.auth.sign_in(tableau_auth):
current_site = server.sites.get_by_id(server.site_id)

if args.delete:
print("You can only delete the site you are currently in")
print("Delete site `{}`?".format(current_site.name))
# server.sites.delete(server.site_id)

elif args.create:
new_site = TSC.SiteItem(args.create, args.url or args.create)
site_item = server.sites.create(new_site)
print(site_item)
# to do anything further with the site, you need to log into it
# if a PAT is required, that means going to the UI to create one

else:
new_site = current_site
print(current_site, "current user quota:", current_site.user_quota)
print("Remember, you can only update the site you are currently in")
if args.url:
new_site.content_url = args.url
if args.user_quota:
new_site.user_quota = args.user_quota
try:
updated_site = server.sites.update(new_site)
print(updated_site, "new user quota:", updated_site.user_quota)
except TSC.ServerResponseError as e:
print(e)


if __name__ == "__main__":
main()
5 changes: 4 additions & 1 deletion samples/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ def main():
count = 0
for resource in TSC.Pager(endpoint.get, options):
count = count + 1
print(resource.id, resource.name)
# endpoint.populate_connections(resource)
print(resource.name[:18], " ") # , resource._connections())
if count > 100:
break
print("Total: {}".format(count))


Expand Down
2 changes: 2 additions & 0 deletions samples/online_users.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ayoung@tableau.com, , , "Creator", None, Yes
ahsiao@tableau.com, , , "Explorer", None, No
19 changes: 1 addition & 18 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
[wheel]
universal = 1

[pep8]
max_line_length = 120

# See the docstring in versioneer.py for instructions. Note that you must
# re-run 'versioneer.py setup' after changing this section, and commit the
# resulting files.

# versioneer does not support pyproject.toml
[versioneer]
VCS = git
style = pep440-pre
versionfile_source = tableauserverclient/_version.py
versionfile_build = tableauserverclient/_version.py
tag_prefix = v
#parentdir_prefix =

[aliases]
smoke=pytest

[tool:pytest]
testpaths = test smoke
addopts = --junitxml=./test.junit.xml

[mypy]
ignore_missing_imports = True
49 changes: 11 additions & 38 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,22 @@
import sys
import versioneer
from setuptools import setup

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

from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

# 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 []
test_requirements = ['black', 'mock', 'pytest', 'requests-mock>=1.0,<2.0', 'mypy>=0.920']

"""
once versioneer 0.25 gets released, we can move this from setup.cfg to pyproject.toml
[tool.versioneer]
VCS = "git"
style = "pep440-pre"
versionfile_source = "tableauserverclient/_version.py"
versionfile_build = "tableauserverclient/_version.py"
tag_prefix = "v"
"""
setup(
name='tableauserverclient',
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
author='Tableau',
author_email='github@tableau.com',
url='https://github.com/tableau/server-client-python',
package_data={'tableauserverclient':['py.typed']},
# not yet sure how to move this to pyproject.toml
packages=['tableauserverclient',
'tableauserverclient.helpers',
'tableauserverclient.models',
'tableauserverclient.server',
'tableauserverclient.server.endpoint'],
license='MIT',
description='A Python module for working with the Tableau Server REST API.',
long_description=long_description,
long_description_content_type='text/markdown',
test_suite='test',
setup_requires=pytest_runner,
install_requires=[
'defusedxml>=0.7.1',
'requests>=2.11,<3.0',
],
python_requires='>3.7.0',
tests_require=test_requirements,
extras_require={
'test': test_requirements
},
zip_safe=False
)
Empty file removed smoke/__init__.py
Empty file.
Loading