tableauserverclient 0.25__py3-none-any.whl → 0.27.post0.dev1__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 +42 -1
- tableauserverclient/_version.py +4 -4
- tableauserverclient/config.py +13 -0
- tableauserverclient/datetime_helpers.py +4 -0
- tableauserverclient/helpers/logging.py +4 -0
- tableauserverclient/models/__init__.py +1 -1
- tableauserverclient/models/column_item.py +3 -0
- tableauserverclient/models/connection_credentials.py +7 -0
- tableauserverclient/models/connection_item.py +1 -1
- tableauserverclient/models/custom_view_item.py +5 -0
- tableauserverclient/models/data_acceleration_report_item.py +3 -0
- tableauserverclient/models/datasource_item.py +10 -54
- tableauserverclient/models/favorites_item.py +56 -40
- tableauserverclient/models/fileupload_item.py +2 -2
- tableauserverclient/models/flow_item.py +30 -25
- tableauserverclient/models/group_item.py +1 -4
- tableauserverclient/models/interval_item.py +12 -0
- tableauserverclient/models/job_item.py +10 -1
- tableauserverclient/models/metric_item.py +36 -29
- tableauserverclient/models/pagination_item.py +3 -0
- tableauserverclient/models/permissions_item.py +8 -5
- tableauserverclient/models/project_item.py +11 -13
- tableauserverclient/models/schedule_item.py +6 -7
- tableauserverclient/models/server_info_item.py +2 -2
- tableauserverclient/models/site_item.py +3 -0
- tableauserverclient/models/subscription_item.py +8 -0
- tableauserverclient/models/table_item.py +6 -0
- tableauserverclient/models/tableau_auth.py +41 -6
- tableauserverclient/models/tableau_types.py +4 -2
- tableauserverclient/models/user_item.py +5 -1
- tableauserverclient/models/view_item.py +39 -36
- tableauserverclient/models/workbook_item.py +14 -43
- tableauserverclient/server/__init__.py +1 -3
- tableauserverclient/server/endpoint/__init__.py +1 -5
- tableauserverclient/server/endpoint/auth_endpoint.py +29 -8
- tableauserverclient/server/endpoint/custom_views_endpoint.py +1 -1
- tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +1 -1
- tableauserverclient/server/endpoint/data_alert_endpoint.py +1 -1
- tableauserverclient/server/endpoint/databases_endpoint.py +1 -1
- tableauserverclient/server/endpoint/datasources_endpoint.py +21 -15
- tableauserverclient/server/endpoint/default_permissions_endpoint.py +1 -1
- tableauserverclient/server/endpoint/dqw_endpoint.py +1 -1
- tableauserverclient/server/endpoint/endpoint.py +98 -11
- tableauserverclient/server/endpoint/exceptions.py +1 -5
- tableauserverclient/server/endpoint/favorites_endpoint.py +71 -29
- tableauserverclient/server/endpoint/fileuploads_endpoint.py +11 -10
- tableauserverclient/server/endpoint/flow_runs_endpoint.py +1 -1
- tableauserverclient/server/endpoint/flows_endpoint.py +5 -5
- tableauserverclient/server/endpoint/groups_endpoint.py +5 -2
- tableauserverclient/server/endpoint/jobs_endpoint.py +1 -1
- tableauserverclient/server/endpoint/metadata_endpoint.py +1 -1
- tableauserverclient/server/endpoint/metrics_endpoint.py +1 -1
- tableauserverclient/server/endpoint/permissions_endpoint.py +1 -1
- tableauserverclient/server/endpoint/projects_endpoint.py +3 -1
- tableauserverclient/server/endpoint/resource_tagger.py +3 -3
- tableauserverclient/server/endpoint/schedules_endpoint.py +2 -1
- tableauserverclient/server/endpoint/server_info_endpoint.py +2 -4
- tableauserverclient/server/endpoint/sites_endpoint.py +1 -1
- tableauserverclient/server/endpoint/subscriptions_endpoint.py +1 -1
- tableauserverclient/server/endpoint/tables_endpoint.py +1 -1
- tableauserverclient/server/endpoint/tasks_endpoint.py +12 -1
- tableauserverclient/server/endpoint/users_endpoint.py +1 -1
- tableauserverclient/server/endpoint/views_endpoint.py +1 -1
- tableauserverclient/server/endpoint/webhooks_endpoint.py +1 -1
- tableauserverclient/server/endpoint/workbooks_endpoint.py +4 -2
- tableauserverclient/server/exceptions.py +8 -1
- tableauserverclient/server/filter.py +5 -1
- tableauserverclient/server/request_factory.py +56 -12
- tableauserverclient/server/request_options.py +4 -2
- tableauserverclient/server/server.py +12 -13
- {tableauserverclient-0.25.dist-info → tableauserverclient-0.27.post0.dev1.dist-info}/METADATA +12 -10
- tableauserverclient-0.27.post0.dev1.dist-info/RECORD +97 -0
- {tableauserverclient-0.25.dist-info → tableauserverclient-0.27.post0.dev1.dist-info}/WHEEL +1 -1
- tableauserverclient-0.25.dist-info/RECORD +0 -95
- {tableauserverclient-0.25.dist-info → tableauserverclient-0.27.post0.dev1.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.25.dist-info → tableauserverclient-0.27.post0.dev1.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.25.dist-info → tableauserverclient-0.27.post0.dev1.dist-info}/top_level.txt +0 -0
tableauserverclient/__init__.py
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
from ._version import get_versions
|
|
2
2
|
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
|
|
3
|
-
from .models import
|
|
3
|
+
from .models import (
|
|
4
|
+
BackgroundJobItem,
|
|
5
|
+
ColumnItem,
|
|
6
|
+
ConnectionCredentials,
|
|
7
|
+
ConnectionItem,
|
|
8
|
+
CustomViewItem,
|
|
9
|
+
DQWItem,
|
|
10
|
+
DailyInterval,
|
|
11
|
+
DataAlertItem,
|
|
12
|
+
DatabaseItem,
|
|
13
|
+
DatasourceItem,
|
|
14
|
+
FavoriteItem,
|
|
15
|
+
FlowItem,
|
|
16
|
+
FlowRunItem,
|
|
17
|
+
FileuploadItem,
|
|
18
|
+
GroupItem,
|
|
19
|
+
HourlyInterval,
|
|
20
|
+
IntervalItem,
|
|
21
|
+
JobItem,
|
|
22
|
+
JWTAuth,
|
|
23
|
+
MetricItem,
|
|
24
|
+
MonthlyInterval,
|
|
25
|
+
PaginationItem,
|
|
26
|
+
Permission,
|
|
27
|
+
PermissionsRule,
|
|
28
|
+
PersonalAccessTokenAuth,
|
|
29
|
+
ProjectItem,
|
|
30
|
+
RevisionItem,
|
|
31
|
+
ScheduleItem,
|
|
32
|
+
SiteItem,
|
|
33
|
+
ServerInfoItem,
|
|
34
|
+
SubscriptionItem,
|
|
35
|
+
TableItem,
|
|
36
|
+
TableauAuth,
|
|
37
|
+
Target,
|
|
38
|
+
TaskItem,
|
|
39
|
+
UserItem,
|
|
40
|
+
ViewItem,
|
|
41
|
+
WebhookItem,
|
|
42
|
+
WeeklyInterval,
|
|
43
|
+
WorkbookItem,
|
|
44
|
+
)
|
|
4
45
|
from .server import (
|
|
5
46
|
CSVRequestOptions,
|
|
6
47
|
ExcelRequestOptions,
|
tableauserverclient/_version.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
# This file was generated by 'versioneer.py' (0.
|
|
2
|
+
# This file was generated by 'versioneer.py' (0.29) from
|
|
3
3
|
# revision-control system data, or from the parent directory name of an
|
|
4
4
|
# unpacked source archive. Distribution tarballs contain a pre-generated copy
|
|
5
5
|
# of this file.
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2023-
|
|
11
|
+
"date": "2023-10-04T00:33:03-0700",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "72eb3c8500193e4f20defa20c8a6f8bbf34b2f43",
|
|
15
|
+
"version": "0.27.post0.dev1"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# TODO: check for env variables, else set default values
|
|
2
|
+
|
|
3
|
+
ALLOWED_FILE_EXTENSIONS = ["tds", "tdsx", "tde", "hyper", "parquet"]
|
|
4
|
+
|
|
5
|
+
BYTES_PER_MB = 1024 * 1024
|
|
6
|
+
|
|
7
|
+
# For when a datasource is over 64MB, break it into 5MB(standard chunk size) chunks
|
|
8
|
+
CHUNK_SIZE_MB = 5 * 10 # 5MB felt too slow, upped it to 50
|
|
9
|
+
|
|
10
|
+
DELAY_SLEEP_SECONDS = 10
|
|
11
|
+
|
|
12
|
+
# The maximum size of a file that can be published in a single request is 64MB
|
|
13
|
+
FILESIZE_LIMIT_MB = 64
|
|
@@ -5,6 +5,10 @@ ZERO = datetime.timedelta(0)
|
|
|
5
5
|
HOUR = datetime.timedelta(hours=1)
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
def timestamp():
|
|
9
|
+
return datetime.datetime.now().strftime("%H:%M:%S")
|
|
10
|
+
|
|
11
|
+
|
|
8
12
|
# This class is a concrete implementation of the abstract base class tzinfo
|
|
9
13
|
# docs: https://docs.python.org/2.3/lib/datetime-tzinfo.html
|
|
10
14
|
class UTC(datetime.tzinfo):
|
|
@@ -31,7 +31,7 @@ from .server_info_item import ServerInfoItem
|
|
|
31
31
|
from .site_item import SiteItem
|
|
32
32
|
from .subscription_item import SubscriptionItem
|
|
33
33
|
from .table_item import TableItem
|
|
34
|
-
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth
|
|
34
|
+
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
|
|
35
35
|
from .tableau_types import Resource, TableauItem, plural_type
|
|
36
36
|
from .tag_item import TagItem
|
|
37
37
|
from .target import Target
|
|
@@ -15,6 +15,13 @@ class ConnectionCredentials(object):
|
|
|
15
15
|
self.embed = embed
|
|
16
16
|
self.oauth = oauth
|
|
17
17
|
|
|
18
|
+
def __repr__(self):
|
|
19
|
+
if self.password:
|
|
20
|
+
print = "redacted"
|
|
21
|
+
else:
|
|
22
|
+
print = "None"
|
|
23
|
+
return f"<{self.__class__.__name__} name={self.name} password={print} embed={self.embed} oauth={self.oauth} >"
|
|
24
|
+
|
|
18
25
|
@property
|
|
19
26
|
def embed(self):
|
|
20
27
|
return self._embed
|
|
@@ -5,6 +5,7 @@ from defusedxml.ElementTree import fromstring
|
|
|
5
5
|
|
|
6
6
|
from .connection_credentials import ConnectionCredentials
|
|
7
7
|
from .property_decorators import property_is_boolean
|
|
8
|
+
from tableauserverclient.helpers.logging import logger
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class ConnectionItem(object):
|
|
@@ -46,7 +47,6 @@ class ConnectionItem(object):
|
|
|
46
47
|
def query_tagging(self, value: Optional[bool]):
|
|
47
48
|
# if connection type = hyper, Snowflake, or Teradata, we can't change this value: it is always true
|
|
48
49
|
if self._connection_type in ["hyper", "snowflake", "teradata"]:
|
|
49
|
-
logger = logging.getLogger("tableauserverclient.models.connection_item")
|
|
50
50
|
logger.debug(
|
|
51
51
|
"Cannot update value: Query tagging is always enabled for {} connections".format(self._connection_type)
|
|
52
52
|
)
|
|
@@ -134,6 +134,7 @@ class CustomViewItem(object):
|
|
|
134
134
|
cv_item._content_url = custom_view_xml.get("contentUrl", None)
|
|
135
135
|
cv_item._id = custom_view_xml.get("id", None)
|
|
136
136
|
cv_item._name = custom_view_xml.get("name", None)
|
|
137
|
+
cv_item._shared = string_to_bool(custom_view_xml.get("shared", None))
|
|
137
138
|
|
|
138
139
|
if owner_elem is not None:
|
|
139
140
|
parsed_owners = UserItem.from_response_as_owner(tostring(custom_view_xml), ns)
|
|
@@ -154,3 +155,7 @@ class CustomViewItem(object):
|
|
|
154
155
|
|
|
155
156
|
all_view_items.append(cv_item)
|
|
156
157
|
return all_view_items
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def string_to_bool(s: Optional[str]) -> bool:
|
|
161
|
+
return (s or "").lower() == "true"
|
|
@@ -46,6 +46,9 @@ class DataAccelerationReportItem(object):
|
|
|
46
46
|
def __init__(self, comparison_records):
|
|
47
47
|
self._comparison_records = comparison_records
|
|
48
48
|
|
|
49
|
+
def __repr__(self):
|
|
50
|
+
return f"<(deprecated)DataAccelerationReportItem site={self.site} sheet={sheet_uri}>"
|
|
51
|
+
|
|
49
52
|
@property
|
|
50
53
|
def comparison_records(self):
|
|
51
54
|
return self._comparison_records
|
|
@@ -32,7 +32,7 @@ class DatasourceItem(object):
|
|
|
32
32
|
self.project_id,
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
def __init__(self, project_id: str, name: Optional[str] = None) -> None:
|
|
35
|
+
def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None) -> None:
|
|
36
36
|
self._ask_data_enablement = None
|
|
37
37
|
self._certified = None
|
|
38
38
|
self._certification_note = None
|
|
@@ -135,12 +135,11 @@ class DatasourceItem(object):
|
|
|
135
135
|
return self._id
|
|
136
136
|
|
|
137
137
|
@property
|
|
138
|
-
def project_id(self) -> str:
|
|
138
|
+
def project_id(self) -> Optional[str]:
|
|
139
139
|
return self._project_id
|
|
140
140
|
|
|
141
141
|
@project_id.setter
|
|
142
|
-
|
|
143
|
-
def project_id(self, value: str):
|
|
142
|
+
def project_id(self, value: Optional[str]):
|
|
144
143
|
self._project_id = value
|
|
145
144
|
|
|
146
145
|
@property
|
|
@@ -306,50 +305,16 @@ class DatasourceItem(object):
|
|
|
306
305
|
all_datasource_xml = parsed_response.findall(".//t:datasource", namespaces=ns)
|
|
307
306
|
|
|
308
307
|
for datasource_xml in all_datasource_xml:
|
|
309
|
-
(
|
|
310
|
-
ask_data_enablement,
|
|
311
|
-
certified,
|
|
312
|
-
certification_note,
|
|
313
|
-
content_url,
|
|
314
|
-
created_at,
|
|
315
|
-
datasource_type,
|
|
316
|
-
description,
|
|
317
|
-
encrypt_extracts,
|
|
318
|
-
has_extracts,
|
|
319
|
-
id_,
|
|
320
|
-
name,
|
|
321
|
-
owner_id,
|
|
322
|
-
project_id,
|
|
323
|
-
project_name,
|
|
324
|
-
tags,
|
|
325
|
-
updated_at,
|
|
326
|
-
use_remote_query_agent,
|
|
327
|
-
webpage_url,
|
|
328
|
-
) = cls._parse_element(datasource_xml, ns)
|
|
329
|
-
datasource_item = cls(project_id)
|
|
330
|
-
datasource_item._set_values(
|
|
331
|
-
ask_data_enablement,
|
|
332
|
-
certified,
|
|
333
|
-
certification_note,
|
|
334
|
-
content_url,
|
|
335
|
-
created_at,
|
|
336
|
-
datasource_type,
|
|
337
|
-
description,
|
|
338
|
-
encrypt_extracts,
|
|
339
|
-
has_extracts,
|
|
340
|
-
id_,
|
|
341
|
-
name,
|
|
342
|
-
owner_id,
|
|
343
|
-
None,
|
|
344
|
-
project_name,
|
|
345
|
-
tags,
|
|
346
|
-
updated_at,
|
|
347
|
-
use_remote_query_agent,
|
|
348
|
-
webpage_url,
|
|
349
|
-
)
|
|
308
|
+
datasource_item = cls.from_xml(datasource_xml, ns)
|
|
350
309
|
all_datasource_items.append(datasource_item)
|
|
351
310
|
return all_datasource_items
|
|
352
311
|
|
|
312
|
+
@classmethod
|
|
313
|
+
def from_xml(cls, datasource_xml, ns):
|
|
314
|
+
datasource_item = cls()
|
|
315
|
+
datasource_item._set_values(*cls._parse_element(datasource_xml, ns))
|
|
316
|
+
return datasource_item
|
|
317
|
+
|
|
353
318
|
@staticmethod
|
|
354
319
|
def _parse_element(datasource_xml: ET.Element, ns: Dict) -> Tuple:
|
|
355
320
|
id_ = datasource_xml.get("id", None)
|
|
@@ -361,17 +326,8 @@ class DatasourceItem(object):
|
|
|
361
326
|
updated_at = parse_datetime(datasource_xml.get("updatedAt", None))
|
|
362
327
|
certification_note = datasource_xml.get("certificationNote", None)
|
|
363
328
|
certified = str(datasource_xml.get("isCertified", None)).lower() == "true"
|
|
364
|
-
certification_note = datasource_xml.get("certificationNote", None)
|
|
365
|
-
certified = str(datasource_xml.get("isCertified", None)).lower() == "true"
|
|
366
|
-
content_url = datasource_xml.get("contentUrl", None)
|
|
367
|
-
created_at = parse_datetime(datasource_xml.get("createdAt", None))
|
|
368
|
-
datasource_type = datasource_xml.get("type", None)
|
|
369
|
-
description = datasource_xml.get("description", None)
|
|
370
329
|
encrypt_extracts = datasource_xml.get("encryptExtracts", None)
|
|
371
330
|
has_extracts = datasource_xml.get("hasExtracts", None)
|
|
372
|
-
id_ = datasource_xml.get("id", None)
|
|
373
|
-
name = datasource_xml.get("name", None)
|
|
374
|
-
updated_at = parse_datetime(datasource_xml.get("updatedAt", None))
|
|
375
331
|
use_remote_query_agent = datasource_xml.get("useRemoteQueryAgent", None)
|
|
376
332
|
webpage_url = datasource_xml.get("webpageUrl", None)
|
|
377
333
|
|
|
@@ -1,74 +1,90 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
from defusedxml.ElementTree import fromstring
|
|
4
|
+
from .tableau_types import TableauItem
|
|
4
5
|
|
|
5
6
|
from .datasource_item import DatasourceItem
|
|
6
7
|
from .flow_item import FlowItem
|
|
7
8
|
from .project_item import ProjectItem
|
|
9
|
+
from .metric_item import MetricItem
|
|
8
10
|
from .view_item import ViewItem
|
|
9
11
|
from .workbook_item import WorkbookItem
|
|
12
|
+
from typing import Dict, List
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
from tableauserverclient.helpers.logging import logger
|
|
13
15
|
from typing import Dict, List, Union
|
|
14
16
|
|
|
15
17
|
FavoriteType = Dict[
|
|
16
18
|
str,
|
|
17
|
-
List[
|
|
18
|
-
Union[
|
|
19
|
-
DatasourceItem,
|
|
20
|
-
ProjectItem,
|
|
21
|
-
FlowItem,
|
|
22
|
-
ViewItem,
|
|
23
|
-
WorkbookItem,
|
|
24
|
-
]
|
|
25
|
-
],
|
|
19
|
+
List[TableauItem],
|
|
26
20
|
]
|
|
27
21
|
|
|
28
22
|
|
|
29
23
|
class FavoriteItem:
|
|
30
|
-
class Type:
|
|
31
|
-
Workbook: str = "workbook"
|
|
32
|
-
Datasource: str = "datasource"
|
|
33
|
-
View: str = "view"
|
|
34
|
-
Project: str = "project"
|
|
35
|
-
Flow: str = "flow"
|
|
36
|
-
|
|
37
24
|
@classmethod
|
|
38
25
|
def from_response(cls, xml: str, namespace: Dict) -> FavoriteType:
|
|
39
26
|
favorites: FavoriteType = {
|
|
40
27
|
"datasources": [],
|
|
41
28
|
"flows": [],
|
|
42
29
|
"projects": [],
|
|
30
|
+
"metrics": [],
|
|
43
31
|
"views": [],
|
|
44
32
|
"workbooks": [],
|
|
45
33
|
}
|
|
46
|
-
|
|
47
34
|
parsed_response = fromstring(xml)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
|
|
36
|
+
datasources_xml = parsed_response.findall(".//t:favorite/t:datasource", namespace)
|
|
37
|
+
flows_xml = parsed_response.findall(".//t:favorite/t:flow", namespace)
|
|
38
|
+
metrics_xml = parsed_response.findall(".//t:favorite/t:metric", namespace)
|
|
39
|
+
projects_xml = parsed_response.findall(".//t:favorite/t:project", namespace)
|
|
40
|
+
views_xml = parsed_response.findall(".//t:favorite/t:view", namespace)
|
|
41
|
+
workbooks_xml = parsed_response.findall(".//t:favorite/t:workbook", namespace)
|
|
42
|
+
|
|
43
|
+
logger.debug(
|
|
44
|
+
"ds: {}, flows: {}, metrics: {}, projects: {}, views: {}, wbs: {}".format(
|
|
45
|
+
len(datasources_xml),
|
|
46
|
+
len(flows_xml),
|
|
47
|
+
len(metrics_xml),
|
|
48
|
+
len(projects_xml),
|
|
49
|
+
len(views_xml),
|
|
50
|
+
len(workbooks_xml),
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
for datasource in datasources_xml:
|
|
54
|
+
fav_datasource = DatasourceItem.from_xml(datasource, namespace)
|
|
61
55
|
if fav_datasource:
|
|
56
|
+
logger.debug(fav_datasource)
|
|
62
57
|
favorites["datasources"].append(fav_datasource)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if fav_project:
|
|
67
|
-
favorites["projects"].append(fav_project)
|
|
68
|
-
for flow in parsed_response.findall(".//t:favorite/t:flow", namespace):
|
|
69
|
-
fav_flow = FlowItem("flows")
|
|
70
|
-
fav_flow._set_values(*fav_flow._parse_element(flow, namespace))
|
|
58
|
+
|
|
59
|
+
for flow in flows_xml:
|
|
60
|
+
fav_flow = FlowItem.from_xml(flow, namespace)
|
|
71
61
|
if fav_flow:
|
|
62
|
+
logger.debug(fav_flow)
|
|
72
63
|
favorites["flows"].append(fav_flow)
|
|
73
64
|
|
|
65
|
+
for metric in metrics_xml:
|
|
66
|
+
fav_metric = MetricItem.from_xml(metric, namespace)
|
|
67
|
+
if fav_metric:
|
|
68
|
+
logger.debug(fav_metric)
|
|
69
|
+
favorites["metrics"].append(fav_metric)
|
|
70
|
+
|
|
71
|
+
for project in projects_xml:
|
|
72
|
+
fav_project = ProjectItem.from_xml(project, namespace)
|
|
73
|
+
if fav_project:
|
|
74
|
+
logger.debug(fav_project)
|
|
75
|
+
favorites["projects"].append(fav_project)
|
|
76
|
+
|
|
77
|
+
for view in views_xml:
|
|
78
|
+
fav_view = ViewItem.from_xml(view, namespace)
|
|
79
|
+
if fav_view:
|
|
80
|
+
logger.debug(fav_view)
|
|
81
|
+
favorites["views"].append(fav_view)
|
|
82
|
+
|
|
83
|
+
for workbook in workbooks_xml:
|
|
84
|
+
fav_workbook = WorkbookItem.from_xml(workbook, namespace)
|
|
85
|
+
if fav_workbook:
|
|
86
|
+
logger.debug(fav_workbook)
|
|
87
|
+
favorites["workbooks"].append(fav_workbook)
|
|
88
|
+
|
|
89
|
+
logger.debug(favorites)
|
|
74
90
|
return favorites
|
|
@@ -176,34 +176,39 @@ class FlowItem(object):
|
|
|
176
176
|
all_flow_xml = parsed_response.findall(".//t:flow", namespaces=ns)
|
|
177
177
|
|
|
178
178
|
for flow_xml in all_flow_xml:
|
|
179
|
-
(
|
|
180
|
-
id_,
|
|
181
|
-
name,
|
|
182
|
-
description,
|
|
183
|
-
webpage_url,
|
|
184
|
-
created_at,
|
|
185
|
-
updated_at,
|
|
186
|
-
tags,
|
|
187
|
-
project_id,
|
|
188
|
-
project_name,
|
|
189
|
-
owner_id,
|
|
190
|
-
) = cls._parse_element(flow_xml, ns)
|
|
191
|
-
flow_item = cls(project_id)
|
|
192
|
-
flow_item._set_values(
|
|
193
|
-
id_,
|
|
194
|
-
name,
|
|
195
|
-
description,
|
|
196
|
-
webpage_url,
|
|
197
|
-
created_at,
|
|
198
|
-
updated_at,
|
|
199
|
-
tags,
|
|
200
|
-
None,
|
|
201
|
-
project_name,
|
|
202
|
-
owner_id,
|
|
203
|
-
)
|
|
179
|
+
flow_item = cls.from_xml(flow_xml, ns)
|
|
204
180
|
all_flow_items.append(flow_item)
|
|
205
181
|
return all_flow_items
|
|
206
182
|
|
|
183
|
+
@classmethod
|
|
184
|
+
def from_xml(cls, flow_xml, ns) -> "FlowItem":
|
|
185
|
+
(
|
|
186
|
+
id_,
|
|
187
|
+
name,
|
|
188
|
+
description,
|
|
189
|
+
webpage_url,
|
|
190
|
+
created_at,
|
|
191
|
+
updated_at,
|
|
192
|
+
tags,
|
|
193
|
+
project_id,
|
|
194
|
+
project_name,
|
|
195
|
+
owner_id,
|
|
196
|
+
) = cls._parse_element(flow_xml, ns)
|
|
197
|
+
flow_item = cls(project_id)
|
|
198
|
+
flow_item._set_values(
|
|
199
|
+
id_,
|
|
200
|
+
name,
|
|
201
|
+
description,
|
|
202
|
+
webpage_url,
|
|
203
|
+
created_at,
|
|
204
|
+
updated_at,
|
|
205
|
+
tags,
|
|
206
|
+
None,
|
|
207
|
+
project_name,
|
|
208
|
+
owner_id,
|
|
209
|
+
)
|
|
210
|
+
return flow_item
|
|
211
|
+
|
|
207
212
|
@staticmethod
|
|
208
213
|
def _parse_element(flow_xml, ns):
|
|
209
214
|
id_ = flow_xml.get("id", None)
|
|
@@ -26,11 +26,9 @@ class GroupItem(object):
|
|
|
26
26
|
self.name: Optional[str] = name
|
|
27
27
|
self.domain_name: Optional[str] = domain_name
|
|
28
28
|
|
|
29
|
-
def
|
|
29
|
+
def __repr__(self):
|
|
30
30
|
return "{}({!r})".format(self.__class__.__name__, self.__dict__)
|
|
31
31
|
|
|
32
|
-
__repr__ = __str__
|
|
33
|
-
|
|
34
32
|
@property
|
|
35
33
|
def domain_name(self) -> Optional[str]:
|
|
36
34
|
return self._domain_name
|
|
@@ -48,7 +46,6 @@ class GroupItem(object):
|
|
|
48
46
|
return self._name
|
|
49
47
|
|
|
50
48
|
@name.setter
|
|
51
|
-
@property_not_empty
|
|
52
49
|
def name(self, value: str) -> None:
|
|
53
50
|
self._name = value
|
|
54
51
|
|
|
@@ -31,6 +31,9 @@ class HourlyInterval(object):
|
|
|
31
31
|
self.end_time = end_time
|
|
32
32
|
self.interval = interval_value
|
|
33
33
|
|
|
34
|
+
def __repr__(self):
|
|
35
|
+
return f"<{self.__class__.__name__} start={self.start_time} end={self.end_time} interval={self.interval}>"
|
|
36
|
+
|
|
34
37
|
@property
|
|
35
38
|
def _frequency(self):
|
|
36
39
|
return IntervalItem.Frequency.Hourly
|
|
@@ -86,6 +89,9 @@ class DailyInterval(object):
|
|
|
86
89
|
self.start_time = start_time
|
|
87
90
|
self.interval = interval_values
|
|
88
91
|
|
|
92
|
+
def __repr__(self):
|
|
93
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
94
|
+
|
|
89
95
|
@property
|
|
90
96
|
def _frequency(self):
|
|
91
97
|
return IntervalItem.Frequency.Daily
|
|
@@ -114,6 +120,9 @@ class WeeklyInterval(object):
|
|
|
114
120
|
self.start_time = start_time
|
|
115
121
|
self.interval = interval_values
|
|
116
122
|
|
|
123
|
+
def __repr__(self):
|
|
124
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
125
|
+
|
|
117
126
|
@property
|
|
118
127
|
def _frequency(self):
|
|
119
128
|
return IntervalItem.Frequency.Weekly
|
|
@@ -148,6 +157,9 @@ class MonthlyInterval(object):
|
|
|
148
157
|
self.start_time = start_time
|
|
149
158
|
self.interval = str(interval_value)
|
|
150
159
|
|
|
160
|
+
def __repr__(self):
|
|
161
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
162
|
+
|
|
151
163
|
@property
|
|
152
164
|
def _frequency(self):
|
|
153
165
|
return IntervalItem.Frequency.Monthly
|
|
@@ -117,12 +117,15 @@ class JobItem(object):
|
|
|
117
117
|
def updated_at(self) -> Optional[datetime.datetime]:
|
|
118
118
|
return self._updated_at
|
|
119
119
|
|
|
120
|
-
def
|
|
120
|
+
def __str__(self):
|
|
121
121
|
return (
|
|
122
122
|
"<Job#{_id} {_type} created_at({_created_at}) started_at({_started_at}) updated_at({_updated_at}) completed_at({_completed_at})"
|
|
123
123
|
" progress ({_progress}) finish_code({_finish_code})>".format(**self.__dict__)
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
+
def __repr__(self):
|
|
127
|
+
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
|
|
128
|
+
|
|
126
129
|
@classmethod
|
|
127
130
|
def from_response(cls, xml, ns) -> List["JobItem"]:
|
|
128
131
|
parsed_response = fromstring(xml)
|
|
@@ -202,6 +205,12 @@ class BackgroundJobItem(object):
|
|
|
202
205
|
self._title = title
|
|
203
206
|
self._subtitle = subtitle
|
|
204
207
|
|
|
208
|
+
def __str__(self):
|
|
209
|
+
return f"<{self.__class__.name} {self._id} {self._type}>"
|
|
210
|
+
|
|
211
|
+
def __repr__(self):
|
|
212
|
+
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
|
|
213
|
+
|
|
205
214
|
@property
|
|
206
215
|
def id(self) -> str:
|
|
207
216
|
return self._id
|