Skip to content

Commit e8c9e0a

Browse files
authored
Merge branch 'master' into schedules-multiple-intervals
2 parents f17a75d + 3ec49bc commit e8c9e0a

40 files changed

+417
-95
lines changed

.github/workflows/code-coverage.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ jobs:
3030
3131
# https://github.com/marketplace/actions/pytest-coverage-comment
3232
- name: Generate coverage report
33-
run: pytest --junitxml=pytest.xml --cov=tableauserverclient tests/ | tee pytest-coverage.txt
33+
run: pytest --junitxml=pytest.xml --cov=tableauserverclient test/ | tee pytest-coverage.txt
3434

3535
- name: Comment on pull request with coverage
36+
continue-on-error: true
3637
uses: MishaKav/pytest-coverage-comment@main
3738
with:
3839
pytest-coverage-path: ./pytest-coverage.txt

.github/workflows/publish-pypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
fetch-depth: 0
2020
- uses: actions/setup-python@v4
2121
with:
22-
python-version: 3.7
22+
python-version: 3.9
2323
- name: Build dist files
2424
run: |
2525
python -m pip install --upgrade pip

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ For more information on installing and using TSC, see the documentation:
1919

2020

2121
## License
22-
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python?ref=badge_large)
22+
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python?ref=badge_large)

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ dependencies = [
1515
'defusedxml>=0.7.1', # latest as at 7/31/23
1616
'packaging>=23.1', # latest as at 7/31/23
1717
'requests>=2.31', # latest as at 7/31/23
18-
'urllib3==2.0.4', # latest as at 7/31/23
18+
'urllib3==2.0.7', # latest as at 7/31/23
1919
]
2020
requires-python = ">=3.7"
2121
classifiers = [
@@ -31,7 +31,8 @@ classifiers = [
3131
repository = "https://github.com/tableau/server-client-python"
3232

3333
[project.optional-dependencies]
34-
test = ["argparse", "black==23.7", "mock", "mypy==1.4", "pytest>=7.0", "pytest-subtests", "requests-mock>=1.0,<2.0"]
34+
test = ["argparse", "black==23.7", "mock", "mypy==1.4", "pytest>=7.0", "pytest-cov", "pytest-subtests",
35+
"requests-mock>=1.0,<2.0"]
3536

3637
[tool.black]
3738
line-length = 120

samples/create_extract_task.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
####
2+
# This script demonstrates how to create extract tasks in Tableau Cloud
3+
# using the Tableau Server Client.
4+
#
5+
# To run the script, you must have installed Python 3.7 or later.
6+
####
7+
8+
9+
import argparse
10+
import logging
11+
12+
from datetime import time
13+
14+
import tableauserverclient as TSC
15+
16+
17+
def main():
18+
parser = argparse.ArgumentParser(description="Creates sample extract refresh task.")
19+
# Common options; please keep those in sync across all samples
20+
parser.add_argument("--server", "-s", help="server address")
21+
parser.add_argument("--site", "-S", help="site name")
22+
parser.add_argument("--token-name", "-p", help="name of the personal access token used to sign into the server")
23+
parser.add_argument("--token-value", "-v", help="value of the personal access token used to sign into the server")
24+
parser.add_argument(
25+
"--logging-level",
26+
"-l",
27+
choices=["debug", "info", "error"],
28+
default="error",
29+
help="desired logging level (set to error by default)",
30+
)
31+
# Options specific to this sample:
32+
# This sample has no additional options, yet. If you add some, please add them here
33+
34+
args = parser.parse_args()
35+
36+
# Set logging level based on user input, or error by default
37+
logging_level = getattr(logging, args.logging_level.upper())
38+
logging.basicConfig(level=logging_level)
39+
40+
tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site)
41+
server = TSC.Server(args.server, use_server_version=False)
42+
server.add_http_options({"verify": False})
43+
server.use_server_version()
44+
with server.auth.sign_in(tableau_auth):
45+
# Monthly Schedule
46+
# This schedule will run on the 15th of every month at 11:30PM
47+
monthly_interval = TSC.MonthlyInterval(start_time=time(23, 30), interval_value=15)
48+
monthly_schedule = TSC.ScheduleItem(
49+
None,
50+
None,
51+
None,
52+
None,
53+
monthly_interval,
54+
)
55+
56+
# Default to using first workbook found in server
57+
all_workbook_items, pagination_item = server.workbooks.get()
58+
my_workbook: TSC.WorkbookItem = all_workbook_items[0]
59+
60+
target_item = TSC.Target(
61+
my_workbook.id, # the id of the workbook or datasource
62+
"workbook", # alternatively can be "datasource"
63+
)
64+
65+
extract_item = TSC.TaskItem(
66+
None,
67+
"FullRefresh",
68+
None,
69+
None,
70+
None,
71+
monthly_schedule,
72+
None,
73+
target_item,
74+
)
75+
76+
try:
77+
response = server.tasks.create(extract_item)
78+
print(response)
79+
except Exception as e:
80+
print(e)
81+
82+
83+
if __name__ == "__main__":
84+
main()

tableauserverclient/__init__.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,47 @@
11
from ._version import get_versions
22
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
3-
from .models import *
3+
from .models import (
4+
BackgroundJobItem,
5+
ColumnItem,
6+
ConnectionCredentials,
7+
ConnectionItem,
8+
CustomViewItem,
9+
DQWItem,
10+
DailyInterval,
11+
DataAlertItem,
12+
DatabaseItem,
13+
DatasourceItem,
14+
FavoriteItem,
15+
FlowItem,
16+
FlowRunItem,
17+
FileuploadItem,
18+
GroupItem,
19+
HourlyInterval,
20+
IntervalItem,
21+
JobItem,
22+
JWTAuth,
23+
MetricItem,
24+
MonthlyInterval,
25+
PaginationItem,
26+
Permission,
27+
PermissionsRule,
28+
PersonalAccessTokenAuth,
29+
ProjectItem,
30+
RevisionItem,
31+
ScheduleItem,
32+
SiteItem,
33+
ServerInfoItem,
34+
SubscriptionItem,
35+
TableItem,
36+
TableauAuth,
37+
Target,
38+
TaskItem,
39+
UserItem,
40+
ViewItem,
41+
WebhookItem,
42+
WeeklyInterval,
43+
WorkbookItem,
44+
)
445
from .server import (
546
CSVRequestOptions,
647
ExcelRequestOptions,

tableauserverclient/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from .site_item import SiteItem
3232
from .subscription_item import SubscriptionItem
3333
from .table_item import TableItem
34-
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth
34+
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
3535
from .tableau_types import Resource, TableauItem, plural_type
3636
from .tag_item import TagItem
3737
from .target import Target

tableauserverclient/models/column_item.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ def __init__(self, name, description=None):
99
self.description = description
1010
self.name = name
1111

12+
def __repr__(self):
13+
return f"<{self.__class__.__name__} {self._id} {self.name} {self.description}>"
14+
1215
@property
1316
def id(self):
1417
return self._id

tableauserverclient/models/connection_credentials.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ def __init__(self, name, password, embed=True, oauth=False):
1515
self.embed = embed
1616
self.oauth = oauth
1717

18+
def __repr__(self):
19+
if self.password:
20+
print = "redacted"
21+
else:
22+
print = "None"
23+
return f"<{self.__class__.__name__} name={self.name} password={print} embed={self.embed} oauth={self.oauth} >"
24+
1825
@property
1926
def embed(self):
2027
return self._embed

tableauserverclient/models/custom_view_item.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def from_xml_element(cls, parsed_response, ns, workbook_id="") -> List["CustomVi
134134
cv_item._content_url = custom_view_xml.get("contentUrl", None)
135135
cv_item._id = custom_view_xml.get("id", None)
136136
cv_item._name = custom_view_xml.get("name", None)
137+
cv_item._shared = string_to_bool(custom_view_xml.get("shared", None))
137138

138139
if owner_elem is not None:
139140
parsed_owners = UserItem.from_response_as_owner(tostring(custom_view_xml), ns)
@@ -154,3 +155,7 @@ def from_xml_element(cls, parsed_response, ns, workbook_id="") -> List["CustomVi
154155

155156
all_view_items.append(cv_item)
156157
return all_view_items
158+
159+
160+
def string_to_bool(s: Optional[str]) -> bool:
161+
return (s or "").lower() == "true"

0 commit comments

Comments
 (0)