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.
- tableauserverclient/bin/_version.py → _version.py +3 -3
- bin/__init__.py +3 -0
- bin/_version.py +21 -0
- {tableauserverclient/helpers → helpers}/strings.py +25 -1
- {tableauserverclient/models → models}/__init__.py +15 -1
- models/collection_item.py +52 -0
- {tableauserverclient/models → models}/connection_item.py +16 -2
- {tableauserverclient/models → models}/custom_view_item.py +8 -0
- {tableauserverclient/models → models}/data_freshness_policy_item.py +3 -3
- {tableauserverclient/models → models}/datasource_item.py +113 -3
- models/extensions_item.py +186 -0
- models/extract_item.py +82 -0
- {tableauserverclient/models → models}/favorites_item.py +21 -8
- {tableauserverclient/models → models}/flow_item.py +3 -3
- {tableauserverclient/models → models}/group_item.py +18 -1
- {tableauserverclient/models → models}/groupset_item.py +14 -0
- {tableauserverclient/models → models}/interval_item.py +42 -1
- models/location_item.py +53 -0
- models/oidc_item.py +82 -0
- {tableauserverclient/models → models}/permissions_item.py +2 -0
- {tableauserverclient/models → models}/project_item.py +141 -29
- {tableauserverclient/models → models}/property_decorators.py +2 -2
- {tableauserverclient/models → models}/reference_item.py +12 -6
- {tableauserverclient/models → models}/schedule_item.py +67 -1
- {tableauserverclient/models → models}/site_item.py +54 -0
- {tableauserverclient/models → models}/table_item.py +7 -3
- {tableauserverclient/models → models}/tableau_auth.py +13 -6
- {tableauserverclient/models → models}/tableau_types.py +13 -1
- {tableauserverclient/models → models}/user_item.py +111 -4
- {tableauserverclient/models → models}/view_item.py +79 -5
- {tableauserverclient/models → models}/workbook_item.py +153 -3
- {tableauserverclient/server → server}/endpoint/__init__.py +4 -0
- {tableauserverclient/server → server}/endpoint/databases_endpoint.py +101 -18
- {tableauserverclient/server → server}/endpoint/datasources_endpoint.py +155 -25
- {tableauserverclient/server → server}/endpoint/dqw_endpoint.py +16 -6
- {tableauserverclient/server → server}/endpoint/endpoint.py +39 -0
- server/endpoint/extensions_endpoint.py +79 -0
- {tableauserverclient/server → server}/endpoint/flow_task_endpoint.py +1 -1
- {tableauserverclient/server → server}/endpoint/flows_endpoint.py +5 -4
- server/endpoint/oidc_endpoint.py +157 -0
- {tableauserverclient/server → server}/endpoint/projects_endpoint.py +12 -0
- server/endpoint/schedules_endpoint.py +328 -0
- {tableauserverclient/server → server}/endpoint/sites_endpoint.py +18 -1
- {tableauserverclient/server → server}/endpoint/tables_endpoint.py +140 -17
- {tableauserverclient/server → server}/endpoint/users_endpoint.py +296 -10
- {tableauserverclient/server → server}/endpoint/views_endpoint.py +23 -0
- {tableauserverclient/server → server}/endpoint/workbooks_endpoint.py +124 -9
- {tableauserverclient/server → server}/query.py +36 -0
- {tableauserverclient/server → server}/request_factory.py +286 -2
- {tableauserverclient/server → server}/request_options.py +139 -3
- {tableauserverclient/server → server}/server.py +46 -0
- {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/METADATA +5 -26
- tableauserverclient-0.39.dist-info/RECORD +107 -0
- {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/WHEEL +1 -1
- tableauserverclient-0.39.dist-info/top_level.txt +4 -0
- tableauserverclient/__init__.py +0 -141
- tableauserverclient/config.py +0 -27
- tableauserverclient/datetime_helpers.py +0 -45
- tableauserverclient/exponential_backoff.py +0 -30
- tableauserverclient/filesys_helpers.py +0 -63
- tableauserverclient/namespace.py +0 -37
- tableauserverclient/py.typed +0 -0
- tableauserverclient/server/endpoint/schedules_endpoint.py +0 -151
- tableauserverclient-0.37.dist-info/RECORD +0 -106
- tableauserverclient-0.37.dist-info/licenses/LICENSE.versioneer +0 -7
- tableauserverclient-0.37.dist-info/top_level.txt +0 -1
- {tableauserverclient/helpers → helpers}/__init__.py +0 -0
- {tableauserverclient/helpers → helpers}/headers.py +0 -0
- {tableauserverclient/helpers → helpers}/logging.py +0 -0
- {tableauserverclient/models → models}/column_item.py +0 -0
- {tableauserverclient/models → models}/connection_credentials.py +0 -0
- {tableauserverclient/models → models}/data_acceleration_report_item.py +0 -0
- {tableauserverclient/models → models}/data_alert_item.py +0 -0
- {tableauserverclient/models → models}/database_item.py +0 -0
- {tableauserverclient/models → models}/dqw_item.py +0 -0
- {tableauserverclient/models → models}/exceptions.py +0 -0
- {tableauserverclient/models → models}/fileupload_item.py +0 -0
- {tableauserverclient/models → models}/flow_run_item.py +0 -0
- {tableauserverclient/models → models}/job_item.py +0 -0
- {tableauserverclient/models → models}/linked_tasks_item.py +0 -0
- {tableauserverclient/models → models}/metric_item.py +0 -0
- {tableauserverclient/models → models}/pagination_item.py +0 -0
- {tableauserverclient/models → models}/revision_item.py +0 -0
- {tableauserverclient/models → models}/server_info_item.py +0 -0
- {tableauserverclient/models → models}/subscription_item.py +0 -0
- {tableauserverclient/models → models}/tag_item.py +0 -0
- {tableauserverclient/models → models}/target.py +0 -0
- {tableauserverclient/models → models}/task_item.py +0 -0
- {tableauserverclient/models → models}/virtual_connection_item.py +0 -0
- {tableauserverclient/models → models}/webhook_item.py +0 -0
- {tableauserverclient/server → server}/__init__.py +0 -0
- {tableauserverclient/server → server}/endpoint/auth_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/custom_views_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/data_acceleration_report_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/data_alert_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/default_permissions_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/exceptions.py +0 -0
- {tableauserverclient/server → server}/endpoint/favorites_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/fileuploads_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/flow_runs_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/groups_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/groupsets_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/jobs_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/linked_tasks_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/metadata_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/metrics_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/permissions_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/resource_tagger.py +0 -0
- {tableauserverclient/server → server}/endpoint/server_info_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/subscriptions_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/tasks_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/virtual_connections_endpoint.py +0 -0
- {tableauserverclient/server → server}/endpoint/webhooks_endpoint.py +0 -0
- {tableauserverclient/server → server}/exceptions.py +0 -0
- {tableauserverclient/server → server}/filter.py +0 -0
- {tableauserverclient/server → server}/pager.py +0 -0
- {tableauserverclient/server → server}/sort.py +0 -0
- {tableauserverclient-0.37.dist-info → tableauserverclient-0.39.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,6 +6,7 @@ from tableauserverclient.server.endpoint.databases_endpoint import Databases
|
|
|
6
6
|
from tableauserverclient.server.endpoint.datasources_endpoint import Datasources
|
|
7
7
|
from tableauserverclient.server.endpoint.endpoint import Endpoint, QuerysetEndpoint
|
|
8
8
|
from tableauserverclient.server.endpoint.exceptions import ServerResponseError, MissingRequiredFieldError
|
|
9
|
+
from tableauserverclient.server.endpoint.extensions_endpoint import Extensions
|
|
9
10
|
from tableauserverclient.server.endpoint.favorites_endpoint import Favorites
|
|
10
11
|
from tableauserverclient.server.endpoint.fileuploads_endpoint import Fileuploads
|
|
11
12
|
from tableauserverclient.server.endpoint.flow_runs_endpoint import FlowRuns
|
|
@@ -17,6 +18,7 @@ from tableauserverclient.server.endpoint.jobs_endpoint import Jobs
|
|
|
17
18
|
from tableauserverclient.server.endpoint.linked_tasks_endpoint import LinkedTasks
|
|
18
19
|
from tableauserverclient.server.endpoint.metadata_endpoint import Metadata
|
|
19
20
|
from tableauserverclient.server.endpoint.metrics_endpoint import Metrics
|
|
21
|
+
from tableauserverclient.server.endpoint.oidc_endpoint import OIDC
|
|
20
22
|
from tableauserverclient.server.endpoint.projects_endpoint import Projects
|
|
21
23
|
from tableauserverclient.server.endpoint.schedules_endpoint import Schedules
|
|
22
24
|
from tableauserverclient.server.endpoint.server_info_endpoint import ServerInfo
|
|
@@ -41,6 +43,7 @@ __all__ = [
|
|
|
41
43
|
"QuerysetEndpoint",
|
|
42
44
|
"MissingRequiredFieldError",
|
|
43
45
|
"Endpoint",
|
|
46
|
+
"Extensions",
|
|
44
47
|
"Favorites",
|
|
45
48
|
"Fileuploads",
|
|
46
49
|
"FlowRuns",
|
|
@@ -52,6 +55,7 @@ __all__ = [
|
|
|
52
55
|
"LinkedTasks",
|
|
53
56
|
"Metadata",
|
|
54
57
|
"Metrics",
|
|
58
|
+
"OIDC",
|
|
55
59
|
"Projects",
|
|
56
60
|
"Schedules",
|
|
57
61
|
"ServerInfo",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import Union
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Union
|
|
3
3
|
from collections.abc import Iterable
|
|
4
4
|
|
|
5
|
+
from tableauserverclient.models.permissions_item import PermissionsRule
|
|
5
6
|
from tableauserverclient.server.endpoint.default_permissions_endpoint import _DefaultPermissionsEndpoint
|
|
6
7
|
from tableauserverclient.server.endpoint.dqw_endpoint import _DataQualityWarningEndpoint
|
|
7
8
|
from tableauserverclient.server.endpoint.endpoint import api, Endpoint
|
|
@@ -13,6 +14,10 @@ from tableauserverclient.models import DatabaseItem, TableItem, PaginationItem,
|
|
|
13
14
|
|
|
14
15
|
from tableauserverclient.helpers.logging import logger
|
|
15
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from tableauserverclient.models.dqw_item import DQWItem
|
|
19
|
+
from tableauserverclient.server.request_options import RequestOptions
|
|
20
|
+
|
|
16
21
|
|
|
17
22
|
class Databases(Endpoint, TaggingMixin):
|
|
18
23
|
def __init__(self, parent_srv):
|
|
@@ -23,11 +28,29 @@ class Databases(Endpoint, TaggingMixin):
|
|
|
23
28
|
self._data_quality_warnings = _DataQualityWarningEndpoint(parent_srv, Resource.Database)
|
|
24
29
|
|
|
25
30
|
@property
|
|
26
|
-
def baseurl(self):
|
|
31
|
+
def baseurl(self) -> str:
|
|
27
32
|
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/databases"
|
|
28
33
|
|
|
29
34
|
@api(version="3.5")
|
|
30
|
-
def get(self, req_options=None):
|
|
35
|
+
def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[DatabaseItem], PaginationItem]:
|
|
36
|
+
"""
|
|
37
|
+
Get information about all databases on the site. Endpoint is paginated,
|
|
38
|
+
and will return a default of 100 items per page. Use the `req_options`
|
|
39
|
+
parameter to customize the request.
|
|
40
|
+
|
|
41
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#query_databases
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
req_options : RequestOptions, optional
|
|
46
|
+
Options to customize the request. If not provided, defaults to None.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
tuple[list[DatabaseItem], PaginationItem]
|
|
51
|
+
A tuple containing a list of DatabaseItem objects and a
|
|
52
|
+
PaginationItem object.
|
|
53
|
+
"""
|
|
31
54
|
logger.info("Querying all databases on site")
|
|
32
55
|
url = self.baseurl
|
|
33
56
|
server_response = self.get_request(url, req_options)
|
|
@@ -37,7 +60,27 @@ class Databases(Endpoint, TaggingMixin):
|
|
|
37
60
|
|
|
38
61
|
# Get 1 database
|
|
39
62
|
@api(version="3.5")
|
|
40
|
-
def get_by_id(self, database_id):
|
|
63
|
+
def get_by_id(self, database_id: str) -> DatabaseItem:
|
|
64
|
+
"""
|
|
65
|
+
Get information about a single database asset on the site.
|
|
66
|
+
|
|
67
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#query_database
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
database_id : str
|
|
72
|
+
The ID of the database to retrieve.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
DatabaseItem
|
|
77
|
+
A DatabaseItem object representing the database.
|
|
78
|
+
|
|
79
|
+
Raises
|
|
80
|
+
------
|
|
81
|
+
ValueError
|
|
82
|
+
If the database ID is undefined.
|
|
83
|
+
"""
|
|
41
84
|
if not database_id:
|
|
42
85
|
error = "database ID undefined."
|
|
43
86
|
raise ValueError(error)
|
|
@@ -47,7 +90,24 @@ class Databases(Endpoint, TaggingMixin):
|
|
|
47
90
|
return DatabaseItem.from_response(server_response.content, self.parent_srv.namespace)[0]
|
|
48
91
|
|
|
49
92
|
@api(version="3.5")
|
|
50
|
-
def delete(self, database_id):
|
|
93
|
+
def delete(self, database_id: str) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Deletes a single database asset from the server.
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
database_id : str
|
|
100
|
+
The ID of the database to delete.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
None
|
|
105
|
+
|
|
106
|
+
Raises
|
|
107
|
+
------
|
|
108
|
+
ValueError
|
|
109
|
+
If the database ID is undefined.
|
|
110
|
+
"""
|
|
51
111
|
if not database_id:
|
|
52
112
|
error = "Database ID undefined."
|
|
53
113
|
raise ValueError(error)
|
|
@@ -56,7 +116,28 @@ class Databases(Endpoint, TaggingMixin):
|
|
|
56
116
|
logger.info(f"Deleted single database (ID: {database_id})")
|
|
57
117
|
|
|
58
118
|
@api(version="3.5")
|
|
59
|
-
def update(self, database_item):
|
|
119
|
+
def update(self, database_item: DatabaseItem) -> DatabaseItem:
|
|
120
|
+
"""
|
|
121
|
+
Update the database description, certify the database, set permissions,
|
|
122
|
+
or assign a User as the database contact.
|
|
123
|
+
|
|
124
|
+
REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#update_database
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
database_item : DatabaseItem
|
|
129
|
+
The DatabaseItem object to update.
|
|
130
|
+
|
|
131
|
+
Returns
|
|
132
|
+
-------
|
|
133
|
+
DatabaseItem
|
|
134
|
+
The updated DatabaseItem object.
|
|
135
|
+
|
|
136
|
+
Raises
|
|
137
|
+
------
|
|
138
|
+
MissingRequiredFieldError
|
|
139
|
+
If the database item is missing an ID.
|
|
140
|
+
"""
|
|
60
141
|
if not database_item.id:
|
|
61
142
|
error = "Database item missing ID."
|
|
62
143
|
raise MissingRequiredFieldError(error)
|
|
@@ -88,43 +169,45 @@ class Databases(Endpoint, TaggingMixin):
|
|
|
88
169
|
return tables
|
|
89
170
|
|
|
90
171
|
@api(version="3.5")
|
|
91
|
-
def populate_permissions(self, item):
|
|
172
|
+
def populate_permissions(self, item: DatabaseItem) -> None:
|
|
92
173
|
self._permissions.populate(item)
|
|
93
174
|
|
|
94
175
|
@api(version="3.5")
|
|
95
|
-
def update_permissions(self, item, rules):
|
|
176
|
+
def update_permissions(self, item: DatabaseItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
|
|
96
177
|
return self._permissions.update(item, rules)
|
|
97
178
|
|
|
98
179
|
@api(version="3.5")
|
|
99
|
-
def delete_permission(self, item, rules):
|
|
180
|
+
def delete_permission(self, item: DatabaseItem, rules: list[PermissionsRule]) -> None:
|
|
100
181
|
self._permissions.delete(item, rules)
|
|
101
182
|
|
|
102
183
|
@api(version="3.5")
|
|
103
|
-
def populate_table_default_permissions(self, item):
|
|
184
|
+
def populate_table_default_permissions(self, item: DatabaseItem):
|
|
104
185
|
self._default_permissions.populate_default_permissions(item, Resource.Table)
|
|
105
186
|
|
|
106
187
|
@api(version="3.5")
|
|
107
|
-
def update_table_default_permissions(
|
|
108
|
-
|
|
188
|
+
def update_table_default_permissions(
|
|
189
|
+
self, item: DatabaseItem, rules: list[PermissionsRule]
|
|
190
|
+
) -> list[PermissionsRule]:
|
|
191
|
+
return self._default_permissions.update_default_permissions(item, rules, Resource.Table)
|
|
109
192
|
|
|
110
193
|
@api(version="3.5")
|
|
111
|
-
def delete_table_default_permissions(self, item):
|
|
112
|
-
self._default_permissions.delete_default_permission(item, Resource.Table)
|
|
194
|
+
def delete_table_default_permissions(self, rule: PermissionsRule, item: DatabaseItem) -> None:
|
|
195
|
+
self._default_permissions.delete_default_permission(item, rule, Resource.Table)
|
|
113
196
|
|
|
114
197
|
@api(version="3.5")
|
|
115
|
-
def populate_dqw(self, item):
|
|
198
|
+
def populate_dqw(self, item: DatabaseItem) -> None:
|
|
116
199
|
self._data_quality_warnings.populate(item)
|
|
117
200
|
|
|
118
201
|
@api(version="3.5")
|
|
119
|
-
def update_dqw(self, item, warning):
|
|
202
|
+
def update_dqw(self, item: DatabaseItem, warning: "DQWItem") -> list["DQWItem"]:
|
|
120
203
|
return self._data_quality_warnings.update(item, warning)
|
|
121
204
|
|
|
122
205
|
@api(version="3.5")
|
|
123
|
-
def add_dqw(self, item, warning):
|
|
206
|
+
def add_dqw(self, item: DatabaseItem, warning: "DQWItem") -> list["DQWItem"]:
|
|
124
207
|
return self._data_quality_warnings.add(item, warning)
|
|
125
208
|
|
|
126
209
|
@api(version="3.5")
|
|
127
|
-
def delete_dqw(self, item):
|
|
210
|
+
def delete_dqw(self, item: DatabaseItem) -> None:
|
|
128
211
|
self._data_quality_warnings.clear(item)
|
|
129
212
|
|
|
130
213
|
@api(version="3.9")
|
|
@@ -6,8 +6,8 @@ import os
|
|
|
6
6
|
|
|
7
7
|
from contextlib import closing
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Literal, Optional, TYPE_CHECKING, Union, overload
|
|
10
|
-
from collections.abc import Iterable,
|
|
9
|
+
from typing import Literal, Optional, TYPE_CHECKING, TypedDict, TypeVar, Union, overload
|
|
10
|
+
from collections.abc import Iterable, Sequence
|
|
11
11
|
|
|
12
12
|
from tableauserverclient.helpers.headers import fix_filename
|
|
13
13
|
from tableauserverclient.models.dqw_item import DQWItem
|
|
@@ -50,13 +50,50 @@ FilePath = Union[str, os.PathLike]
|
|
|
50
50
|
FileObject = Union[io.BufferedReader, io.BytesIO]
|
|
51
51
|
PathOrFile = Union[FilePath, FileObject]
|
|
52
52
|
|
|
53
|
-
FilePath = Union[str, os.PathLike]
|
|
54
53
|
FileObjectR = Union[io.BufferedReader, io.BytesIO]
|
|
55
54
|
FileObjectW = Union[io.BufferedWriter, io.BytesIO]
|
|
56
55
|
PathOrFileR = Union[FilePath, FileObjectR]
|
|
57
56
|
PathOrFileW = Union[FilePath, FileObjectW]
|
|
58
57
|
|
|
59
58
|
|
|
59
|
+
HyperActionCondition = TypedDict(
|
|
60
|
+
"HyperActionCondition",
|
|
61
|
+
{
|
|
62
|
+
"op": str,
|
|
63
|
+
"target-col": str,
|
|
64
|
+
"source-col": str,
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
HyperActionRow = TypedDict(
|
|
69
|
+
"HyperActionRow",
|
|
70
|
+
{
|
|
71
|
+
"action": Literal[
|
|
72
|
+
"update",
|
|
73
|
+
"upsert",
|
|
74
|
+
"delete",
|
|
75
|
+
],
|
|
76
|
+
"source-table": str,
|
|
77
|
+
"target-table": str,
|
|
78
|
+
"condition": HyperActionCondition,
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
HyperActionTable = TypedDict(
|
|
83
|
+
"HyperActionTable",
|
|
84
|
+
{
|
|
85
|
+
"action": Literal[
|
|
86
|
+
"insert",
|
|
87
|
+
"replace",
|
|
88
|
+
],
|
|
89
|
+
"source-table": str,
|
|
90
|
+
"target-table": str,
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
HyperAction = Union[HyperActionTable, HyperActionRow]
|
|
95
|
+
|
|
96
|
+
|
|
60
97
|
class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]):
|
|
61
98
|
def __init__(self, parent_srv: "Server") -> None:
|
|
62
99
|
super().__init__(parent_srv)
|
|
@@ -191,16 +228,34 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
191
228
|
self.delete_request(url)
|
|
192
229
|
logger.info(f"Deleted single datasource (ID: {datasource_id})")
|
|
193
230
|
|
|
231
|
+
T = TypeVar("T", bound=FileObjectW)
|
|
232
|
+
|
|
233
|
+
@overload
|
|
234
|
+
def download(
|
|
235
|
+
self,
|
|
236
|
+
datasource_id: str,
|
|
237
|
+
filepath: T,
|
|
238
|
+
include_extract: bool = True,
|
|
239
|
+
) -> T: ...
|
|
240
|
+
|
|
241
|
+
@overload
|
|
242
|
+
def download(
|
|
243
|
+
self,
|
|
244
|
+
datasource_id: str,
|
|
245
|
+
filepath: Optional[FilePath] = None,
|
|
246
|
+
include_extract: bool = True,
|
|
247
|
+
) -> str: ...
|
|
248
|
+
|
|
194
249
|
# Download 1 datasource by id
|
|
195
250
|
@api(version="2.0")
|
|
196
251
|
@parameter_added_in(no_extract="2.5")
|
|
197
252
|
@parameter_added_in(include_extract="2.5")
|
|
198
253
|
def download(
|
|
199
254
|
self,
|
|
200
|
-
datasource_id
|
|
201
|
-
filepath
|
|
202
|
-
include_extract
|
|
203
|
-
)
|
|
255
|
+
datasource_id,
|
|
256
|
+
filepath=None,
|
|
257
|
+
include_extract=True,
|
|
258
|
+
):
|
|
204
259
|
"""
|
|
205
260
|
Downloads the specified data source from a site. The data source is
|
|
206
261
|
downloaded as a .tdsx file.
|
|
@@ -319,8 +374,63 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
319
374
|
logger.info(f"Updated datasource item (ID: {datasource_item.id} & connection item {connection_item.id}")
|
|
320
375
|
return connection
|
|
321
376
|
|
|
377
|
+
@api(version="3.26")
|
|
378
|
+
def update_connections(
|
|
379
|
+
self,
|
|
380
|
+
datasource_item: DatasourceItem,
|
|
381
|
+
connection_luids: Iterable[str],
|
|
382
|
+
authentication_type: str,
|
|
383
|
+
username: Optional[str] = None,
|
|
384
|
+
password: Optional[str] = None,
|
|
385
|
+
embed_password: Optional[bool] = None,
|
|
386
|
+
) -> list[ConnectionItem]:
|
|
387
|
+
"""
|
|
388
|
+
Bulk updates one or more datasource connections by LUID.
|
|
389
|
+
|
|
390
|
+
Parameters
|
|
391
|
+
----------
|
|
392
|
+
datasource_item : DatasourceItem
|
|
393
|
+
The datasource item containing the connections.
|
|
394
|
+
|
|
395
|
+
connection_luids : Iterable of str
|
|
396
|
+
The connection LUIDs to update.
|
|
397
|
+
|
|
398
|
+
authentication_type : str
|
|
399
|
+
The authentication type to use (e.g., 'auth-keypair').
|
|
400
|
+
|
|
401
|
+
username : str, optional
|
|
402
|
+
The username to set.
|
|
403
|
+
|
|
404
|
+
password : str, optional
|
|
405
|
+
The password or secret to set.
|
|
406
|
+
|
|
407
|
+
embed_password : bool, optional
|
|
408
|
+
Whether to embed the password.
|
|
409
|
+
|
|
410
|
+
Returns
|
|
411
|
+
-------
|
|
412
|
+
Iterable of str
|
|
413
|
+
The connection LUIDs that were updated.
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
url = f"{self.baseurl}/{datasource_item.id}/connections"
|
|
417
|
+
|
|
418
|
+
request_body = RequestFactory.Datasource.update_connections_req(
|
|
419
|
+
connection_luids=connection_luids,
|
|
420
|
+
authentication_type=authentication_type,
|
|
421
|
+
username=username,
|
|
422
|
+
password=password,
|
|
423
|
+
embed_password=embed_password,
|
|
424
|
+
)
|
|
425
|
+
server_response = self.put_request(url, request_body)
|
|
426
|
+
connection_items = ConnectionItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
427
|
+
updated_ids: list[str] = [conn.id for conn in connection_items]
|
|
428
|
+
|
|
429
|
+
logger.info(f"Updated connections for datasource {datasource_item.id}: {', '.join(updated_ids)}")
|
|
430
|
+
return connection_items
|
|
431
|
+
|
|
322
432
|
@api(version="2.8")
|
|
323
|
-
def refresh(self, datasource_item: DatasourceItem, incremental: bool = False) -> JobItem:
|
|
433
|
+
def refresh(self, datasource_item: Union[DatasourceItem, str], incremental: bool = False) -> JobItem:
|
|
324
434
|
"""
|
|
325
435
|
Refreshes the extract of an existing workbook.
|
|
326
436
|
|
|
@@ -328,8 +438,8 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
328
438
|
|
|
329
439
|
Parameters
|
|
330
440
|
----------
|
|
331
|
-
workbook_item :
|
|
332
|
-
The
|
|
441
|
+
workbook_item : DatasourceItem | str
|
|
442
|
+
The datasource item or datasource ID.
|
|
333
443
|
incremental: bool
|
|
334
444
|
Whether to do a full refresh or incremental refresh of the extract data
|
|
335
445
|
|
|
@@ -424,13 +534,13 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
424
534
|
@parameter_added_in(as_job="3.0")
|
|
425
535
|
def publish(
|
|
426
536
|
self,
|
|
427
|
-
datasource_item
|
|
428
|
-
file
|
|
429
|
-
mode
|
|
430
|
-
connection_credentials
|
|
431
|
-
connections
|
|
432
|
-
as_job
|
|
433
|
-
)
|
|
537
|
+
datasource_item,
|
|
538
|
+
file,
|
|
539
|
+
mode,
|
|
540
|
+
connection_credentials=None,
|
|
541
|
+
connections=None,
|
|
542
|
+
as_job=False,
|
|
543
|
+
):
|
|
434
544
|
"""
|
|
435
545
|
Publishes a data source to a server, or appends data to an existing
|
|
436
546
|
data source.
|
|
@@ -576,7 +686,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
576
686
|
datasource_or_connection_item: Union[DatasourceItem, ConnectionItem, str],
|
|
577
687
|
*,
|
|
578
688
|
request_id: str,
|
|
579
|
-
actions: Sequence[
|
|
689
|
+
actions: Sequence[HyperAction],
|
|
580
690
|
payload: Optional[FilePath] = None,
|
|
581
691
|
) -> JobItem:
|
|
582
692
|
"""
|
|
@@ -733,7 +843,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
733
843
|
self._data_quality_warnings.populate(item)
|
|
734
844
|
|
|
735
845
|
@api(version="3.5")
|
|
736
|
-
def update_dqw(self, item, warning):
|
|
846
|
+
def update_dqw(self, item: DatasourceItem, warning: "DQWItem") -> list["DQWItem"]:
|
|
737
847
|
"""
|
|
738
848
|
Update the warning type, status, and message of a data quality warning.
|
|
739
849
|
|
|
@@ -755,7 +865,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
755
865
|
return self._data_quality_warnings.update(item, warning)
|
|
756
866
|
|
|
757
867
|
@api(version="3.5")
|
|
758
|
-
def add_dqw(self, item, warning):
|
|
868
|
+
def add_dqw(self, item: DatasourceItem, warning: "DQWItem") -> list["DQWItem"]:
|
|
759
869
|
"""
|
|
760
870
|
Add a data quality warning to a datasource.
|
|
761
871
|
|
|
@@ -786,7 +896,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
786
896
|
return self._data_quality_warnings.add(item, warning)
|
|
787
897
|
|
|
788
898
|
@api(version="3.5")
|
|
789
|
-
def delete_dqw(self, item):
|
|
899
|
+
def delete_dqw(self, item: DatasourceItem) -> None:
|
|
790
900
|
"""
|
|
791
901
|
Delete a data quality warnings from an asset.
|
|
792
902
|
|
|
@@ -843,15 +953,35 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
|
|
|
843
953
|
revisions = RevisionItem.from_response(server_response.content, self.parent_srv.namespace, datasource_item)
|
|
844
954
|
return revisions
|
|
845
955
|
|
|
846
|
-
|
|
847
|
-
|
|
956
|
+
T = TypeVar("T", bound=FileObjectW)
|
|
957
|
+
|
|
958
|
+
@overload
|
|
848
959
|
def download_revision(
|
|
849
960
|
self,
|
|
850
961
|
datasource_id: str,
|
|
851
962
|
revision_number: Optional[str],
|
|
852
|
-
filepath:
|
|
963
|
+
filepath: T,
|
|
853
964
|
include_extract: bool = True,
|
|
854
|
-
) ->
|
|
965
|
+
) -> T: ...
|
|
966
|
+
|
|
967
|
+
@overload
|
|
968
|
+
def download_revision(
|
|
969
|
+
self,
|
|
970
|
+
datasource_id: str,
|
|
971
|
+
revision_number: Optional[str],
|
|
972
|
+
filepath: Optional[FilePath] = None,
|
|
973
|
+
include_extract: bool = True,
|
|
974
|
+
) -> str: ...
|
|
975
|
+
|
|
976
|
+
# Download 1 datasource revision by revision number
|
|
977
|
+
@api(version="2.3")
|
|
978
|
+
def download_revision(
|
|
979
|
+
self,
|
|
980
|
+
datasource_id,
|
|
981
|
+
revision_number,
|
|
982
|
+
filepath=None,
|
|
983
|
+
include_extract=True,
|
|
984
|
+
):
|
|
855
985
|
"""
|
|
856
986
|
Downloads a specific version of a data source prior to the current one
|
|
857
987
|
in .tdsx format. To download the current version of a data source set
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Callable, Optional, Protocol, TYPE_CHECKING
|
|
2
3
|
|
|
3
4
|
from .endpoint import Endpoint
|
|
4
5
|
from .exceptions import MissingRequiredFieldError
|
|
@@ -7,6 +8,15 @@ from tableauserverclient.models import DQWItem
|
|
|
7
8
|
|
|
8
9
|
from tableauserverclient.helpers.logging import logger
|
|
9
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from tableauserverclient.server.request_options import RequestOptions
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class HasId(Protocol):
|
|
16
|
+
@property
|
|
17
|
+
def id(self) -> Optional[str]: ...
|
|
18
|
+
def _set_data_quality_warnings(self, dqw: Callable[[], list[DQWItem]]): ...
|
|
19
|
+
|
|
10
20
|
|
|
11
21
|
class _DataQualityWarningEndpoint(Endpoint):
|
|
12
22
|
def __init__(self, parent_srv, resource_type):
|
|
@@ -14,12 +24,12 @@ class _DataQualityWarningEndpoint(Endpoint):
|
|
|
14
24
|
self.resource_type = resource_type
|
|
15
25
|
|
|
16
26
|
@property
|
|
17
|
-
def baseurl(self):
|
|
27
|
+
def baseurl(self) -> str:
|
|
18
28
|
return "{}/sites/{}/dataQualityWarnings/{}".format(
|
|
19
29
|
self.parent_srv.baseurl, self.parent_srv.site_id, self.resource_type
|
|
20
30
|
)
|
|
21
31
|
|
|
22
|
-
def add(self, resource, warning):
|
|
32
|
+
def add(self, resource: HasId, warning: DQWItem) -> list[DQWItem]:
|
|
23
33
|
url = f"{self.baseurl}/{resource.id}"
|
|
24
34
|
add_req = RequestFactory.DQW.add_req(warning)
|
|
25
35
|
response = self.post_request(url, add_req)
|
|
@@ -28,7 +38,7 @@ class _DataQualityWarningEndpoint(Endpoint):
|
|
|
28
38
|
|
|
29
39
|
return warnings
|
|
30
40
|
|
|
31
|
-
def update(self, resource, warning):
|
|
41
|
+
def update(self, resource: HasId, warning: DQWItem) -> list[DQWItem]:
|
|
32
42
|
url = f"{self.baseurl}/{resource.id}"
|
|
33
43
|
add_req = RequestFactory.DQW.update_req(warning)
|
|
34
44
|
response = self.put_request(url, add_req)
|
|
@@ -37,11 +47,11 @@ class _DataQualityWarningEndpoint(Endpoint):
|
|
|
37
47
|
|
|
38
48
|
return warnings
|
|
39
49
|
|
|
40
|
-
def clear(self, resource):
|
|
50
|
+
def clear(self, resource: HasId) -> None:
|
|
41
51
|
url = f"{self.baseurl}/{resource.id}"
|
|
42
52
|
return self.delete_request(url)
|
|
43
53
|
|
|
44
|
-
def populate(self, item):
|
|
54
|
+
def populate(self, item: HasId) -> None:
|
|
45
55
|
if not item.id:
|
|
46
56
|
error = "Server item is missing ID. Item must be retrieved from server first."
|
|
47
57
|
raise MissingRequiredFieldError(error)
|
|
@@ -52,7 +62,7 @@ class _DataQualityWarningEndpoint(Endpoint):
|
|
|
52
62
|
item._set_data_quality_warnings(dqw_fetcher)
|
|
53
63
|
logger.info(f"Populated permissions for item (ID: {item.id})")
|
|
54
64
|
|
|
55
|
-
def _get_data_quality_warnings(self, item, req_options=None):
|
|
65
|
+
def _get_data_quality_warnings(self, item: HasId, req_options: Optional["RequestOptions"] = None) -> list[DQWItem]:
|
|
56
66
|
url = f"{self.baseurl}/{item.id}"
|
|
57
67
|
server_response = self.get_request(url, req_options)
|
|
58
68
|
dqws = DQWItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
@@ -14,6 +14,7 @@ from typing import (
|
|
|
14
14
|
TypeVar,
|
|
15
15
|
Union,
|
|
16
16
|
)
|
|
17
|
+
from typing_extensions import Self
|
|
17
18
|
|
|
18
19
|
from tableauserverclient.models.pagination_item import PaginationItem
|
|
19
20
|
from tableauserverclient.server.request_options import RequestOptions
|
|
@@ -353,3 +354,41 @@ class QuerysetEndpoint(Endpoint, Generic[T]):
|
|
|
353
354
|
@abc.abstractmethod
|
|
354
355
|
def get(self, request_options: Optional[RequestOptions] = None) -> tuple[list[T], PaginationItem]:
|
|
355
356
|
raise NotImplementedError(f".get has not been implemented for {self.__class__.__qualname__}")
|
|
357
|
+
|
|
358
|
+
def fields(self: Self, *fields: str) -> QuerySet:
|
|
359
|
+
"""
|
|
360
|
+
Add fields to the request options. If no fields are provided, the
|
|
361
|
+
default fields will be used. If fields are provided, the default fields
|
|
362
|
+
will be used in addition to the provided fields.
|
|
363
|
+
|
|
364
|
+
Parameters
|
|
365
|
+
----------
|
|
366
|
+
fields : str
|
|
367
|
+
The fields to include in the request options.
|
|
368
|
+
|
|
369
|
+
Returns
|
|
370
|
+
-------
|
|
371
|
+
QuerySet
|
|
372
|
+
"""
|
|
373
|
+
queryset = QuerySet(self)
|
|
374
|
+
queryset.request_options.fields |= set(fields) | set(("_default_",))
|
|
375
|
+
return queryset
|
|
376
|
+
|
|
377
|
+
def only_fields(self: Self, *fields: str) -> QuerySet:
|
|
378
|
+
"""
|
|
379
|
+
Add fields to the request options. If no fields are provided, the
|
|
380
|
+
default fields will be used. If fields are provided, the default fields
|
|
381
|
+
will be replaced by the provided fields.
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
fields : str
|
|
386
|
+
The fields to include in the request options.
|
|
387
|
+
|
|
388
|
+
Returns
|
|
389
|
+
-------
|
|
390
|
+
QuerySet
|
|
391
|
+
"""
|
|
392
|
+
queryset = QuerySet(self)
|
|
393
|
+
queryset.request_options.fields |= set(fields)
|
|
394
|
+
return queryset
|