8000 Merge pull request #170 from RussTheAerialist/vnext · SnarkyPapi/server-client-python@e53f6d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit e53f6d7

Browse files
author
Russell Hay
authored
Merge pull request tableau#170 from RussTheAerialist/vnext
Let's get rid of vnext
2 parents 48f8e3e + 1cc8f39 commit e53f6d7

29 files changed

+561
-80
lines changed

docs/docs/samples.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ The following list describes the samples available in the repository:
4040

4141
* `explore_workbook.py`. Queries workbooks, selects a workbook, populates the connections and views for a workbook, then updates the workbook.
4242

43+
* `download_view_image.py`. Queries for view based on name specified in filter, populates the image and saves the image to specified file path.
44+
4345
* `move_workbook_projects.py`. Updates the properties of a workbook to move the workbook from one project to another.
4446

4547
* `move_workbook_sites.py`. Downloads a workbook, stores it in-memory, and uploads it to another site.

samples/download_view_image.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
####
2+
# This script demonstrates how to use the Tableau Server Client
3+
# to download a high resolution image of a view from Tableau Server.
4+
#
5+
# For more information, refer to the documentations on 'Query View Image'
6+
# (https://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm)
7+
#
8+
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
9+
####
10+
11+
import argparse
12+
import getpass
13+
import logging
14+
15+
import tableauserverclient as TSC
16+
17+
18+
def main():
19+
20+
parser = argparse.ArgumentParser(description='Query View Image From Server')
21+
parser.add_argument('--server', '-s', required=True, help='server address')
22+
parser.add_argument('--site-id', '-si', required=False,
23+
help='content url for site the view is on')
24+
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
25+
parser.add_argument('--view-name', '-v', required=True,
26+
help='name of view to download an image of')
27+
parser.add_argument('--filepath', '-f', required=True, help='filepath to save the image returned')
28+
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
29+
help='desired logging level (set to error by default)')
30+
31+
args = parser.parse_args()
32+
33+
password = getpass.getpass("Password: ")
34+
35+
# Set logging level based on user input, or error by default
36+
logging_level = getattr(logging, args.logging_level.upper())
37+
logging.basicConfig(level=logging_level)
38+
39+
# Step 1: Sign in to server.
40+
site_id = args.site_id
41+
if not site_id:
42+
site_id = ""
43+
tableau_auth = TSC.TableauAuth(args.username, password, site_id=site_id)
44+
server = TSC.Server(args.server)
45+
# The new endpoint was introduced in Version 2.5
46+
server.version = 2.5
47+
48+
with server.auth.sign_in(tableau_auth):
49+
# Step 2: Query for the view that we want an image of
50+
req_option = TSC.RequestOptions()
51+
req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
52+
TSC.RequestOptions.Operator.Equals, args.view_name))
53+
all_views, pagination_item = server.views.get(req_option)
54+
if not all_views:
55+
raise LookupError("View with the specified name was not found.")
56+
view_item = all_views[0]
57+
58+
# Step 3: Query the image endpoint and save the image to the specified location
59+
image_req_option = TSC.ImageRequestOptions(imageresolution=TSC.ImageRequestOptions.Resolution.High)
60+
server.views.populate_image(view_item, image_req_option)
61+
62+
with open(args.filepath, "wb") as image_file:
63+
image_file.write(view_item.image)
64+
65+
print("View image saved to {0}".format(args.filepath))
66+
67+
if __name__ == '__main__':
68+
main()

samples/explore_datasource.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def main():
3737
# SIGN IN
3838
tableau_auth = TSC.TableauAuth(args.username, password)
3939
server = TSC.Server(args.server)
40+
server.use_highest_version()
4041
with server.auth.sign_in(tableau_auth):
4142
# Query projects for use when demonstrating publishing and updating
4243
all_projects, pagination_item = server.projects.get()
@@ -67,6 +68,16 @@ def main():
6768
print(["{0}({1})".format(connection.id, connection.datasource_name)
6869
for connection in sample_datasource.connections])
6970

71+
# Add some tags to the datasource
72+
original_tag_set = set(sample_datasource.tags)
73+
sample_datasource.tags.update('a', 'b', 'c', 'd')
74+
server.datasources.update(sample_datasource)
75+
print("\nOld tag set: {}".format(original_tag_set))
76+
print("New tag set: {}".format(sample_datasource.tags))
77+
78+
# Delete all tags that were added by setting tags to original
79+
sample_datasource.tags = original_tag_set
80+
server.datasources.update(sample_datasource)
7081

7182
if __name__ == '__main__':
7283
main()

