tableauserverclient 0.33__py3-none-any.whl → 0.35__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tableauserverclient/__init__.py +33 -23
- tableauserverclient/{_version.py → bin/_version.py} +3 -3
- tableauserverclient/config.py +5 -3
- tableauserverclient/models/column_item.py +1 -1
- tableauserverclient/models/connection_credentials.py +18 -2
- tableauserverclient/models/connection_item.py +44 -6
- tableauserverclient/models/custom_view_item.py +78 -11
- tableauserverclient/models/data_acceleration_report_item.py +2 -2
- tableauserverclient/models/data_alert_item.py +5 -5
- tableauserverclient/models/data_freshness_policy_item.py +6 -6
- tableauserverclient/models/database_item.py +3 -3
- tableauserverclient/models/datasource_item.py +10 -10
- tableauserverclient/models/dqw_item.py +1 -1
- tableauserverclient/models/favorites_item.py +5 -6
- tableauserverclient/models/fileupload_item.py +1 -1
- tableauserverclient/models/flow_item.py +54 -9
- tableauserverclient/models/flow_run_item.py +3 -3
- tableauserverclient/models/group_item.py +44 -4
- tableauserverclient/models/groupset_item.py +4 -4
- tableauserverclient/models/interval_item.py +9 -9
- tableauserverclient/models/job_item.py +73 -8
- tableauserverclient/models/linked_tasks_item.py +5 -5
- tableauserverclient/models/metric_item.py +5 -5
- tableauserverclient/models/pagination_item.py +1 -1
- tableauserverclient/models/permissions_item.py +12 -10
- tableauserverclient/models/project_item.py +73 -19
- tableauserverclient/models/property_decorators.py +12 -11
- tableauserverclient/models/reference_item.py +2 -2
- tableauserverclient/models/revision_item.py +3 -3
- tableauserverclient/models/schedule_item.py +2 -2
- tableauserverclient/models/server_info_item.py +26 -6
- tableauserverclient/models/site_item.py +69 -3
- tableauserverclient/models/subscription_item.py +3 -3
- tableauserverclient/models/table_item.py +1 -1
- tableauserverclient/models/tableau_auth.py +115 -5
- tableauserverclient/models/tableau_types.py +2 -2
- tableauserverclient/models/tag_item.py +3 -4
- tableauserverclient/models/task_item.py +34 -4
- tableauserverclient/models/user_item.py +47 -17
- tableauserverclient/models/view_item.py +66 -13
- tableauserverclient/models/virtual_connection_item.py +6 -5
- tableauserverclient/models/webhook_item.py +39 -6
- tableauserverclient/models/workbook_item.py +116 -13
- tableauserverclient/namespace.py +1 -1
- tableauserverclient/server/__init__.py +2 -1
- tableauserverclient/server/endpoint/auth_endpoint.py +69 -10
- tableauserverclient/server/endpoint/custom_views_endpoint.py +258 -29
- tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
- tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
- tableauserverclient/server/endpoint/databases_endpoint.py +13 -12
- tableauserverclient/server/endpoint/datasources_endpoint.py +61 -62
- tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
- tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
- tableauserverclient/server/endpoint/endpoint.py +19 -21
- tableauserverclient/server/endpoint/exceptions.py +23 -7
- tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
- tableauserverclient/server/endpoint/fileuploads_endpoint.py +9 -11
- tableauserverclient/server/endpoint/flow_runs_endpoint.py +15 -13
- tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
- tableauserverclient/server/endpoint/flows_endpoint.py +344 -29
- tableauserverclient/server/endpoint/groups_endpoint.py +342 -27
- tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
- tableauserverclient/server/endpoint/jobs_endpoint.py +116 -7
- tableauserverclient/server/endpoint/linked_tasks_endpoint.py +2 -2
- tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
- tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
- tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
- tableauserverclient/server/endpoint/projects_endpoint.py +681 -30
- tableauserverclient/server/endpoint/resource_tagger.py +14 -13
- tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
- tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
- tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
- tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
- tableauserverclient/server/endpoint/tables_endpoint.py +15 -14
- tableauserverclient/server/endpoint/tasks_endpoint.py +86 -8
- tableauserverclient/server/endpoint/users_endpoint.py +366 -19
- tableauserverclient/server/endpoint/views_endpoint.py +262 -20
- tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
- tableauserverclient/server/endpoint/webhooks_endpoint.py +88 -11
- tableauserverclient/server/endpoint/workbooks_endpoint.py +653 -65
- tableauserverclient/server/filter.py +2 -2
- tableauserverclient/server/pager.py +29 -6
- tableauserverclient/server/query.py +68 -19
- tableauserverclient/server/request_factory.py +57 -37
- tableauserverclient/server/request_options.py +243 -141
- tableauserverclient/server/server.py +76 -10
- tableauserverclient/server/sort.py +16 -2
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/METADATA +7 -7
- tableauserverclient-0.35.dist-info/RECORD +106 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/WHEEL +1 -1
- tableauserverclient-0.33.dist-info/RECORD +0 -106
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from contextlib import closing
|
|
3
3
|
|
|
4
|
+
from tableauserverclient.models.permissions_item import PermissionsRule
|
|
4
5
|
from tableauserverclient.server.endpoint.endpoint import QuerysetEndpoint, api
|
|
5
6
|
from tableauserverclient.server.endpoint.exceptions import MissingRequiredFieldError
|
|
6
7
|
from tableauserverclient.server.endpoint.permissions_endpoint import _PermissionsEndpoint
|
|
@@ -11,7 +12,8 @@ from tableauserverclient.models import ViewItem, PaginationItem
|
|
|
11
12
|
|
|
12
13
|
from tableauserverclient.helpers.logging import logger
|
|
13
14
|
|
|
14
|
-
from typing import
|
|
15
|
+
from typing import Optional, TYPE_CHECKING, Union
|
|
16
|
+
from collections.abc import Iterable, Iterator
|
|
15
17
|
|
|
16
18
|
if TYPE_CHECKING:
|
|
17
19
|
from tableauserverclient.server.request_options import (
|
|
@@ -24,23 +26,47 @@ if TYPE_CHECKING:
|
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
29
|
+
"""
|
|
30
|
+
The Tableau Server Client provides methods for interacting with view
|
|
31
|
+
resources, or endpoints. These methods correspond to the endpoints for views
|
|
32
|
+
in the Tableau Server REST API.
|
|
33
|
+
"""
|
|
34
|
+
|
|
27
35
|
def __init__(self, parent_srv):
|
|
28
|
-
super(
|
|
36
|
+
super().__init__(parent_srv)
|
|
29
37
|
self._permissions = _PermissionsEndpoint(parent_srv, lambda: self.baseurl)
|
|
30
38
|
|
|
31
39
|
# Used because populate_preview_image functionaliy requires workbook endpoint
|
|
32
40
|
@property
|
|
33
41
|
def siteurl(self) -> str:
|
|
34
|
-
return "{
|
|
42
|
+
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}"
|
|
35
43
|
|
|
36
44
|
@property
|
|
37
45
|
def baseurl(self) -> str:
|
|
38
|
-
return "{
|
|
46
|
+
return f"{self.siteurl}/views"
|
|
39
47
|
|
|
40
48
|
@api(version="2.2")
|
|
41
49
|
def get(
|
|
42
50
|
self, req_options: Optional["RequestOptions"] = None, usage: bool = False
|
|
43
|
-
) ->
|
|
51
|
+
) -> tuple[list[ViewItem], PaginationItem]:
|
|
52
|
+
"""
|
|
53
|
+
Returns the list of views on the site. Paginated endpoint.
|
|
54
|
+
|
|
55
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_views_for_site
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
req_options: Optional[RequestOptions], default None
|
|
60
|
+
The request options for the request. These options can include
|
|
61
|
+
parameters such as page size and sorting.
|
|
62
|
+
|
|
63
|
+
usage: bool, default False
|
|
64
|
+
If True, includes usage statistics in the response.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
views: tuple[list[ViewItem], PaginationItem]
|
|
69
|
+
"""
|
|
44
70
|
logger.info("Querying all views on site")
|
|
45
71
|
url = self.baseurl
|
|
46
72
|
if usage:
|
|
@@ -52,11 +78,28 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
52
78
|
|
|
53
79
|
@api(version="3.1")
|
|
54
80
|
def get_by_id(self, view_id: str, usage: bool = False) -> ViewItem:
|
|
81
|
+
"""
|
|
82
|
+
Returns the details of a specific view.
|
|
83
|
+
|
|
84
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#get_view
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
view_id: str
|
|
89
|
+
The view ID.
|
|
90
|
+
|
|
91
|
+
usage: bool, default False
|
|
92
|
+
If True, includes usage statistics in the response.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
view_item: ViewItem
|
|
97
|
+
"""
|
|
55
98
|
if not view_id:
|
|
56
99
|
error = "View item missing ID."
|
|
57
100
|
raise MissingRequiredFieldError(error)
|
|
58
|
-
logger.info("Querying single view (ID: {
|
|
59
|
-
url = "{
|
|
101
|
+
logger.info(f"Querying single view (ID: {view_id})")
|
|
102
|
+
url = f"{self.baseurl}/{view_id}"
|
|
60
103
|
if usage:
|
|
61
104
|
url += "?includeUsageStatistics=true"
|
|
62
105
|
server_response = self.get_request(url)
|
|
@@ -64,6 +107,24 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
64
107
|
|
|
65
108
|
@api(version="2.0")
|
|
66
109
|
def populate_preview_image(self, view_item: ViewItem) -> None:
|
|
110
|
+
"""
|
|
111
|
+
Populates a preview image for the specified view.
|
|
112
|
+
|
|
113
|
+
This method gets the preview image (thumbnail) for the specified view
|
|
114
|
+
item. The method uses the id and workbook_id fields to query the preview
|
|
115
|
+
image. The method populates the preview_image for the view.
|
|
116
|
+
|
|
117
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_with_preview
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
view_item: ViewItem
|
|
122
|
+
The view item for which to populate the preview image.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
None
|
|
127
|
+
"""
|
|
67
128
|
if not view_item.id or not view_item.workbook_id:
|
|
68
129
|
error = "View item missing ID or workbook ID."
|
|
69
130
|
raise MissingRequiredFieldError(error)
|
|
@@ -72,16 +133,37 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
72
133
|
return self._get_preview_for_view(view_item)
|
|
73
134
|
|
|
74
135
|
view_item._set_preview_image(image_fetcher)
|
|
75
|
-
logger.info("Populated preview image for view (ID: {
|
|
136
|
+
logger.info(f"Populated preview image for view (ID: {view_item.id})")
|
|
76
137
|
|
|
77
138
|
def _get_preview_for_view(self, view_item: ViewItem) -> bytes:
|
|
78
|
-
url = "{
|
|
139
|
+
url = f"{self.siteurl}/workbooks/{view_item.workbook_id}/views/{view_item.id}/previewImage"
|
|
79
140
|
server_response = self.get_request(url)
|
|
80
141
|
image = server_response.content
|
|
81
142
|
return image
|
|
82
143
|
|
|
83
144
|
@api(version="2.5")
|
|
84
145
|
def populate_image(self, view_item: ViewItem, req_options: Optional["ImageRequestOptions"] = None) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Populates the image of the specified view.
|
|
148
|
+
|
|
149
|
+
This method uses the id field to query the image, and populates the
|
|
150
|
+
image content as the image field.
|
|
151
|
+
|
|
152
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_image
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
view_item: ViewItem
|
|
157
|
+
The view item for which to populate the image.
|
|
158
|
+
|
|
159
|
+
req_options: Optional[ImageRequestOptions], default None
|
|
160
|
+
Optional request options for the request. These options can include
|
|
161
|
+
parameters such as image resolution and max age.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
None
|
|
166
|
+
"""
|
|
85
167
|
if not view_item.id:
|
|
86
168
|
error = "View item missing ID."
|
|
87
169
|
raise MissingRequiredFieldError(error)
|
|
@@ -90,16 +172,36 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
90
172
|
return self._get_view_image(view_item, req_options)
|
|
91
173
|
|
|
92
174
|
view_item._set_image(image_fetcher)
|
|
93
|
-
logger.info("Populated image for view (ID: {
|
|
175
|
+
logger.info(f"Populated image for view (ID: {view_item.id})")
|
|
94
176
|
|
|
95
177
|
def _get_view_image(self, view_item: ViewItem, req_options: Optional["ImageRequestOptions"]) -> bytes:
|
|
96
|
-
url = "{
|
|
178
|
+
url = f"{self.baseurl}/{view_item.id}/image"
|
|
97
179
|
server_response = self.get_request(url, req_options)
|
|
98
180
|
image = server_response.content
|
|
99
181
|
return image
|
|
100
182
|
|
|
101
183
|
@api(version="2.7")
|
|
102
184
|
def populate_pdf(self, view_item: ViewItem, req_options: Optional["PDFRequestOptions"] = None) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Populates the PDF content of the specified view.
|
|
187
|
+
|
|
188
|
+
This method populates a PDF with image(s) of the view you specify.
|
|
189
|
+
|
|
190
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_pdf
|
|
191
|
+
|
|
192
|
+
Parameters
|
|
193
|
+
----------
|
|
194
|
+
view_item: ViewItem
|
|
195
|
+
The view item for which to populate the PDF.
|
|
196
|
+
|
|
197
|
+
req_options: Optional[PDFRequestOptions], default None
|
|
198
|
+
Optional request options for the request. These options can include
|
|
199
|
+
parameters such as orientation and paper size.
|
|
200
|
+
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
None
|
|
204
|
+
"""
|
|
103
205
|
if not view_item.id:
|
|
104
206
|
error = "View item missing ID."
|
|
105
207
|
raise MissingRequiredFieldError(error)
|
|
@@ -108,16 +210,37 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
108
210
|
return self._get_view_pdf(view_item, req_options)
|
|
109
211
|
|
|
110
212
|
view_item._set_pdf(pdf_fetcher)
|
|
111
|
-
logger.info("Populated pdf for view (ID: {
|
|
213
|
+
logger.info(f"Populated pdf for view (ID: {view_item.id})")
|
|
112
214
|
|
|
113
215
|
def _get_view_pdf(self, view_item: ViewItem, req_options: Optional["PDFRequestOptions"]) -> bytes:
|
|
114
|
-
url = "{
|
|
216
|
+
url = f"{self.baseurl}/{view_item.id}/pdf"
|
|
115
217
|
server_response = self.get_request(url, req_options)
|
|
116
218
|
pdf = server_response.content
|
|
117
219
|
return pdf
|
|
118
220
|
|
|
119
221
|
@api(version="2.7")
|
|
120
222
|
def populate_csv(self, view_item: ViewItem, req_options: Optional["CSVRequestOptions"] = None) -> None:
|
|
223
|
+
"""
|
|
224
|
+
Populates the CSV data of the specified view.
|
|
225
|
+
|
|
226
|
+
This method uses the id field to query the CSV data, and populates the
|
|
227
|
+
data as the csv field.
|
|
228
|
+
|
|
229
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_data
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
view_item: ViewItem
|
|
234
|
+
The view item for which to populate the CSV data.
|
|
235
|
+
|
|
236
|
+
req_options: Optional[CSVRequestOptions], default None
|
|
237
|
+
Optional request options for the request. These options can include
|
|
238
|
+
parameters such as view filters and max age.
|
|
239
|
+
|
|
240
|
+
Returns
|
|
241
|
+
-------
|
|
242
|
+
None
|
|
243
|
+
"""
|
|
121
244
|
if not view_item.id:
|
|
122
245
|
error = "View item missing ID."
|
|
123
246
|
raise MissingRequiredFieldError(error)
|
|
@@ -126,16 +249,37 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
126
249
|
return self._get_view_csv(view_item, req_options)
|
|
127
250
|
|
|
128
251
|
view_item._set_csv(csv_fetcher)
|
|
129
|
-
logger.info("Populated csv for view (ID: {
|
|
252
|
+
logger.info(f"Populated csv for view (ID: {view_item.id})")
|
|
130
253
|
|
|
131
254
|
def _get_view_csv(self, view_item: ViewItem, req_options: Optional["CSVRequestOptions"]) -> Iterator[bytes]:
|
|
132
|
-
url = "{
|
|
255
|
+
url = f"{self.baseurl}/{view_item.id}/data"
|
|
133
256
|
|
|
134
257
|
with closing(self.get_request(url, request_object=req_options, parameters={"stream": True})) as server_response:
|
|
135
258
|
yield from server_response.iter_content(1024)
|
|
136
259
|
|
|
137
260
|
@api(version="3.8")
|
|
138
261
|
def populate_excel(self, view_item: ViewItem, req_options: Optional["ExcelRequestOptions"] = None) -> None:
|
|
262
|
+
"""
|
|
263
|
+
Populates the Excel data of the specified view.
|
|
264
|
+
|
|
265
|
+
This method uses the id field to query the Excel data, and populates the
|
|
266
|
+
data as the Excel field.
|
|
267
|
+
|
|
268
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#download_view_excel
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
view_item: ViewItem
|
|
273
|
+
The view item for which to populate the Excel data.
|
|
274
|
+
|
|
275
|
+
req_options: Optional[ExcelRequestOptions], default None
|
|
276
|
+
Optional request options for the request. These options can include
|
|
277
|
+
parameters such as view filters and max age.
|
|
278
|
+
|
|
279
|
+
Returns
|
|
280
|
+
-------
|
|
281
|
+
None
|
|
282
|
+
"""
|
|
139
283
|
if not view_item.id:
|
|
140
284
|
error = "View item missing ID."
|
|
141
285
|
raise MissingRequiredFieldError(error)
|
|
@@ -144,28 +288,76 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
144
288
|
return self._get_view_excel(view_item, req_options)
|
|
145
289
|
|
|
146
290
|
view_item._set_excel(excel_fetcher)
|
|
147
|
-
logger.info("Populated excel for view (ID: {
|
|
291
|
+
logger.info(f"Populated excel for view (ID: {view_item.id})")
|
|
148
292
|
|
|
149
293
|
def _get_view_excel(self, view_item: ViewItem, req_options: Optional["ExcelRequestOptions"]) -> Iterator[bytes]:
|
|
150
|
-
url = "{
|
|
294
|
+
url = f"{self.baseurl}/{view_item.id}/crosstab/excel"
|
|
151
295
|
|
|
152
296
|
with closing(self.get_request(url, request_object=req_options, parameters={"stream": True})) as server_response:
|
|
153
297
|
yield from server_response.iter_content(1024)
|
|
154
298
|
|
|
155
299
|
@api(version="3.2")
|
|
156
300
|
def populate_permissions(self, item: ViewItem) -> None:
|
|
301
|
+
"""
|
|
302
|
+
Returns a list of permissions for the specific view.
|
|
303
|
+
|
|
304
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_permissions.htm#query_view_permissions
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
item: ViewItem
|
|
309
|
+
The view item for which to populate the permissions.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
None
|
|
314
|
+
"""
|
|
157
315
|
self._permissions.populate(item)
|
|
158
316
|
|
|
159
317
|
@api(version="3.2")
|
|
160
|
-
def update_permissions(self, resource, rules):
|
|
318
|
+
def update_permissions(self, resource: ViewItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
|
|
319
|
+
""" """
|
|
161
320
|
return self._permissions.update(resource, rules)
|
|
162
321
|
|
|
163
322
|
@api(version="3.2")
|
|
164
|
-
def delete_permission(self, item, capability_item):
|
|
323
|
+
def delete_permission(self, item: ViewItem, capability_item: PermissionsRule) -> None:
|
|
324
|
+
"""
|
|
325
|
+
Deletes permission to the specified view (also known as a sheet) for a
|
|
326
|
+
Tableau Server user or group.
|
|
327
|
+
|
|
328
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_permissions.htm#delete_view_permission
|
|
329
|
+
|
|
330
|
+
Parameters
|
|
331
|
+
----------
|
|
332
|
+
item: ViewItem
|
|
333
|
+
The view item for which to delete the permission.
|
|
334
|
+
|
|
335
|
+
capability_item: PermissionsRule
|
|
336
|
+
The permission rule to delete.
|
|
337
|
+
|
|
338
|
+
Returns
|
|
339
|
+
-------
|
|
340
|
+
None
|
|
341
|
+
"""
|
|
165
342
|
return self._permissions.delete(item, capability_item)
|
|
166
343
|
|
|
167
344
|
# Update view. Currently only tags can be updated
|
|
168
345
|
def update(self, view_item: ViewItem) -> ViewItem:
|
|
346
|
+
"""
|
|
347
|
+
Updates the tags for the specified view. All other fields are managed
|
|
348
|
+
through the WorkbookItem object.
|
|
349
|
+
|
|
350
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#add_tags_to_view
|
|
351
|
+
|
|
352
|
+
Parameters
|
|
353
|
+
----------
|
|
354
|
+
view_item: ViewItem
|
|
355
|
+
The view item for which to update tags.
|
|
356
|
+
|
|
357
|
+
Returns
|
|
358
|
+
-------
|
|
359
|
+
ViewItem
|
|
360
|
+
"""
|
|
169
361
|
if not view_item.id:
|
|
170
362
|
error = "View item missing ID. View must be retrieved from server first."
|
|
171
363
|
raise MissingRequiredFieldError(error)
|
|
@@ -176,15 +368,65 @@ class Views(QuerysetEndpoint[ViewItem], TaggingMixin[ViewItem]):
|
|
|
176
368
|
return view_item
|
|
177
369
|
|
|
178
370
|
@api(version="1.0")
|
|
179
|
-
def add_tags(self, item: Union[ViewItem, str], tags: Union[Iterable[str], str]) ->
|
|
371
|
+
def add_tags(self, item: Union[ViewItem, str], tags: Union[Iterable[str], str]) -> set[str]:
|
|
372
|
+
"""
|
|
373
|
+
Adds tags to the specified view.
|
|
374
|
+
|
|
375
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#add_tags_to_view
|
|
376
|
+
|
|
377
|
+
Parameters
|
|
378
|
+
----------
|
|
379
|
+
item: Union[ViewItem, str]
|
|
380
|
+
The view item or view ID to which to add tags.
|
|
381
|
+
|
|
382
|
+
tags: Union[Iterable[str], str]
|
|
383
|
+
The tags to add to the view.
|
|
384
|
+
|
|
385
|
+
Returns
|
|
386
|
+
-------
|
|
387
|
+
set[str]
|
|
388
|
+
|
|
389
|
+
"""
|
|
180
390
|
return super().add_tags(item, tags)
|
|
181
391
|
|
|
182
392
|
@api(version="1.0")
|
|
183
393
|
def delete_tags(self, item: Union[ViewItem, str], tags: Union[Iterable[str], str]) -> None:
|
|
394
|
+
"""
|
|
395
|
+
Deletes tags from the specified view.
|
|
396
|
+
|
|
397
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#delete_tags_from_view
|
|
398
|
+
|
|
399
|
+
Parameters
|
|
400
|
+
----------
|
|
401
|
+
item: Union[ViewItem, str]
|
|
402
|
+
The view item or view ID from which to delete tags.
|
|
403
|
+
|
|
404
|
+
tags: Union[Iterable[str], str]
|
|
405
|
+
The tags to delete from the view.
|
|
406
|
+
|
|
407
|
+
Returns
|
|
408
|
+
-------
|
|
409
|
+
None
|
|
410
|
+
"""
|
|
184
411
|
return super().delete_tags(item, tags)
|
|
185
412
|
|
|
186
413
|
@api(version="1.0")
|
|
187
414
|
def update_tags(self, item: ViewItem) -> None:
|
|
415
|
+
"""
|
|
416
|
+
Updates the tags for the specified view. Any changes to the tags must
|
|
417
|
+
be made by editing the tags attribute of the view item.
|
|
418
|
+
|
|
419
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#add_tags_to_view
|
|
420
|
+
|
|
421
|
+
Parameters
|
|
422
|
+
----------
|
|
423
|
+
item: ViewItem
|
|
424
|
+
The view item for which to update tags.
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
None
|
|
429
|
+
"""
|
|
188
430
|
return super().update_tags(item)
|
|
189
431
|
|
|
190
432
|
def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> QuerySet[ViewItem]:
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from functools import partial
|
|
2
2
|
import json
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional, TYPE_CHECKING, Union
|
|
5
|
+
from collections.abc import Iterable
|
|
5
6
|
|
|
6
7
|
from tableauserverclient.models.connection_item import ConnectionItem
|
|
7
8
|
from tableauserverclient.models.pagination_item import PaginationItem
|
|
@@ -28,7 +29,7 @@ class VirtualConnections(QuerysetEndpoint[VirtualConnectionItem], TaggingMixin):
|
|
|
28
29
|
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/virtualConnections"
|
|
29
30
|
|
|
30
31
|
@api(version="3.18")
|
|
31
|
-
def get(self, req_options: Optional[RequestOptions] = None) ->
|
|
32
|
+
def get(self, req_options: Optional[RequestOptions] = None) -> tuple[list[VirtualConnectionItem], PaginationItem]:
|
|
32
33
|
server_response = self.get_request(self.baseurl, req_options)
|
|
33
34
|
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
34
35
|
virtual_connections = VirtualConnectionItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
@@ -44,7 +45,7 @@ class VirtualConnections(QuerysetEndpoint[VirtualConnectionItem], TaggingMixin):
|
|
|
44
45
|
|
|
45
46
|
def _get_virtual_database_connections(
|
|
46
47
|
self, virtual_connection: VirtualConnectionItem, req_options: Optional[RequestOptions] = None
|
|
47
|
-
) ->
|
|
48
|
+
) -> tuple[list[ConnectionItem], PaginationItem]:
|
|
48
49
|
server_response = self.get_request(f"{self.baseurl}/{virtual_connection.id}/connections", req_options)
|
|
49
50
|
connections = ConnectionItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
50
51
|
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
@@ -83,7 +84,7 @@ class VirtualConnections(QuerysetEndpoint[VirtualConnectionItem], TaggingMixin):
|
|
|
83
84
|
@api(version="3.23")
|
|
84
85
|
def get_revisions(
|
|
85
86
|
self, virtual_connection: VirtualConnectionItem, req_options: Optional[RequestOptions] = None
|
|
86
|
-
) ->
|
|
87
|
+
) -> tuple[list[RevisionItem], PaginationItem]:
|
|
87
88
|
server_response = self.get_request(f"{self.baseurl}/{virtual_connection.id}/revisions", req_options)
|
|
88
89
|
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
89
90
|
revisions = RevisionItem.from_response(server_response.content, self.parent_srv.namespace, virtual_connection)
|
|
@@ -159,7 +160,7 @@ class VirtualConnections(QuerysetEndpoint[VirtualConnectionItem], TaggingMixin):
|
|
|
159
160
|
@api(version="3.23")
|
|
160
161
|
def add_tags(
|
|
161
162
|
self, virtual_connection: Union[VirtualConnectionItem, str], tags: Union[Iterable[str], str]
|
|
162
|
-
) ->
|
|
163
|
+
) -> set[str]:
|
|
163
164
|
return super().add_tags(virtual_connection, tags)
|
|
164
165
|
|
|
165
166
|
@api(version="3.23")
|
|
@@ -6,7 +6,7 @@ from tableauserverclient.models import WebhookItem, PaginationItem
|
|
|
6
6
|
|
|
7
7
|
from tableauserverclient.helpers.logging import logger
|
|
8
8
|
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Optional, TYPE_CHECKING
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from ..server import Server
|
|
@@ -15,14 +15,29 @@ if TYPE_CHECKING:
|
|
|
15
15
|
|
|
16
16
|
class Webhooks(Endpoint):
|
|
17
17
|
def __init__(self, parent_srv: "Server") -> None:
|
|
18
|
-
super(
|
|
18
|
+
super().__init__(parent_srv)
|
|
19
19
|
|
|
20
20
|
@property
|
|
21
21
|
def baseurl(self) -> str:
|
|
22
|
-
return "{
|
|
22
|
+
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/webhooks"
|
|
23
23
|
|
|
24
24
|
@api(version="3.6")
|
|
25
|
-
def get(self, req_options: Optional["RequestOptions"] = None) ->
|
|
25
|
+
def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[WebhookItem], PaginationItem]:
|
|
26
|
+
"""
|
|
27
|
+
Returns a list of all webhooks on the site.
|
|
28
|
+
|
|
29
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#list_webhooks_for_site
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
req_options : Optional[RequestOptions]
|
|
34
|
+
Filter and sorting options for the request.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
tuple[list[WebhookItem], PaginationItem]
|
|
39
|
+
A tuple of the list of webhooks and pagination item
|
|
40
|
+
"""
|
|
26
41
|
logger.info("Querying all Webhooks on site")
|
|
27
42
|
url = self.baseurl
|
|
28
43
|
server_response = self.get_request(url, req_options)
|
|
@@ -32,39 +47,101 @@ class Webhooks(Endpoint):
|
|
|
32
47
|
|
|
33
48
|
@api(version="3.6")
|
|
34
49
|
def get_by_id(self, webhook_id: str) -> WebhookItem:
|
|
50
|
+
"""
|
|
51
|
+
Returns information about a specified Webhook.
|
|
52
|
+
|
|
53
|
+
Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#get_webhook
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
webhook_id : str
|
|
58
|
+
The ID of the webhook to query.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
WebhookItem
|
|
63
|
+
An object containing information about the webhook.
|
|
64
|
+
"""
|
|
35
65
|
if not webhook_id:
|
|
36
66
|
error = "Webhook ID undefined."
|
|
37
67
|
raise ValueError(error)
|
|
38
|
-
logger.info("Querying single webhook (ID: {
|
|
39
|
-
url = "{
|
|
68
|
+
logger.info(f"Querying single webhook (ID: {webhook_id})")
|
|
69
|
+
url = f"{self.baseurl}/{webhook_id}"
|
|
40
70
|
server_response = self.get_request(url)
|
|
41
71
|
return WebhookItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
42
72
|
|
|
43
73
|
@api(version="3.6")
|
|
44
74
|
def delete(self, webhook_id: str) -> None:
|
|
75
|
+
"""
|
|
76
|
+
Deletes a specified webhook.
|
|
77
|
+
|
|
78
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#delete_webhook
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
webhook_id : str
|
|
83
|
+
The ID of the webhook to delete.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
None
|
|
88
|
+
"""
|
|
45
89
|
if not webhook_id:
|
|
46
90
|
error = "Webhook ID undefined."
|
|
47
91
|
raise ValueError(error)
|
|
48
|
-
url = "{
|
|
92
|
+
url = f"{self.baseurl}/{webhook_id}"
|
|
49
93
|
self.delete_request(url)
|
|
50
|
-
logger.info("Deleted single webhook (ID: {
|
|
94
|
+
logger.info(f"Deleted single webhook (ID: {webhook_id})")
|
|
51
95
|
|
|
52
96
|
@api(version="3.6")
|
|
53
97
|
def create(self, webhook_item: WebhookItem) -> WebhookItem:
|
|
98
|
+
"""
|
|
99
|
+
Creates a new webhook on the site.
|
|
100
|
+
|
|
101
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#create_webhook
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
webhook_item : WebhookItem
|
|
106
|
+
The webhook item to create.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
WebhookItem
|
|
111
|
+
An object containing information about the created webhook
|
|
112
|
+
"""
|
|
54
113
|
url = self.baseurl
|
|
55
114
|
create_req = RequestFactory.Webhook.create_req(webhook_item)
|
|
56
115
|
server_response = self.post_request(url, create_req)
|
|
57
116
|
new_webhook = WebhookItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
58
117
|
|
|
59
|
-
logger.info("Created new webhook (ID: {
|
|
118
|
+
logger.info(f"Created new webhook (ID: {new_webhook.id})")
|
|
60
119
|
return new_webhook
|
|
61
120
|
|
|
62
121
|
@api(version="3.6")
|
|
63
122
|
def test(self, webhook_id: str):
|
|
123
|
+
"""
|
|
124
|
+
Tests the specified webhook. Sends an empty payload to the configured
|
|
125
|
+
destination URL of the webhook and returns the response from the server.
|
|
126
|
+
This is useful for testing, to ensure that things are being sent from
|
|
127
|
+
Tableau and received back as expected.
|
|
128
|
+
|
|
129
|
+
Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#test_webhook
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
webhook_id : str
|
|
134
|
+
The ID of the webhook to test.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
XML Response
|
|
139
|
+
|
|
140
|
+
"""
|
|
64
141
|
if not webhook_id:
|
|
65
142
|
error = "Webhook ID undefined."
|
|
66
143
|
raise ValueError(error)
|
|
67
|
-
url = "{
|
|
144
|
+
url = f"{self.baseurl}/{webhook_id}/test"
|
|
68
145
|
testOutcome = self.get_request(url)
|
|
69
|
-
logger.info("Testing webhook (ID: {
|
|
146
|
+
logger.info(f"Testing webhook (ID: {webhook_id} returned {testOutcome})")
|
|
70
147
|
return testOutcome
|