tableauserverclient 0.32__py3-none-any.whl → 0.34__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 (96) hide show
  1. tableauserverclient/__init__.py +34 -18
  2. tableauserverclient/_version.py +3 -3
  3. tableauserverclient/config.py +20 -6
  4. tableauserverclient/models/__init__.py +12 -0
  5. tableauserverclient/models/column_item.py +1 -1
  6. tableauserverclient/models/connection_credentials.py +1 -1
  7. tableauserverclient/models/connection_item.py +10 -8
  8. tableauserverclient/models/custom_view_item.py +29 -6
  9. tableauserverclient/models/data_acceleration_report_item.py +2 -2
  10. tableauserverclient/models/data_alert_item.py +5 -5
  11. tableauserverclient/models/data_freshness_policy_item.py +6 -6
  12. tableauserverclient/models/database_item.py +8 -2
  13. tableauserverclient/models/datasource_item.py +10 -10
  14. tableauserverclient/models/dqw_item.py +1 -1
  15. tableauserverclient/models/favorites_item.py +5 -6
  16. tableauserverclient/models/fileupload_item.py +1 -1
  17. tableauserverclient/models/flow_item.py +12 -12
  18. tableauserverclient/models/flow_run_item.py +3 -3
  19. tableauserverclient/models/group_item.py +4 -4
  20. tableauserverclient/models/groupset_item.py +53 -0
  21. tableauserverclient/models/interval_item.py +36 -23
  22. tableauserverclient/models/job_item.py +26 -10
  23. tableauserverclient/models/linked_tasks_item.py +102 -0
  24. tableauserverclient/models/metric_item.py +5 -5
  25. tableauserverclient/models/pagination_item.py +1 -1
  26. tableauserverclient/models/permissions_item.py +19 -14
  27. tableauserverclient/models/project_item.py +35 -19
  28. tableauserverclient/models/property_decorators.py +12 -11
  29. tableauserverclient/models/reference_item.py +2 -2
  30. tableauserverclient/models/revision_item.py +3 -3
  31. tableauserverclient/models/schedule_item.py +2 -2
  32. tableauserverclient/models/server_info_item.py +26 -6
  33. tableauserverclient/models/site_item.py +69 -3
  34. tableauserverclient/models/subscription_item.py +3 -3
  35. tableauserverclient/models/table_item.py +1 -1
  36. tableauserverclient/models/tableau_auth.py +115 -5
  37. tableauserverclient/models/tableau_types.py +11 -9
  38. tableauserverclient/models/tag_item.py +3 -4
  39. tableauserverclient/models/task_item.py +4 -4
  40. tableauserverclient/models/user_item.py +47 -17
  41. tableauserverclient/models/view_item.py +11 -10
  42. tableauserverclient/models/virtual_connection_item.py +78 -0
  43. tableauserverclient/models/webhook_item.py +6 -6
  44. tableauserverclient/models/workbook_item.py +90 -12
  45. tableauserverclient/namespace.py +1 -1
  46. tableauserverclient/server/__init__.py +2 -1
  47. tableauserverclient/server/endpoint/__init__.py +8 -0
  48. tableauserverclient/server/endpoint/auth_endpoint.py +68 -11
  49. tableauserverclient/server/endpoint/custom_views_endpoint.py +124 -19
  50. tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
  51. tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
  52. tableauserverclient/server/endpoint/databases_endpoint.py +32 -17
  53. tableauserverclient/server/endpoint/datasources_endpoint.py +150 -59
  54. tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
  55. tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
  56. tableauserverclient/server/endpoint/endpoint.py +47 -31
  57. tableauserverclient/server/endpoint/exceptions.py +23 -7
  58. tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
  59. tableauserverclient/server/endpoint/fileuploads_endpoint.py +11 -13
  60. tableauserverclient/server/endpoint/flow_runs_endpoint.py +59 -17
  61. tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
  62. tableauserverclient/server/endpoint/flows_endpoint.py +73 -35
  63. tableauserverclient/server/endpoint/groups_endpoint.py +96 -27
  64. tableauserverclient/server/endpoint/groupsets_endpoint.py +127 -0
  65. tableauserverclient/server/endpoint/jobs_endpoint.py +79 -12
  66. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +45 -0
  67. tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
  68. tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
  69. tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
  70. tableauserverclient/server/endpoint/projects_endpoint.py +124 -30
  71. tableauserverclient/server/endpoint/resource_tagger.py +139 -6
  72. tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
  73. tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
  74. tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
  75. tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
  76. tableauserverclient/server/endpoint/tables_endpoint.py +33 -19
  77. tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
  78. tableauserverclient/server/endpoint/users_endpoint.py +405 -19
  79. tableauserverclient/server/endpoint/views_endpoint.py +111 -25
  80. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +174 -0
  81. tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
  82. tableauserverclient/server/endpoint/workbooks_endpoint.py +735 -68
  83. tableauserverclient/server/filter.py +2 -2
  84. tableauserverclient/server/pager.py +8 -10
  85. tableauserverclient/server/query.py +70 -20
  86. tableauserverclient/server/request_factory.py +213 -41
  87. tableauserverclient/server/request_options.py +125 -145
  88. tableauserverclient/server/server.py +73 -9
  89. tableauserverclient/server/sort.py +2 -2
  90. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/METADATA +17 -17
  91. tableauserverclient-0.34.dist-info/RECORD +106 -0
  92. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
  93. tableauserverclient-0.32.dist-info/RECORD +0 -100
  94. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
  95. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
  96. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
@@ -7,11 +7,13 @@ from contextlib import closing
7
7
  from pathlib import Path
8
8
 
9
9
  from tableauserverclient.helpers.headers import fix_filename
10
+ from tableauserverclient.models.permissions_item import PermissionsRule
11
+ from tableauserverclient.server.query import QuerySet
10
12
 
11
- from .endpoint import QuerysetEndpoint, api, parameter_added_in
12
- from .exceptions import InternalServerError, MissingRequiredFieldError
13
- from .permissions_endpoint import _PermissionsEndpoint
14
- from .resource_tagger import _ResourceTagger
13
+ from tableauserverclient.server.endpoint.endpoint import QuerysetEndpoint, api, parameter_added_in
14
+ from tableauserverclient.server.endpoint.exceptions import InternalServerError, MissingRequiredFieldError
15
+ from tableauserverclient.server.endpoint.permissions_endpoint import _PermissionsEndpoint
16
+ from tableauserverclient.server.endpoint.resource_tagger import TaggingMixin
15
17
 
