tableauserverclient 0.34__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.
Files changed (35) hide show
  1. tableauserverclient/__init__.py +5 -1
  2. tableauserverclient/{_version.py → bin/_version.py} +3 -3
  3. tableauserverclient/models/connection_credentials.py +17 -1
  4. tableauserverclient/models/connection_item.py +38 -0
  5. tableauserverclient/models/custom_view_item.py +49 -5
  6. tableauserverclient/models/flow_item.py +49 -4
  7. tableauserverclient/models/group_item.py +40 -0
  8. tableauserverclient/models/job_item.py +65 -0
  9. tableauserverclient/models/project_item.py +39 -1
  10. tableauserverclient/models/task_item.py +30 -0
  11. tableauserverclient/models/view_item.py +55 -3
  12. tableauserverclient/models/webhook_item.py +33 -0
  13. tableauserverclient/models/workbook_item.py +26 -1
  14. tableauserverclient/server/endpoint/auth_endpoint.py +4 -2
  15. tableauserverclient/server/endpoint/custom_views_endpoint.py +197 -12
  16. tableauserverclient/server/endpoint/datasources_endpoint.py +13 -9
  17. tableauserverclient/server/endpoint/flows_endpoint.py +314 -0
  18. tableauserverclient/server/endpoint/groups_endpoint.py +325 -11
  19. tableauserverclient/server/endpoint/jobs_endpoint.py +109 -0
  20. tableauserverclient/server/endpoint/projects_endpoint.py +600 -0
  21. tableauserverclient/server/endpoint/tasks_endpoint.py +78 -0
  22. tableauserverclient/server/endpoint/views_endpoint.py +243 -2
  23. tableauserverclient/server/endpoint/webhooks_endpoint.py +77 -0
  24. tableauserverclient/server/endpoint/workbooks_endpoint.py +6 -4
  25. tableauserverclient/server/pager.py +24 -0
  26. tableauserverclient/server/request_factory.py +20 -1
  27. tableauserverclient/server/request_options.py +126 -2
  28. tableauserverclient/server/server.py +11 -1
  29. tableauserverclient/server/sort.py +14 -0
  30. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/METADATA +2 -2
  31. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/RECORD +35 -35
  32. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/WHEEL +1 -1
  33. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/LICENSE +0 -0
  34. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/LICENSE.versioneer +0 -0
  35. {tableauserverclient-0.34.dist-info → tableauserverclient-0.35.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@ import logging
3
3
  import os
4
4
  from contextlib import closing
5
5
  from pathlib import Path
6
- from typing import Optional, Union
6
+ from typing import Optional, Union, TYPE_CHECKING
7
7
  from collections.abc import Iterator
8
8
 
9
9
  from tableauserverclient.config import BYTES_PER_MB, config
@@ -21,6 +21,9 @@ from tableauserverclient.server import (
21
21
 
22
22
  from tableauserverclient.helpers.logging import logger
23
23
 
24
+ if TYPE_CHECKING:
25
+ from tableauserverclient.server.query import QuerySet
26
+
24
27
  """
25
28
  Get a list of custom views on a site
26
29
  get the details of a custom view
@@ -51,19 +54,31 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
51
54
  def expurl(self) -> str:
52
55
  return f"{self.parent_srv._server_address}/api/exp/sites/{self.parent_srv.site_id}/customviews"
53
56
 
54
- """
55
- If the request has no filter parameters: Administrators will see all custom views.
56
- Other users will see only custom views that they own.
57
- If the filter parameters include ownerId: Users will see only custom views that they own.
58
- If the filter parameters include viewId and/or workbookId, and don't include ownerId:
59
- Users will see those custom views that they have Write and WebAuthoring permissions for.
60
- If site user visibility is not set to Limited, the Users will see those custom views that are "public",
61
- meaning the value of their shared attribute is true.
62
- If site user visibility is set to Limited, ????
63
- """
64
-
65
57
  @api(version="3.18")
66
58
  def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[CustomViewItem], PaginationItem]:
59
+ """
60
+ Get a list of custom views on a site.
61
+
62
+ If the request has no filter parameters: Administrators will see all custom views.
63
+ Other users will see only custom views that they own.
64
+ If the filter parameters include ownerId: Users will see only custom views that they own.
65
+ If the filter parameters include viewId and/or workbookId, and don't include ownerId:
66
+ Users will see those custom views that they have Write and WebAuthoring permissions for.
67
+ If site user visibility is not set to Limited, the Users will see those custom views that are "public",
68
+ meaning the value of their shared attribute is true.
69
+ If site user visibility is set to Limited, ????
70
+
71
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#list_custom_views
72
+
73
+ Parameters
74
+ ----------
75
+ req_options : RequestOptions, optional
76
+ Filtering options for the request, by default None
77
+
78
+ Returns
79
+ -------
80
+ tuple[list[CustomViewItem], PaginationItem]
81
+ """
67
82
  logger.info("Querying all custom views on site")
68
83
  url = self.baseurl
69
84
  server_response = self.get_request(url, req_options)
@@ -73,6 +88,19 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
73
88
 
74
89
  @api(version="3.18")
75
90
  def get_by_id(self, view_id: str) -> Optional[CustomViewItem]:
91
+ """
92
+ Get the details of a specific custom view.
93
+
94
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#get_custom_view
95
+
96
+ Parameters
97
+ ----------
98
+ view_id : str
99
+
100
+ Returns
101
+ -------
102
+ Optional[CustomViewItem]
103
+ """
76
104
  if not view_id:
77
105
  error = "Custom view item missing ID."
78
106
  raise MissingRequiredFieldError(error)
@@ -83,6 +111,27 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
83
111
 
84
112
  @api(version="3.18")
85
113
  def populate_image(self, view_item: CustomViewItem, req_options: Optional["ImageRequestOptions"] = None) -> None:
114
+ """
115
+ Populate the image of a custom view.
116
+
117
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#get_custom_view_image
118
+
119
+ Parameters
120
+ ----------
121
+ view_item : CustomViewItem
122
+
123
+ req_options : ImageRequestOptions, optional
124
+ Options to customize the image returned, by default None
125
+
126
+ Returns
127
+ -------
128
+ None
129
+
130
+ Raises
131
+ ------
132
+ MissingRequiredFieldError
133
+ If the view_item is missing an ID
134
+ """
86
135
  if not view_item.id:
87
136
  error = "Custom View item missing ID."
88
137
  raise MissingRequiredFieldError(error)
@@ -101,6 +150,26 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
101
150
 
102
151
  @api(version="3.23")
103
152
  def populate_pdf(self, custom_view_item: CustomViewItem, req_options: Optional["PDFRequestOptions"] = None) -> None:
153
+ """
154
+ Populate the PDF of a custom view.
155
+
156
+ Parameters
157
+ ----------
158
+ custom_view_item : CustomViewItem
159
+ The custom view item to populate the PDF for.
160
+
161
+ req_options : PDFRequestOptions, optional
162
+ Options to customize the PDF returned, by default None
163
+
164
+ Returns
165
+ -------
166
+ None
167
+
168
+ Raises
169
+ ------
170
+ MissingRequiredFieldError
171
+ If the custom view item is missing an ID
172
+ """
104
173
  if not custom_view_item.id:
105
174
  error = "Custom View item missing ID."
106
175
  raise MissingRequiredFieldError(error)
@@ -121,6 +190,26 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
121
190
 
122
191
  @api(version="3.23")
123
192
  def populate_csv(self, custom_view_item: CustomViewItem, req_options: Optional["CSVRequestOptions"] = None) -> None:
193
+ """
194
+ Populate the CSV of a custom view.
195
+
196
+ Parameters
197
+ ----------
198
+ custom_view_item : CustomViewItem
199
+ The custom view item to populate the CSV for.
200
+
201
+ req_options : CSVRequestOptions, optional
202
+ Options to customize the CSV returned, by default None
203
+
204
+ Returns
205
+ -------
206
+ None
207
+
208
+ Raises
209
+ ------
210
+ MissingRequiredFieldError
211
+ If the custom view item is missing an ID
212
+ """
124
213
  if not custom_view_item.id:
125
214
  error = "Custom View item missing ID."
126
215
  raise MissingRequiredFieldError(error)
@@ -141,6 +230,21 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
141
230
 
142
231
  @api(version="3.18")
143
232
  def update(self, view_item: CustomViewItem) -> Optional[CustomViewItem]:
233
+ """
234
+ Updates the name, owner, or shared status of a custom view.
235
+
236
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#update_custom_view
237
+
238
+ Parameters
239
+ ----------
240
+ view_item : CustomViewItem
241
+ The custom view item to update.
242
+
243
+ Returns
244
+ -------
245
+ Optional[CustomViewItem]
246
+ The updated custom view item.
247
+ """
144
248
  if not view_item.id:
145
249
  error = "Custom view item missing ID."
146
250
  raise MissingRequiredFieldError(error)
@@ -158,6 +262,25 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
158
262
  # Delete 1 view by id
159
263
  @api(version="3.19")
160
264
  def delete(self, view_id: str) -> None:
265
+ """
266
+ Deletes a single custom view by ID.
267
+
268
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#delete_custom_view
269
+
270
+ Parameters
271
+ ----------
272
+ view_id : str
273
+ The ID of the custom view to delete.
274
+
275
+ Returns
276
+ -------
277
+ None
278
+
279
+ Raises
280
+ ------
281
+ ValueError
282
+ If the view_id is not provided.
283
+ """
161
284
  if not view_id:
162
285
  error = "Custom View ID undefined."
163
286
  raise ValueError(error)
@@ -167,6 +290,27 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
167
290
 
168
291
  @api(version="3.21")
169
292
  def download(self, view_item: CustomViewItem, file: PathOrFileW) -> PathOrFileW:
293
+ """
294
+ Download the definition of a custom view as json. The file parameter can
295
+ be a file path or a file object. If a file path is provided, the file
296
+ will be written to that location. If a file object is provided, the file
297
+ will be written to that object.
298
+
299
+ May contain sensitive information.
300
+
301
+ Parameters
302
+ ----------
303
+ view_item : CustomViewItem
304
+ The custom view item to download.
305
+
306
+ file : PathOrFileW
307
+ The file path or file object to write the custom view to.
308
+
309
+ Returns
310
+ -------
311
+ PathOrFileW
312
+ The file path or file object that the custom view was written to.
313
+ """
170
314
  url = f"{self.expurl}/{view_item.id}/content"
171
315
  server_response = self.get_request(url)
172
316
  if isinstance(file, io_types_w):
@@ -180,6 +324,25 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
180
324
 
181
325
  @api(version="3.21")
182
326
  def publish(self, view_item: CustomViewItem, file: PathOrFileR) -> Optional[CustomViewItem]:
327
+ """
328
+ Publish a custom view to Tableau Server. The file parameter can be a
329
+ file path or a file object. If a file path is provided, the file will be
330
+ read from that location. If a file object is provided, the file will be
331
+ read from that object.
332
+
333
+ Parameters
334
+ ----------
335
+ view_item : CustomViewItem
336
+ The custom view item to publish.
337
+
338
+ file : PathOrFileR
339
+ The file path or file object to read the custom view from.
340
+
341
+ Returns
342
+ -------
343
+ Optional[CustomViewItem]
344
+ The published custom view item.
345
+ """
183
346
  url = self.expurl
184
347
  if isinstance(file, io_types_r):
185
348
  size = get_file_object_size(file)
@@ -207,3 +370,25 @@ class CustomViews(QuerysetEndpoint[CustomViewItem]):
207
370
 
208
371
  server_response = self.post_request(url, xml_request, content_type)
209
372
  return CustomViewItem.from_response(server_response.content, self.parent_srv.namespace)
373
+
374
+ def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> "QuerySet[CustomViewItem]":
375
+ """
376
+ Queries the Tableau Server for items using the specified filters. Page
377
+ size can be specified to limit the number of items returned in a single
378
+ request. If not specified, the default page size is 100. Page size can
379
+ be an integer between 1 and 1000.
380
+
381
+ No positional arguments are allowed. All filters must be specified as
382
+ keyword arguments. If you use the equality operator, you can specify it
383
+ through <field_name>=<value>. If you want to use a different operator,
384
+ you can specify it through <field_name>__<operator>=<value>. Field
385
+ names can either be in snake_case or camelCase.
386
+
387
+ This endpoint supports the following fields and operators:
388
+
389
+ view_id=...
390
+ workbook_id=...
391
+ owner_id=...
392
+ """
393
+
394
+ return super().filter(*invalid, page_size=page_size, **kwargs)
@@ -102,10 +102,15 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
102
102
  datasource_item._set_connections(connections_fetcher)
103
103
  logger.info(f"Populated connections for datasource (ID: {datasource_item.id})")
104
104
 
105
- def _get_datasource_connections(self, datasource_item, req_options=None):
105
+ def _get_datasource_connections(
106
+ self, datasource_item: DatasourceItem, req_options: Optional[RequestOptions] = None
107
+ ) -> list[ConnectionItem]:
106
108
  url = f"{self.baseurl}/{datasource_item.id}/connections"
107
109
  server_response = self.get_request(url, req_options)
108
110
  connections = ConnectionItem.from_response(server_response.content, self.parent_srv.namespace)
111
+ for connection in connections:
112
+ connection._datasource_id = datasource_item.id
113
+ connection._datasource_name = datasource_item.name
109
114
  return connections
110
115
 
111
116
  # Delete 1 datasource by id
@@ -182,11 +187,11 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
182
187
  return connection
183
188
 
184
189
  @api(version="2.8")
185
- def refresh(self, datasource_item: DatasourceItem) -> JobItem:
190
+ def refresh(self, datasource_item: DatasourceItem, incremental: bool = False) -> JobItem:
186
191
  id_ = getattr(datasource_item, "id", datasource_item)
187
192
  url = f"{self.baseurl}/{id_}/refresh"
188
- empty_req = RequestFactory.Empty.empty_req()
189
- server_response = self.post_request(url, empty_req)
193
+ refresh_req = RequestFactory.Task.refresh_req(incremental)
194
+ server_response = self.post_request(url, refresh_req)
190
195
  new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0]
191
196
  return new_job
192
197
 
@@ -255,13 +260,12 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
255
260
  else:
256
261
  raise TypeError("file should be a filepath or file object.")
257
262
 
258
- if not mode or not hasattr(self.parent_srv.PublishMode, mode):
259
- error = "Invalid mode defined."
260
- raise ValueError(error)
261
-
262
263
  # Construct the url with the defined mode
263
264
  url = f"{self.baseurl}?datasourceType={file_extension}"
264
- if mode == self.parent_srv.PublishMode.Overwrite or mode == self.parent_srv.PublishMode.Append:
265
+ if not mode or not hasattr(self.parent_srv.PublishMode, mode):
266
+ error = f"Invalid mode defined: {mode}"
267
+ raise ValueError(error)
268
+ else:
265
269
  url += f"&{mode.lower()}=true"
266
270
 
267
271
  if as_job: