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.
- tableauserverclient/__init__.py +34 -18
- tableauserverclient/_version.py +3 -3
- tableauserverclient/config.py +20 -6
- tableauserverclient/models/__init__.py +12 -0
- tableauserverclient/models/column_item.py +1 -1
- tableauserverclient/models/connection_credentials.py +1 -1
- tableauserverclient/models/connection_item.py +10 -8
- 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 +8 -2
- 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 +12 -12
- tableauserverclient/models/flow_run_item.py +3 -3
- tableauserverclient/models/group_item.py +4 -4
- tableauserverclient/models/groupset_item.py +53 -0
- tableauserverclient/models/interval_item.py +36 -23
- tableauserverclient/models/job_item.py +26 -10
- tableauserverclient/models/linked_tasks_item.py +102 -0
- tableauserverclient/models/metric_item.py +5 -5
- tableauserverclient/models/pagination_item.py +1 -1
- tableauserverclient/models/permissions_item.py +19 -14
- 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 +11 -9
- 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 +78 -0
- 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/__init__.py +8 -0
- tableauserverclient/server/endpoint/auth_endpoint.py +68 -11
- tableauserverclient/server/endpoint/custom_views_endpoint.py +124 -19
- 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 +32 -17
- tableauserverclient/server/endpoint/datasources_endpoint.py +150 -59
- tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
- tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
- tableauserverclient/server/endpoint/endpoint.py +47 -31
- tableauserverclient/server/endpoint/exceptions.py +23 -7
- tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
- tableauserverclient/server/endpoint/fileuploads_endpoint.py +11 -13
- tableauserverclient/server/endpoint/flow_runs_endpoint.py +59 -17
- tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
- tableauserverclient/server/endpoint/flows_endpoint.py +73 -35
- tableauserverclient/server/endpoint/groups_endpoint.py +96 -27
- tableauserverclient/server/endpoint/groupsets_endpoint.py +127 -0
- tableauserverclient/server/endpoint/jobs_endpoint.py +79 -12
- tableauserverclient/server/endpoint/linked_tasks_endpoint.py +45 -0
- 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 +124 -30
- tableauserverclient/server/endpoint/resource_tagger.py +139 -6
- 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 +33 -19
- tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
- tableauserverclient/server/endpoint/users_endpoint.py +405 -19
- tableauserverclient/server/endpoint/views_endpoint.py +111 -25
- tableauserverclient/server/endpoint/virtual_connections_endpoint.py +174 -0
- tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
- tableauserverclient/server/endpoint/workbooks_endpoint.py +735 -68
- tableauserverclient/server/filter.py +2 -2
- tableauserverclient/server/pager.py +8 -10
- tableauserverclient/server/query.py +70 -20
- tableauserverclient/server/request_factory.py +213 -41
- tableauserverclient/server/request_options.py +125 -145
- tableauserverclient/server/server.py +73 -9
- tableauserverclient/server/sort.py +2 -2
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/METADATA +17 -17
- tableauserverclient-0.34.dist-info/RECORD +106 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
- tableauserverclient-0.32.dist-info/RECORD +0 -100
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Callable, Optional, TypeVar, TYPE_CHECKING, Union
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from typing_extensions import ParamSpec
|
|
3
6
|
|
|
4
7
|
from requests.packages.urllib3.fields import RequestField
|
|
5
8
|
from requests.packages.urllib3.filepost import encode_multipart_formdata
|
|
9
|
+
from typing_extensions import Concatenate
|
|
6
10
|
|
|
7
11
|
from tableauserverclient.models import *
|
|
8
12
|
|
|
@@ -12,7 +16,7 @@ if TYPE_CHECKING:
|
|
|
12
16
|
# this file could be largely replaced if we were willing to import the huge file from generateDS
|
|
13
17
|
|
|
14
18
|
|
|
15
|
-
def _add_multipart(parts:
|
|
19
|
+
def _add_multipart(parts: dict) -> tuple[Any, str]:
|
|
16
20
|
mime_multipart_parts = list()
|
|
17
21
|
for name, (filename, data, content_type) in parts.items():
|
|
18
22
|
multipart_part = RequestField(name=name, data=data, filename=filename)
|
|
@@ -23,8 +27,12 @@ def _add_multipart(parts: Dict) -> Tuple[Any, str]:
|
|
|
23
27
|
return xml_request, content_type
|
|
24
28
|
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
T = TypeVar("T")
|
|
31
|
+
P = ParamSpec("P")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _tsrequest_wrapped(func: Callable[Concatenate[T, ET.Element, P], Any]) -> Callable[Concatenate[T, P], bytes]:
|
|
35
|
+
def wrapper(self: T, *args: P.args, **kwargs: P.kwargs) -> bytes:
|
|
28
36
|
xml_request = ET.Element("tsRequest")
|
|
29
37
|
func(self, xml_request, *args, **kwargs)
|
|
30
38
|
return ET.tostring(xml_request)
|
|
@@ -73,7 +81,7 @@ def _add_credentials_element(parent_element, connection_credentials):
|
|
|
73
81
|
credentials_element.attrib["oAuth"] = "true"
|
|
74
82
|
|
|
75
83
|
|
|
76
|
-
class AuthRequest
|
|
84
|
+
class AuthRequest:
|
|
77
85
|
def signin_req(self, auth_item):
|
|
78
86
|
xml_request = ET.Element("tsRequest")
|
|
79
87
|
|
|
@@ -97,7 +105,7 @@ class AuthRequest(object):
|
|
|
97
105
|
return ET.tostring(xml_request)
|
|
98
106
|
|
|
99
107
|
|
|
100
|
-
class ColumnRequest
|
|
108
|
+
class ColumnRequest:
|
|
101
109
|
def update_req(self, column_item):
|
|
102
110
|
xml_request = ET.Element("tsRequest")
|
|
103
111
|
column_element = ET.SubElement(xml_request, "column")
|
|
@@ -108,7 +116,7 @@ class ColumnRequest(object):
|
|
|
108
116
|
return ET.tostring(xml_request)
|
|
109
117
|
|
|
110
118
|
|
|
111
|
-
class DataAlertRequest
|
|
119
|
+
class DataAlertRequest:
|
|
112
120
|
def add_user_to_alert(self, alert_item: "DataAlertItem", user_id: str) -> bytes:
|
|
113
121
|
xml_request = ET.Element("tsRequest")
|
|
114
122
|
user_element = ET.SubElement(xml_request, "user")
|
|
@@ -133,7 +141,7 @@ class DataAlertRequest(object):
|
|
|
133
141
|
return ET.tostring(xml_request)
|
|
134
142
|
|
|
135
143
|
|
|
136
|
-
class DatabaseRequest
|
|
144
|
+
class DatabaseRequest:
|
|
137
145
|
def update_req(self, database_item):
|
|
138
146
|
xml_request = ET.Element("tsRequest")
|
|
139
147
|
database_element = ET.SubElement(xml_request, "database")
|
|
@@ -152,7 +160,7 @@ class DatabaseRequest(object):
|
|
|
152
160
|
return ET.tostring(xml_request)
|
|
153
161
|
|
|
154
162
|
|
|
155
|
-
class DatasourceRequest
|
|
163
|
+
class DatasourceRequest:
|
|
156
164
|
def _generate_xml(self, datasource_item: DatasourceItem, connection_credentials=None, connections=None):
|
|
157
165
|
xml_request = ET.Element("tsRequest")
|
|
158
166
|
datasource_element = ET.SubElement(xml_request, "datasource")
|
|
@@ -237,7 +245,7 @@ class DatasourceRequest(object):
|
|
|
237
245
|
return _add_multipart(parts)
|
|
238
246
|
|
|
239
247
|
|
|
240
|
-
class DQWRequest
|
|
248
|
+
class DQWRequest:
|
|
241
249
|
def add_req(self, dqw_item):
|
|
242
250
|
xml_request = ET.Element("tsRequest")
|
|
243
251
|
dqw_element = ET.SubElement(xml_request, "dataQualityWarning")
|
|
@@ -267,7 +275,7 @@ class DQWRequest(object):
|
|
|
267
275
|
return ET.tostring(xml_request)
|
|
268
276
|
|
|
269
277
|
|
|
270
|
-
class FavoriteRequest
|
|
278
|
+
class FavoriteRequest:
|
|
271
279
|
def add_request(self, id_: Optional[str], target_type: str, label: Optional[str]) -> bytes:
|
|
272
280
|
"""
|
|
273
281
|
<favorite label="...">
|
|
@@ -322,7 +330,7 @@ class FavoriteRequest(object):
|
|
|
322
330
|
return self.add_request(id_, Resource.Workbook, name)
|
|
323
331
|
|
|
324
332
|
|
|
325
|
-
class FileuploadRequest
|
|
333
|
+
class FileuploadRequest:
|
|
326
334
|
def chunk_req(self, chunk):
|
|
327
335
|
parts = {
|
|
328
336
|
"request_payload": ("", "", "text/xml"),
|
|
@@ -331,8 +339,8 @@ class FileuploadRequest(object):
|
|
|
331
339
|
return _add_multipart(parts)
|
|
332
340
|
|
|
333
341
|
|
|
334
|
-
class FlowRequest
|
|
335
|
-
def _generate_xml(self, flow_item: "FlowItem", connections: Optional[
|
|
342
|
+
class FlowRequest:
|
|
343
|
+
def _generate_xml(self, flow_item: "FlowItem", connections: Optional[list["ConnectionItem"]] = None) -> bytes:
|
|
336
344
|
xml_request = ET.Element("tsRequest")
|
|
337
345
|
flow_element = ET.SubElement(xml_request, "flow")
|
|
338
346
|
if flow_item.name is not None:
|
|
@@ -363,8 +371,8 @@ class FlowRequest(object):
|
|
|
363
371
|
flow_item: "FlowItem",
|
|
364
372
|
filename: str,
|
|
365
373
|
file_contents: bytes,
|
|
366
|
-
connections: Optional[
|
|
367
|
-
) ->
|
|
374
|
+
connections: Optional[list["ConnectionItem"]] = None,
|
|
375
|
+
) -> tuple[Any, str]:
|
|
368
376
|
xml_request = self._generate_xml(flow_item, connections)
|
|
369
377
|
|
|
370
378
|
parts = {
|
|
@@ -373,20 +381,42 @@ class FlowRequest(object):
|
|
|
373
381
|
}
|
|
374
382
|
return _add_multipart(parts)
|
|
375
383
|
|
|
376
|
-
def publish_req_chunked(self, flow_item, connections=None) ->
|
|
384
|
+
def publish_req_chunked(self, flow_item, connections=None) -> tuple[Any, str]:
|
|
377
385
|
xml_request = self._generate_xml(flow_item, connections)
|
|
378
386
|
|
|
379
387
|
parts = {"request_payload": ("", xml_request, "text/xml")}
|
|
380
388
|
return _add_multipart(parts)
|
|
381
389
|
|
|
382
390
|
|
|
383
|
-
class GroupRequest
|
|
391
|
+
class GroupRequest:
|
|
384
392
|
def add_user_req(self, user_id: str) -> bytes:
|
|
385
393
|
xml_request = ET.Element("tsRequest")
|
|
386
394
|
user_element = ET.SubElement(xml_request, "user")
|
|
387
395
|
user_element.attrib["id"] = user_id
|
|
388
396
|
return ET.tostring(xml_request)
|
|
389
397
|
|
|
398
|
+
@_tsrequest_wrapped
|
|
399
|
+
def add_users_req(self, xml_request: ET.Element, users: Iterable[Union[str, UserItem]]) -> bytes:
|
|
400
|
+
users_element = ET.SubElement(xml_request, "users")
|
|
401
|
+
for user in users:
|
|
402
|
+
user_element = ET.SubElement(users_element, "user")
|
|
403
|
+
if not (user_id := user.id if isinstance(user, UserItem) else user):
|
|
404
|
+
raise ValueError("User ID must be populated")
|
|
405
|
+
user_element.attrib["id"] = user_id
|
|
406
|
+
|
|
407
|
+
return ET.tostring(xml_request)
|
|
408
|
+
|
|
409
|
+
@_tsrequest_wrapped
|
|
410
|
+
def remove_users_req(self, xml_request: ET.Element, users: Iterable[Union[str, UserItem]]) -> bytes:
|
|
411
|
+
users_element = ET.SubElement(xml_request, "users")
|
|
412
|
+
for user in users:
|
|
413
|
+
user_element = ET.SubElement(users_element, "user")
|
|
414
|
+
if not (user_id := user.id if isinstance(user, UserItem) else user):
|
|
415
|
+
raise ValueError("User ID must be populated")
|
|
416
|
+
user_element.attrib["id"] = user_id
|
|
417
|
+
|
|
418
|
+
return ET.tostring(xml_request)
|
|
419
|
+
|
|
390
420
|
def create_local_req(self, group_item: GroupItem) -> bytes:
|
|
391
421
|
xml_request = ET.Element("tsRequest")
|
|
392
422
|
group_element = ET.SubElement(xml_request, "group")
|
|
@@ -448,7 +478,7 @@ class GroupRequest(object):
|
|
|
448
478
|
return ET.tostring(xml_request)
|
|
449
479
|
|
|
450
480
|
|
|
451
|
-
class PermissionRequest
|
|
481
|
+
class PermissionRequest:
|
|
452
482
|
def add_req(self, rules: Iterable[PermissionsRule]) -> bytes:
|
|
453
483
|
xml_request = ET.Element("tsRequest")
|
|
454
484
|
permissions_element = ET.SubElement(xml_request, "permissions")
|
|
@@ -470,7 +500,7 @@ class PermissionRequest(object):
|
|
|
470
500
|
capability_element.attrib["mode"] = mode
|
|
471
501
|
|
|
472
502
|
|
|
473
|
-
class ProjectRequest
|
|
503
|
+
class ProjectRequest:
|
|
474
504
|
def update_req(self, project_item: "ProjectItem") -> bytes:
|
|
475
505
|
xml_request = ET.Element("tsRequest")
|
|
476
506
|
project_element = ET.SubElement(xml_request, "project")
|
|
@@ -501,7 +531,7 @@ class ProjectRequest(object):
|
|
|
501
531
|
return ET.tostring(xml_request)
|
|
502
532
|
|
|
503
533
|
|
|
504
|
-
class ScheduleRequest
|
|
534
|
+
class ScheduleRequest:
|
|
505
535
|
def create_req(self, schedule_item):
|
|
506
536
|
xml_request = ET.Element("tsRequest")
|
|
507
537
|
schedule_element = ET.SubElement(xml_request, "schedule")
|
|
@@ -580,7 +610,7 @@ class ScheduleRequest(object):
|
|
|
580
610
|
return self._add_to_req(id_, "flow", task_type)
|
|
581
611
|
|
|
582
612
|
|
|
583
|
-
class SiteRequest
|
|
613
|
+
class SiteRequest:
|
|
584
614
|
def update_req(self, site_item: "SiteItem", parent_srv: Optional["Server"] = None):
|
|
585
615
|
xml_request = ET.Element("tsRequest")
|
|
586
616
|
site_element = ET.SubElement(xml_request, "site")
|
|
@@ -819,7 +849,7 @@ class SiteRequest(object):
|
|
|
819
849
|
warnings.warn("In version 3.10 and earlier there is only one option: FlowsEnabled")
|
|
820
850
|
|
|
821
851
|
|
|
822
|
-
class TableRequest
|
|
852
|
+
class TableRequest:
|
|
823
853
|
def update_req(self, table_item):
|
|
824
854
|
xml_request = ET.Element("tsRequest")
|
|
825
855
|
table_element = ET.SubElement(xml_request, "table")
|
|
@@ -839,7 +869,10 @@ class TableRequest(object):
|
|
|
839
869
|
return ET.tostring(xml_request)
|
|
840
870
|
|
|
841
871
|
|
|
842
|
-
|
|
872
|
+
content_types = Iterable[Union["ColumnItem", "DatabaseItem", "DatasourceItem", "FlowItem", "TableItem", "WorkbookItem"]]
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
class TagRequest:
|
|
843
876
|
def add_req(self, tag_set):
|
|
844
877
|
xml_request = ET.Element("tsRequest")
|
|
845
878
|
tags_element = ET.SubElement(xml_request, "tags")
|
|
@@ -848,8 +881,24 @@ class TagRequest(object):
|
|
|
848
881
|
tag_element.attrib["label"] = tag
|
|
849
882
|
return ET.tostring(xml_request)
|
|
850
883
|
|
|
884
|
+
@_tsrequest_wrapped
|
|
885
|
+
def batch_create(self, element: ET.Element, tags: set[str], content: content_types) -> bytes:
|
|
886
|
+
tag_batch = ET.SubElement(element, "tagBatch")
|
|
887
|
+
tags_element = ET.SubElement(tag_batch, "tags")
|
|
888
|
+
for tag in tags:
|
|
889
|
+
tag_element = ET.SubElement(tags_element, "tag")
|
|
890
|
+
tag_element.attrib["label"] = tag
|
|
891
|
+
contents_element = ET.SubElement(tag_batch, "contents")
|
|
892
|
+
for item in content:
|
|
893
|
+
content_element = ET.SubElement(contents_element, "content")
|
|
894
|
+
if item.id is None:
|
|
895
|
+
raise ValueError(f"Item {item} must have an ID to be tagged.")
|
|
896
|
+
content_element.attrib["id"] = item.id
|
|
897
|
+
|
|
898
|
+
return ET.tostring(element)
|
|
851
899
|
|
|
852
|
-
|
|
900
|
+
|
|
901
|
+
class UserRequest:
|
|
853
902
|
def update_req(self, user_item: UserItem, password: Optional[str]) -> bytes:
|
|
854
903
|
xml_request = ET.Element("tsRequest")
|
|
855
904
|
user_element = ET.SubElement(xml_request, "user")
|
|
@@ -883,7 +932,7 @@ class UserRequest(object):
|
|
|
883
932
|
return ET.tostring(xml_request)
|
|
884
933
|
|
|
885
934
|
|
|
886
|
-
class WorkbookRequest
|
|
935
|
+
class WorkbookRequest:
|
|
887
936
|
def _generate_xml(
|
|
888
937
|
self,
|
|
889
938
|
workbook_item,
|
|
@@ -947,9 +996,9 @@ class WorkbookRequest(object):
|
|
|
947
996
|
if data_freshness_policy_config.option == "FreshEvery":
|
|
948
997
|
if data_freshness_policy_config.fresh_every_schedule is not None:
|
|
949
998
|
fresh_every_element = ET.SubElement(data_freshness_policy_element, "freshEverySchedule")
|
|
950
|
-
fresh_every_element.attrib[
|
|
951
|
-
|
|
952
|
-
|
|
999
|
+
fresh_every_element.attrib["frequency"] = (
|
|
1000
|
+
data_freshness_policy_config.fresh_every_schedule.frequency
|
|
1001
|
+
)
|
|
953
1002
|
fresh_every_element.attrib["value"] = str(data_freshness_policy_config.fresh_every_schedule.value)
|
|
954
1003
|
else:
|
|
955
1004
|
raise ValueError(f"data_freshness_policy_config.fresh_every_schedule must be populated.")
|
|
@@ -1014,17 +1063,20 @@ class WorkbookRequest(object):
|
|
|
1014
1063
|
return _add_multipart(parts)
|
|
1015
1064
|
|
|
1016
1065
|
@_tsrequest_wrapped
|
|
1017
|
-
def embedded_extract_req(
|
|
1066
|
+
def embedded_extract_req(
|
|
1067
|
+
self, xml_request: ET.Element, include_all: bool = True, datasources: Optional[Iterable[DatasourceItem]] = None
|
|
1068
|
+
) -> None:
|
|
1018
1069
|
list_element = ET.SubElement(xml_request, "datasources")
|
|
1019
1070
|
if include_all:
|
|
1020
1071
|
list_element.attrib["includeAll"] = "true"
|
|
1021
1072
|
elif datasources:
|
|
1022
1073
|
for datasource_item in datasources:
|
|
1023
1074
|
datasource_element = ET.SubElement(list_element, "datasource")
|
|
1024
|
-
|
|
1075
|
+
if (id_ := datasource_item.id) is not None:
|
|
1076
|
+
datasource_element.attrib["id"] = id_
|
|
1025
1077
|
|
|
1026
1078
|
|
|
1027
|
-
class Connection
|
|
1079
|
+
class Connection:
|
|
1028
1080
|
@_tsrequest_wrapped
|
|
1029
1081
|
def update_req(self, xml_request: ET.Element, connection_item: "ConnectionItem") -> None:
|
|
1030
1082
|
connection_element = ET.SubElement(xml_request, "connection")
|
|
@@ -1047,9 +1099,9 @@ class Connection(object):
|
|
|
1047
1099
|
connection_element.attrib["queryTaggingEnabled"] = str(connection_item.query_tagging).lower()
|
|
1048
1100
|
|
|
1049
1101
|
|
|
1050
|
-
class TaskRequest
|
|
1102
|
+
class TaskRequest:
|
|
1051
1103
|
@_tsrequest_wrapped
|
|
1052
|
-
def run_req(self, xml_request, task_item):
|
|
1104
|
+
def run_req(self, xml_request: ET.Element, task_item: Any) -> None:
|
|
1053
1105
|
# Send an empty tsRequest
|
|
1054
1106
|
pass
|
|
1055
1107
|
|
|
@@ -1086,7 +1138,7 @@ class TaskRequest(object):
|
|
|
1086
1138
|
return ET.tostring(xml_request)
|
|
1087
1139
|
|
|
1088
1140
|
|
|
1089
|
-
class FlowTaskRequest
|
|
1141
|
+
class FlowTaskRequest:
|
|
1090
1142
|
@_tsrequest_wrapped
|
|
1091
1143
|
def create_flow_task_req(self, xml_request: ET.Element, flow_item: "TaskItem") -> bytes:
|
|
1092
1144
|
flow_element = ET.SubElement(xml_request, "runFlow")
|
|
@@ -1120,7 +1172,7 @@ class FlowTaskRequest(object):
|
|
|
1120
1172
|
return ET.tostring(xml_request)
|
|
1121
1173
|
|
|
1122
1174
|
|
|
1123
|
-
class SubscriptionRequest
|
|
1175
|
+
class SubscriptionRequest:
|
|
1124
1176
|
@_tsrequest_wrapped
|
|
1125
1177
|
def create_req(self, xml_request: ET.Element, subscription_item: "SubscriptionItem") -> bytes:
|
|
1126
1178
|
subscription_element = ET.SubElement(xml_request, "subscription")
|
|
@@ -1184,13 +1236,13 @@ class SubscriptionRequest(object):
|
|
|
1184
1236
|
return ET.tostring(xml_request)
|
|
1185
1237
|
|
|
1186
1238
|
|
|
1187
|
-
class EmptyRequest
|
|
1239
|
+
class EmptyRequest:
|
|
1188
1240
|
@_tsrequest_wrapped
|
|
1189
|
-
def empty_req(self, xml_request):
|
|
1241
|
+
def empty_req(self, xml_request: ET.Element) -> None:
|
|
1190
1242
|
pass
|
|
1191
1243
|
|
|
1192
1244
|
|
|
1193
|
-
class WebhookRequest
|
|
1245
|
+
class WebhookRequest:
|
|
1194
1246
|
@_tsrequest_wrapped
|
|
1195
1247
|
def create_req(self, xml_request: ET.Element, webhook_item: "WebhookItem") -> bytes:
|
|
1196
1248
|
webhook = ET.SubElement(xml_request, "webhook")
|
|
@@ -1236,7 +1288,7 @@ class MetricRequest:
|
|
|
1236
1288
|
return ET.tostring(xml_request)
|
|
1237
1289
|
|
|
1238
1290
|
|
|
1239
|
-
class CustomViewRequest
|
|
1291
|
+
class CustomViewRequest:
|
|
1240
1292
|
@_tsrequest_wrapped
|
|
1241
1293
|
def update_req(self, xml_request: ET.Element, custom_view_item: CustomViewItem):
|
|
1242
1294
|
updating_element = ET.SubElement(xml_request, "customView")
|
|
@@ -1245,8 +1297,126 @@ class CustomViewRequest(object):
|
|
|
1245
1297
|
if custom_view_item.name is not None:
|
|
1246
1298
|
updating_element.attrib["name"] = custom_view_item.name
|
|
1247
1299
|
|
|
1300
|
+
@_tsrequest_wrapped
|
|
1301
|
+
def _publish_xml(self, xml_request: ET.Element, custom_view_item: CustomViewItem) -> bytes:
|
|
1302
|
+
custom_view_element = ET.SubElement(xml_request, "customView")
|
|
1303
|
+
if (name := custom_view_item.name) is not None:
|
|
1304
|
+
custom_view_element.attrib["name"] = name
|
|
1305
|
+
else:
|
|
1306
|
+
raise ValueError(f"Custom View Item missing name: {custom_view_item}")
|
|
1307
|
+
if (shared := custom_view_item.shared) is not None:
|
|
1308
|
+
custom_view_element.attrib["shared"] = str(shared).lower()
|
|
1309
|
+
else:
|
|
1310
|
+
raise ValueError(f"Custom View Item missing shared: {custom_view_item}")
|
|
1311
|
+
if (owner := custom_view_item.owner) is not None:
|
|
1312
|
+
owner_element = ET.SubElement(custom_view_element, "owner")
|
|
1313
|
+
if (owner_id := owner.id) is not None:
|
|
1314
|
+
owner_element.attrib["id"] = owner_id
|
|
1315
|
+
else:
|
|
1316
|
+
raise ValueError(f"Custom View Item owner missing id: {owner}")
|
|
1317
|
+
else:
|
|
1318
|
+
raise ValueError(f"Custom View Item missing owner: {custom_view_item}")
|
|
1319
|
+
if (workbook := custom_view_item.workbook) is not None:
|
|
1320
|
+
workbook_element = ET.SubElement(custom_view_element, "workbook")
|
|
1321
|
+
if (workbook_id := workbook.id) is not None:
|
|
1322
|
+
workbook_element.attrib["id"] = workbook_id
|
|
1323
|
+
else:
|
|
1324
|
+
raise ValueError(f"Custom View Item workbook missing id: {workbook}")
|
|
1325
|
+
else:
|
|
1326
|
+
raise ValueError(f"Custom View Item missing workbook: {custom_view_item}")
|
|
1327
|
+
|
|
1328
|
+
return ET.tostring(xml_request)
|
|
1329
|
+
|
|
1330
|
+
def publish_req_chunked(self, custom_view_item: CustomViewItem):
|
|
1331
|
+
xml_request = self._publish_xml(custom_view_item)
|
|
1332
|
+
parts = {"request_payload": ("", xml_request, "text/xml")}
|
|
1333
|
+
return _add_multipart(parts)
|
|
1334
|
+
|
|
1335
|
+
def publish_req(self, custom_view_item: CustomViewItem, filename: str, file_contents: bytes):
|
|
1336
|
+
xml_request = self._publish_xml(custom_view_item)
|
|
1337
|
+
parts = {
|
|
1338
|
+
"request_payload": ("", xml_request, "text/xml"),
|
|
1339
|
+
"tableau_customview": (filename, file_contents, "application/octet-stream"),
|
|
1340
|
+
}
|
|
1341
|
+
return _add_multipart(parts)
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
class GroupSetRequest:
|
|
1345
|
+
@_tsrequest_wrapped
|
|
1346
|
+
def create_request(self, xml_request: ET.Element, group_set_item: "GroupSetItem") -> bytes:
|
|
1347
|
+
group_set_element = ET.SubElement(xml_request, "groupSet")
|
|
1348
|
+
if group_set_item.name is not None:
|
|
1349
|
+
group_set_element.attrib["name"] = group_set_item.name
|
|
1350
|
+
return ET.tostring(xml_request)
|
|
1351
|
+
|
|
1352
|
+
@_tsrequest_wrapped
|
|
1353
|
+
def update_request(self, xml_request: ET.Element, group_set_item: "GroupSetItem") -> bytes:
|
|
1354
|
+
group_set_element = ET.SubElement(xml_request, "groupSet")
|
|
1355
|
+
if group_set_item.name is not None:
|
|
1356
|
+
group_set_element.attrib["name"] = group_set_item.name
|
|
1357
|
+
return ET.tostring(xml_request)
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
class VirtualConnectionRequest:
|
|
1361
|
+
@_tsrequest_wrapped
|
|
1362
|
+
def update_db_connection(self, xml_request: ET.Element, connection_item: ConnectionItem) -> bytes:
|
|
1363
|
+
connection_element = ET.SubElement(xml_request, "connection")
|
|
1364
|
+
if connection_item.server_address is not None:
|
|
1365
|
+
connection_element.attrib["serverAddress"] = connection_item.server_address
|
|
1366
|
+
if connection_item.server_port is not None:
|
|
1367
|
+
connection_element.attrib["serverPort"] = str(connection_item.server_port)
|
|
1368
|
+
if connection_item.username is not None:
|
|
1369
|
+
connection_element.attrib["userName"] = connection_item.username
|
|
1370
|
+
if connection_item.password is not None:
|
|
1371
|
+
connection_element.attrib["password"] = connection_item.password
|
|
1372
|
+
|
|
1373
|
+
return ET.tostring(xml_request)
|
|
1374
|
+
|
|
1375
|
+
@_tsrequest_wrapped
|
|
1376
|
+
def update(self, xml_request: ET.Element, virtual_connection: VirtualConnectionItem) -> bytes:
|
|
1377
|
+
vc_element = ET.SubElement(xml_request, "virtualConnection")
|
|
1378
|
+
if virtual_connection.name is not None:
|
|
1379
|
+
vc_element.attrib["name"] = virtual_connection.name
|
|
1380
|
+
if virtual_connection.is_certified is not None:
|
|
1381
|
+
vc_element.attrib["isCertified"] = str(virtual_connection.is_certified).lower()
|
|
1382
|
+
if virtual_connection.certification_note is not None:
|
|
1383
|
+
vc_element.attrib["certificationNote"] = virtual_connection.certification_note
|
|
1384
|
+
if virtual_connection.project_id is not None:
|
|
1385
|
+
project_element = ET.SubElement(vc_element, "project")
|
|
1386
|
+
project_element.attrib["id"] = virtual_connection.project_id
|
|
1387
|
+
if virtual_connection.owner_id is not None:
|
|
1388
|
+
owner_element = ET.SubElement(vc_element, "owner")
|
|
1389
|
+
owner_element.attrib["id"] = virtual_connection.owner_id
|
|
1390
|
+
|
|
1391
|
+
return ET.tostring(xml_request)
|
|
1392
|
+
|
|
1393
|
+
@_tsrequest_wrapped
|
|
1394
|
+
def publish(self, xml_request: ET.Element, virtual_connection: VirtualConnectionItem, content: str) -> bytes:
|
|
1395
|
+
vc_element = ET.SubElement(xml_request, "virtualConnection")
|
|
1396
|
+
if virtual_connection.name is not None:
|
|
1397
|
+
vc_element.attrib["name"] = virtual_connection.name
|
|
1398
|
+
else:
|
|
1399
|
+
raise ValueError("Virtual Connection must have a name.")
|
|
1400
|
+
if virtual_connection.project_id is not None:
|
|
1401
|
+
project_element = ET.SubElement(vc_element, "project")
|
|
1402
|
+
project_element.attrib["id"] = virtual_connection.project_id
|
|
1403
|
+
else:
|
|
1404
|
+
raise ValueError("Virtual Connection must have a project id.")
|
|
1405
|
+
if virtual_connection.owner_id is not None:
|
|
1406
|
+
owner_element = ET.SubElement(vc_element, "owner")
|
|
1407
|
+
owner_element.attrib["id"] = virtual_connection.owner_id
|
|
1408
|
+
else:
|
|
1409
|
+
raise ValueError("Virtual Connection must have an owner id.")
|
|
1410
|
+
if content is not None:
|
|
1411
|
+
content_element = ET.SubElement(vc_element, "content")
|
|
1412
|
+
content_element.text = content
|
|
1413
|
+
else:
|
|
1414
|
+
raise ValueError("Virtual Connection must have content.")
|
|
1415
|
+
|
|
1416
|
+
return ET.tostring(xml_request)
|
|
1417
|
+
|
|
1248
1418
|
|
|
1249
|
-
class RequestFactory
|
|
1419
|
+
class RequestFactory:
|
|
1250
1420
|
Auth = AuthRequest()
|
|
1251
1421
|
Connection = Connection()
|
|
1252
1422
|
Column = ColumnRequest()
|
|
@@ -1261,6 +1431,7 @@ class RequestFactory(object):
|
|
|
1261
1431
|
Flow = FlowRequest()
|
|
1262
1432
|
FlowTask = FlowTaskRequest()
|
|
1263
1433
|
Group = GroupRequest()
|
|
1434
|
+
GroupSet = GroupSetRequest()
|
|
1264
1435
|
Metric = MetricRequest()
|
|
1265
1436
|
Permission = PermissionRequest()
|
|
1266
1437
|
Project = ProjectRequest()
|
|
@@ -1271,5 +1442,6 @@ class RequestFactory(object):
|
|
|
1271
1442
|
Tag = TagRequest()
|
|
1272
1443
|
Task = TaskRequest()
|
|
1273
1444
|
User = UserRequest()
|
|
1445
|
+
VirtualConnection = VirtualConnectionRequest()
|
|
1274
1446
|
Workbook = WorkbookRequest()
|
|
1275
1447
|
Webhook = WebhookRequest()
|