16
18
  from tableauserverclient.filesys_helpers import (
17
19
  to_filename,
@@ -24,19 +26,17 @@ from tableauserverclient.models import WorkbookItem, ConnectionItem, ViewItem, P
24
26
  from tableauserverclient.server import RequestFactory
25
27
 
26
28
  from typing import (
27
- List,
28
29
  Optional,
29
- Sequence,
30
- Tuple,
31
30
  TYPE_CHECKING,
32
31
  Union,
33
32
  )
33
+ from collections.abc import Iterable, Sequence
34
34
 
35
35
  if TYPE_CHECKING:
36
36
  from tableauserverclient.server import Server
37
37
  from tableauserverclient.server.request_options import RequestOptions
38
- from tableauserverclient.models import DatasourceItem, ConnectionCredentials
39
- from .schedules_endpoint import AddResponse
38
+ from tableauserverclient.models import DatasourceItem
39
+ from tableauserverclient.server.endpoint.schedules_endpoint import AddResponse
40
40
 
41
41
  io_types_r = (io.BytesIO, io.BufferedReader)
42
42
  io_types_w = (io.BytesIO, io.BufferedWriter)
@@ -56,21 +56,36 @@ PathOrFileR = Union[FilePath, FileObjectR]
56
56
  PathOrFileW = Union[FilePath, FileObjectW]
57
57
 
58
58
 
59
- class Workbooks(QuerysetEndpoint[WorkbookItem]):
59
+ class Workbooks(QuerysetEndpoint[WorkbookItem], TaggingMixin[WorkbookItem]):
60
60
  def __init__(self, parent_srv: "Server") -> None:
61
- super(Workbooks, self).__init__(parent_srv)
62
- self._resource_tagger = _ResourceTagger(parent_srv)
61
+ super().__init__(parent_srv)
63
62
  self._permissions = _PermissionsEndpoint(parent_srv, lambda: self.baseurl)
64
63
 
65
64
  return None
66
65
 
67
66
  @property
68
67
  def baseurl(self) -> str:
69
- return "{0}/sites/{1}/workbooks".format(self.parent_srv.baseurl, self.parent_srv.site_id)
68
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/workbooks"
70
69
 
71
70
  # Get all workbooks on site
72
71
  @api(version="2.0")
73
- def get(self, req_options: Optional["RequestOptions"] = None) -> Tuple[List[WorkbookItem], PaginationItem]:
72
+ def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[WorkbookItem], PaginationItem]:
73
+ """
74
+ Queries the server and returns information about the workbooks the site.
75
+
76
+ Parameters
77
+ ----------
78
+ req_options : RequestOptions, optional
79
+ (Optional) You can pass the method a request object that contains
80
+ additional parameters to filter the request. For example, if you
81
+ were searching for a specific workbook, you could specify the name
82
+ of the workbook or the name of the owner.
83
+
84
+ Returns
85
+ -------
86
+ Tuple containing one page's worth of workbook items and pagination
87
+ information.
88
+ """
74
89
  logger.info("Querying all workbooks on site")
75
90
  url = self.baseurl
76
91
  server_response = self.get_request(url, req_options)
@@ -81,18 +96,44 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
81
96
  # Get 1 workbook
82
97
  @api(version="2.0")
83
98
  def get_by_id(self, workbook_id: str) -> WorkbookItem:
99
+ """
100
+ Returns information about the specified workbook on the site.
101
+
102
+ Parameters
103
+ ----------
104
+ workbook_id : str
105
+ The workbook ID.
106
+
107
+ Returns
108
+ -------
109
+ WorkbookItem
110
+ The workbook item.
111
+ """
84
112
  if not workbook_id:
85
113
  error = "Workbook ID undefined."
86
114
  raise ValueError(error)
87
- logger.info("Querying single workbook (ID: {0})".format(workbook_id))
88
- url = "{0}/{1}".format(self.baseurl, workbook_id)
115
+ logger.info(f"Querying single workbook (ID: {workbook_id})")
116
+ url = f"{self.baseurl}/{workbook_id}"
89
117
  server_response = self.get_request(url)
90
118
  return WorkbookItem.from_response(server_response.content, self.parent_srv.namespace)[0]
91
119
 
92
120
  @api(version="2.8")
93
121
  def refresh(self, workbook_item: Union[WorkbookItem, str]) -> JobItem:
122
+ """
123
+ Refreshes the extract of an existing workbook.
124
+
125
+ Parameters
126
+ ----------
127
+ workbook_item : WorkbookItem | str
128
+ The workbook item or workbook ID.
129
+
130
+ Returns
131
+ -------
132
+ JobItem
133
+ The job item.
134
+ """
94
135
  id_ = getattr(workbook_item, "id", workbook_item)
95
- url = "{0}/{1}/refresh".format(self.baseurl, id_)
136
+ url = f"{self.baseurl}/{id_}/refresh"
96
137
  empty_req = RequestFactory.Empty.empty_req()
97
138
  server_response = self.post_request(url, empty_req)
98
139
  new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0]
@@ -105,10 +146,37 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
105
146
  workbook_item: WorkbookItem,
106
147
  encrypt: bool = False,
107
148
  includeAll: bool = True,
108
- datasources: Optional[List["DatasourceItem"]] = None,
149
+ datasources: Optional[list["DatasourceItem"]] = None,
109
150
  ) -> JobItem:
151
+ """
152
+ Create one or more extracts on 1 workbook, optionally encrypted.
153
+
154
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#create_extracts_for_workbook
155
+
156
+ Parameters
157
+ ----------
158
+ workbook_item : WorkbookItem
159
+ The workbook item to create extracts for.
160
+
161
+ encrypt : bool, default False
162
+ Set to True to encrypt the extracts.
163
+
164
+ includeAll : bool, default True
165
+ If True, all data sources in the workbook will have an extract
166
+ created for them. If False, then a data source must be supplied in
167
+ the request.
168
+
169
+ datasources : list[DatasourceItem] | None
170
+ List of DatasourceItem objects for the data sources to create
171
+ extracts for. Only required if includeAll is False.
172
+
173
+ Returns
174
+ -------
175
+ JobItem
176
+ The job item for the extract creation.
177
+ """
110
178
  id_ = getattr(workbook_item, "id", workbook_item)
