tableauserverclient 0.33__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.
- tableauserverclient/__init__.py +28 -22
- tableauserverclient/_version.py +3 -3
- tableauserverclient/config.py +5 -3
- tableauserverclient/models/column_item.py +1 -1
- tableauserverclient/models/connection_credentials.py +1 -1
- tableauserverclient/models/connection_item.py +6 -6
- tableauserverclient/models/custom_view_item.py +29 -6
- tableauserverclient/models/data_acceleration_report_item.py +2 -2
- tableauserverclient/models/data_alert_item.py +5 -5
- tableauserverclient/models/data_freshness_policy_item.py +6 -6
- tableauserverclient/models/database_item.py +3 -3
- tableauserverclient/models/datasource_item.py +10 -10
- tableauserverclient/models/dqw_item.py +1 -1
- tableauserverclient/models/favorites_item.py +5 -6
- tableauserverclient/models/fileupload_item.py +1 -1
- tableauserverclient/models/flow_item.py +6 -6
- tableauserverclient/models/flow_run_item.py +3 -3
- tableauserverclient/models/group_item.py +4 -4
- tableauserverclient/models/groupset_item.py +4 -4
- tableauserverclient/models/interval_item.py +9 -9
- tableauserverclient/models/job_item.py +8 -8
- tableauserverclient/models/linked_tasks_item.py +5 -5
- tableauserverclient/models/metric_item.py +5 -5
- tableauserverclient/models/pagination_item.py +1 -1
- tableauserverclient/models/permissions_item.py +12 -10
- tableauserverclient/models/project_item.py +35 -19
- tableauserverclient/models/property_decorators.py +12 -11
- tableauserverclient/models/reference_item.py +2 -2
- tableauserverclient/models/revision_item.py +3 -3
- tableauserverclient/models/schedule_item.py +2 -2
- tableauserverclient/models/server_info_item.py +26 -6
- tableauserverclient/models/site_item.py +69 -3
- tableauserverclient/models/subscription_item.py +3 -3
- tableauserverclient/models/table_item.py +1 -1
- tableauserverclient/models/tableau_auth.py +115 -5
- tableauserverclient/models/tableau_types.py +2 -2
- tableauserverclient/models/tag_item.py +3 -4
- tableauserverclient/models/task_item.py +4 -4
- tableauserverclient/models/user_item.py +47 -17
- tableauserverclient/models/view_item.py +11 -10
- tableauserverclient/models/virtual_connection_item.py +6 -5
- tableauserverclient/models/webhook_item.py +6 -6
- tableauserverclient/models/workbook_item.py +90 -12
- tableauserverclient/namespace.py +1 -1
- tableauserverclient/server/__init__.py +2 -1
- tableauserverclient/server/endpoint/auth_endpoint.py +65 -8
- tableauserverclient/server/endpoint/custom_views_endpoint.py +62 -18
- tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
- tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
- tableauserverclient/server/endpoint/databases_endpoint.py +13 -12
- tableauserverclient/server/endpoint/datasources_endpoint.py +49 -54
- tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
- tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
- tableauserverclient/server/endpoint/endpoint.py +19 -21
- tableauserverclient/server/endpoint/exceptions.py +23 -7
- tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
- tableauserverclient/server/endpoint/fileuploads_endpoint.py +9 -11
- tableauserverclient/server/endpoint/flow_runs_endpoint.py +15 -13
- tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
- tableauserverclient/server/endpoint/flows_endpoint.py +30 -29
- tableauserverclient/server/endpoint/groups_endpoint.py +18 -17
- tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
- tableauserverclient/server/endpoint/jobs_endpoint.py +7 -7
- tableauserverclient/server/endpoint/linked_tasks_endpoint.py +2 -2
- tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
- tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
- tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
- tableauserverclient/server/endpoint/projects_endpoint.py +81 -30
- tableauserverclient/server/endpoint/resource_tagger.py +14 -13
- tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
- tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
- tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
- tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
- tableauserverclient/server/endpoint/tables_endpoint.py +15 -14
- tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
- tableauserverclient/server/endpoint/users_endpoint.py +366 -19
- tableauserverclient/server/endpoint/views_endpoint.py +19 -18
- tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
- tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
- tableauserverclient/server/endpoint/workbooks_endpoint.py +647 -61
- tableauserverclient/server/filter.py +2 -2
- tableauserverclient/server/pager.py +5 -6
- tableauserverclient/server/query.py +68 -19
- tableauserverclient/server/request_factory.py +37 -36
- tableauserverclient/server/request_options.py +123 -145
- tableauserverclient/server/server.py +65 -9
- tableauserverclient/server/sort.py +2 -2
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/METADATA +6 -6
- tableauserverclient-0.34.dist-info/RECORD +106 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
- tableauserverclient-0.33.dist-info/RECORD +0 -106
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
|
@@ -5,9 +5,10 @@ from tableauserverclient.server.endpoint.endpoint import QuerysetEndpoint, api,
|
|
|
5
5
|
from tableauserverclient.server.endpoint.exceptions import MissingRequiredFieldError
|
|
6
6
|
from tableauserverclient.server.endpoint.permissions_endpoint import _PermissionsEndpoint
|
|
7
7
|
from tableauserverclient.server import RequestFactory, RequestOptions
|
|
8
|
+
from tableauserverclient.models.permissions_item import PermissionsRule
|
|
8
9
|
from tableauserverclient.models import ProjectItem, PaginationItem, Resource
|
|
9
10
|
|
|
10
|
-
from typing import
|
|
11
|
+
from typing import Optional, TYPE_CHECKING
|
|
11
12
|
|
|
12
13
|
from tableauserverclient.server.query import QuerySet
|
|
13
14
|
|
|
@@ -20,17 +21,17 @@ from tableauserverclient.helpers.logging import logger
|
|
|
20
21
|
|
|
21
22
|
class Projects(QuerysetEndpoint[ProjectItem]):
|
|
22
23
|
def __init__(self, parent_srv: "Server") -> None:
|
|
23
|
-
super(
|
|
24
|
+
super().__init__(parent_srv)
|
|
24
25
|
|
|
25
26
|
self._permissions = _PermissionsEndpoint(parent_srv, lambda: self.baseurl)
|
|
26
27
|
self._default_permissions = _DefaultPermissionsEndpoint(parent_srv, lambda: self.baseurl)
|
|
27
28
|
|
|
28
29
|
@property
|
|
29
30
|
def baseurl(self) -> str:
|
|
30
|
-
return "{
|
|
31
|
+
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/projects"
|
|
31
32
|
|
|
32
33
|
@api(version="2.0")
|
|
33
|
-
def get(self, req_options: Optional["RequestOptions"] = None) ->
|
|
34
|
+
def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[ProjectItem], PaginationItem]:
|
|
34
35
|
logger.info("Querying all projects on site")
|
|
35
36
|
url = self.baseurl
|
|
36
37
|
server_response = self.get_request(url, req_options)
|
|
@@ -43,9 +44,9 @@ class Projects(QuerysetEndpoint[ProjectItem]):
|
|
|
43
44
|
if not project_id:
|
|
44
45
|
error = "Project ID undefined."
|
|
45
46
|
raise ValueError(error)
|
|
46
|
-
url = "{
|
|
47
|
+
url = f"{self.baseurl}/{project_id}"
|
|
47
48
|
self.delete_request(url)
|
|
48
|
-
logger.info("Deleted single project (ID: {
|
|
49
|
+
logger.info(f"Deleted single project (ID: {project_id})")
|
|
49
50
|
|
|
50
51
|
@api(version="2.0")
|
|
51
52
|
def update(self, project_item: ProjectItem, samples: bool = False) -> ProjectItem:
|
|
@@ -54,10 +55,10 @@ class Projects(QuerysetEndpoint[ProjectItem]):
|
|
|
54
55
|
raise MissingRequiredFieldError(error)
|
|
55
56
|
|
|
56
57
|
params = {"params": {RequestOptions.Field.PublishSamples: samples}}
|
|
57
|
-
url = "{
|
|
58
|
+
url = f"{self.baseurl}/{project_item.id}"
|
|
58
59
|
update_req = RequestFactory.Project.update_req(project_item)
|
|
59
60
|
server_response = self.put_request(url, update_req, XML_CONTENT_TYPE, params)
|
|
60
|
-
logger.info("Updated project item (ID: {
|
|
61
|
+
logger.info(f"Updated project item (ID: {project_item.id})")
|
|
61
62
|
updated_project = ProjectItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
62
63
|
return updated_project
|
|
63
64
|
|
|
@@ -66,11 +67,11 @@ class Projects(QuerysetEndpoint[ProjectItem]):
|
|
|
66
67
|
params = {"params": {RequestOptions.Field.PublishSamples: samples}}
|
|
67
68
|
url = self.baseurl
|
|
68
69
|
if project_item._samples:
|
|
69
|
-
url = "{
|
|
70
|
+
url = f"{self.baseurl}?publishSamples={project_item._samples}"
|
|
70
71
|
create_req = RequestFactory.Project.create_req(project_item)
|
|
71
72
|
server_response = self.post_request(url, create_req, XML_CONTENT_TYPE, params)
|
|
72
73
|
new_project = ProjectItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
73
|
-
logger.info("Created new project (ID: {
|
|
74
|
+
logger.info(f"Created new project (ID: {new_project.id})")
|
|
74
75
|
return new_project
|
|
75
76
|
|
|
76
77
|
@api(version="2.0")
|
|
@@ -78,85 +79,135 @@ class Projects(QuerysetEndpoint[ProjectItem]):
|
|
|
78
79
|
self._permissions.populate(item)
|
|
79
80
|
|
|
80
81
|
@api(version="2.0")
|
|
81
|
-
def update_permissions(self, item, rules):
|
|
82
|
+
def update_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
|
|
82
83
|
return self._permissions.update(item, rules)
|
|
83
84
|
|
|
84
85
|
@api(version="2.0")
|
|
85
|
-
def delete_permission(self, item, rules):
|
|
86
|
+
def delete_permission(self, item: ProjectItem, rules: list[PermissionsRule]) -> None:
|
|
86
87
|
self._permissions.delete(item, rules)
|
|
87
88
|
|
|
88
89
|
@api(version="2.1")
|
|
89
|
-
def populate_workbook_default_permissions(self, item):
|
|
90
|
+
def populate_workbook_default_permissions(self, item: ProjectItem) -> None:
|
|
90
91
|
self._default_permissions.populate_default_permissions(item, Resource.Workbook)
|
|
91
92
|
|
|
92
93
|
@api(version="2.1")
|
|
93
|
-
def populate_datasource_default_permissions(self, item):
|
|
94
|
+
def populate_datasource_default_permissions(self, item: ProjectItem) -> None:
|
|
94
95
|
self._default_permissions.populate_default_permissions(item, Resource.Datasource)
|
|
95
96
|
|
|
96
97
|
@api(version="3.2")
|
|
97
|
-
def populate_metric_default_permissions(self, item):
|
|
98
|
+
def populate_metric_default_permissions(self, item: ProjectItem) -> None:
|
|
98
99
|
self._default_permissions.populate_default_permissions(item, Resource.Metric)
|
|
99
100
|
|
|
100
101
|
@api(version="3.4")
|
|
101
|
-
def populate_datarole_default_permissions(self, item):
|
|
102
|
+
def populate_datarole_default_permissions(self, item: ProjectItem) -> None:
|
|
102
103
|
self._default_permissions.populate_default_permissions(item, Resource.Datarole)
|
|
103
104
|
|
|
104
105
|
@api(version="3.4")
|
|
105
|
-
def populate_flow_default_permissions(self, item):
|
|
106
|
+
def populate_flow_default_permissions(self, item: ProjectItem) -> None:
|
|
106
107
|
self._default_permissions.populate_default_permissions(item, Resource.Flow)
|
|
107
108
|
|
|
108
109
|
@api(version="3.4")
|
|
109
|
-
def populate_lens_default_permissions(self, item):
|
|
110
|
+
def populate_lens_default_permissions(self, item: ProjectItem) -> None:
|
|
110
111
|
self._default_permissions.populate_default_permissions(item, Resource.Lens)
|
|
111
112
|
|
|
113
|
+
@api(version="3.23")
|
|
114
|
+
def populate_virtualconnection_default_permissions(self, item: ProjectItem) -> None:
|
|
115
|
+
self._default_permissions.populate_default_permissions(item, Resource.VirtualConnection)
|
|
116
|
+
|
|
117
|
+
@api(version="3.23")
|
|
118
|
+
def populate_database_default_permissions(self, item: ProjectItem) -> None:
|
|
119
|
+
self._default_permissions.populate_default_permissions(item, Resource.Database)
|
|
120
|
+
|
|
121
|
+
@api(version="3.23")
|
|
122
|
+
def populate_table_default_permissions(self, item: ProjectItem) -> None:
|
|
123
|
+
self._default_permissions.populate_default_permissions(item, Resource.Table)
|
|
124
|
+
|
|
112
125
|
@api(version="2.1")
|
|
113
|
-
def update_workbook_default_permissions(
|
|
126
|
+
def update_workbook_default_permissions(
|
|
127
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
128
|
+
) -> list[PermissionsRule]:
|
|
114
129
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Workbook)
|
|
115
130
|
|
|
116
131
|
@api(version="2.1")
|
|
117
|
-
def update_datasource_default_permissions(
|
|
132
|
+
def update_datasource_default_permissions(
|
|
133
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
134
|
+
) -> list[PermissionsRule]:
|
|
118
135
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Datasource)
|
|
119
136
|
|
|
120
137
|
@api(version="3.2")
|
|
121
|
-
def update_metric_default_permissions(
|
|
138
|
+
def update_metric_default_permissions(
|
|
139
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
140
|
+
) -> list[PermissionsRule]:
|
|
122
141
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Metric)
|
|
123
142
|
|
|
124
143
|
@api(version="3.4")
|
|
125
|
-
def update_datarole_default_permissions(
|
|
144
|
+
def update_datarole_default_permissions(
|
|
145
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
146
|
+
) -> list[PermissionsRule]:
|
|
126
147
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Datarole)
|
|
127
148
|
|
|
128
149
|
@api(version="3.4")
|
|
129
|
-
def update_flow_default_permissions(self, item, rules):
|
|
150
|
+
def update_flow_default_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
|
|
130
151
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Flow)
|
|
131
152
|
|
|
132
153
|
@api(version="3.4")
|
|
133
|
-
def update_lens_default_permissions(self, item, rules):
|
|
154
|
+
def update_lens_default_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
|
|
134
155
|
return self._default_permissions.update_default_permissions(item, rules, Resource.Lens)
|
|
135
156
|
|
|
157
|
+
@api(version="3.23")
|
|
158
|
+
def update_virtualconnection_default_permissions(
|
|
159
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
160
|
+
) -> list[PermissionsRule]:
|
|
161
|
+
return self._default_permissions.update_default_permissions(item, rules, Resource.VirtualConnection)
|
|
162
|
+
|
|
163
|
+
@api(version="3.23")
|
|
164
|
+
def update_database_default_permissions(
|
|
165
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
166
|
+
) -> list[PermissionsRule]:
|
|
167
|
+
return self._default_permissions.update_default_permissions(item, rules, Resource.Database)
|
|
168
|
+
|
|
169
|
+
@api(version="3.23")
|
|
170
|
+
def update_table_default_permissions(
|
|
171
|
+
self, item: ProjectItem, rules: list[PermissionsRule]
|
|
172
|
+
) -> list[PermissionsRule]:
|
|
173
|
+
return self._default_permissions.update_default_permissions(item, rules, Resource.Table)
|
|
174
|
+
|
|
136
175
|
@api(version="2.1")
|
|
137
|
-
def delete_workbook_default_permissions(self, item, rule):
|
|
176
|
+
def delete_workbook_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
138
177
|
self._default_permissions.delete_default_permission(item, rule, Resource.Workbook)
|
|
139
178
|
|
|
140
179
|
@api(version="2.1")
|
|
141
|
-
def delete_datasource_default_permissions(self, item, rule):
|
|
180
|
+
def delete_datasource_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
142
181
|
self._default_permissions.delete_default_permission(item, rule, Resource.Datasource)
|
|
143
182
|
|
|
144
183
|
@api(version="3.2")
|
|
145
|
-
def delete_metric_default_permissions(self, item, rule):
|
|
184
|
+
def delete_metric_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
146
185
|
self._default_permissions.delete_default_permission(item, rule, Resource.Metric)
|
|
147
186
|
|
|
148
187
|
@api(version="3.4")
|
|
149
|
-
def delete_datarole_default_permissions(self, item, rule):
|
|
188
|
+
def delete_datarole_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
150
189
|
self._default_permissions.delete_default_permission(item, rule, Resource.Datarole)
|
|
151
190
|
|
|
152
191
|
@api(version="3.4")
|
|
153
|
-
def delete_flow_default_permissions(self, item, rule):
|
|
192
|
+
def delete_flow_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
154
193
|
self._default_permissions.delete_default_permission(item, rule, Resource.Flow)
|
|
155
194
|
|
|
156
195
|
@api(version="3.4")
|
|
157
|
-
def delete_lens_default_permissions(self, item, rule):
|
|
196
|
+
def delete_lens_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
158
197
|
self._default_permissions.delete_default_permission(item, rule, Resource.Lens)
|
|
159
198
|
|
|
199
|
+
@api(version="3.23")
|
|
200
|
+
def delete_virtualconnection_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
201
|
+
self._default_permissions.delete_default_permission(item, rule, Resource.VirtualConnection)
|
|
202
|
+
|
|
203
|
+
@api(version="3.23")
|
|
204
|
+
def delete_database_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
205
|
+
self._default_permissions.delete_default_permission(item, rule, Resource.Database)
|
|
206
|
+
|
|
207
|
+
@api(version="3.23")
|
|
208
|
+
def delete_table_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
|
|
209
|
+
self._default_permissions.delete_default_permission(item, rule, Resource.Table)
|
|
210
|
+
|
|
160
211
|
def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> QuerySet[ProjectItem]:
|
|
161
212
|
"""
|
|
162
213
|
Queries the Tableau Server for items using the specified filters. Page
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import copy
|
|
3
|
-
from typing import Generic,
|
|
3
|
+
from typing import Generic, Optional, Protocol, TypeVar, Union, TYPE_CHECKING, runtime_checkable
|
|
4
|
+
from collections.abc import Iterable
|
|
4
5
|
import urllib.parse
|
|
5
6
|
|
|
6
7
|
from tableauserverclient.server.endpoint.endpoint import Endpoint, api
|
|
@@ -24,7 +25,7 @@ if TYPE_CHECKING:
|
|
|
24
25
|
class _ResourceTagger(Endpoint):
|
|
25
26
|
# Add new tags to resource
|
|
26
27
|
def _add_tags(self, baseurl, resource_id, tag_set):
|
|
27
|
-
url = "{
|
|
28
|
+
url = f"{baseurl}/{resource_id}/tags"
|
|
28
29
|
add_req = RequestFactory.Tag.add_req(tag_set)
|
|
29
30
|
|
|
30
31
|
try:
|
|
@@ -39,7 +40,7 @@ class _ResourceTagger(Endpoint):
|
|
|
39
40
|
# Delete a resource's tag by name
|
|
40
41
|
def _delete_tag(self, baseurl, resource_id, tag_name):
|
|
41
42
|
encoded_tag_name = urllib.parse.quote(tag_name)
|
|
42
|
-
url = "{
|
|
43
|
+
url = f"{baseurl}/{resource_id}/tags/{encoded_tag_name}"
|
|
43
44
|
|
|
44
45
|
try:
|
|
45
46
|
self.delete_request(url)
|
|
@@ -59,7 +60,7 @@ class _ResourceTagger(Endpoint):
|
|
|
59
60
|
if add_set:
|
|
60
61
|
resource_item.tags = self._add_tags(baseurl, resource_item.id, add_set)
|
|
61
62
|
resource_item._initial_tags = copy.copy(resource_item.tags)
|
|
62
|
-
logger.info("Updated tags to {
|
|
63
|
+
logger.info(f"Updated tags to {resource_item.tags}")
|
|
63
64
|
|
|
64
65
|
|
|
65
66
|
class Response(Protocol):
|
|
@@ -68,8 +69,8 @@ class Response(Protocol):
|
|
|
68
69
|
|
|
69
70
|
@runtime_checkable
|
|
70
71
|
class Taggable(Protocol):
|
|
71
|
-
tags:
|
|
72
|
-
_initial_tags:
|
|
72
|
+
tags: set[str]
|
|
73
|
+
_initial_tags: set[str]
|
|
73
74
|
|
|
74
75
|
@property
|
|
75
76
|
def id(self) -> Optional[str]:
|
|
@@ -95,14 +96,14 @@ class TaggingMixin(abc.ABC, Generic[T]):
|
|
|
95
96
|
def delete_request(self, url) -> None:
|
|
96
97
|
pass
|
|
97
98
|
|
|
98
|
-
def add_tags(self, item: Union[T, str], tags: Union[Iterable[str], str]) ->
|
|
99
|
+
def add_tags(self, item: Union[T, str], tags: Union[Iterable[str], str]) -> set[str]:
|
|
99
100
|
item_id = getattr(item, "id", item)
|
|
100
101
|
|
|
101
102
|
if not isinstance(item_id, str):
|
|
102
103
|
raise ValueError("ID not found.")
|
|
103
104
|
|
|
104
105
|
if isinstance(tags, str):
|
|
105
|
-
tag_set =
|
|
106
|
+
tag_set = {tags}
|
|
106
107
|
else:
|
|
107
108
|
tag_set = set(tags)
|
|
108
109
|
|
|
@@ -118,7 +119,7 @@ class TaggingMixin(abc.ABC, Generic[T]):
|
|
|
118
119
|
raise ValueError("ID not found.")
|
|
119
120
|
|
|
120
121
|
if isinstance(tags, str):
|
|
121
|
-
tag_set =
|
|
122
|
+
tag_set = {tags}
|
|
122
123
|
else:
|
|
123
124
|
tag_set = set(tags)
|
|
124
125
|
|
|
@@ -158,9 +159,9 @@ class Tags(Endpoint):
|
|
|
158
159
|
return f"{self.parent_srv.baseurl}/tags"
|
|
159
160
|
|
|
160
161
|
@api(version="3.9")
|
|
161
|
-
def batch_add(self, tags: Union[Iterable[str], str], content: content) ->
|
|
162
|
+
def batch_add(self, tags: Union[Iterable[str], str], content: content) -> set[str]:
|
|
162
163
|
if isinstance(tags, str):
|
|
163
|
-
tag_set =
|
|
164
|
+
tag_set = {tags}
|
|
164
165
|
else:
|
|
165
166
|
tag_set = set(tags)
|
|
166
167
|
|
|
@@ -170,9 +171,9 @@ class Tags(Endpoint):
|
|
|
170
171
|
return TagItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
171
172
|
|
|
172
173
|
@api(version="3.9")
|
|
173
|
-
def batch_delete(self, tags: Union[Iterable[str], str], content: content) ->
|
|
174
|
+
def batch_delete(self, tags: Union[Iterable[str], str], content: content) -> set[str]:
|
|
174
175
|
if isinstance(tags, str):
|
|
175
|
-
tag_set =
|
|
176
|
+
tag_set = {tags}
|
|
176
177
|
else:
|
|
177
178
|
tag_set = set(tags)
|
|
178
179
|
|
|
@@ -2,7 +2,7 @@ import copy
|
|
|
2
2
|
import logging
|
|
3
3
|
import warnings
|
|
4
4
|
from collections import namedtuple
|
|
5
|
-
from typing import TYPE_CHECKING, Callable,
|
|
5
|
+
from typing import TYPE_CHECKING, Callable, Optional, Union
|
|
6
6
|
|
|
7
7
|
from .endpoint import Endpoint, api, parameter_added_in
|
|
8
8
|
from .exceptions import MissingRequiredFieldError
|
|
@@ -22,14 +22,14 @@ if TYPE_CHECKING:
|
|
|
22
22
|
class Schedules(Endpoint):
|
|
23
23
|
@property
|
|
24
24
|
def baseurl(self) -> str:
|
|
25
|
-
return "{
|
|
25
|
+
return f"{self.parent_srv.baseurl}/schedules"
|
|
26
26
|
|
|
27
27
|
@property
|
|
28
28
|
def siteurl(self) -> str:
|
|
29
|
-
return "{
|
|
29
|
+
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/schedules"
|
|
30
30
|
|
|
31
31
|
@api(version="2.3")
|
|
32
|
-
def get(self, req_options: Optional["RequestOptions"] = None) ->
|
|
32
|
+
def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[ScheduleItem], PaginationItem]:
|
|
33
33
|
logger.info("Querying all schedules")
|
|
34
34
|
url = self.baseurl
|
|
35
35
|
server_response = self.get_request(url, req_options)
|
|
@@ -42,8 +42,8 @@ class Schedules(Endpoint):
|
|
|
42
42
|
if not schedule_id:
|
|
43
43
|
error = "No Schedule ID provided"
|
|
44
44
|
raise ValueError(error)
|
|
45
|
-
logger.info("Querying a single schedule by id ({})"
|
|
46
|
-
url = "{
|
|
45
|
+
logger.info(f"Querying a single schedule by id ({schedule_id})")
|
|
46
|
+
url = f"{self.baseurl}/{schedule_id}"
|
|
47
47
|
server_response = self.get_request(url)
|
|
48
48
|
return ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
49
49
|
|
|
@@ -52,9 +52,9 @@ class Schedules(Endpoint):
|
|
|
52
52
|
if not schedule_id:
|
|
53
53
|
error = "Schedule ID undefined"
|
|
54
54
|
raise ValueError(error)
|
|
55
|
-
url = "{
|
|
55
|
+
url = f"{self.baseurl}/{schedule_id}"
|
|
56
56
|
self.delete_request(url)
|
|
57
|
-
logger.info("Deleted single schedule (ID: {
|
|
57
|
+
logger.info(f"Deleted single schedule (ID: {schedule_id})")
|
|
58
58
|
|
|
59
59
|
@api(version="2.3")
|
|
60
60
|
def update(self, schedule_item: ScheduleItem) -> ScheduleItem:
|
|
@@ -62,10 +62,10 @@ class Schedules(Endpoint):
|
|
|
62
62
|
error = "Schedule item missing ID."
|
|
63
63
|
raise MissingRequiredFieldError(error)
|
|
64
64
|
|
|
65
|
-
url = "{
|
|
65
|
+
url = f"{self.baseurl}/{schedule_item.id}"
|
|
66
66
|
update_req = RequestFactory.Schedule.update_req(schedule_item)
|
|
67
67
|
server_response = self.put_request(url, update_req)
|
|
68
|
-
logger.info("Updated schedule item (ID: {
|
|
68
|
+
logger.info(f"Updated schedule item (ID: {schedule_item.id})")
|
|
69
69
|
updated_schedule = copy.copy(schedule_item)
|
|
70
70
|
return updated_schedule._parse_common_tags(server_response.content, self.parent_srv.namespace)
|
|
71
71
|
|
|
@@ -79,7 +79,7 @@ class Schedules(Endpoint):
|
|
|
79
79
|
create_req = RequestFactory.Schedule.create_req(schedule_item)
|
|
80
80
|
server_response = self.post_request(url, create_req)
|
|
81
81
|
new_schedule = ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
82
|
-
logger.info("Created new schedule (ID: {
|
|
82
|
+
logger.info(f"Created new schedule (ID: {new_schedule.id})")
|
|
83
83
|
return new_schedule
|
|
84
84
|
|
|
85
85
|
@api(version="2.8")
|
|
@@ -91,12 +91,12 @@ class Schedules(Endpoint):
|
|
|
91
91
|
datasource: Optional["DatasourceItem"] = None,
|
|
92
92
|
flow: Optional["FlowItem"] = None,
|
|
93
93
|
task_type: Optional[str] = None,
|
|
94
|
-
) ->
|
|
94
|
+
) -> list[AddResponse]:
|
|
95
95
|
# There doesn't seem to be a good reason to allow one item of each type?
|
|
96
96
|
if workbook and datasource:
|
|
97
97
|
warnings.warn("Passing in multiple items for add_to_schedule will be deprecated", PendingDeprecationWarning)
|
|
98
|
-
items:
|
|
99
|
-
|
|
98
|
+
items: list[
|
|
99
|
+
tuple[str, Union[WorkbookItem, FlowItem, DatasourceItem], str, Callable[[Optional[str], str], bytes], str]
|
|
100
100
|
] = []
|
|
101
101
|
|
|
102
102
|
if workbook is not None:
|
|
@@ -115,8 +115,7 @@ class Schedules(Endpoint):
|
|
|
115
115
|
) # type:ignore[arg-type]
|
|
116
116
|
|
|
117
117
|
results = (self._add_to(*x) for x in items)
|
|
118
|
-
|
|
119
|
-
return list(filter(lambda x: not x.result, results)) # type:ignore[arg-type]
|
|
118
|
+
return [x for x in results if not x.result]
|
|
120
119
|
|
|
121
120
|
def _add_to(
|
|
122
121
|
self,
|
|
@@ -133,13 +132,13 @@ class Schedules(Endpoint):
|
|
|
133
132
|
item_task_type,
|
|
134
133
|
) -> AddResponse:
|
|
135
134
|
id_ = resource.id
|
|
136
|
-
url = "{
|
|
135
|
+
url = f"{self.siteurl}/{schedule_id}/{type_}s"
|
|
137
136
|
add_req = req_factory(id_, task_type=item_task_type) # type: ignore[call-arg, arg-type]
|
|
138
137
|
response = self.put_request(url, add_req)
|
|
139
138
|
|
|
140
139
|
error, warnings, task_created = ScheduleItem.parse_add_to_schedule_response(response, self.parent_srv.namespace)
|
|
141
140
|
if task_created:
|
|
142
|
-
logger.info("Added {} to {} to schedule {}"
|
|
141
|
+
logger.info(f"Added {type_} to {id_} to schedule {schedule_id}")
|
|
143
142
|
|
|
144
143
|
if error is not None or warnings is not None:
|
|
145
144
|
return AddResponse(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Union
|
|
2
3
|
|
|
3
4
|
from .endpoint import Endpoint, api
|
|
4
5
|
from .exceptions import ServerResponseError
|
|
@@ -21,15 +22,49 @@ class ServerInfo(Endpoint):
|
|
|
21
22
|
return self._info
|
|
22
23
|
|
|
23
24
|
def __repr__(self):
|
|
24
|
-
return "<Endpoint {}>"
|
|
25
|
+
return f"<Endpoint {self.serverInfo}>"
|
|
25
26
|
|
|
26
27
|
@property
|
|
27
|
-
def baseurl(self):
|
|
28
|
-
return "{
|
|
28
|
+
def baseurl(self) -> str:
|
|
29
|
+
return f"{self.parent_srv.baseurl}/serverInfo"
|
|
29
30
|
|
|
30
31
|
@api(version="2.4")
|
|
31
|
-
def get(self):
|
|
32
|
-
"""
|
|
32
|
+
def get(self) -> Union[ServerInfoItem, None]:
|
|
33
|
+
"""
|
|
34
|
+
Retrieve the build and version information for the server.
|
|
35
|
+
|
|
36
|
+
This method makes an unauthenticated call, so no sign in or
|
|
37
|
+
authentication token is required.
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
:class:`~tableauserverclient.models.ServerInfoItem`
|
|
42
|
+
|
|
43
|
+
Raises
|
|
44
|
+
------
|
|
45
|
+
:class:`~tableauserverclient.exceptions.ServerInfoEndpointNotFoundError`
|
|
46
|
+
Raised when the server info endpoint is not found.
|
|
47
|
+
|
|
48
|
+
:class:`~tableauserverclient.exceptions.EndpointUnavailableError`
|
|
49
|
+
Raised when the server info endpoint is not available.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> import tableauserverclient as TSC
|
|
54
|
+
|
|
55
|
+
>>> # create a instance of server
|
|
56
|
+
>>> server = TSC.Server('https://MY-SERVER')
|
|
57
|
+
|
|
58
|
+
>>> # set the version number > 2.3
|
|
59
|
+
>>> # the server_info.get() method works in 2.4 and later
|
|
60
|
+
>>> server.version = '2.5'
|
|
61
|
+
|
|
62
|
+
>>> s_info = server.server_info.get()
|
|
63
|
+
>>> print("\nServer info:")
|
|
64
|
+
>>> print("\tProduct version: {0}".format(s_info.product_version))
|
|
65
|
+
>>> print("\tREST API version: {0}".format(s_info.rest_api_version))
|
|
66
|
+
>>> print("\tBuild number: {0}".format(s_info.build_number))
|
|
67
|
+
"""
|
|
33
68
|
try:
|
|
34
69
|
server_response = self.get_unauthenticated_request(self.baseurl)
|
|
35
70
|
except ServerResponseError as e:
|