Skip to content

Commit ef26c64

Browse files
committed
add the vizql initial support
1 parent bf85704 commit ef26c64

File tree

7 files changed

+606
-16
lines changed

7 files changed

+606
-16
lines changed

samples/vds.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
####
2+
# Getting Started Part Three of Three
3+
# This script demonstrates all the different types of 'content' a server contains
4+
#
5+
# To make it easy to run, it doesn't take any arguments - you need to edit the code with your info
6+
####
7+
8+
from typing import Dict, Any
9+
from rich import print
10+
11+
import getpass
12+
import tableauserverclient as TSC
13+
14+
15+
def main():
16+
# 1 - replace with your server domain: stop at the slash
17+
server_url = ""
18+
19+
# 2 - optional - change to false **for testing only** if you get a certificate error
20+
use_ssl = True
21+
22+
server = TSC.Server(server_url, use_server_version=True, http_options={"verify": use_ssl})
23+
print(f"Connected to {server.server_info.baseurl}")
24+
25+
# 3 - replace with your site name exactly as it looks in the url
26+
# e.g https://my-server/#/site/this-is-your-site-url-name/not-this-part
27+
site_url_name = "" # leave empty if there is no site name in the url (you are on the default site)
28+
29+
# 4 - replace with your username.
30+
# REMEMBER: if you are using Tableau Online, your username is the entire email address
31+
username = ""
32+
password = "" #getpass.getpass("Enter your password:") # so you don't save it in this file
33+
tableau_auth = TSC.TableauAuth(username, password, site_id=site_url_name)
34+
35+
# OR instead of username+password, use a Personal Access Token (PAT) (required by Tableau Cloud)
36+
# token_name = "your-token-name"
37+
# token_value = "your-token-value-long-random-string"
38+
# tableau_auth = TSC.PersonalAccessTokenAuth(token_name, token_value, site_id=site_url_name)
39+
40+
with server.auth.sign_in(tableau_auth):
41+
# schema - may be used to understand the schema of the VDS API
42+
print(server.vizql.VizQL_Schema)
43+
# query
44+
query_dict: Dict[str, Any] = {
45+
"fields": [{"fieldCaption": "School Code"}],
46+
"filters": [
47+
{
48+
"field": {"fieldCaption": "Enrollment (K-12)", "function": "SUM"},
49+
"filterType": "QUANTITATIVE_NUMERICAL",
50+
"quantitativeFilterType": "MIN",
51+
"min": 500
52+
}
53+
]
54+
}
55+
datasource_id = "e4d75fd4-af1c-4fb8-a049-058e3fef57bc"
56+
57+
# query metadata
58+
vds_metadata = server.vizql.query_vds_metadata(
59+
datasource_id=datasource_id
60+
)
61+
if vds_metadata:
62+
print(vds_metadata)
63+
64+
# query data
65+
vds_data = server.vizql.query_vds_data(
66+
query=query_dict,
67+
datasource_id=datasource_id
68+
)
69+
if vds_data:
70+
print(vds_data)
71+
if __name__ == "__main__":
72+
main()

setup.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[versioneer]
2+
VCS = git
3+
style = pep440-pre
4+
versionfile_source = tableauserverclient/bin/_version.py
5+
versionfile_build = tableauserverclient/bin/_version.py
6+
tag_prefix = v

tableauserverclient/server/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
Views,
4646
Webhooks,
4747
Workbooks,
48+
VizQL,
4849
)
4950

5051
__all__ = [
@@ -91,4 +92,5 @@
9192
"Views",
9293
"Webhooks",
9394
"Workbooks",
95+
"VizQL",
9496
]

tableauserverclient/server/endpoint/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from tableauserverclient.server.endpoint.virtual_connections_endpoint import VirtualConnections
3131
from tableauserverclient.server.endpoint.webhooks_endpoint import Webhooks
3232
from tableauserverclient.server.endpoint.workbooks_endpoint import Workbooks
33-
33+
from tableauserverclient.server.endpoint.vizql_endpoint import VizQL
3434
__all__ = [
3535
"Auth",
3636
"CustomViews",
@@ -66,4 +66,5 @@
6666
"VirtualConnections",
6767
"Webhooks",
6868
"Workbooks",
69+
"VizQL",
6970
]

tableauserverclient/server/endpoint/endpoint.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def set_parameters(http_options, auth_token, content, content_type, parameters)
6666
parameters["headers"][CONTENT_TYPE_HEADER] = content_type
6767

6868
Endpoint.set_user_agent(parameters)
69-
if content is not None:
69+
if content is not None and content_type != JSON_CONTENT_TYPE:
7070
parameters["data"] = content
7171
return parameters or {}
7272

@@ -86,21 +86,20 @@ def set_user_agent(parameters):
8686
# return explicitly for testing only
8787
return parameters
8888

89-
def _blocking_request(self, method, url, parameters={}) -> Optional[Union["Response", Exception]]:
89+
def _blocking_request(self, method, url, parameters={}, content=None, content_type=None) -> Optional[Union["Response", Exception]]:
9090
response = None
9191
logger.debug(f"[{datetime.timestamp()}] Begin blocking request to {url}")
9292
try:
93-
response = method(url, **parameters)
93+
if content and content_type == JSON_CONTENT_TYPE:
94+
response = method(url, json=content, **parameters)
95+
else:
96+
response = method(url, **parameters)
9497
logger.debug(f"[{datetime.timestamp()}] Call finished")
9598
except Exception as e:
9699
logger.debug(f"Error making request to server: {e}")
97100
raise e
98101
return response
99102

100-
def send_request_while_show_progress_threaded(
101-
self, method, url, parameters={}, request_timeout=None
102-
) -> Optional[Union["Response", Exception]]:
103-
return self._blocking_request(method, url, parameters)
104103

105104
def _make_request(
106105
self,
@@ -116,17 +115,19 @@ def _make_request(
116115
)
117116

118117
logger.debug(f"request method {method.__name__}, url: {url}")
119-
if content:
120-
redacted = helpers.strings.redact_xml(content[:200])
121-
# this needs to be under a trace or something, it's a LOT
122-
# logger.debug("request content: {}".format(redacted))
123118

124119
# a request can, for stuff like publishing, spin for ages waiting for a response.
125120
# we need some user-facing activity so they know it's not dead.
126-
request_timeout = self.parent_srv.http_options.get("timeout") or 0
127-
server_response: Optional[Union["Response", Exception]] = self.send_request_while_show_progress_threaded(
128-
method, url, parameters, request_timeout
129-
)
121+
122+
if content and content_type == JSON_CONTENT_TYPE:
123+
server_response: Optional[Union["Response", Exception]] = self._blocking_request(
124+
method, url, parameters, content, content_type
125+
)
126+
else:
127+
server_response: Optional[Union["Response", Exception]] = self._blocking_request(
128+
method, url, parameters
129+
)
130+
130131
logger.debug(f"[{datetime.timestamp()}] Async request returned: received {server_response}")
131132
# is this blocking retry really necessary? I guess if it was just the threading messing it up?
132133
if server_response is None:

0 commit comments

Comments
 (0)