111
- url = "{0}/{1}/createExtract?encrypt={2}".format(self.baseurl, id_, encrypt)
179
+ url = f"{self.baseurl}/{id_}/createExtract?encrypt={encrypt}"
112
180
 
113
181
  datasource_req = RequestFactory.Workbook.embedded_extract_req(includeAll, datasources)
114
182
  server_response = self.post_request(url, datasource_req)
@@ -118,8 +186,31 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
118
186
  # delete all the extracts on 1 workbook
119
187
  @api(version="3.3")
120
188
  def delete_extract(self, workbook_item: WorkbookItem, includeAll: bool = True, datasources=None) -> JobItem:
189
+ """
190
+ Delete all extracts of embedded datasources on 1 workbook.
191
+
192
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#delete_extracts_from_workbook
193
+
194
+ Parameters
195
+ ----------
196
+ workbook_item : WorkbookItem
197
+ The workbook item to delete extracts from.
198
+
199
+ includeAll : bool, default True
200
+ If True, all data sources in the workbook will have their extracts
201
+ deleted. If False, then a data source must be supplied in the
202
+ request.
203
+
204
+ datasources : list[DatasourceItem] | None
205
+ List of DatasourceItem objects for the data sources to delete
206
+ extracts from. Only required if includeAll is False.
207
+
208
+ Returns
209
+ -------
210
+ JobItem
211
+ """
121
212
  id_ = getattr(workbook_item, "id", workbook_item)
122
- url = "{0}/{1}/deleteExtract".format(self.baseurl, id_)
213
+ url = f"{self.baseurl}/{id_}/deleteExtract"
123
214
  datasource_req = RequestFactory.Workbook.embedded_extract_req(includeAll, datasources)
124
215
  server_response = self.post_request(url, datasource_req)
125
216
  new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0]
@@ -128,12 +219,24 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
128
219
  # Delete 1 workbook by id
129
220
  @api(version="2.0")
130
221
  def delete(self, workbook_id: str) -> None:
222
+ """
223
+ Deletes a workbook with the specified ID.
224
+
225
+ Parameters
226
+ ----------
227
+ workbook_id : str
228
+ The workbook ID.
229
+
230
+ Returns
231
+ -------
232
+ None
233
+ """
131
234
  if not workbook_id:
132
235
  error = "Workbook ID undefined."
133
236
  raise ValueError(error)
134
- url = "{0}/{1}".format(self.baseurl, workbook_id)
237
+ url = f"{self.baseurl}/{workbook_id}"
135
238
  self.delete_request(url)
136
- logger.info("Deleted single workbook (ID: {0})".format(workbook_id))
239
+ logger.info(f"Deleted single workbook (ID: {workbook_id})")
137
240
 
138
241
  # Update workbook
139
242
  @api(version="2.0")
@@ -143,34 +246,77 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
143
246
  workbook_item: WorkbookItem,
144
247
  include_view_acceleration_status: bool = False,
145
248
  ) -> WorkbookItem:
249
+ """
250
+ Modifies an existing workbook. Use this method to change the owner or
251
+ the project that the workbook belongs to, or to change whether the
252
+ workbook shows views in tabs. The workbook item must include the
253
+ workbook ID and overrides the existing settings.
254
+
255
+ See https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#update_workbook
256
+ for a list of fields that can be updated.
257
+
258
+ Parameters
259
+ ----------
260
+ workbook_item : WorkbookItem
261
+ The workbook item to update. ID is required. Other fields are
262
+ optional. Any fields that are not specified will not be changed.
263
+
264
+ include_view_acceleration_status : bool, default False
265
+ Set to True to include the view acceleration status in the response.
266
+
267
+ Returns
268
+ -------
269
+ WorkbookItem
270
+ The updated workbook item.
271
+ """
146
272
  if not workbook_item.id:
147
273
  error = "Workbook item missing ID. Workbook must be retrieved from server first."
148
274
  raise MissingRequiredFieldError(error)
149
275
 
150
- self._resource_tagger.update_tags(self.baseurl, workbook_item)
276
+ self.update_tags(workbook_item)
151
277
 
152
278
  # Update the workbook itself
153
- url = "{0}/{1}".format(self.baseurl, workbook_item.id)
279
+ url = f"{self.baseurl}/{workbook_item.id}"
154
280
  if include_view_acceleration_status:
155
281
  url += "?includeViewAccelerationStatus=True"
156
282
 
157
283
  update_req = RequestFactory.Workbook.update_req(workbook_item)
158
284
  server_response = self.put_request(url, update_req)
159
- logger.info("Updated workbook item (ID: {0})".format(workbook_item.id))
285
+ logger.info(f"Updated workbook item (ID: {workbook_item.id})")
160
286
  updated_workbook = copy.copy(workbook_item)
161
287
  return updated_workbook._parse_common_tags(server_response.content, self.parent_srv.namespace)
162
288
 
163
289
  # Update workbook_connection
164
290
  @api(version="2.3")
165
291
  def update_connection(self, workbook_item: WorkbookItem, connection_item: ConnectionItem) -> ConnectionItem:
166
- url = "{0}/{1}/connections/{2}".format(self.baseurl, workbook_item.id, connection_item.id)
292
+ """
293
+ Updates a workbook connection information (server addres, server port,
294
+ user name, and password).
295
+
296
+ The workbook connections must be populated before the strings can be
297
+ updated.
298
+
299
+ Rest API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#update_workbook_connection
300
+
301
+ Parameters
302
+ ----------
303
+ workbook_item : WorkbookItem
304
+ The workbook item to update.
305
+
306
+ connection_item : ConnectionItem
307
+ The connection item to update.
308
+
309
+ Returns
310
+ -------
311
+ ConnectionItem
312
+ The updated connection item.
313
+ """
314
+ url = f"{self.baseurl}/{workbook_item.id}/connections/{connection_item.id}"
167
315
  update_req = RequestFactory.Connection.update_req(connection_item)
168
316
  server_response = self.put_request(url, update_req)
169
317
  connection = ConnectionItem.from_response(server_response.content, self.parent_srv.namespace)[0]
170
318
 
