tableauserverclient 0.37__py3-none-any.whl → 0.39__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 (118) hide show
  1. tableauserverclient/bin/_version.py → _version.py +3 -3
  2. bin/__init__.py +3 -0
  3. bin/_version.py +21 -0
  4. {tableauserverclient/helpers → helpers}/strings.py +25 -1
  5. {tableauserverclient/models → models}/__init__.py +15 -1
  6. models/collection_item.py +52 -0
  7. {tableauserverclient/models → models}/connection_item.py +16 -2
  8. {tableauserverclient/models → models}/custom_view_item.py +8 -0
  9. {tableauserverclient/models → models}/data_freshness_policy_item.py +3 -3
  10. {tableauserverclient/models → models}/datasource_item.py +113 -3
  11. models/extensions_item.py +186 -0
  12. models/extract_item.py +82 -0
  13. {tableauserverclient/models → models}/favorites_item.py +21 -8
  14. {tableauserverclient/models → models}/flow_item.py +3 -3
  15. {tableauserverclient/models → models}/group_item.py +18 -1
  16. {tableauserverclient/models → models}/groupset_item.py +14 -0
  17. {tableauserverclient/models → models}/interval_item.py +42 -1
  18. models/location_item.py +53 -0
  19. models/oidc_item.py +82 -0
  20. {tableauserverclient/models → models}/permissions_item.py +2 -0
  21. {tableauserverclient/models → models}/project_item.py +141 -29
  22. {tableauserverclient/models → models}/property_decorators.py +2 -2
  23. {tableauserverclient/models → models}/reference_item.py +12 -6
  24. {tableauserverclient/models → models}/schedule_item.py +67 -1
  25. {tableauserverclient/models → models}/site_item.py +54 -0
  26. {tableauserverclient/models → models}/table_item.py +7 -3
  27. {tableauserverclient/models → models}/tableau_auth.py +13 -6
  28. {tableauserverclient/models → models}/tableau_types.py +13 -1
  29. {tableauserverclient/models → models}/user_item.py +111 -4
  30. {tableauserverclient/models → models}/view_item.py +79 -5
  31. {tableauserverclient/models → models}/workbook_item.py +153 -3
  32. {tableauserverclient/server → server}/endpoint/__init__.py +4 -0
  33. {tableauserverclient/server → server}/endpoint/databases_endpoint.py +101 -18
  34. {tableauserverclient/server → server}/endpoint/datasources_endpoint.py +155 -25
  35. {tableauserverclient/server → server}/endpoint/dqw_endpoint.py +16 -6
  36. {tableauserverclient/server → server}/endpoint/endpoint.py +39 -0
  37. server/endpoint/extensions_endpoint.py +79 -0
  38. {tableauserverclient/server → server}/endpoint/flow_task_endpoint.py +1 -1
  39. {tableauserverclient/server → server}/endpoint/flows_endpoint.py +5 -4
  40. server/endpoint/oidc_endpoint.py +157 -0
  41. {tableauserverclient/server → server}/endpoint/projects_endpoint.py +12 -0
  42. server/endpoint/schedules_endpoint.py +328 -0
  43. {tableauserverclient/server → server}/endpoint/sites_endpoint.py +18 -1
  44. {tableauserverclient/server → server}/endpoint/tables_endpoint.py +140 -17
  45. {tableauserverclient/server → server}/endpoint/users_endpoint.py +296 -10
  46. {tableauserverclient/server → server}/endpoint/views_endpoint.py +23 -0
  47. {tableauserverclient/server → server}/endpoint/workbooks_endpoint.py +124 -9
  48. {tableauserverclient/server → server}/query.py +36 -0
  49. {tableauserverclient/server → server}/request_factory.py +286 -2
  50. {tableauserverclient/server → server}/request_options.py +139 -3
  51. {tableauserverclient/server → server}/server.py +46 -0
  52. {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/METADATA +5 -26
  53. tableauserverclient-0.39.dist-info/RECORD +107 -0
  54. {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/WHEEL +1 -1
  55. tableauserverclient-0.39.dist-info/top_level.txt +4 -0
  56. tableauserverclient/__init__.py +0 -141
  57. tableauserverclient/config.py +0 -27
  58. tableauserverclient/datetime_helpers.py +0 -45
  59. tableauserverclient/exponential_backoff.py +0 -30
  60. tableauserverclient/filesys_helpers.py +0 -63
  61. tableauserverclient/namespace.py +0 -37
  62. tableauserverclient/py.typed +0 -0
  63. tableauserverclient/server/endpoint/schedules_endpoint.py +0 -151
  64. tableauserverclient-0.37.dist-info/RECORD +0 -106
  65. tableauserverclient-0.37.dist-info/licenses/LICENSE.versioneer +0 -7
  66. tableauserverclient-0.37.dist-info/top_level.txt +0 -1
  67. {tableauserverclient/helpers → helpers}/__init__.py +0 -0
  68. {tableauserverclient/helpers → helpers}/headers.py +0 -0
  69. {tableauserverclient/helpers → helpers}/logging.py +0 -0
  70. {tableauserverclient/models → models}/column_item.py +0 -0
  71. {tableauserverclient/models → models}/connection_credentials.py +0 -0
  72. {tableauserverclient/models → models}/data_acceleration_report_item.py +0 -0
  73. {tableauserverclient/models → models}/data_alert_item.py +0 -0
  74. {tableauserverclient/models → models}/database_item.py +0 -0
  75. {tableauserverclient/models → models}/dqw_item.py +0 -0
  76. {tableauserverclient/models → models}/exceptions.py +0 -0
  77. {tableauserverclient/models → models}/fileupload_item.py +0 -0
  78. {tableauserverclient/models → models}/flow_run_item.py +0 -0
  79. {tableauserverclient/models → models}/job_item.py +0 -0
  80. {tableauserverclient/models → models}/linked_tasks_item.py +0 -0
  81. {tableauserverclient/models → models}/metric_item.py +0 -0
  82. {tableauserverclient/models → models}/pagination_item.py +0 -0
  83. {tableauserverclient/models → models}/revision_item.py +0 -0
  84. {tableauserverclient/models → models}/server_info_item.py +0 -0
  85. {tableauserverclient/models → models}/subscription_item.py +0 -0
  86. {tableauserverclient/models → models}/tag_item.py +0 -0
  87. {tableauserverclient/models → models}/target.py +0 -0
  88. {tableauserverclient/models → models}/task_item.py +0 -0
  89. {tableauserverclient/models → models}/virtual_connection_item.py +0 -0
  90. {tableauserverclient/models → models}/webhook_item.py +0 -0
  91. {tableauserverclient/server → server}/__init__.py +0 -0
  92. {tableauserverclient/server → server}/endpoint/auth_endpoint.py +0 -0
  93. {tableauserverclient/server → server}/endpoint/custom_views_endpoint.py +0 -0
  94. {tableauserverclient/server → server}/endpoint/data_acceleration_report_endpoint.py +0 -0
  95. {tableauserverclient/server → server}/endpoint/data_alert_endpoint.py +0 -0
  96. {tableauserverclient/server → server}/endpoint/default_permissions_endpoint.py +0 -0
  97. {tableauserverclient/server → server}/endpoint/exceptions.py +0 -0
  98. {tableauserverclient/server → server}/endpoint/favorites_endpoint.py +0 -0
  99. {tableauserverclient/server → server}/endpoint/fileuploads_endpoint.py +0 -0
  100. {tableauserverclient/server → server}/endpoint/flow_runs_endpoint.py +0 -0
  101. {tableauserverclient/server → server}/endpoint/groups_endpoint.py +0 -0
  102. {tableauserverclient/server → server}/endpoint/groupsets_endpoint.py +0 -0
  103. {tableauserverclient/server → server}/endpoint/jobs_endpoint.py +0 -0
  104. {tableauserverclient/server → server}/endpoint/linked_tasks_endpoint.py +0 -0
  105. {tableauserverclient/server → server}/endpoint/metadata_endpoint.py +0 -0
  106. {tableauserverclient/server → server}/endpoint/metrics_endpoint.py +0 -0
  107. {tableauserverclient/server → server}/endpoint/permissions_endpoint.py +0 -0
  108. {tableauserverclient/server → server}/endpoint/resource_tagger.py +0 -0
  109. {tableauserverclient/server → server}/endpoint/server_info_endpoint.py +0 -0
  110. {tableauserverclient/server → server}/endpoint/subscriptions_endpoint.py +0 -0
  111. {tableauserverclient/server → server}/endpoint/tasks_endpoint.py +0 -0
  112. {tableauserverclient/server → server}/endpoint/virtual_connections_endpoint.py +0 -0
  113. {tableauserverclient/server → server}/endpoint/webhooks_endpoint.py +0 -0
  114. {tableauserverclient/server → server}/exceptions.py +0 -0
  115. {tableauserverclient/server → server}/filter.py +0 -0
  116. {tableauserverclient/server → server}/pager.py +0 -0
  117. {tableauserverclient/server → server}/sort.py +0 -0
  118. {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,79 @@
1
+ from tableauserverclient.models.extensions_item import ExtensionsServer, ExtensionsSiteSettings
2
+ from tableauserverclient.server.endpoint.endpoint import Endpoint
3
+ from tableauserverclient.server.endpoint.endpoint import api
4
+ from tableauserverclient.server.request_factory import RequestFactory
5
+
6
+
7
+ class Extensions(Endpoint):
8
+ def __init__(self, parent_srv):
9
+ super().__init__(parent_srv)
10
+
11
+ @property
12
+ def _server_baseurl(self) -> str:
13
+ return f"{self.parent_srv.baseurl}/settings/extensions"
14
+
15
+ @property
16
+ def baseurl(self) -> str:
17
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/settings/extensions"
18
+
19
+ @api(version="3.21")
20
+ def get_server_settings(self) -> ExtensionsServer:
21
+ """Lists the settings for extensions of a server
22
+
23
+ Returns
24
+ -------
25
+ ExtensionsServer
26
+ The server extensions settings
27
+ """
28
+ response = self.get_request(self._server_baseurl)
29
+ return ExtensionsServer.from_response(response.content, self.parent_srv.namespace)
30
+
31
+ @api(version="3.21")
32
+ def update_server_settings(self, extensions_server: ExtensionsServer) -> ExtensionsServer:
33
+ """Updates the settings for extensions of a server. Overwrites all existing settings. Any
34
+ sites omitted from the block list will be unblocked.
35
+
36
+ Parameters
37
+ ----------
38
+ extensions_server : ExtensionsServer
39
+ The server extensions settings to update
40
+
41
+ Returns
42
+ -------
43
+ ExtensionsServer
44
+ The updated server extensions settings
45
+ """
46
+ req = RequestFactory.Extensions.update_server_extensions(extensions_server)
47
+ response = self.put_request(self._server_baseurl, req)
48
+ return ExtensionsServer.from_response(response.content, self.parent_srv.namespace)
49
+
50
+ @api(version="3.21")
51
+ def get(self) -> ExtensionsSiteSettings:
52
+ """Lists the extensions settings for the site
53
+
54
+ Returns
55
+ -------
56
+ ExtensionsSiteSettings
57
+ The site extensions settings
58
+ """
59
+ response = self.get_request(self.baseurl)
60
+ return ExtensionsSiteSettings.from_response(response.content, self.parent_srv.namespace)
61
+
62
+ @api(version="3.21")
63
+ def update(self, extensions_site_settings: ExtensionsSiteSettings) -> ExtensionsSiteSettings:
64
+ """Updates the extensions settings for the site. Any extensions omitted
65
+ from the safe extensions list will be removed.
66
+
67
+ Parameters
68
+ ----------
69
+ extensions_site_settings : ExtensionsSiteSettings
70
+ The site extensions settings to update
71
+
72
+ Returns
73
+ -------
74
+ ExtensionsSiteSettings
75
+ The updated site extensions settings
76
+ """
77
+ req = RequestFactory.Extensions.update_site_extensions(extensions_site_settings)
78
+ response = self.put_request(self.baseurl, req)
79
+ return ExtensionsSiteSettings.from_response(response.content, self.parent_srv.namespace)
@@ -18,7 +18,7 @@ class FlowTasks(Endpoint):
18
18
  return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/tasks/flows"
19
19
 
20
20
  @api(version="3.22")
21
- def create(self, flow_item: TaskItem) -> TaskItem:
21
+ def create(self, flow_item: TaskItem) -> bytes:
22
22
  if not flow_item:
23
23
  error = "No flow provided"
24
24
  raise ValueError(error)
@@ -308,7 +308,7 @@ class Flows(QuerysetEndpoint[FlowItem], TaggingMixin[FlowItem]):
308
308
  return connection
309
309
 
310
310
  @api(version="3.3")
311
- def refresh(self, flow_item: FlowItem) -> JobItem:
311
+ def refresh(self, flow_item: Union[FlowItem, str]) -> JobItem:
312
312
  """
313
313
  Runs the flow to refresh the data.
314
314
 
@@ -316,15 +316,16 @@ class Flows(QuerysetEndpoint[FlowItem], TaggingMixin[FlowItem]):
316
316
 
317
317
  Parameters
318
318
  ----------
319
- flow_item: FlowItem
320
- The flow item to refresh.
319
+ flow_item: FlowItem | str
320
+ The FlowItem or str of the flow id to refresh.
321
321
 
322
322
  Returns
323
323
  -------
324
324
  JobItem
325
325
  The job item that was created to refresh the flow.
326
326
  """
327
- url = f"{self.baseurl}/{flow_item.id}/run"
327
+ flow_id = getattr(flow_item, "id", flow_item)
328
+ url = f"{self.baseurl}/{flow_id}/run"
328
329
  empty_req = RequestFactory.Empty.empty_req()
329
330
  server_response = self.post_request(url, empty_req)
330
331
  new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0]
@@ -0,0 +1,157 @@
1
+ from typing import Protocol, Union, TYPE_CHECKING
2
+ from tableauserverclient.models.oidc_item import SiteOIDCConfiguration
3
+ from tableauserverclient.server.endpoint import Endpoint
4
+ from tableauserverclient.server.request_factory import RequestFactory
5
+ from tableauserverclient.server.endpoint.endpoint import api
6
+
7
+ if TYPE_CHECKING:
8
+ from tableauserverclient.models.site_item import SiteAuthConfiguration
9
+ from tableauserverclient.server.server import Server
10
+
11
+
12
+ class IDPAttributes(Protocol):
13
+ idp_configuration_id: str
14
+
15
+
16
+ class IDPProperty(Protocol):
17
+ @property
18
+ def idp_configuration_id(self) -> str: ...
19
+
20
+
21
+ HasIdpConfigurationID = Union[str, IDPAttributes]
22
+
23
+
24
+ class OIDC(Endpoint):
25
+ def __init__(self, server: "Server") -> None:
26
+ self.parent_srv = server
27
+
28
+ @property
29
+ def baseurl(self) -> str:
30
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/site-oidc-configuration"
31
+
32
+ @api(version="3.24")
33
+ def get(self) -> list["SiteAuthConfiguration"]:
34
+ """
35
+ Get all OpenID Connect (OIDC) configurations for the currently
36
+ authenticated Tableau Cloud site. To get all of the configuration
37
+ details, use the get_by_id method.
38
+
39
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_identity_pools.htm#AuthnService_ListAuthConfigurations
40
+
41
+ Returns
42
+ -------
43
+ list[SiteAuthConfiguration]
44
+ """
45
+ return self.parent_srv.sites.list_auth_configurations()
46
+
47
+ @api(version="3.24")
48
+ def get_by_id(self, id: Union[str, HasIdpConfigurationID]) -> SiteOIDCConfiguration:
49
+ """
50
+ Get details about a specific OpenID Connect (OIDC) configuration on the
51
+ current Tableau Cloud site. Only retrieves configurations for the
52
+ currently authenticated site.
53
+
54
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_openid_connect.htm#get_openid_connect_configuration
55
+
56
+ Parameters
57
+ ----------
58
+ id : Union[str, HasID]
59
+ The ID of the OIDC configuration to retrieve. Can be either the
60
+ ID string or an object with an id attribute.
61
+
62
+ Returns
63
+ -------
64
+ SiteOIDCConfiguration
65
+ The OIDC configuration for the specified site.
66
+ """
67
+ target = getattr(id, "idp_configuration_id", id)
68
+ url = f"{self.baseurl}/{target}"
69
+ response = self.get_request(url)
70
+ return SiteOIDCConfiguration.from_response(response.content, self.parent_srv.namespace)
71
+
72
+ @api(version="3.22")
73
+ def create(self, config_item: SiteOIDCConfiguration) -> SiteOIDCConfiguration:
74
+ """
75
+ Create the OpenID Connect (OIDC) configuration for the currently
76
+ authenticated Tableau Cloud site. The config_item must have the
77
+ following attributes set, others are optional:
78
+
79
+ idp_configuration_name
80
+ client_id
81
+ client_secret
82
+ authorization_endpoint
83
+ token_endpoint
84
+ userinfo_endpoint
85
+ enabled
86
+ jwks_uri
87
+
88
+ The secret in the returned config will be masked.
89
+
90
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_openid_connect.htm#create_openid_connect_configuration
91
+
92
+ Parameters
93
+ ----------
94
+ config : SiteOIDCConfiguration
95
+ The OIDC configuration to create.
96
+
97
+ Returns
98
+ -------
99
+ SiteOIDCConfiguration
100
+ The created OIDC configuration.
101
+ """
102
+ url = self.baseurl
103
+ create_req = RequestFactory.OIDC.create_req(config_item)
104
+ response = self.put_request(url, create_req)
105
+ return SiteOIDCConfiguration.from_response(response.content, self.parent_srv.namespace)
106
+
107
+ @api(version="3.24")
108
+ def delete_configuration(self, config: Union[str, HasIdpConfigurationID]) -> None:
109
+ """
110
+ Delete the OpenID Connect (OIDC) configuration for the currently
111
+ authenticated Tableau Cloud site. The config parameter can be either
112
+ the ID of the configuration or the configuration object itself.
113
+
114
+ **Important**: Before removing the OIDC configuration, make sure that
115
+ users who are set to authenticate with OIDC are set to use a different
116
+ authentication type. Users who are not set with a different
117
+ authentication type before removing the OIDC configuration will not be
118
+ able to sign in to Tableau Cloud.
119
+
120
+
121
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_openid_connect.htm#remove_openid_connect_configuration
122
+
123
+ Parameters
124
+ ----------
125
+ config : Union[str, HasID]
126
+ The OIDC configuration to delete. Can be either the ID of the
127
+ configuration or the configuration object itself.
128
+ """
129
+
130
+ target = getattr(config, "idp_configuration_id", config)
131
+
132
+ url = f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/disable-site-oidc-configuration?idpConfigurationId={target}"
133
+ _ = self.put_request(url)
134
+ return None
135
+
136
+ @api(version="3.22")
137
+ def update(self, config: SiteOIDCConfiguration) -> SiteOIDCConfiguration:
138
+ """
139
+ Update the Tableau Cloud site's OpenID Connect (OIDC) configuration. The
140
+ secret in the returned config will be masked.
141
+
142
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_openid_connect.htm#update_openid_connect_configuration
143
+
144
+ Parameters
145
+ ----------
146
+ config : SiteOIDCConfiguration
147
+ The OIDC configuration to update. Must have the id attribute set.
148
+
149
+ Returns
150
+ -------
151
+ SiteOIDCConfiguration
152
+ The updated OIDC configuration.
153
+ """
154
+ url = f"{self.baseurl}/{config.idp_configuration_id}"
155
+ update_req = RequestFactory.OIDC.update_req(config)
156
+ response = self.put_request(url, update_req)
157
+ return SiteOIDCConfiguration.from_response(response.content, self.parent_srv.namespace)
@@ -89,6 +89,18 @@ class Projects(QuerysetEndpoint[ProjectItem]):
89
89
  self.delete_request(url)
90
90
  logger.info(f"Deleted single project (ID: {project_id})")
91
91
 
92
+ @api(version="2.0")
93
+ def get_by_id(self, project_id: str) -> ProjectItem:
94
+ """
95
+ Fetch a project by ID. This is a convenience method making up for a gap in the server API.
96
+ It uses the same endpoint as the update method, but without the ability to update the project.
97
+ """
98
+ if not project_id:
99
+ error = "Project ID undefined."
100
+ raise ValueError(error)
101
+ project = ProjectItem(id=project_id)
102
+ return self.update(project, samples=False)
103
+
92
104
  @api(version="2.0")
93
105
  def update(self, project_item: ProjectItem, samples: bool = False) -> ProjectItem:
94
106
  """
@@ -0,0 +1,328 @@
1
+ from collections.abc import Iterable
2
+ import copy
3
+ import logging
4
+ import warnings
5
+ from collections import namedtuple
6
+ from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union, overload
7
+
8
+ from .endpoint import Endpoint, api, parameter_added_in
9
+ from .exceptions import MissingRequiredFieldError
10
+ from tableauserverclient.server import RequestFactory
11
+ from tableauserverclient.models import PaginationItem, ScheduleItem, TaskItem, ExtractItem
12
+ from tableauserverclient.models.schedule_item import parse_batch_schedule_state
13
+
14
+ from tableauserverclient.helpers.logging import logger
15
+
16
+ AddResponse = namedtuple("AddResponse", ("result", "error", "warnings", "task_created"))
17
+ OK = AddResponse(result=True, error=None, warnings=None, task_created=None)
18
+
19
+ if TYPE_CHECKING:
20
+ from ..request_options import RequestOptions
21
+ from ...models import DatasourceItem, WorkbookItem, FlowItem
22
+
23
+
24
+ class Schedules(Endpoint):
25
+ @property
26
+ def baseurl(self) -> str:
27
+ return f"{self.parent_srv.baseurl}/schedules"
28
+
29
+ @property
30
+ def siteurl(self) -> str:
31
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/schedules"
32
+
33
+ @api(version="2.3")
34
+ def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[ScheduleItem], PaginationItem]:
35
+ """
36
+ Returns a list of flows, extract, and subscription server schedules on
37
+ Tableau Server. For each schedule, the API returns name, frequency,
38
+ priority, and other information.
39
+
40
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#query_schedules
41
+
42
+ Parameters
43
+ ----------
44
+ req_options : Optional[RequestOptions]
45
+ Filtering and paginating options for request.
46
+
47
+ Returns
48
+ -------
49
+ Tuple[List[ScheduleItem], PaginationItem]
50
+ A tuple of list of ScheduleItem and PaginationItem
51
+ """
52
+ logger.info("Querying all schedules")
53
+ url = self.baseurl
54
+ server_response = self.get_request(url, req_options)
55
+ pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
56
+ all_schedule_items = ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)
57
+ return all_schedule_items, pagination_item
58
+
59
+ @api(version="3.8")
60
+ def get_by_id(self, schedule_id: str) -> ScheduleItem:
61
+ """
62
+ Returns detailed information about the specified server schedule.
63
+
64
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#get-schedule
65
+
66
+ Parameters
67
+ ----------
68
+ schedule_id : str
69
+ The ID of the schedule to get information for.
70
+
71
+ Returns
72
+ -------
73
+ ScheduleItem
74
+ The schedule item that corresponds to the given ID.
75
+ """
76
+ if not schedule_id:
77
+ error = "No Schedule ID provided"
78
+ raise ValueError(error)
79
+ logger.info(f"Querying a single schedule by id ({schedule_id})")
80
+ url = f"{self.baseurl}/{schedule_id}"
81
+ server_response = self.get_request(url)
82
+ return ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
83
+
84
+ @api(version="2.3")
85
+ def delete(self, schedule_id: str) -> None:
86
+ """
87
+ Deletes the specified schedule from the server.
88
+
89
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#delete_schedule
90
+
91
+ Parameters
92
+ ----------
93
+ schedule_id : str
94
+ The ID of the schedule to delete.
95
+
96
+ Returns
97
+ -------
98
+ None
99
+ """
100
+ if not schedule_id:
101
+ error = "Schedule ID undefined"
102
+ raise ValueError(error)
103
+ url = f"{self.baseurl}/{schedule_id}"
104
+ self.delete_request(url)
105
+ logger.info(f"Deleted single schedule (ID: {schedule_id})")
106
+
107
+ @api(version="2.3")
108
+ def update(self, schedule_item: ScheduleItem) -> ScheduleItem:
109
+ """
110
+ Modifies settings for the specified server schedule, including the name,
111
+ priority, and frequency details on Tableau Server. For Tableau Cloud,
112
+ see the tasks and subscritpions API.
113
+
114
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#update_schedule
115
+
116
+ Parameters
117
+ ----------
118
+ schedule_item : ScheduleItem
119
+ The schedule item to update.
120
+
121
+ Returns
122
+ -------
123
+ ScheduleItem
124
+ The updated schedule item.
125
+ """
126
+ if not schedule_item.id:
127
+ error = "Schedule item missing ID."
128
+ raise MissingRequiredFieldError(error)
129
+
130
+ url = f"{self.baseurl}/{schedule_item.id}"
131
+ update_req = RequestFactory.Schedule.update_req(schedule_item)
132
+ server_response = self.put_request(url, update_req)
133
+ logger.info(f"Updated schedule item (ID: {schedule_item.id})")
134
+ updated_schedule = copy.copy(schedule_item)
135
+ return updated_schedule._parse_common_tags(server_response.content, self.parent_srv.namespace)
136
+
137
+ @api(version="2.3")
138
+ def create(self, schedule_item: ScheduleItem) -> ScheduleItem:
139
+ """
140
+ Creates a new server schedule on Tableau Server. For Tableau Cloud, use
141
+ the tasks and subscriptions API.
142
+
143
+ Parameters
144
+ ----------
145
+ schedule_item : ScheduleItem
146
+ The schedule item to create.
147
+
148
+ Returns
149
+ -------
150
+ ScheduleItem
151
+ The newly created schedule.
152
+ """
153
+ if schedule_item.interval_item is None:
154
+ error = "Interval item must be defined."
155
+ raise MissingRequiredFieldError(error)
156
+
157
+ url = self.baseurl
158
+ create_req = RequestFactory.Schedule.create_req(schedule_item)
159
+ server_response = self.post_request(url, create_req)
160
+ new_schedule = ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
161
+ logger.info(f"Created new schedule (ID: {new_schedule.id})")
162
+ return new_schedule
163
+
164
+ @api(version="2.8")
165
+ @parameter_added_in(flow="3.3")
166
+ def add_to_schedule(
167
+ self,
168
+ schedule_id: str,
169
+ workbook: Optional["WorkbookItem"] = None,
170
+ datasource: Optional["DatasourceItem"] = None,
171
+ flow: Optional["FlowItem"] = None,
172
+ task_type: Optional[str] = None,
173
+ ) -> list[AddResponse]:
174
+ """
175
+ Adds a workbook, datasource, or flow to a schedule on Tableau Server.
176
+ Only one of workbook, datasource, or flow can be passed in at a time.
177
+
178
+ The task type is optional and will default to ExtractRefresh if a
179
+ workbook or datasource is passed in, and RunFlow if a flow is passed in.
180
+
181
+ 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
182
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_jobs_tasks_and_schedules.htm#add_data_source_to_schedule
183
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#add_flow_task_to_schedule
184
+
185
+ Parameters
186
+ ----------
187
+ schedule_id : str
188
+ The ID of the schedule to add the item to.
189
+
190
+ workbook : Optional[WorkbookItem]
191
+ The workbook to add to the schedule.
192
+
193
+ datasource : Optional[DatasourceItem]
194
+ The datasource to add to the schedule.
195
+
196
+ flow : Optional[FlowItem]
197
+ The flow to add to the schedule.
198
+
199
+ task_type : Optional[str]
200
+ The type of task to add to the schedule. If not provided, it will
201
+ default to ExtractRefresh if a workbook or datasource is passed in,
202
+ and RunFlow if a flow is passed in.
203
+
204
+ Returns
205
+ -------
206
+ list[AddResponse]
207
+ A list of responses for each item added to the schedule.
208
+ """
209
+ # There doesn't seem to be a good reason to allow one item of each type?
210
+ if workbook and datasource:
211
+ warnings.warn("Passing in multiple items for add_to_schedule will be deprecated", PendingDeprecationWarning)
212
+ items: list[
213
+ tuple[str, Union[WorkbookItem, FlowItem, DatasourceItem], str, Callable[[Optional[str], str], bytes], str]
214
+ ] = []
215
+
216
+ if workbook is not None:
217
+ if not task_type:
218
+ task_type = TaskItem.Type.ExtractRefresh
219
+ items.append((schedule_id, workbook, "workbook", RequestFactory.Schedule.add_workbook_req, task_type))
220
+ if datasource is not None:
221
+ if not task_type:
222
+ task_type = TaskItem.Type.ExtractRefresh
223
+ items.append((schedule_id, datasource, "datasource", RequestFactory.Schedule.add_datasource_req, task_type))
224
+ if flow is not None and not (workbook or datasource): # Cannot pass a flow with any other type
225
+ if not task_type:
226
+ task_type = TaskItem.Type.RunFlow
227
+ items.append(
228
+ (schedule_id, flow, "flow", RequestFactory.Schedule.add_flow_req, task_type)
229
+ ) # type:ignore[arg-type]
230
+
231
+ results = (self._add_to(*x) for x in items)
232
+ return [x for x in results if not x.result]
233
+
234
+ def _add_to(
235
+ self,
236
+ schedule_id,
237
+ resource: Union["DatasourceItem", "WorkbookItem", "FlowItem"],
238
+ type_: str,
239
+ req_factory: Callable[
240
+ [
241
+ str,
242
+ str,
243
+ ],
244
+ bytes,
245
+ ],
246
+ item_task_type,
247
+ ) -> AddResponse:
248
+ id_ = resource.id
249
+ url = f"{self.siteurl}/{schedule_id}/{type_}s"
250
+ add_req = req_factory(id_, task_type=item_task_type) # type: ignore[call-arg, arg-type]
251
+ response = self.put_request(url, add_req)
252
+
253
+ error, warnings, task_created = ScheduleItem.parse_add_to_schedule_response(response, self.parent_srv.namespace)
254
+ if task_created:
255
+ logger.info(f"Added {type_} to {id_} to schedule {schedule_id}")
256
+
257
+ if error is not None or warnings is not None:
258
+ return AddResponse(
259
+ result=False,
260
+ error=error,
261
+ warnings=warnings,
262
+ task_created=task_created,
263
+ )
264
+ else:
265
+ return OK
266
+
267
+ @api(version="2.3")
268
+ def get_extract_refresh_tasks(
269
+ self, schedule_id: str, req_options: Optional["RequestOptions"] = None
270
+ ) -> tuple[list["ExtractItem"], "PaginationItem"]:
271
+ """Get all extract refresh tasks for the specified schedule."""
272
+ if not schedule_id:
273
+ error = "Schedule ID undefined"
274
+ raise ValueError(error)
275
+
276
+ logger.info(f"Querying extract refresh tasks for schedule (ID: {schedule_id})")
277
+ url = f"{self.siteurl}/{schedule_id}/extracts"
278
+ server_response = self.get_request(url, req_options)
279
+
280
+ pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
281
+ extract_items = ExtractItem.from_response(server_response.content, self.parent_srv.namespace)
282
+
283
+ return extract_items, pagination_item
284
+
285
+ @overload
286
+ def batch_update_state(
287
+ self,
288
+ schedules: Iterable[ScheduleItem | str],
289
+ state: Literal["active", "suspended"],
290
+ update_all: Literal[False] = False,
291
+ ) -> list[str]: ...
292
+
293
+ @overload
294
+ def batch_update_state(
295
+ self, schedules: Any, state: Literal["active", "suspended"], update_all: Literal[True]
296
+ ) -> list[str]: ...
297
+
298
+ @api(version="3.27")
299
+ def batch_update_state(self, schedules, state, update_all=False) -> list[str]:
300
+ """
301
+ Batch update the status of one or more scheudles. If update_all is set,
302
+ all schedules on the Tableau Server are affected.
303
+
304
+ Parameters
305
+ ----------
306
+ schedules: Iterable[ScheudleItem | str] | Any
307
+ The schedules to be updated. If update_all=True, this is ignored.
308
+
309
+ state: Literal["active", "suspended"]
310
+ The state of the schedules, whether active or suspended.
311
+
312
+ update_all: bool
313
+ Whether or not to apply the status to all schedules.
314
+
315
+ Returns
316
+ -------
317
+ List[str]
318
+ The IDs of the affected schedules.
319
+ """
320
+ params = {"state": state}
321
+ if update_all:
322
+ params["updateAll"] = "true"
323
+ payload = RequestFactory.Empty.empty_req()
324
+ else:
325
+ payload = RequestFactory.Schedule.batch_update_state(schedules)
326
+
327
+ response = self.put_request(self.baseurl, payload, parameters={"params": params})
328
+ return parse_batch_schedule_state(response, self.parent_srv.namespace)
@@ -4,7 +4,7 @@ import logging
4
4
  from .endpoint import Endpoint, api
5
5
  from .exceptions import MissingRequiredFieldError
6
6
  from tableauserverclient.server import RequestFactory
7
- from tableauserverclient.models import SiteItem, PaginationItem
7
+ from tableauserverclient.models import SiteAuthConfiguration, SiteItem, PaginationItem
8
8
 
9
9
  from tableauserverclient.helpers.logging import logger
10
10
 
@@ -418,3 +418,20 @@ class Sites(Endpoint):
418
418
 
419
419
  empty_req = RequestFactory.Empty.empty_req()
420
420
  self.post_request(url, empty_req)
421
+
422
+ @api(version="3.24")
423
+ def list_auth_configurations(self) -> list[SiteAuthConfiguration]:
424
+ """
425
+ Lists all authentication configurations on the current site.
426
+
427
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_site.htm#list_authentication_configurations_site
428
+
429
+ Returns
430
+ -------
431
+ list[SiteAuthConfiguration]
432
+ A list of authentication configurations on the current site.
433
+ """
434
+ url = f"{self.baseurl}/{self.parent_srv.site_id}/site-auth-configurations"
435
+ server_response = self.get_request(url)
436
+ auth_configurations = SiteAuthConfiguration.from_response(server_response.content, self.parent_srv.namespace)
437
+ return auth_configurations