samples/explore_workbook.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def main():
4040
# SIGN IN
4141
tableau_auth = TSC.TableauAuth(args.username, password)
4242
server = TSC.Server(args.server)
43+
server.use_highest_version()
4344

4445
overwrite_true = TSC.Server.PublishMode.Overwrite
4546

@@ -82,14 +83,26 @@ def main():
8283
sample_workbook.tags.update('a', 'b', 'c', 'd')
8384
sample_workbook.show_tabs = True
8485
server.workbooks.update(sample_workbook)
85-
print("\nOld tag set: {}".format(original_tag_set))
86-
print("New tag set: {}".format(sample_workbook.tags))
86+
print("\nWorkbook's old tag set: {}".format(original_tag_set))
87+
print("Workbook's new tag set: {}".format(sample_workbook.tags))
8788
print("Workbook tabbed: {}".format(sample_workbook.show_tabs))
8889

8990
# Delete all tags that were added by setting tags to original
9091
sample_workbook.tags = original_tag_set
9192
server.workbooks.update(sample_workbook)
9293

94+
# Add tag to just one view
95+
sample_view = sample_workbook.views[0]
96+
original_tag_set = set(sample_view.tags)
97+
sample_view.tags.add("view_tag")
98+
server.views.update(sample_view)
99+
print("\nView's old tag set: {}".format(original_tag_set))
100+
print("View's new tag set: {}".format(sample_view.tags))
101+
102+
# Delete tag from just one view
103+
sample_view.tags = original_tag_set
104+
server.views.update(sample_view)
105+
93106
if args.download:
94107
# Download
95108
path = server.workbooks.download(sample_workbook.id, args.download)

samples/refresh_tasks.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
####
2+
# This script demonstrates how to use the Tableau Server Client
3+
# to query extract refresh tasks and run them as needed.
4+
#
5+
# To run the script, you must have installed Python 2.7.X or 3.3 and later.
6+
####
7+
8+
import argparse
9+
import getpass
10+
import logging
11+
12+
import tableauserverclient as TSC
13+
14+
15+
def handle_run(server, args):
16+
task = server.tasks.get_by_id(args.id)
17+
print(server.tasks.run(task))
18+
19+
20+
def handle_list(server, _):
21+
tasks, pagination = server.tasks.get()
22+
for task in tasks:
23+
print("{}".format(task))
24+
25+
26+
def handle_info(server, args):
27+
task = server.tasks.get_by_id(args.id)
28+
print("{}".format(task))
29+
30+
31+
def main():
32+
parser = argparse.ArgumentParser(description='Get all of the refresh tasks available on a server')
33+
parser.add_argument('--server', '-s', required=True, help='server address')
34+
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
35+
parser.add_argument('--site', '-S', default=None)
36+
parser.add_argument('-p', default=None)
37+
38+
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
39+
help='desired logging level (set to error by default)')
40+
41+
subcommands = parser.add_subparsers()
42+
43+
list_arguments = subcommands.add_parser('list')
44+
list_arguments.set_defaults(func=handle_list)
45+
46+
run_arguments = subcommands.add_parser('run')
47+
run_arguments.add_argument('id', default=None)
48+
run_arguments.set_defaults(func=handle_run)
49+
50+
info_arguments = subcommands.add_parser('info')
51+
info_arguments.add_argument('id', default=None)
52+
info_arguments.set_defaults(func=handle_info)
53+
54+
args = parser.parse_args()
55+
56+
if args.p is None:
57+
password = getpass.getpass("Password: ")
58+
else:
59+
password = args.p
60+
61+
# Set logging level based on user input, or error by default
62+
logging_level = getattr(logging, args.logging_level.upper())
63+
logging.basicConfig(level=logging_level)
64+
65+
# SIGN IN
66+
tableau_auth = TSC.TableauAuth(args.username, password, args.site)
67+
server = TSC.Server(args.server)
68+
server.version = '2.6'
69+
with server.auth.sign_in(tableau_auth):
70+
args.func(server, args)
71+
72+
73+
if __name__ == '__main__':
74+
main()

tableauserverclient/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
33
GroupItem, PaginationItem, ProjectItem, ScheduleItem, \
44
SiteItem, TableauAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError, \
5-
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem
6-
from .server import RequestOptions, Filter, Sort, Server, ServerResponseError,\
5+
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem
6+
from .server import RequestOptions, ImageRequestOptions, Filter, Sort, Server, ServerResponseError,\
77
MissingRequiredFieldError, NotSignedInError, Pager
88

99
from ._version import get_versions

tableauserverclient/datetime_helpers.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import datetime
22