171
- logger.info(
172
- "Updated workbook item (ID: {0} & connection item {1})".format(workbook_item.id, connection_item.id)
173
- )
319
+ logger.info(f"Updated workbook item (ID: {workbook_item.id} & connection item {connection_item.id})")
174
320
  return connection
175
321
 
176
322
  # Download workbook contents with option of passing in filepath
@@ -182,7 +328,35 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
182
328
  workbook_id: str,
183
329
  filepath: Optional[PathOrFileW] = None,
184
330
  include_extract: bool = True,
185
- ) -> str:
331
+ ) -> PathOrFileW:
332
+ """
333
+ Downloads a workbook to the specified directory (optional).
334
+
335
+ Parameters
336
+ ----------
337
+ workbook_id : str
338
+ The workbook ID.
339
+
340
+ filepath : Path or File object, optional
341
+ Downloads the file to the location you specify. If no location is
342
+ specified, the file is downloaded to the current working directory.
343
+ The default is Filepath=None.
344
+
345
+ include_extract : bool, default True
346
+ Set to False to exclude the extract from the download. The default
347
+ is True.
348
+
349
+ Returns
350
+ -------
351
+ Path or File object
352
+ The path to the downloaded workbook or the file object.
353
+
354
+ Raises
355
+ ------
356
+ ValueError
357
+ If the workbook ID is not defined.
358
+ """
359
+
186
360
  return self.download_revision(
187
361
  workbook_id,
188
362
  None,
@@ -193,18 +367,48 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
193
367
  # Get all views of workbook
194
368
  @api(version="2.0")
195
369
  def populate_views(self, workbook_item: WorkbookItem, usage: bool = False) -> None:
370
+ """
371
+ Populates (or gets) a list of views for a workbook.
372
+
373
+ You must first call this method to populate views before you can iterate
374
+ through the views.
375
+
376
+ This method retrieves the view information for the specified workbook.
377
+ The REST API is designed to return only the information you ask for
378
+ explicitly. When you query for all the workbooks, the view information
379
+ is not included. Use this method to retrieve the views. The method adds
380
+ the list of views to the workbook item (workbook_item.views). This is a
381
+ list of ViewItem.
382
+
383
+ Parameters
384
+ ----------
385
+ workbook_item : WorkbookItem
386
+ The workbook item to populate views for.
387
+
388
+ usage : bool, default False
389
+ Set to True to include usage statistics for each view.
390
+
391
+ Returns
392
+ -------
393
+ None
394
+
395
+ Raises
396
+ ------
397
+ MissingRequiredFieldError
398
+ If the workbook item is missing an ID.
399
+ """
196
400
  if not workbook_item.id:
197
401
  error = "Workbook item missing ID. Workbook must be retrieved from server first."
198
402
  raise MissingRequiredFieldError(error)
199
403
 
200
- def view_fetcher() -> List[ViewItem]:
404
+ def view_fetcher() -> list[ViewItem]:
201
405
  return self._get_views_for_workbook(workbook_item, usage)
202
406
 
203
407
  workbook_item._set_views(view_fetcher)
204
- logger.info("Populated views for workbook (ID: {0})".format(workbook_item.id))
408
+ logger.info(f"Populated views for workbook (ID: {workbook_item.id})")
205
409
 
206
- def _get_views_for_workbook(self, workbook_item: WorkbookItem, usage: bool) -> List[ViewItem]:
207
- url = "{0}/{1}/views".format(self.baseurl, workbook_item.id)
410
+ def _get_views_for_workbook(self, workbook_item: WorkbookItem, usage: bool) -> list[ViewItem]:
411
+ url = f"{self.baseurl}/{workbook_item.id}/views"
208
412
  if usage:
209
413
  url += "?includeUsageStatistics=true"
210
414
  server_response = self.get_request(url)
@@ -218,6 +422,36 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
218
422
  # Get all connections of workbook
219
423
  @api(version="2.0")
220
424
  def populate_connections(self, workbook_item: WorkbookItem) -> None:
425
+ """
426
+ Populates a list of data source connections for the specified workbook.
427
+
428
+ You must populate connections before you can iterate through the
429
+ connections.
430
+
431
+ This method retrieves the data source connection information for the
432
+ specified workbook. The REST API is designed to return only the
433
+ information you ask for explicitly. When you query all the workbooks,
434
+ the data source connection information is not included. Use this method
435
+ to retrieve the connection information for any data sources used by the
436
+ workbook. The method adds the list of data connections to the workbook
437
+ item (workbook_item.connections). This is a list of ConnectionItem.
438
+
439
+ REST API docs: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#query_workbook_connections
440
+
441
+ Parameters
442
+ ----------
443
+ workbook_item : WorkbookItem
444
+ The workbook item to populate connections for.
445
+
446
+ Returns
447
+ -------
448
+ None
449
+
450
+ Raises
451
+ ------
452
+ MissingRequiredFieldError
453
+ If the workbook item is missing an ID.
454
+ """
221
455
  if not workbook_item.id:
222
456
  error = "Workbook item missing ID. Workbook must be retrieved from server first."
223
457
  raise MissingRequiredFieldError(error)
@@ -226,12 +460,12 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
226
460
  return self._get_workbook_connections(workbook_item)
227
461
 
228
462
  workbook_item._set_connections(connection_fetcher)
229
- logger.info("Populated connections for workbook (ID: {0})".format(workbook_item.id))
463
+ logger.info(f"Populated connections for workbook (ID: {workbook_item.id})")
230
464
 
231
465
  def _get_workbook_connections(
232
466
  self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"] = None
233
- ) -> List[ConnectionItem]:
234
- url = "{0}/{1}/connections".format(self.baseurl, workbook_item.id)
467
+ ) -> list[ConnectionItem]:
468
+ url = f"{self.baseurl}/{workbook_item.id}/connections"
235
469
  server_response = self.get_request(url, req_options)
236
470
  connections = ConnectionItem.from_response(server_response.content, self.parent_srv.namespace)
237
471
  return connections
@@ -239,6 +473,34 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
239
473
  # Get the pdf of the entire workbook if its tabs are enabled, pdf of the default view if its tabs are disabled
240
474
  @api(version="3.4")
