tableauserverclient 0.33__py3-none-any.whl → 0.35__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 +33 -23
- tableauserverclient/{_version.py → bin/_version.py} +3 -3
- tableauserverclient/config.py +5 -3
- tableauserverclient/models/column_item.py +1 -1
- tableauserverclient/models/connection_credentials.py +18 -2
- tableauserverclient/models/connection_item.py +44 -6
- tableauserverclient/models/custom_view_item.py +78 -11
- 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 +54 -9
- tableauserverclient/models/flow_run_item.py +3 -3
- tableauserverclient/models/group_item.py +44 -4
- tableauserverclient/models/groupset_item.py +4 -4
- tableauserverclient/models/interval_item.py +9 -9
- tableauserverclient/models/job_item.py +73 -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 +73 -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 +34 -4
- tableauserverclient/models/user_item.py +47 -17
- tableauserverclient/models/view_item.py +66 -13
- tableauserverclient/models/virtual_connection_item.py +6 -5
- tableauserverclient/models/webhook_item.py +39 -6
- tableauserverclient/models/workbook_item.py +116 -13
- tableauserverclient/namespace.py +1 -1
- tableauserverclient/server/__init__.py +2 -1
- tableauserverclient/server/endpoint/auth_endpoint.py +69 -10
- tableauserverclient/server/endpoint/custom_views_endpoint.py +258 -29
- 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 +61 -62
- 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 +344 -29
- tableauserverclient/server/endpoint/groups_endpoint.py +342 -27
- tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
- tableauserverclient/server/endpoint/jobs_endpoint.py +116 -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 +681 -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 +86 -8
- tableauserverclient/server/endpoint/users_endpoint.py +366 -19
- tableauserverclient/server/endpoint/views_endpoint.py +262 -20
- tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
- tableauserverclient/server/endpoint/webhooks_endpoint.py +88 -11
- tableauserverclient/server/endpoint/workbooks_endpoint.py +653 -65
- tableauserverclient/server/filter.py +2 -2
- tableauserverclient/server/pager.py +29 -6
- tableauserverclient/server/query.py +68 -19
- tableauserverclient/server/request_factory.py +57 -37
- tableauserverclient/server/request_options.py +243 -141
- tableauserverclient/server/server.py +76 -10
- tableauserverclient/server/sort.py +16 -2
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/METADATA +7 -7
- tableauserverclient-0.35.dist-info/RECORD +106 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/WHEEL +1 -1
- tableauserverclient-0.33.dist-info/RECORD +0 -106
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/top_level.txt +0 -0
tableauserverclient/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from tableauserverclient._version import get_versions
|
|
1
|
+
from tableauserverclient.bin._version import get_versions
|
|
2
2
|
from tableauserverclient.namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
|
|
3
3
|
from tableauserverclient.models import (
|
|
4
4
|
BackgroundJobItem,
|
|
@@ -32,11 +32,13 @@ from tableauserverclient.models import (
|
|
|
32
32
|
PermissionsRule,
|
|
33
33
|
PersonalAccessTokenAuth,
|
|
34
34
|
ProjectItem,
|
|
35
|
+
Resource,
|
|
35
36
|
RevisionItem,
|
|
36
37
|
ScheduleItem,
|
|
37
38
|
SiteItem,
|
|
38
39
|
ServerInfoItem,
|
|
39
40
|
SubscriptionItem,
|
|
41
|
+
TableauItem,
|
|
40
42
|
TableItem,
|
|
41
43
|
TableauAuth,
|
|
42
44
|
Target,
|
|
@@ -56,6 +58,7 @@ from tableauserverclient.server import (
|
|
|
56
58
|
PDFRequestOptions,
|
|
57
59
|
RequestOptions,
|
|
58
60
|
MissingRequiredFieldError,
|
|
61
|
+
FailedSignInError,
|
|
59
62
|
NotSignedInError,
|
|
60
63
|
ServerResponseError,
|
|
61
64
|
Filter,
|
|
@@ -65,65 +68,72 @@ from tableauserverclient.server import (
|
|
|
65
68
|
)
|
|
66
69
|
|
|
67
70
|
__all__ = [
|
|
68
|
-
"get_versions",
|
|
69
|
-
"DEFAULT_NAMESPACE",
|
|
70
71
|
"BackgroundJobItem",
|
|
71
72
|
"BackgroundJobItem",
|
|
72
73
|
"ColumnItem",
|
|
73
74
|
"ConnectionCredentials",
|
|
74
75
|
"ConnectionItem",
|
|
76
|
+
"CSVRequestOptions",
|
|
75
77
|
"CustomViewItem",
|
|
76
|
-
"DQWItem",
|
|
77
78
|
"DailyInterval",
|
|
78
79
|
"DataAlertItem",
|
|
79
80
|
"DatabaseItem",
|
|
80
81
|
"DataFreshnessPolicyItem",
|
|
81
82
|
"DatasourceItem",
|
|
83
|
+
"DEFAULT_NAMESPACE",
|
|
84
|
+
"DQWItem",
|
|
85
|
+
"ExcelRequestOptions",
|
|
86
|
+
"FailedSignInError",
|
|
82
87
|
"FavoriteItem",
|
|
88
|
+
"FileuploadItem",
|
|
89
|
+
"Filter",
|
|
83
90
|
"FlowItem",
|
|
84
91
|
"FlowRunItem",
|
|
85
|
-
"
|
|
92
|
+
"get_versions",
|
|
86
93
|
"GroupItem",
|
|
87
94
|
"GroupSetItem",
|
|
88
95
|
"HourlyInterval",
|
|
96
|
+
"ImageRequestOptions",
|
|
89
97
|
"IntervalItem",
|
|
90
98
|
"JobItem",
|
|
91
99
|
"JWTAuth",
|
|
100
|
+
"LinkedTaskFlowRunItem",
|
|
101
|
+
"LinkedTaskItem",
|
|
102
|
+
"LinkedTaskStepItem",
|
|
92
103
|
"MetricItem",
|
|
104
|
+
"MissingRequiredFieldError",
|
|
93
105
|
"MonthlyInterval",
|
|
106
|
+
"NotSignedInError",
|
|
107
|
+
"Pager",
|
|
94
108
|
"PaginationItem",
|
|
109
|
+
"PDFRequestOptions",
|
|
95
110
|
"Permission",
|
|
96
111
|
"PermissionsRule",
|
|
97
112
|
"PersonalAccessTokenAuth",
|
|
98
113
|
"ProjectItem",
|
|
114
|
+
"RequestOptions",
|
|
115
|
+
"Resource",
|
|
99
116
|
"RevisionItem",
|
|
100
117
|
"ScheduleItem",
|
|
101
|
-
"
|
|
118
|
+
"Server",
|
|
102
119
|
"ServerInfoItem",
|
|
120
|
+
"ServerResponseError",
|
|
121
|
+
"SiteItem",
|
|
122
|
+
"Sort",
|
|
103
123
|
"SubscriptionItem",
|
|
104
|
-
"TableItem",
|
|
105
124
|
"TableauAuth",
|
|
125
|
+
"TableauItem",
|
|
126
|
+
"TableItem",
|
|
106
127
|
"Target",
|
|
107
128
|
"TaskItem",
|
|
108
129
|
"UserItem",
|
|
109
130
|
"ViewItem",
|
|
131
|
+
"VirtualConnectionItem",
|
|
110
132
|
"WebhookItem",
|
|
111
133
|
"WeeklyInterval",
|
|
112
134
|
"WorkbookItem",
|
|
113
|
-
"CSVRequestOptions",
|
|
114
|
-
"ExcelRequestOptions",
|
|
115
|
-
"ImageRequestOptions",
|
|
116
|
-
"PDFRequestOptions",
|
|
117
|
-
"RequestOptions",
|
|
118
|
-
"MissingRequiredFieldError",
|
|
119
|
-
"NotSignedInError",
|
|
120
|
-
"ServerResponseError",
|
|
121
|
-
"Filter",
|
|
122
|
-
"Pager",
|
|
123
|
-
"Server",
|
|
124
|
-
"Sort",
|
|
125
|
-
"LinkedTaskItem",
|
|
126
|
-
"LinkedTaskStepItem",
|
|
127
|
-
"LinkedTaskFlowRunItem",
|
|
128
|
-
"VirtualConnectionItem",
|
|
129
135
|
]
|
|
136
|
+
|
|
137
|
+
from .bin import _version
|
|
138
|
+
|
|
139
|
+
__version__ = _version.get_versions()["version"]
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "
|
|
11
|
+
"date": "2025-01-03T19:22:57-0800",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "c5e016fe5320267f795de4252b0dc92fa84495b5",
|
|
15
|
+
"version": "0.35"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
tableauserverclient/config.py
CHANGED
|
@@ -6,11 +6,13 @@ BYTES_PER_MB = 1024 * 1024
|
|
|
6
6
|
|
|
7
7
|
DELAY_SLEEP_SECONDS = 0.1
|
|
8
8
|
|
|
9
|
-
# The maximum size of a file that can be published in a single request is 64MB
|
|
10
|
-
FILESIZE_LIMIT_MB = 64
|
|
11
|
-
|
|
12
9
|
|
|
13
10
|
class Config:
|
|
11
|
+
# The maximum size of a file that can be published in a single request is 64MB
|
|
12
|
+
@property
|
|
13
|
+
def FILESIZE_LIMIT_MB(self):
|
|
14
|
+
return min(int(os.getenv("TSC_FILESIZE_LIMIT_MB", 64)), 64)
|
|
15
|
+
|
|
14
16
|
# For when a datasource is over 64MB, break it into 5MB(standard chunk size) chunks
|
|
15
17
|
@property
|
|
16
18
|
def CHUNK_SIZE_MB(self):
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
from .property_decorators import property_is_boolean
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class ConnectionCredentials
|
|
5
|
-
"""
|
|
4
|
+
class ConnectionCredentials:
|
|
5
|
+
"""
|
|
6
|
+
Connection Credentials for Workbooks and Datasources publish request.
|
|
6
7
|
|
|
7
8
|
Consider removing this object and other variables holding secrets
|
|
8
9
|
as soon as possible after use to avoid them hanging around in memory.
|
|
9
10
|
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
name: str
|
|
14
|
+
The username for the connection.
|
|
15
|
+
|
|
16
|
+
password: str
|
|
17
|
+
The password used for the connection.
|
|
18
|
+
|
|
19
|
+
embed: bool, default True
|
|
20
|
+
Determines whether to embed the password (True) for the workbook or data source connection or not (False).
|
|
21
|
+
|
|
22
|
+
oauth: bool, default False
|
|
23
|
+
Determines whether to use OAuth for the connection (True) or not (False).
|
|
24
|
+
For more information see: https://help.tableau.com/current/server/en-us/protected_auth.htm
|
|
25
|
+
|
|
10
26
|
"""
|
|
11
27
|
|
|
12
28
|
def __init__(self, name, password, embed=True, oauth=False):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from defusedxml.ElementTree import fromstring
|
|
5
5
|
|
|
@@ -8,7 +8,45 @@ from .property_decorators import property_is_boolean
|
|
|
8
8
|
from tableauserverclient.helpers.logging import logger
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class ConnectionItem
|
|
11
|
+
class ConnectionItem:
|
|
12
|
+
"""
|
|
13
|
+
Corresponds to workbook and data source connections.
|
|
14
|
+
|
|
15
|
+
Attributes
|
|
16
|
+
----------
|
|
17
|
+
datasource_id: str
|
|
18
|
+
The identifier of the data source.
|
|
19
|
+
|
|
20
|
+
datasource_name: str
|
|
21
|
+
The name of the data source.
|
|
22
|
+
|
|
23
|
+
id: str
|
|
24
|
+
The identifier of the connection.
|
|
25
|
+
|
|
26
|
+
connection_type: str
|
|
27
|
+
The type of connection.
|
|
28
|
+
|
|
29
|
+
username: str
|
|
30
|
+
The username for the connection. (see ConnectionCredentials)
|
|
31
|
+
|
|
32
|
+
password: str
|
|
33
|
+
The password used for the connection. (see ConnectionCredentials)
|
|
34
|
+
|
|
35
|
+
embed_password: bool
|
|
36
|
+
Determines whether to embed the password (True) for the workbook or data source connection or not (False). (see ConnectionCredentials)
|
|
37
|
+
|
|
38
|
+
server_address: str
|
|
39
|
+
The server address for the connection.
|
|
40
|
+
|
|
41
|
+
server_port: str
|
|
42
|
+
The port used for the connection.
|
|
43
|
+
|
|
44
|
+
connection_credentials: ConnectionCredentials
|
|
45
|
+
The Connection Credentials object containing authentication details for
|
|
46
|
+
the connection. Replaces username/password/embed_password when
|
|
47
|
+
publishing a flow, document or workbook file in the request body.
|
|
48
|
+
"""
|
|
49
|
+
|
|
12
50
|
def __init__(self):
|
|
13
51
|
self._datasource_id: Optional[str] = None
|
|
14
52
|
self._datasource_name: Optional[str] = None
|
|
@@ -48,7 +86,7 @@ class ConnectionItem(object):
|
|
|
48
86
|
# if connection type = hyper, Snowflake, or Teradata, we can't change this value: it is always true
|
|
49
87
|
if self._connection_type in ["hyper", "snowflake", "teradata"]:
|
|
50
88
|
logger.debug(
|
|
51
|
-
"Cannot update value: Query tagging is always enabled for {} connections"
|
|
89
|
+
f"Cannot update value: Query tagging is always enabled for {self._connection_type} connections"
|
|
52
90
|
)
|
|
53
91
|
return
|
|
54
92
|
self._query_tagging = value
|
|
@@ -59,7 +97,7 @@ class ConnectionItem(object):
|
|
|
59
97
|
)
|
|
60
98
|
|
|
61
99
|
@classmethod
|
|
62
|
-
def from_response(cls, resp, ns) ->
|
|
100
|
+
def from_response(cls, resp, ns) -> list["ConnectionItem"]:
|
|
63
101
|
all_connection_items = list()
|
|
64
102
|
parsed_response = fromstring(resp)
|
|
65
103
|
all_connection_xml = parsed_response.findall(".//t:connection", namespaces=ns)
|
|
@@ -82,7 +120,7 @@ class ConnectionItem(object):
|
|
|
82
120
|
return all_connection_items
|
|
83
121
|
|
|
84
122
|
@classmethod
|
|
85
|
-
def from_xml_element(cls, parsed_response, ns) ->
|
|
123
|
+
def from_xml_element(cls, parsed_response, ns) -> list["ConnectionItem"]:
|
|
86
124
|
"""
|
|
87
125
|
<connections>
|
|
88
126
|
<connection serverAddress="mysql.test.com">
|
|
@@ -93,7 +131,7 @@ class ConnectionItem(object):
|
|
|
93
131
|
</connection>
|
|
94
132
|
</connections>
|
|
95
133
|
"""
|
|
96
|
-
all_connection_items:
|
|
134
|
+
all_connection_items: list["ConnectionItem"] = list()
|
|
97
135
|
all_connection_xml = parsed_response.findall(".//t:connection", namespaces=ns)
|
|
98
136
|
|
|
99
137
|
for connection_xml in all_connection_xml:
|
|
@@ -2,21 +2,68 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
from defusedxml import ElementTree
|
|
4
4
|
from defusedxml.ElementTree import fromstring, tostring
|
|
5
|
-
from typing import Callable,
|
|
5
|
+
from typing import Callable, Optional
|
|
6
|
+
from collections.abc import Iterator
|
|
6
7
|
|
|
7
|
-
from .exceptions import UnpopulatedPropertyError
|
|
8
|
-
from .user_item import UserItem
|
|
9
|
-
from .view_item import ViewItem
|
|
10
|
-
from .workbook_item import WorkbookItem
|
|
11
|
-
from
|
|
8
|
+
from tableauserverclient.models.exceptions import UnpopulatedPropertyError
|
|
9
|
+
from tableauserverclient.models.user_item import UserItem
|
|
10
|
+
from tableauserverclient.models.view_item import ViewItem
|
|
11
|
+
from tableauserverclient.models.workbook_item import WorkbookItem
|
|
12
|
+
from tableauserverclient.datetime_helpers import parse_datetime
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class CustomViewItem
|
|
15
|
+
class CustomViewItem:
|
|
16
|
+
"""
|
|
17
|
+
Represents a Custom View item on Tableau Server.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
id : Optional[str]
|
|
22
|
+
The ID of the Custom View item.
|
|
23
|
+
|
|
24
|
+
name : Optional[str]
|
|
25
|
+
The name of the Custom View item.
|
|
26
|
+
|
|
27
|
+
Attributes
|
|
28
|
+
----------
|
|
29
|
+
content_url : Optional[str]
|
|
30
|
+
The content URL of the Custom View item.
|
|
31
|
+
|
|
32
|
+
created_at : Optional[datetime]
|
|
33
|
+
The date and time the Custom View item was created.
|
|
34
|
+
|
|
35
|
+
image: bytes
|
|
36
|
+
The image of the Custom View item. Must be populated first.
|
|
37
|
+
|
|
38
|
+
pdf: bytes
|
|
39
|
+
The PDF of the Custom View item. Must be populated first.
|
|
40
|
+
|
|
41
|
+
csv: Iterator[bytes]
|
|
42
|
+
The CSV of the Custom View item. Must be populated first.
|
|
43
|
+
|
|
44
|
+
shared : Optional[bool]
|
|
45
|
+
Whether the Custom View item is shared.
|
|
46
|
+
|
|
47
|
+
updated_at : Optional[datetime]
|
|
48
|
+
The date and time the Custom View item was last updated.
|
|
49
|
+
|
|
50
|
+
owner : Optional[UserItem]
|
|
51
|
+
The id of the owner of the Custom View item.
|
|
52
|
+
|
|
53
|
+
workbook : Optional[WorkbookItem]
|
|
54
|
+
The id of the workbook the Custom View item belongs to.
|
|
55
|
+
|
|
56
|
+
view : Optional[ViewItem]
|
|
57
|
+
The id of the view the Custom View item belongs to.
|
|
58
|
+
"""
|
|
59
|
+
|
|
15
60
|
def __init__(self, id: Optional[str] = None, name: Optional[str] = None) -> None:
|
|
16
61
|
self._content_url: Optional[str] = None # ?
|
|
17
62
|
self._created_at: Optional["datetime"] = None
|
|
18
63
|
self._id: Optional[str] = id
|
|
19
64
|
self._image: Optional[Callable[[], bytes]] = None
|
|
65
|
+
self._pdf: Optional[Callable[[], bytes]] = None
|
|
66
|
+
self._csv: Optional[Callable[[], Iterator[bytes]]] = None
|
|
20
67
|
self._name: Optional[str] = name
|
|
21
68
|
self._shared: Optional[bool] = False
|
|
22
69
|
self._updated_at: Optional["datetime"] = None
|
|
@@ -35,11 +82,17 @@ class CustomViewItem(object):
|
|
|
35
82
|
owner_info = ""
|
|
36
83
|
if self._owner:
|
|
37
84
|
owner_info = " owner='{}'".format(self._owner.name or self._owner.id or "unknown")
|
|
38
|
-
return "<CustomViewItem id={} name=`{}`{}{}{}>"
|
|
85
|
+
return f"<CustomViewItem id={self.id} name=`{self.name}`{view_info}{wb_info}{owner_info}>"
|
|
39
86
|
|
|
40
87
|
def _set_image(self, image):
|
|
41
88
|
self._image = image
|
|
42
89
|
|
|
90
|
+
def _set_pdf(self, pdf):
|
|
91
|
+
self._pdf = pdf
|
|
92
|
+
|
|
93
|
+
def _set_csv(self, csv):
|
|
94
|
+
self._csv = csv
|
|
95
|
+
|
|
43
96
|
@property
|
|
44
97
|
def content_url(self) -> Optional[str]:
|
|
45
98
|
return self._content_url
|
|
@@ -55,10 +108,24 @@ class CustomViewItem(object):
|
|
|
55
108
|
@property
|
|
56
109
|
def image(self) -> bytes:
|
|
57
110
|
if self._image is None:
|
|
58
|
-
error = "View item must be populated with its png image first."
|
|
111
|
+
error = "Custom View item must be populated with its png image first."
|
|
59
112
|
raise UnpopulatedPropertyError(error)
|
|
60
113
|
return self._image()
|
|
61
114
|
|
|
115
|
+
@property
|
|
116
|
+
def pdf(self) -> bytes:
|
|
117
|
+
if self._pdf is None:
|
|
118
|
+
error = "Custom View item must be populated with its pdf first."
|
|
119
|
+
raise UnpopulatedPropertyError(error)
|
|
120
|
+
return self._pdf()
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def csv(self) -> Iterator[bytes]:
|
|
124
|
+
if self._csv is None:
|
|
125
|
+
error = "Custom View item must be populated with its csv first."
|
|
126
|
+
raise UnpopulatedPropertyError(error)
|
|
127
|
+
return self._csv()
|
|
128
|
+
|
|
62
129
|
@property
|
|
63
130
|
def name(self) -> Optional[str]:
|
|
64
131
|
return self._name
|
|
@@ -104,7 +171,7 @@ class CustomViewItem(object):
|
|
|
104
171
|
return item[0]
|
|
105
172
|
|
|
106
173
|
@classmethod
|
|
107
|
-
def list_from_response(cls, resp, ns, workbook_id="") ->
|
|
174
|
+
def list_from_response(cls, resp, ns, workbook_id="") -> list["CustomViewItem"]:
|
|
108
175
|
return cls.from_xml_element(fromstring(resp), ns, workbook_id)
|
|
109
176
|
|
|
110
177
|
"""
|
|
@@ -121,7 +188,7 @@ class CustomViewItem(object):
|
|
|
121
188
|
"""
|
|
122
189
|
|
|
123
190
|
@classmethod
|
|
124
|
-
def from_xml_element(cls, parsed_response, ns, workbook_id="") ->
|
|
191
|
+
def from_xml_element(cls, parsed_response, ns, workbook_id="") -> list["CustomViewItem"]:
|
|
125
192
|
all_view_items = list()
|
|
126
193
|
all_view_xml = parsed_response.findall(".//t:customView", namespaces=ns)
|
|
127
194
|
for custom_view_xml in all_view_xml:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from defusedxml.ElementTree import fromstring
|
|
5
5
|
|
|
@@ -10,7 +10,7 @@ from .property_decorators import (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class DataAlertItem
|
|
13
|
+
class DataAlertItem:
|
|
14
14
|
class Frequency:
|
|
15
15
|
Once = "Once"
|
|
16
16
|
Frequently = "Frequently"
|
|
@@ -34,7 +34,7 @@ class DataAlertItem(object):
|
|
|
34
34
|
self._workbook_name: Optional[str] = None
|
|
35
35
|
self._project_id: Optional[str] = None
|
|
36
36
|
self._project_name: Optional[str] = None
|
|
37
|
-
self._recipients: Optional[
|
|
37
|
+
self._recipients: Optional[list[str]] = None
|
|
38
38
|
|
|
39
39
|
def __repr__(self) -> str:
|
|
40
40
|
return "<Data Alert {_id} subject={_subject} frequency={_frequency} \
|
|
@@ -78,7 +78,7 @@ class DataAlertItem(object):
|
|
|
78
78
|
return self._creatorId
|
|
79
79
|
|
|
80
80
|
@property
|
|
81
|
-
def recipients(self) ->
|
|
81
|
+
def recipients(self) -> list[str]:
|
|
82
82
|
return self._recipients or list()
|
|
83
83
|
|
|
84
84
|
@property
|
|
@@ -174,7 +174,7 @@ class DataAlertItem(object):
|
|
|
174
174
|
self._recipients = recipients
|
|
175
175
|
|
|
176
176
|
@classmethod
|
|
177
|
-
def from_response(cls, resp, ns) ->
|
|
177
|
+
def from_response(cls, resp, ns) -> list["DataAlertItem"]:
|
|
178
178
|
all_alert_items = list()
|
|
179
179
|
parsed_response = fromstring(resp)
|
|
180
180
|
all_alert_xml = parsed_response.findall(".//t:dataAlert", namespaces=ns)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Optional
|
|
4
4
|
from tableauserverclient.models.property_decorators import property_is_enum, property_not_nullable
|
|
5
5
|
from .interval_item import IntervalItem
|
|
6
6
|
|
|
@@ -50,11 +50,11 @@ class DataFreshnessPolicyItem:
|
|
|
50
50
|
Week = "Week"
|
|
51
51
|
Month = "Month"
|
|
52
52
|
|
|
53
|
-
def __init__(self, frequency: str, time: str, timezone, interval_item: Optional[
|
|
53
|
+
def __init__(self, frequency: str, time: str, timezone, interval_item: Optional[list[str]] = None):
|
|
54
54
|
self.frequency = frequency
|
|
55
55
|
self.time = time
|
|
56
56
|
self.timezone = timezone
|
|
57
|
-
self.interval_item: Optional[
|
|
57
|
+
self.interval_item: Optional[list[str]] = interval_item
|
|
58
58
|
|
|
59
59
|
def __repr__(self):
|
|
60
60
|
return (
|
|
@@ -62,11 +62,11 @@ class DataFreshnessPolicyItem:
|
|
|
62
62
|
).format(**vars(self))
|
|
63
63
|
|
|
64
64
|
@property
|
|
65
|
-
def interval_item(self) -> Optional[
|
|
65
|
+
def interval_item(self) -> Optional[list[str]]:
|
|
66
66
|
return self._interval_item
|
|
67
67
|
|
|
68
68
|
@interval_item.setter
|
|
69
|
-
def interval_item(self, value:
|
|
69
|
+
def interval_item(self, value: list[str]):
|
|
70
70
|
self._interval_item = value
|
|
71
71
|
|
|
72
72
|
@property
|
|
@@ -186,7 +186,7 @@ def parse_week_intervals(interval_values):
|
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
def parse_month_intervals(interval_values):
|
|
189
|
-
error = "Invalid interval value for a monthly frequency: {}."
|
|
189
|
+
error = f"Invalid interval value for a monthly frequency: {interval_values}."
|
|
190
190
|
|
|
191
191
|
# Month interval can have value either only ['LastDay'] or list of dates e.g. ["1", 20", "30"]
|
|
192
192
|
# First check if the list only have LastDay value. When using LastDay, there shouldn't be
|
|
@@ -10,7 +10,7 @@ from .property_decorators import (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class DatabaseItem
|
|
13
|
+
class DatabaseItem:
|
|
14
14
|
class ContentPermissions:
|
|
15
15
|
LockedToProject = "LockedToDatabase"
|
|
16
16
|
ManagedByOwner = "ManagedByOwner"
|
|
@@ -45,7 +45,7 @@ class DatabaseItem(object):
|
|
|
45
45
|
self._tables = None # Not implemented yet
|
|
46
46
|
|
|
47
47
|
def __str__(self):
|
|
48
|
-
return "<Database {
|
|
48
|
+
return f"<Database {self._id} '{self.name}'>"
|
|
49
49
|
|
|
50
50
|
def __repr__(self):
|
|
51
51
|
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
|
|
@@ -250,7 +250,7 @@ class DatabaseItem(object):
|
|
|
250
250
|
self._tables = tables
|
|
251
251
|
|
|
252
252
|
def _set_default_permissions(self, permissions, content_type):
|
|
253
|
-
attr = "_default_{
|
|
253
|
+
attr = f"_default_{content_type}_permissions"
|
|
254
254
|
setattr(
|
|
255
255
|
self,
|
|
256
256
|
attr,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import datetime
|
|
3
3
|
import xml.etree.ElementTree as ET
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional
|
|
5
5
|
|
|
6
6
|
from defusedxml.ElementTree import fromstring
|
|
7
7
|
|
|
@@ -18,14 +18,14 @@ from tableauserverclient.models.revision_item import RevisionItem
|
|
|
18
18
|
from tableauserverclient.models.tag_item import TagItem
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class DatasourceItem
|
|
21
|
+
class DatasourceItem:
|
|
22
22
|
class AskDataEnablement:
|
|
23
23
|
Enabled = "Enabled"
|
|
24
24
|
Disabled = "Disabled"
|
|
25
25
|
SiteDefault = "SiteDefault"
|
|
26
26
|
|
|
27
27
|
def __repr__(self):
|
|
28
|
-
return "<Datasource {
|
|
28
|
+
return "<Datasource {} '{}' ({} parent={} >".format(
|
|
29
29
|
self._id,
|
|
30
30
|
self.name,
|
|
31
31
|
self.description or "No Description",
|
|
@@ -44,7 +44,7 @@ class DatasourceItem(object):
|
|
|
44
44
|
self._encrypt_extracts = None
|
|
45
45
|
self._has_extracts = None
|
|
46
46
|
self._id: Optional[str] = None
|
|
47
|
-
self._initial_tags:
|
|
47
|
+
self._initial_tags: set = set()
|
|
48
48
|
self._project_name: Optional[str] = None
|
|
49
49
|
self._revisions = None
|
|
50
50
|
self._size: Optional[int] = None
|
|
@@ -55,7 +55,7 @@ class DatasourceItem(object):
|
|
|
55
55
|
self.name = name
|
|
56
56
|
self.owner_id: Optional[str] = None
|
|
57
57
|
self.project_id = project_id
|
|
58
|
-
self.tags:
|
|
58
|
+
self.tags: set[str] = set()
|
|
59
59
|
|
|
60
60
|
self._permissions = None
|
|
61
61
|
self._data_quality_warnings = None
|
|
@@ -72,14 +72,14 @@ class DatasourceItem(object):
|
|
|
72
72
|
self._ask_data_enablement = value
|
|
73
73
|
|
|
74
74
|
@property
|
|
75
|
-
def connections(self) -> Optional[
|
|
75
|
+
def connections(self) -> Optional[list[ConnectionItem]]:
|
|
76
76
|
if self._connections is None:
|
|
77
77
|
error = "Datasource item must be populated with connections first."
|
|
78
78
|
raise UnpopulatedPropertyError(error)
|
|
79
79
|
return self._connections()
|
|
80
80
|
|
|
81
81
|
@property
|
|
82
|
-
def permissions(self) -> Optional[
|
|
82
|
+
def permissions(self) -> Optional[list[PermissionsRule]]:
|
|
83
83
|
if self._permissions is None:
|
|
84
84
|
error = "Project item must be populated with permissions first."
|
|
85
85
|
raise UnpopulatedPropertyError(error)
|
|
@@ -177,7 +177,7 @@ class DatasourceItem(object):
|
|
|
177
177
|
return self._webpage_url
|
|
178
178
|
|
|
179
179
|
@property
|
|
180
|
-
def revisions(self) ->
|
|
180
|
+
def revisions(self) -> list[RevisionItem]:
|
|
181
181
|
if self._revisions is None:
|
|
182
182
|
error = "Datasource item must be populated with revisions first."
|
|
183
183
|
raise UnpopulatedPropertyError(error)
|
|
@@ -309,7 +309,7 @@ class DatasourceItem(object):
|
|
|
309
309
|
self._size = int(size)
|
|
310
310
|
|
|
311
311
|
@classmethod
|
|
312
|
-
def from_response(cls, resp: str, ns:
|
|
312
|
+
def from_response(cls, resp: str, ns: dict) -> list["DatasourceItem"]:
|
|
313
313
|
all_datasource_items = list()
|
|
314
314
|
parsed_response = fromstring(resp)
|
|
315
315
|
all_datasource_xml = parsed_response.findall(".//t:datasource", namespaces=ns)
|
|
@@ -326,7 +326,7 @@ class DatasourceItem(object):
|
|
|
326
326
|
return datasource_item
|
|
327
327
|
|
|
328
328
|
@staticmethod
|
|
329
|
-
def _parse_element(datasource_xml: ET.Element, ns:
|
|
329
|
+
def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
|
|
330
330
|
id_ = datasource_xml.get("id", None)
|
|
331
331
|
name = datasource_xml.get("name", None)
|
|
332
332
|
datasource_type = datasource_xml.get("type", None)
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
+
from typing import Union
|
|
3
4
|
from defusedxml.ElementTree import fromstring
|
|
4
|
-
from tableauserverclient.models.tableau_types import TableauItem
|
|
5
5
|
|
|
6
|
+
from tableauserverclient.models.tableau_types import TableauItem
|
|
6
7
|
from tableauserverclient.models.datasource_item import DatasourceItem
|
|
7
8
|
from tableauserverclient.models.flow_item import FlowItem
|
|
8
9
|
from tableauserverclient.models.project_item import ProjectItem
|
|
9
10
|
from tableauserverclient.models.metric_item import MetricItem
|
|
10
11
|
from tableauserverclient.models.view_item import ViewItem
|
|
11
12
|
from tableauserverclient.models.workbook_item import WorkbookItem
|
|
12
|
-
from typing import Dict, List
|
|
13
13
|
|
|
14
14
|
from tableauserverclient.helpers.logging import logger
|
|
15
|
-
from typing import Dict, List, Union
|
|
16
15
|
|
|
17
|
-
FavoriteType =
|
|
16
|
+
FavoriteType = dict[
|
|
18
17
|
str,
|
|
19
|
-
|
|
18
|
+
list[TableauItem],
|
|
20
19
|
]
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class FavoriteItem:
|
|
24
23
|
@classmethod
|
|
25
|
-
def from_response(cls, xml: str, namespace:
|
|
24
|
+
def from_response(cls, xml: Union[str, bytes], namespace: dict) -> FavoriteType:
|
|
26
25
|
favorites: FavoriteType = {
|
|
27
26
|
"datasources": [],
|
|
28
27
|
"flows": [],
|