3-
43
# This code below is from the python documentation for tzinfo: https://docs.python.org/2.3/lib/datetime-tzinfo.html
54
ZERO = datetime.timedelta(0)
65
HOUR = datetime.timedelta(hours=1)
76

8-
# A UTC class.
9-
107

118
class UTC(datetime.tzinfo):
129
"""UTC"""
@@ -22,7 +19,6 @@ def dst(self, dt):
2219

2320

2421
utc = UTC()
25-
2622
TABLEAU_DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
2723

2824

tableauserverclient/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .server_info_item import ServerInfoItem
1111
from .site_item import SiteItem
1212
from .tableau_auth import TableauAuth
13+
from .task_item import TaskItem
1314
from .user_item import UserItem
1415
from .view_item import ViewItem
1516
from .workbook_item import WorkbookItem

tableauserverclient/models/datasource_item.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@
44
from .tag_item import TagItem
55
from .. import NAMESPACE
66
from ..datetime_helpers import parse_datetime
7+
import copy
78

89

910
class DatasourceItem(object):
1011
def __init__(self, project_id, name=None):
1112
self._connections = None
1213
self._content_url = None
1314
self._created_at = None
15+
self._datasource_type = None
1416
self._id = None
17+
self._initial_tags = set()
1518
self._project_name = None
16-
self._tags = set()
17-
self._datasource_type = None
1819
self._updated_at = None
1920
self.name = name
2021
self.owner_id = None
2122
self.project_id = project_id
23+
self.tags = set()
2224

2325
@property
2426
def connections(self):
@@ -52,10 +54,6 @@ def project_id(self, value):
5254
def project_name(self):
5355
return self._project_name
5456

55-
@property
56-
def tags(self):
57-
return self._tags
58-
5957
@property
6058
def datasource_type(self):
6159
return self._datasource_type
@@ -90,7 +88,8 @@ def _set_values(self, id, name, datasource_type, content_url, created_at,
9088
if updated_at:
9189
self._updated_at = updated_at
9290
if tags:
93-
self._tags = tags
91+
self.tags = tags
92+
self._initial_tags = copy.copy(tags)
9493
if project_id:
9594
self.project_id = project_id
9695
if project_name:

tableauserverclient/models/schedule_item.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def __init__(self, name, priority, schedule_type, execution_order, interval_item
3333
self.priority = priority
3434
self.schedule_type = schedule_type
3535

36+
def __repr__(self):
37+
return "<Schedule#{_id} \"{_name}\" {interval_item}>".format(**self.__dict__)
38+
3639
@property
3740
def created_at(self):
3841
return self._created_at
@@ -106,7 +109,7 @@ def _parse_common_tags(self, schedule_xml):
106109
(_, name, _, _, updated_at, _, next_run_at, end_schedule_at, execution_order,
107110
priority, interval_item) = self._parse_element(schedule_xml)
108111

109-
self._set_values(id=None,
112+
self._set_values(id_=None,
110113
name=name,
111114
state=None,
112115
created_at=None,
@@ -120,10 +123,10 @@ def _parse_common_tags(self, schedule_xml):
120123

121124
return self
122125

123-
def _set_values(self, id, name, state, created_at, updated_at, schedule_type,
126+
def _set_values(self, id_, name, state, created_at, updated_at, schedule_type,
124127
next_run_at, end_schedule_at, execution_order, priority, interval_item):
125-
if id is not None:
126-
self._id = id
128+
if id_ is not None:
129+
self._id = id_
127130
if name:
128131
self._name = name
129132
if state:
@@ -147,16 +150,20 @@ def _set_values(self, id, name, state, created_at, updated_at, schedule_type,
147150

148151
@classmethod
149152
def from_response(cls, resp):
150-
all_schedule_items = []
151153
parsed_response = ET.fromstring(resp)
154+
return cls.from_element(parsed_response)
155+
156+
@classmethod
157+
def from_element(cls, parsed_response):
158+
all_schedule_items = []
152159
all_schedule_xml = parsed_response.findall('.//t:schedule', namespaces=NAMESPACE)
153160
for schedule_xml in all_schedule_xml:
154-
(id, name, state, created_at, updated_at, schedule_type, next_run_at,
161+
(id_, name, state, created_at, updated_at, schedule_type, next_run_at,
155162
end_schedule_at, execution_order, priority, interval_item) = cls._parse_element(schedule_xml)
156163

157164
schedule_item = cls(name, priority, schedule_type, execution_order, interval_item)
158165

159-
schedule_item._set_values(id=id,
166+
schedule_item._set_values(id_=id_,
160167
name=None,
161168
state=state,
162169
created_at=created_at,

0 commit comments

Comments
 (0)
0