241
475
  def populate_pdf(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"] = None) -> None:
476
+ """
477
+ Populates the PDF for the specified workbook item.
478
+
479
+ This method populates a PDF with image(s) of the workbook view(s) you
480
+ specify.
481
+
482
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#download_workbook_pdf
483
+
484
+ Parameters
485
+ ----------
486
+ workbook_item : WorkbookItem
487
+ The workbook item to populate the PDF for.
488
+
489
+ req_options : RequestOptions, optional
490
+ (Optional) You can pass in request options to specify the page type
491
+ and orientation of the PDF content, as well as the maximum age of
492
+ the PDF rendered on the server. See PDFRequestOptions class for more
493
+ details.
494
+
495
+ Returns
496
+ -------
497
+ None
498
+
499
+ Raises
500
+ ------
501
+ MissingRequiredFieldError
502
+ If the workbook item is missing an ID.
503
+ """
242
504
  if not workbook_item.id:
243
505
  error = "Workbook item missing ID."
244
506
  raise MissingRequiredFieldError(error)
@@ -247,16 +509,46 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
247
509
  return self._get_wb_pdf(workbook_item, req_options)
248
510
 
249
511
  workbook_item._set_pdf(pdf_fetcher)
250
- logger.info("Populated pdf for workbook (ID: {0})".format(workbook_item.id))
512
+ logger.info(f"Populated pdf for workbook (ID: {workbook_item.id})")
251
513
 
252
514
  def _get_wb_pdf(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"]) -> bytes:
253
- url = "{0}/{1}/pdf".format(self.baseurl, workbook_item.id)
515
+ url = f"{self.baseurl}/{workbook_item.id}/pdf"
254
516
  server_response = self.get_request(url, req_options)
255
517
  pdf = server_response.content
256
518
  return pdf
257
519
 
258
520
  @api(version="3.8")
259
521
  def populate_powerpoint(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"] = None) -> None:
522
+ """
523
+ Populates the PowerPoint for the specified workbook item.
524
+
525
+ This method populates a PowerPoint with image(s) of the workbook view(s) you
526
+ specify.
527
+
528
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#download_workbook_powerpoint
529
+
530
+ Parameters
531
+ ----------
532
+ workbook_item : WorkbookItem
533
+ The workbook item to populate the PDF for.
534
+
535
+ req_options : RequestOptions, optional
536
+ (Optional) You can pass in request options to specify the maximum
537
+ number of minutes a workbook .pptx will be cached before being
538
+ refreshed. To prevent multiple .pptx requests from overloading the
539
+ server, the shortest interval you can set is one minute. There is no
540
+ maximum value, but the server job enacting the caching action may
541
+ expire before a long cache period is reached.
542
+
543
+ Returns
544
+ -------
545
+ None
546
+
547
+ Raises
548
+ ------
549
+ MissingRequiredFieldError
550
+ If the workbook item is missing an ID.
551
+ """
260
552
  if not workbook_item.id:
261
553
  error = "Workbook item missing ID."
262
554
  raise MissingRequiredFieldError(error)
@@ -265,10 +557,10 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
265
557
  return self._get_wb_pptx(workbook_item, req_options)
266
558
 
267
559
  workbook_item._set_powerpoint(pptx_fetcher)
268
- logger.info("Populated powerpoint for workbook (ID: {0})".format(workbook_item.id))
560
+ logger.info(f"Populated powerpoint for workbook (ID: {workbook_item.id})")
269
561
 
270
562
  def _get_wb_pptx(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"]) -> bytes:
271
- url = "{0}/{1}/powerpoint".format(self.baseurl, workbook_item.id)
563
+ url = f"{self.baseurl}/{workbook_item.id}/powerpoint"
272
564
  server_response = self.get_request(url, req_options)
273
565
  pptx = server_response.content
274
566
  return pptx
@@ -276,6 +568,26 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
276
568
  # Get preview image of workbook
277
569
  @api(version="2.0")
278
570
  def populate_preview_image(self, workbook_item: WorkbookItem) -> None:
571
+ """
572
+ This method gets the preview image (thumbnail) for the specified workbook item.
573
+
574
+ This method uses the workbook's ID to get the preview image. The method
575
+ adds the preview image to the workbook item (workbook_item.preview_image).
576
+
577
+ Parameters
578
+ ----------
579
+ workbook_item : WorkbookItem
580
+ The workbook item to populate the preview image for.
581
+
582
+ Returns
583
+ -------
584
+ None
585
+
586
+ Raises
587
+ ------
588
+ MissingRequiredFieldError
589
+ If the workbook item is missing an ID.
590
+ """
279
591
  if not workbook_item.id:
280
592
  error = "Workbook item missing ID. Workbook must be retrieved from server first."
281
593
  raise MissingRequiredFieldError(error)
@@ -284,24 +596,75 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
284
596
  return self._get_wb_preview_image(workbook_item)
285
597
 
286
598
  workbook_item._set_preview_image(image_fetcher)
287
- logger.info("Populated preview image for workbook (ID: {0})".format(workbook_item.id))
599
+ logger.info(f"Populated preview image for workbook (ID: {workbook_item.id})")
288
600
 
289
601
  def _get_wb_preview_image(self, workbook_item: WorkbookItem) -> bytes:
290
- url = "{0}/{1}/previewImage".format(self.baseurl, workbook_item.id)
602
+ url = f"{self.baseurl}/{workbook_item.id}/previewImage"
291
603
  server_response = self.get_request(url)
292
604
  preview_image = server_response.content
293
605
  return preview_image
294
606
 
295
607
  @api(version="2.0")
296
608
  def populate_permissions(self, item: WorkbookItem) -> None:
609
+ """
610
+ Populates the permissions for the specified workbook item.
611
+
612
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_permissions.htm#query_workbook_permissions
613
+
614
+ Parameters
615
+ ----------
616
+ item : WorkbookItem
617
+ The workbook item to populate permissions for.
618
+
619
+ Returns
620
+ -------
621
+ None
622
+ """
297
623
  self._permissions.populate(item)
298
624
 
299
625
  @api(version="2.0")
300
- def update_permissions(self, resource, rules):
626
+ def update_permissions(self, resource: WorkbookItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
627
+ """
628
+ Updates the permissions for the specified workbook item. The method
629
+ replaces the existing permissions with the new permissions. Any missing
630
+ permissions are removed.
631
+
632
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_permissions.htm#replace_permissions_for_content
633
+
634
+ Parameters
635
+ ----------
636
+ resource : WorkbookItem
637
+ The workbook item to update permissions for.
638
+
639
+ rules : list[PermissionsRule]
640
+ A list of permissions rules to apply to the workbook item.
641
+
642
+ Returns
643
+ -------
644
+ list[PermissionsRule]
645
+ The updated permissions rules.
646
+ """
301
647
  return self._permissions.update(resource, rules)
302
648
 
303
649
  @api(version="2.0")
304
- def delete_permission(self, item, capability_item):
650
+ def delete_permission(self, item: WorkbookItem, capability_item: PermissionsRule) -> None:
651
+ """
652
+ Deletes a single permission rule from the specified workbook item.
653
+
654
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_permissions.htm#delete_workbook_permission
655
+
656
+ Parameters
657
+ ----------
658
+ item : WorkbookItem
659
+ The workbook item to delete the permission from.
660
+
661
+ capability_item : PermissionsRule
662
+ The permission rule to delete.
663
+
664
+ Returns
665
+ -------
666
+ None
667
+ """
305
668
  return self._permissions.delete(item, capability_item)
306
669
 
307
670
  @api(version="2.0")
@@ -317,10 +680,87 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
317
680
  skip_connection_check: bool = False,
318
681
  parameters=None,
319
682
  ):
683
+ """
684
+ Publish a workbook to the specified site.
685
+
686
+ Note: The REST API cannot automatically include extracts or other
687
+ resources that the workbook uses. Therefore, a .twb file that uses data
688
+ from an Excel or csv file on a local computer cannot be published,
689
+ unless you package the data and workbook in a .twbx file, or publish the
690
+ data source separately.
691
+
692
+ For workbooks that are larger than 64 MB, the publish method
693
+ automatically takes care of chunking the file in parts for uploading.
694
+ Using this method is considerably more convenient than calling the
695
+ publish REST APIs directly.
696
+
697
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#publish_workbook
698
+
699
+ Parameters
700
+ ----------
701
+ workbook_item : WorkbookItem
702
+ The workbook_item specifies the workbook you are publishing. When
703
+ you are adding a workbook, you need to first create a new instance
704
+ of a workbook_item that includes a project_id of an existing
705
+ project. The name of the workbook will be the name of the file,
706
+ unless you also specify a name for the new workbook when you create
707
+ the instance.
708
+
709
+ file : Path or File object
710
+ The file path or file object of the workbook to publish. When
711
+ providing a file object, you must also specifiy the name of the
712
+ workbook in your instance of the workbook_itemworkbook_item , as
713
+ the name cannot be derived from the file name.
714
+
715
+ mode : str
716
+ Specifies whether you are publishing a new workbook (CreateNew) or
717
+ overwriting an existing workbook (Overwrite). You cannot appending
718
+ workbooks. You can also use the publish mode attributes, for
719
+ example: TSC.Server.PublishMode.Overwrite.
720
+
721
+ connections : list[ConnectionItem] | None
722
+ List of ConnectionItems objects for the connections created within
723
+ the workbook.
724
+
725
+ as_job : bool, default False
726
+ Set to True to run the upload as a job (asynchronous upload). If set
727
+ to True a job will start to perform the publishing process and a Job
728
+ object is returned. Defaults to False.
729
+
730
+ skip_connection_check : bool, default False
731
+ Set to True to skip connection check at time of upload. Publishing
732
+ will succeed but unchecked connection issues may result in a
733
+ non-functioning workbook. Defaults to False.
734
+
735
+ Raises
736
+ ------
737
+ OSError
738
+ If the file path does not lead to an existing file.
739
+
740
+ ServerResponseError
741
+ If the server response is not successful.
742
+
743
+ TypeError
744
+ If the file is not a file path or file object.
745
+
746
+ ValueError
747
+ If the file extension is not supported
748
+
749
+ ValueError
750
+ If the mode is invalid.
751
+
752
+ ValueError
753
+ Workbooks cannot be appended.
754
+
755
+ Returns
756
+ -------
757
+ WorkbookItem | JobItem
758
+ The workbook item or job item that was published.
759
+ """
320
760
  if isinstance(file, (str, os.PathLike)):
321
761
  if not os.path.isfile(file):
322
762
  error = "File path does not lead to an existing file."
323
- raise IOError(error)
763
+ raise OSError(error)
324
764
 
325
765
  filename = os.path.basename(file)
326
766
  file_extension = os.path.splitext(filename)[1][1:]
@@ -344,12 +784,12 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
344
784
  elif file_type == "xml":
345
785
  file_extension = "twb"
346
786
  else:
347
- error = "Unsupported file type {}!".format(file_type)
787
+ error = f"Unsupported file type {file_type}!"
348
788
  raise ValueError(error)
349
789
 
350
790
  # Generate filename for file object.
351
791
  # This is needed when publishing the workbook in a single request
352
- filename = "{}.{}".format(workbook_item.name, file_extension)
792
+ filename = f"{workbook_item.name}.{file_extension}"
353
793
  file_size = get_file_object_size(file)
354
794
 
355
795
  else:
@@ -360,30 +800,30 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
360
800
  raise ValueError(error)
361
801
 
362
802
  # Construct the url with the defined mode
363
- url = "{0}?workbookType={1}".format(self.baseurl, file_extension)
803
+ url = f"{self.baseurl}?workbookType={file_extension}"
364
804
  if mode == self.parent_srv.PublishMode.Overwrite:
365
- url += "&{0}=true".format(mode.lower())
805
+ url += f"&{mode.lower()}=true"
366
806
  elif mode == self.parent_srv.PublishMode.Append:
367
807
  error = "Workbooks cannot be appended."
368
808
  raise ValueError(error)
369
809
 
370
810
  if as_job:
371
- url += "&{0}=true".format("asJob")
811
+ url += "&{}=true".format("asJob")
372
812
 
373
813
  if skip_connection_check:
374
- url += "&{0}=true".format("skipConnectionCheck")
814
+ url += "&{}=true".format("skipConnectionCheck")
375
815
 
376
816
  # Determine if chunking is required (64MB is the limit for single upload method)
377
817
  if file_size >= FILESIZE_LIMIT:
378
- logger.info("Publishing {0} to server with chunking method (workbook over 64MB)".format(workbook_item.name))
818
+ logger.info(f"Publishing {workbook_item.name} to server with chunking method (workbook over 64MB)")
379
819
  upload_session_id = self.parent_srv.fileuploads.upload(file)
380
- url = "{0}&uploadSessionId={1}".format(url, upload_session_id)
820
+ url = f"{url}&uploadSessionId={upload_session_id}"
381
821
  xml_request, content_type = RequestFactory.Workbook.publish_req_chunked(
382
822
  workbook_item,
383
823
  connections=connections,
384
824
  )
385
825
  else:
386
- logger.info("Publishing {0} to server".format(filename))
826
+ logger.info(f"Publishing {filename} to server")
387
827
 
388
828
  if isinstance(file, (str, Path)):
389
829
  with open(file, "rb") as f:
@@ -401,7 +841,7 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
401
841
  file_contents,
402
842
  connections=connections,
403
843
  )
404
- logger.debug("Request xml: {0} ".format(redact_xml(xml_request[:1000])))
844
+ logger.debug(f"Request xml: {redact_xml(xml_request[:1000])} ")
405
845
 
406
846
  # Send the publishing request to server
407
847
  try:
@@ -413,16 +853,38 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
413
853
 
414
854
  if as_job:
415
855
  new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0]
416
- logger.info("Published {0} (JOB_ID: {1}".format(workbook_item.name, new_job.id))
856
+ logger.info(f"Published {workbook_item.name} (JOB_ID: {new_job.id}")
417
857
  return new_job
418
858
  else:
419
859
  new_workbook = WorkbookItem.from_response(server_response.content, self.parent_srv.namespace)[0]
420
- logger.info("Published {0} (ID: {1})".format(workbook_item.name, new_workbook.id))
860
+ logger.info(f"Published {workbook_item.name} (ID: {new_workbook.id})")
421
861
  return new_workbook
422
862
 
423
863
  # Populate workbook item's revisions
424
864
  @api(version="2.3")
425
865
  def populate_revisions(self, workbook_item: WorkbookItem) -> None:
866
+ """
867
+ Populates (or gets) a list of revisions for a workbook.
868
+
869
+ You must first call this method to populate revisions before you can
870
+ iterate through the revisions.
871
+
872
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#get_workbook_revisions
873
+
874
+ Parameters
875
+ ----------
876
+ workbook_item : WorkbookItem
877
+ The workbook item to populate revisions for.
878
+
879
+ Returns
880
+ -------
881
+ None
882
+
883
+ Raises
884
+ ------
885
+ MissingRequiredFieldError
886
+ If the workbook item is missing an ID.
887
+ """
426
888
  if not workbook_item.id:
427
889
  error = "Workbook item missing ID. Workbook must be retrieved from server first."
428
890
  raise MissingRequiredFieldError(error)
@@ -431,12 +893,12 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
431
893
  return self._get_workbook_revisions(workbook_item)
432
894
 
433
895
  workbook_item._set_revisions(revisions_fetcher)
434
- logger.info("Populated revisions for workbook (ID: {0})".format(workbook_item.id))
896
+ logger.info(f"Populated revisions for workbook (ID: {workbook_item.id})")
435
897
 
436
898
  def _get_workbook_revisions(
437
899
  self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"] = None
438
- ) -> List[RevisionItem]:
439
- url = "{0}/{1}/revisions".format(self.baseurl, workbook_item.id)
900
+ ) -> list[RevisionItem]:
901
+ url = f"{self.baseurl}/{workbook_item.id}/revisions"
440
902
  server_response = self.get_request(url, req_options)
441
903
  revisions = RevisionItem.from_response(server_response.content, self.parent_srv.namespace, workbook_item)
442
904
  return revisions
@@ -450,13 +912,47 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
450
912
  filepath: Optional[PathOrFileW] = None,
451
913
  include_extract: bool = True,
452
914
  ) -> PathOrFileW:
