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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from .request_options import RequestOptions
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class Filter
|
|
4
|
+
class Filter:
|
|
5
5
|
def __init__(self, field, operator, value):
|
|
6
6
|
self.field = field
|
|
7
7
|
self.operator = operator
|
|
@@ -16,7 +16,7 @@ class Filter(object):
|
|
|
16
16
|
# to [<string1>,<string2>]
|
|
17
17
|
# so effectively, remove any spaces between "," and "'" and then remove all "'"
|
|
18
18
|
value_string = value_string.replace(", '", ",'").replace("'", "")
|
|
19
|
-
return "{
|
|
19
|
+
return f"{self.field}:{self.operator}:{value_string}"
|
|
20
20
|
|
|
21
21
|
@property
|
|
22
22
|
def value(self):
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
from functools import partial
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional, Protocol, TypeVar, Union, runtime_checkable
|
|
4
|
+
from collections.abc import Iterable, Iterator
|
|
4
5
|
|
|
5
6
|
from tableauserverclient.models.pagination_item import PaginationItem
|
|
6
7
|
from tableauserverclient.server.request_options import RequestOptions
|
|
@@ -11,14 +12,12 @@ T = TypeVar("T")
|
|
|
11
12
|
|
|
12
13
|
@runtime_checkable
|
|
13
14
|
class Endpoint(Protocol[T]):
|
|
14
|
-
def get(self, req_options: Optional[RequestOptions]) ->
|
|
15
|
-
...
|
|
15
|
+
def get(self, req_options: Optional[RequestOptions]) -> tuple[list[T], PaginationItem]: ...
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
@runtime_checkable
|
|
19
19
|
class CallableEndpoint(Protocol[T]):
|
|
20
|
-
def __call__(self, __req_options: Optional[RequestOptions], **kwargs) ->
|
|
21
|
-
...
|
|
20
|
+
def __call__(self, __req_options: Optional[RequestOptions], **kwargs) -> tuple[list[T], PaginationItem]: ...
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class Pager(Iterable[T]):
|
|
@@ -27,7 +26,7 @@ class Pager(Iterable[T]):
|
|
|
27
26
|
Supports all `RequestOptions` including starting on any page. Also used by models to load sub-models
|
|
28
27
|
(users in a group, views in a workbook, etc) by passing a different endpoint.
|
|
29
28
|
|
|
30
|
-
Will loop over anything that returns (
|
|
29
|
+
Will loop over anything that returns (list[ModelItem], PaginationItem).
|
|
31
30
|
"""
|
|
32
31
|
|
|
33
32
|
def __init__(
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
from collections.abc import Sized
|
|
1
|
+
from collections.abc import Iterable, Iterator, Sized
|
|
2
2
|
from itertools import count
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional, Protocol, TYPE_CHECKING, TypeVar, overload
|
|
4
|
+
import sys
|
|
4
5
|
from tableauserverclient.config import config
|
|
5
6
|
from tableauserverclient.models.pagination_item import PaginationItem
|
|
7
|
+
from tableauserverclient.server.endpoint.exceptions import ServerResponseError
|
|
6
8
|
from tableauserverclient.server.filter import Filter
|
|
7
9
|
from tableauserverclient.server.request_options import RequestOptions
|
|
8
10
|
from tableauserverclient.server.sort import Sort
|
|
@@ -34,10 +36,36 @@ see pagination_sample
|
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
class QuerySet(Iterable[T], Sized):
|
|
39
|
+
"""
|
|
40
|
+
QuerySet is a class that allows easy filtering, sorting, and iterating over
|
|
41
|
+
many endpoints in TableauServerClient. It is designed to be used in a similar
|
|
42
|
+
way to Django QuerySets, but with a more limited feature set.
|
|
43
|
+
|
|
44
|
+
QuerySet is an iterable, and can be used in for loops, list comprehensions,
|
|
45
|
+
and other places where iterables are expected.
|
|
46
|
+
|
|
47
|
+
QuerySet is also Sized, and can be used in places where the length of the
|
|
48
|
+
QuerySet is needed. The length of the QuerySet is the total number of items
|
|
49
|
+
available in the QuerySet, not just the number of items that have been
|
|
50
|
+
fetched. If the endpoint does not return a total count of items, the length
|
|
51
|
+
of the QuerySet will be sys.maxsize. If there is no total count, the
|
|
52
|
+
QuerySet will continue to fetch items until there are no more items to
|
|
53
|
+
fetch.
|
|
54
|
+
|
|
55
|
+
QuerySet is not re-entrant. It is not designed to be used in multiple places
|
|
56
|
+
at the same time. If you need to use a QuerySet in multiple places, you
|
|
57
|
+
should create a new QuerySet for each place you need to use it, convert it
|
|
58
|
+
to a list, or create a deep copy of the QuerySet.
|
|
59
|
+
|
|
60
|
+
QuerySets are also indexable, and can be sliced. If you try to access an
|
|
61
|
+
index that has not been fetched, the QuerySet will fetch the page that
|
|
62
|
+
contains the item you are looking for.
|
|
63
|
+
"""
|
|
64
|
+
|
|
37
65
|
def __init__(self, model: "QuerysetEndpoint[T]", page_size: Optional[int] = None) -> None:
|
|
38
66
|
self.model = model
|
|
39
67
|
self.request_options = RequestOptions(pagesize=page_size or config.PAGE_SIZE)
|
|
40
|
-
self._result_cache:
|
|
68
|
+
self._result_cache: list[T] = []
|
|
41
69
|
self._pagination_item = PaginationItem()
|
|
42
70
|
|
|
43
71
|
def __iter__(self: Self) -> Iterator[T]:
|
|
@@ -49,19 +77,30 @@ class QuerySet(Iterable[T], Sized):
|
|
|
49
77
|
for page in count(1):
|
|
50
78
|
self.request_options.pagenumber = page
|
|
51
79
|
self._result_cache = []
|
|
52
|
-
self.
|
|
80
|
+
self._pagination_item._page_number = None
|
|
81
|
+
try:
|
|
82
|
+
self._fetch_all()
|
|
83
|
+
except ServerResponseError as e:
|
|
84
|
+
if e.code == "400006":
|
|
85
|
+
# If the endpoint does not support pagination, it will end
|
|
86
|
+
# up overrunning the total number of pages. Catch the
|
|
87
|
+
# error and break out of the loop.
|
|
88
|
+
raise StopIteration
|
|
89
|
+
if len(self._result_cache) == 0:
|
|
90
|
+
return
|
|
53
91
|
yield from self._result_cache
|
|
54
|
-
#
|
|
55
|
-
|
|
92
|
+
# If the length of the QuerySet is unknown, continue fetching until
|
|
93
|
+
# the result cache is empty.
|
|
94
|
+
if (size := len(self)) == 0:
|
|
95
|
+
continue
|
|
96
|
+
if (page * self.page_size) >= size:
|
|
56
97
|
return
|
|
57
98
|
|
|
58
99
|
@overload
|
|
59
|
-
def __getitem__(self: Self, k: Slice) ->
|
|
60
|
-
...
|
|
100
|
+
def __getitem__(self: Self, k: Slice) -> list[T]: ...
|
|
61
101
|
|
|
62
102
|
@overload
|
|
63
|
-
def __getitem__(self: Self, k: int) -> T:
|
|
64
|
-
...
|
|
103
|
+
def __getitem__(self: Self, k: int) -> T: ...
|
|
65
104
|
|
|
66
105
|
def __getitem__(self, k):
|
|
67
106
|
page = self.page_number
|
|
@@ -103,6 +142,7 @@ class QuerySet(Iterable[T], Sized):
|
|
|
103
142
|
elif k in range(self.total_available):
|
|
104
143
|
# Otherwise, check if k is even sensible to return
|
|
105
144
|
self._result_cache = []
|
|
145
|
+
self._pagination_item._page_number = None
|
|
106
146
|
# Add one to k, otherwise it gets stuck at page boundaries, e.g. 100
|
|
107
147
|
self.request_options.pagenumber = max(1, math.ceil((k + 1) / size))
|
|
108
148
|
return self[k]
|
|
@@ -114,11 +154,16 @@ class QuerySet(Iterable[T], Sized):
|
|
|
114
154
|
"""
|
|
115
155
|
Retrieve the data and store result and pagination item in cache
|
|
116
156
|
"""
|
|
117
|
-
if not self._result_cache:
|
|
118
|
-
|
|
157
|
+
if not self._result_cache and self._pagination_item._page_number is None:
|
|
158
|
+
response = self.model.get(self.request_options)
|
|
159
|
+
if isinstance(response, tuple):
|
|
160
|
+
self._result_cache, self._pagination_item = response
|
|
161
|
+
else:
|
|
162
|
+
self._result_cache = response
|
|
163
|
+
self._pagination_item = PaginationItem()
|
|
119
164
|
|
|
120
165
|
def __len__(self: Self) -> int:
|
|
121
|
-
return self.total_available
|
|
166
|
+
return sys.maxsize if self.total_available is None else self.total_available
|
|
122
167
|
|
|
123
168
|
@property
|
|
124
169
|
def total_available(self: Self) -> int:
|
|
@@ -128,12 +173,16 @@ class QuerySet(Iterable[T], Sized):
|
|
|
128
173
|
@property
|
|
129
174
|
def page_number(self: Self) -> int:
|
|
130
175
|
self._fetch_all()
|
|
131
|
-
|
|
176
|
+
# If the PaginationItem is not returned from the endpoint, use the
|
|
177
|
+
# pagenumber from the RequestOptions.
|
|
178
|
+
return self._pagination_item.page_number or self.request_options.pagenumber
|
|
132
179
|
|
|
133
180
|
@property
|
|
134
181
|
def page_size(self: Self) -> int:
|
|
135
182
|
self._fetch_all()
|
|
136
|
-
|
|
183
|
+
# If the PaginationItem is not returned from the endpoint, use the
|
|
184
|
+
# pagesize from the RequestOptions.
|
|
185
|
+
return self._pagination_item.page_size or self.request_options.pagesize
|
|
137
186
|
|
|
138
187
|
def filter(self: Self, *invalid, page_size: Optional[int] = None, **kwargs) -> Self:
|
|
139
188
|
if invalid:
|
|
@@ -160,22 +209,22 @@ class QuerySet(Iterable[T], Sized):
|
|
|
160
209
|
return self
|
|
161
210
|
|
|
162
211
|
@staticmethod
|
|
163
|
-
def _parse_shorthand_filter(key: str) ->
|
|
212
|
+
def _parse_shorthand_filter(key: str) -> tuple[str, str]:
|
|
164
213
|
tokens = key.split("__", 1)
|
|
165
214
|
if len(tokens) == 1:
|
|
166
215
|
operator = RequestOptions.Operator.Equals
|
|
167
216
|
else:
|
|
168
217
|
operator = tokens[1]
|
|
169
218
|
if operator not in RequestOptions.Operator.__dict__.values():
|
|
170
|
-
raise ValueError("Operator `{}` is not valid."
|
|
219
|
+
raise ValueError(f"Operator `{operator}` is not valid.")
|
|
171
220
|
|
|
172
221
|
field = to_camel_case(tokens[0])
|
|
173
222
|
if field not in RequestOptions.Field.__dict__.values():
|
|
174
|
-
raise ValueError("Field name `{}` is not valid."
|
|
223
|
+
raise ValueError(f"Field name `{field}` is not valid.")
|
|
175
224
|
return (field, operator)
|
|
176
225
|
|
|
177
226
|
@staticmethod
|
|
178
|
-
def _parse_shorthand_sort(key: str) ->
|
|
227
|
+
def _parse_shorthand_sort(key: str) -> tuple[str, str]:
|
|
179
228
|
direction = RequestOptions.Direction.Asc
|
|
180
229
|
if key.startswith("-"):
|
|
181
230
|
direction = RequestOptions.Direction.Desc
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
|
-
from typing import Any, Callable,
|
|
2
|
+
from typing import Any, Callable, Optional, TypeVar, TYPE_CHECKING, Union
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
|
|
4
5
|
from typing_extensions import ParamSpec
|
|
5
6
|
|
|
@@ -15,7 +16,7 @@ if TYPE_CHECKING:
|
|
|
15
16
|
# this file could be largely replaced if we were willing to import the huge file from generateDS
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def _add_multipart(parts:
|
|
19
|
+
def _add_multipart(parts: dict) -> tuple[Any, str]:
|
|
19
20
|
mime_multipart_parts = list()
|
|
20
21
|
for name, (filename, data, content_type) in parts.items():
|
|
21
22
|
multipart_part = RequestField(name=name, data=data, filename=filename)
|
|
@@ -80,7 +81,7 @@ def _add_credentials_element(parent_element, connection_credentials):
|
|
|
80
81
|
credentials_element.attrib["oAuth"] = "true"
|
|
81
82
|
|
|
82
83
|
|
|
83
|
-
class AuthRequest
|
|
84
|
+
class AuthRequest:
|
|
84
85
|
def signin_req(self, auth_item):
|
|
85
86
|
xml_request = ET.Element("tsRequest")
|
|
86
87
|
|
|
@@ -104,7 +105,7 @@ class AuthRequest(object):
|
|
|
104
105
|
return ET.tostring(xml_request)
|
|
105
106
|
|
|
106
107
|
|
|
107
|
-
class ColumnRequest
|
|
108
|
+
class ColumnRequest:
|
|
108
109
|
def update_req(self, column_item):
|
|
109
110
|
xml_request = ET.Element("tsRequest")
|
|
110
111
|
column_element = ET.SubElement(xml_request, "column")
|
|
@@ -115,7 +116,7 @@ class ColumnRequest(object):
|
|
|
115
116
|
return ET.tostring(xml_request)
|
|
116
117
|
|
|
117
118
|
|
|
118
|
-
class DataAlertRequest
|
|
119
|
+
class DataAlertRequest:
|
|
119
120
|
def add_user_to_alert(self, alert_item: "DataAlertItem", user_id: str) -> bytes:
|
|
120
121
|
xml_request = ET.Element("tsRequest")
|
|
121
122
|
user_element = ET.SubElement(xml_request, "user")
|
|
@@ -140,7 +141,7 @@ class DataAlertRequest(object):
|
|
|
140
141
|
return ET.tostring(xml_request)
|
|
141
142
|
|
|
142
143
|
|
|
143
|
-
class DatabaseRequest
|
|
144
|
+
class DatabaseRequest:
|
|
144
145
|
def update_req(self, database_item):
|
|
145
146
|
xml_request = ET.Element("tsRequest")
|
|
146
147
|
database_element = ET.SubElement(xml_request, "database")
|
|
@@ -159,7 +160,7 @@ class DatabaseRequest(object):
|
|
|
159
160
|
return ET.tostring(xml_request)
|
|
160
161
|
|
|
161
162
|
|
|
162
|
-
class DatasourceRequest
|
|
163
|
+
class DatasourceRequest:
|
|
163
164
|
def _generate_xml(self, datasource_item: DatasourceItem, connection_credentials=None, connections=None):
|
|
164
165
|
xml_request = ET.Element("tsRequest")
|
|
165
166
|
datasource_element = ET.SubElement(xml_request, "datasource")
|
|
@@ -244,7 +245,7 @@ class DatasourceRequest(object):
|
|
|
244
245
|
return _add_multipart(parts)
|
|
245
246
|
|
|
246
247
|
|
|
247
|
-
class DQWRequest
|
|
248
|
+
class DQWRequest:
|
|
248
249
|
def add_req(self, dqw_item):
|
|
249
250
|
xml_request = ET.Element("tsRequest")
|
|
250
251
|
dqw_element = ET.SubElement(xml_request, "dataQualityWarning")
|
|
@@ -274,7 +275,7 @@ class DQWRequest(object):
|
|
|
274
275
|
return ET.tostring(xml_request)
|
|
275
276
|
|
|
276
277
|
|
|
277
|
-
class FavoriteRequest
|
|
278
|
+
class FavoriteRequest:
|
|
278
279
|
def add_request(self, id_: Optional[str], target_type: str, label: Optional[str]) -> bytes:
|
|
279
280
|
"""
|
|
280
281
|
<favorite label="...">
|
|
@@ -329,7 +330,7 @@ class FavoriteRequest(object):
|
|
|
329
330
|
return self.add_request(id_, Resource.Workbook, name)
|
|
330
331
|
|
|
331
332
|
|
|
332
|
-
class FileuploadRequest
|
|
333
|
+
class FileuploadRequest:
|
|
333
334
|
def chunk_req(self, chunk):
|
|
334
335
|
parts = {
|
|
335
336
|
"request_payload": ("", "", "text/xml"),
|
|
@@ -338,8 +339,8 @@ class FileuploadRequest(object):
|
|
|
338
339
|
return _add_multipart(parts)
|
|
339
340
|
|
|
340
341
|
|
|
341
|
-
class FlowRequest
|
|
342
|
-
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:
|
|
343
344
|
xml_request = ET.Element("tsRequest")
|
|
344
345
|
flow_element = ET.SubElement(xml_request, "flow")
|
|
345
346
|
if flow_item.name is not None:
|
|
@@ -370,8 +371,8 @@ class FlowRequest(object):
|
|
|
370
371
|
flow_item: "FlowItem",
|
|
371
372
|
filename: str,
|
|
372
373
|
file_contents: bytes,
|
|
373
|
-
connections: Optional[
|
|
374
|
-
) ->
|
|
374
|
+
connections: Optional[list["ConnectionItem"]] = None,
|
|
375
|
+
) -> tuple[Any, str]:
|
|
375
376
|
xml_request = self._generate_xml(flow_item, connections)
|
|
376
377
|
|
|
377
378
|
parts = {
|
|
@@ -380,14 +381,14 @@ class FlowRequest(object):
|
|
|
380
381
|
}
|
|
381
382
|
return _add_multipart(parts)
|
|
382
383
|
|
|
383
|
-
def publish_req_chunked(self, flow_item, connections=None) ->
|
|
384
|
+
def publish_req_chunked(self, flow_item, connections=None) -> tuple[Any, str]:
|
|
384
385
|
xml_request = self._generate_xml(flow_item, connections)
|
|
385
386
|
|
|
386
387
|
parts = {"request_payload": ("", xml_request, "text/xml")}
|
|
387
388
|
return _add_multipart(parts)
|
|
388
389
|
|
|
389
390
|
|
|
390
|
-
class GroupRequest
|
|
391
|
+
class GroupRequest:
|
|
391
392
|
def add_user_req(self, user_id: str) -> bytes:
|
|
392
393
|
xml_request = ET.Element("tsRequest")
|
|
393
394
|
user_element = ET.SubElement(xml_request, "user")
|
|
@@ -477,7 +478,7 @@ class GroupRequest(object):
|
|
|
477
478
|
return ET.tostring(xml_request)
|
|
478
479
|
|
|
479
480
|
|
|
480
|
-
class PermissionRequest
|
|
481
|
+
class PermissionRequest:
|
|
481
482
|
def add_req(self, rules: Iterable[PermissionsRule]) -> bytes:
|
|
482
483
|
xml_request = ET.Element("tsRequest")
|
|
483
484
|
permissions_element = ET.SubElement(xml_request, "permissions")
|
|
@@ -499,7 +500,7 @@ class PermissionRequest(object):
|
|
|
499
500
|
capability_element.attrib["mode"] = mode
|
|
500
501
|
|
|
501
502
|
|
|
502
|
-
class ProjectRequest
|
|
503
|
+
class ProjectRequest:
|
|
503
504
|
def update_req(self, project_item: "ProjectItem") -> bytes:
|
|
504
505
|
xml_request = ET.Element("tsRequest")
|
|
505
506
|
project_element = ET.SubElement(xml_request, "project")
|
|
@@ -530,7 +531,7 @@ class ProjectRequest(object):
|
|
|
530
531
|
return ET.tostring(xml_request)
|
|
531
532
|
|
|
532
533
|
|
|
533
|
-
class ScheduleRequest
|
|
534
|
+
class ScheduleRequest:
|
|
534
535
|
def create_req(self, schedule_item):
|
|
535
536
|
xml_request = ET.Element("tsRequest")
|
|
536
537
|
schedule_element = ET.SubElement(xml_request, "schedule")
|
|
@@ -609,7 +610,7 @@ class ScheduleRequest(object):
|
|
|
609
610
|
return self._add_to_req(id_, "flow", task_type)
|
|
610
611
|
|
|
611
612
|
|
|
612
|
-
class SiteRequest
|
|
613
|
+
class SiteRequest:
|
|
613
614
|
def update_req(self, site_item: "SiteItem", parent_srv: Optional["Server"] = None):
|
|
614
615
|
xml_request = ET.Element("tsRequest")
|
|
615
616
|
site_element = ET.SubElement(xml_request, "site")
|
|
@@ -848,7 +849,7 @@ class SiteRequest(object):
|
|
|
848
849
|
warnings.warn("In version 3.10 and earlier there is only one option: FlowsEnabled")
|
|
849
850
|
|
|
850
851
|
|
|
851
|
-
class TableRequest
|
|
852
|
+
class TableRequest:
|
|
852
853
|
def update_req(self, table_item):
|
|
853
854
|
xml_request = ET.Element("tsRequest")
|
|
854
855
|
table_element = ET.SubElement(xml_request, "table")
|
|
@@ -871,7 +872,7 @@ class TableRequest(object):
|
|
|
871
872
|
content_types = Iterable[Union["ColumnItem", "DatabaseItem", "DatasourceItem", "FlowItem", "TableItem", "WorkbookItem"]]
|
|
872
873
|
|
|
873
874
|
|
|
874
|
-
class TagRequest
|
|
875
|
+
class TagRequest:
|
|
875
876
|
def add_req(self, tag_set):
|
|
876
877
|
xml_request = ET.Element("tsRequest")
|
|
877
878
|
tags_element = ET.SubElement(xml_request, "tags")
|
|
@@ -881,7 +882,7 @@ class TagRequest(object):
|
|
|
881
882
|
return ET.tostring(xml_request)
|
|
882
883
|
|
|
883
884
|
@_tsrequest_wrapped
|
|
884
|
-
def batch_create(self, element: ET.Element, tags:
|
|
885
|
+
def batch_create(self, element: ET.Element, tags: set[str], content: content_types) -> bytes:
|
|
885
886
|
tag_batch = ET.SubElement(element, "tagBatch")
|
|
886
887
|
tags_element = ET.SubElement(tag_batch, "tags")
|
|
887
888
|
for tag in tags:
|
|
@@ -897,7 +898,7 @@ class TagRequest(object):
|
|
|
897
898
|
return ET.tostring(element)
|
|
898
899
|
|
|
899
900
|
|
|
900
|
-
class UserRequest
|
|
901
|
+
class UserRequest:
|
|
901
902
|
def update_req(self, user_item: UserItem, password: Optional[str]) -> bytes:
|
|
902
903
|
xml_request = ET.Element("tsRequest")
|
|
903
904
|
user_element = ET.SubElement(xml_request, "user")
|
|
@@ -931,7 +932,7 @@ class UserRequest(object):
|
|
|
931
932
|
return ET.tostring(xml_request)
|
|
932
933
|
|
|
933
934
|
|
|
934
|
-
class WorkbookRequest
|
|
935
|
+
class WorkbookRequest:
|
|
935
936
|
def _generate_xml(
|
|
936
937
|
self,
|
|
937
938
|
workbook_item,
|
|
@@ -995,9 +996,9 @@ class WorkbookRequest(object):
|
|
|
995
996
|
if data_freshness_policy_config.option == "FreshEvery":
|
|
996
997
|
if data_freshness_policy_config.fresh_every_schedule is not None:
|
|
997
998
|
fresh_every_element = ET.SubElement(data_freshness_policy_element, "freshEverySchedule")
|
|
998
|
-
fresh_every_element.attrib[
|
|
999
|
-
|
|
1000
|
-
|
|
999
|
+
fresh_every_element.attrib["frequency"] = (
|
|
1000
|
+
data_freshness_policy_config.fresh_every_schedule.frequency
|
|
1001
|
+
)
|
|
1001
1002
|
fresh_every_element.attrib["value"] = str(data_freshness_policy_config.fresh_every_schedule.value)
|
|
1002
1003
|
else:
|
|
1003
1004
|
raise ValueError(f"data_freshness_policy_config.fresh_every_schedule must be populated.")
|
|
@@ -1075,7 +1076,7 @@ class WorkbookRequest(object):
|
|
|
1075
1076
|
datasource_element.attrib["id"] = id_
|
|
1076
1077
|
|
|
1077
1078
|
|
|
1078
|
-
class Connection
|
|
1079
|
+
class Connection:
|
|
1079
1080
|
@_tsrequest_wrapped
|
|
1080
1081
|
def update_req(self, xml_request: ET.Element, connection_item: "ConnectionItem") -> None:
|
|
1081
1082
|
connection_element = ET.SubElement(xml_request, "connection")
|
|
@@ -1098,7 +1099,7 @@ class Connection(object):
|
|
|
1098
1099
|
connection_element.attrib["queryTaggingEnabled"] = str(connection_item.query_tagging).lower()
|
|
1099
1100
|
|
|
1100
1101
|
|
|
1101
|
-
class TaskRequest
|
|
1102
|
+
class TaskRequest:
|
|
1102
1103
|
@_tsrequest_wrapped
|
|
1103
1104
|
def run_req(self, xml_request: ET.Element, task_item: Any) -> None:
|
|
1104
1105
|
# Send an empty tsRequest
|
|
@@ -1137,7 +1138,7 @@ class TaskRequest(object):
|
|
|
1137
1138
|
return ET.tostring(xml_request)
|
|
1138
1139
|
|
|
1139
1140
|
|
|
1140
|
-
class FlowTaskRequest
|
|
1141
|
+
class FlowTaskRequest:
|
|
1141
1142
|
@_tsrequest_wrapped
|
|
1142
1143
|
def create_flow_task_req(self, xml_request: ET.Element, flow_item: "TaskItem") -> bytes:
|
|
1143
1144
|
flow_element = ET.SubElement(xml_request, "runFlow")
|
|
@@ -1171,7 +1172,7 @@ class FlowTaskRequest(object):
|
|
|
1171
1172
|
return ET.tostring(xml_request)
|
|
1172
1173
|
|
|
1173
1174
|
|
|
1174
|
-
class SubscriptionRequest
|
|
1175
|
+
class SubscriptionRequest:
|
|
1175
1176
|
@_tsrequest_wrapped
|
|
1176
1177
|
def create_req(self, xml_request: ET.Element, subscription_item: "SubscriptionItem") -> bytes:
|
|
1177
1178
|
subscription_element = ET.SubElement(xml_request, "subscription")
|
|
@@ -1235,13 +1236,13 @@ class SubscriptionRequest(object):
|
|
|
1235
1236
|
return ET.tostring(xml_request)
|
|
1236
1237
|
|
|
1237
1238
|
|
|
1238
|
-
class EmptyRequest
|
|
1239
|
+
class EmptyRequest:
|
|
1239
1240
|
@_tsrequest_wrapped
|
|
1240
1241
|
def empty_req(self, xml_request: ET.Element) -> None:
|
|
1241
1242
|
pass
|
|
1242
1243
|
|
|
1243
1244
|
|
|
1244
|
-
class WebhookRequest
|
|
1245
|
+
class WebhookRequest:
|
|
1245
1246
|
@_tsrequest_wrapped
|
|
1246
1247
|
def create_req(self, xml_request: ET.Element, webhook_item: "WebhookItem") -> bytes:
|
|
1247
1248
|
webhook = ET.SubElement(xml_request, "webhook")
|
|
@@ -1287,7 +1288,7 @@ class MetricRequest:
|
|
|
1287
1288
|
return ET.tostring(xml_request)
|
|
1288
1289
|
|
|
1289
1290
|
|
|
1290
|
-
class CustomViewRequest
|
|
1291
|
+
class CustomViewRequest:
|
|
1291
1292
|
@_tsrequest_wrapped
|
|
1292
1293
|
def update_req(self, xml_request: ET.Element, custom_view_item: CustomViewItem):
|
|
1293
1294
|
updating_element = ET.SubElement(xml_request, "customView")
|
|
@@ -1415,7 +1416,7 @@ class VirtualConnectionRequest:
|
|
|
1415
1416
|
return ET.tostring(xml_request)
|
|
1416
1417
|
|
|
1417
1418
|
|
|
1418
|
-
class RequestFactory
|
|
1419
|
+
class RequestFactory:
|
|
1419
1420
|
Auth = AuthRequest()
|
|
1420
1421
|
Connection = Connection()
|
|
1421
1422
|
Column = ColumnRequest()
|