915
+ """
916
+ Downloads a workbook revision to the specified directory (optional).
917
+
918
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#download_workbook_revision
919
+
920
+ Parameters
921
+ ----------
922
+ workbook_id : str
923
+ The workbook ID.
924
+
925
+ revision_number : str | None
926
+ The revision number of the workbook. If None, the latest revision is
927
+ downloaded.
928
+
929
+ filepath : Path or File object, optional
930
+ Downloads the file to the location you specify. If no location is
931
+ specified, the file is downloaded to the current working directory.
932
+ The default is Filepath=None.
933
+
934
+ include_extract : bool, default True
935
+ Set to False to exclude the extract from the download. The default
936
+ is True.
937
+
938
+ Returns
939
+ -------
940
+ Path or File object
941
+ The path to the downloaded workbook or the file object.
942
+
943
+ Raises
944
+ ------
945
+ ValueError
946
+ If the workbook ID is not defined.
947
+ """
948
+
453
949
  if not workbook_id:
454
950
  error = "Workbook ID undefined."
455
951
  raise ValueError(error)
456
952
  if revision_number is None:
457
- url = "{0}/{1}/content".format(self.baseurl, workbook_id)
953
+ url = f"{self.baseurl}/{workbook_id}/content"
458
954
  else:
459
- url = "{0}/{1}/revisions/{2}/content".format(self.baseurl, workbook_id, revision_number)
955
+ url = f"{self.baseurl}/{workbook_id}/revisions/{revision_number}/content"
460
956
 
461
957
  if not include_extract:
462
958
  url += "?includeExtract=False"
@@ -478,23 +974,194 @@ class Workbooks(QuerysetEndpoint[WorkbookItem]):
478
974
  f.write(chunk)
479
975
  return_path = os.path.abspath(download_path)
480
976
 
481
- logger.info(
482
- "Downloaded workbook revision {0} to {1} (ID: {2})".format(revision_number, return_path, workbook_id)
483
- )
977
+ logger.info(f"Downloaded workbook revision {revision_number} to {return_path} (ID: {workbook_id})")
484
978
  return return_path
485
979
 
486
980
  @api(version="2.3")
487
981
  def delete_revision(self, workbook_id: str, revision_number: str) -> None:
982
+ """
983
+ Deletes a specific revision from a workbook on Tableau Server.
984
+
985
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_revisions.htm#remove_workbook_revision
986
+
987
+ Parameters
988
+ ----------
989
+ workbook_id : str
990
+ The workbook ID.
991
+
992
+ revision_number : str
993
+ The revision number of the workbook to delete.
994
+
995
+ Returns
996
+ -------
997
+ None
998
+
999
+ Raises
1000
+ ------
1001
+ ValueError
1002
+ If the workbook ID or revision number is not defined.
1003
+ """
488
1004
  if workbook_id is None or revision_number is None:
489
1005
  raise ValueError
490
1006
  url = "/".join([self.baseurl, workbook_id, "revisions", revision_number])
491
1007
 
492
1008
  self.delete_request(url)
493
- logger.info("Deleted single workbook revision (ID: {0}) (Revision: {1})".format(workbook_id, revision_number))
1009
+ logger.info(f"Deleted single workbook revision (ID: {workbook_id}) (Revision: {revision_number})")
494
1010
 
495
1011
  # a convenience method
496
1012
  @api(version="2.8")
497
1013
  def schedule_extract_refresh(
498
1014
  self, schedule_id: str, item: WorkbookItem
499
- ) -> List["AddResponse"]: # actually should return a task
1015
+ ) -> list["AddResponse"]: # actually should return a task
1016
+ """
1017
+ Adds a workbook to a schedule for extract refresh.
1018
+
1019
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#add_workbook_to_schedule
1020
+
1021
+ Parameters
1022
+ ----------
1023
+ schedule_id : str
1024
+ The schedule ID.
1025
+
1026
+ item : WorkbookItem
1027
+ The workbook item to add to the schedule.
1028
+
1029
+ Returns
1030
+ -------
1031
+ list[AddResponse]
1032
+ The response from the server.
1033
+ """
500
1034
  return self.parent_srv.schedules.add_to_schedule(schedule_id, workbook=item)
1035
+
1036
+ @api(version="1.0")
1037
+ def add_tags(self, item: Union[WorkbookItem, str], tags: Union[Iterable[str], str]) -> set[str]:
1038
+ """
1039
+ Adds tags to a workbook. One or more tags may be added at a time. If a
1040
+ tag already exists on the workbook, it will not be duplicated.
1041
+
1042
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#add_tags_to_workbook
1043
+
1044
+ Parameters
1045
+ ----------
1046
+ item : WorkbookItem | str
1047
+ The workbook item or workbook ID to add tags to.
1048
+
1049
+ tags : Iterable[str] | str
1050
+ The tag or tags to add to the workbook. Tags can be a single tag or
1051
+ a list of tags.
1052
+
1053
+ Returns
1054
+ -------
1055
+ set[str]
1056
+ The set of tags added to the workbook.
1057
+ """
1058
+ return super().add_tags(item, tags)
1059
+
1060
+ @api(version="1.0")
1061
+ def delete_tags(self, item: Union[WorkbookItem, str], tags: Union[Iterable[str], str]) -> None:
1062
+ """
1063
+ Deletes tags from a workbook. One or more tags may be deleted at a time.
1064
+
1065
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#delete_tag_from_workbook
1066
+
1067
+ Parameters
1068
+ ----------
1069
+ item : WorkbookItem | str
1070
+ The workbook item or workbook ID to delete tags from.
1071
+
1072
+ tags : Iterable[str] | str
1073
+ The tag or tags to delete from the workbook. Tags can be a single
1074
+ tag or a list of tags.
1075
+
1076
+ Returns
1077
+ -------
1078
+ None
1079
+ """
1080
+ return super().delete_tags(item, tags)
1081
+
1082
+ @api(version="1.0")
1083
+ def update_tags(self, item: WorkbookItem) -> None:
1084
+ """
1085
+ Updates the tags on a workbook. This method is used to update the tags
1086
+ on the server to match the tags on the workbook item. This method is a
1087
+ convenience method that calls add_tags and delete_tags to update the
1088
+ tags on the server.
1089
+
1090
+ Parameters
1091
+ ----------
1092
+ item : WorkbookItem
1093
+ The workbook item to update the tags for. The tags on the workbook
1094
+ item will be used to update the tags on the server.
1095
+
1096
+ Returns
1097
+ -------
1098
+ None
1099
+ """
1100
+ return super().update_tags(item)
1101
+
1102
+ def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> QuerySet[WorkbookItem]:
1103
+ """
1104
+ Queries the Tableau Server for items using the specified filters. Page
1105
+ size can be specified to limit the number of items returned in a single
1106
+ request. If not specified, the default page size is 100. Page size can
1107
+ be an integer between 1 and 1000.
1108
+
1109
+ No positional arguments are allowed. All filters must be specified as
1110
+ keyword arguments. If you use the equality operator, you can specify it
1111
+ through <field_name>=<value>. If you want to use a different operator,
1112
+ you can specify it through <field_name>__<operator>=<value>. Field
1113
+ names can either be in snake_case or camelCase.
1114
+
1115
+ This endpoint supports the following fields and operators:
1116
+
1117
+
1118
+ created_at=...
1119
+ created_at__gt=...
1120
+ created_at__gte=...
1121
+ created_at__lt=...
1122
+ created_at__lte=...
1123
+ content_url=...
1124
+ content_url__in=...
1125
+ display_tabs=...
1126
+ favorites_total=...
1127
+ favorites_total__gt=...
1128
+ favorites_total__gte=...
1129
+ favorites_total__lt=...
1130
+ favorites_total__lte=...
1131
+ has_alerts=...
1132
+ has_extracts=...
1133
+ name=...
1134
+ name__in=...
1135
+ owner_domain=...
1136
+ owner_domain__in=...
1137
+ owner_email=...
1138
+ owner_email__in=...
1139
+ owner_name=...
1140
+ owner_name__in=...
1141
+ project_name=...
1142
+ project_name__in=...
1143
+ sheet_count=...
1144
+ sheet_count__gt=...
1145
+ sheet_count__gte=...
1146
+ sheet_count__lt=...
1147
+ sheet_count__lte=...
1148
+ size=...
1149
+ size__gt=...
1150
+ size__gte=...
1151
+ size__lt=...
1152
+ size__lte=...
1153
+ subscriptions_total=...
1154
+ subscriptions_total__gt=...
1155
+ subscriptions_total__gte=...
1156
+ subscriptions_total__lt=...
1157
+ subscriptions_total__lte=...
1158
+ tags=...
1159
+ tags__in=...
1160
+ updated_at=...
1161
+ updated_at__gt=...
1162
+ updated_at__gte=...
1163
+ updated_at__lt=...
1164
+ updated_at__lte=...
1165
+ """
1166
+
1167
+ return super().filter(*invalid, page_size=page_size, **kwargs)