10000 Create Data Alert capabilities · zeninpalm/server-client-python@d666f08 · GitHub
[go: up one dir, main page]

Skip to content

Commit d666f08

Browse files
committed
Create Data Alert capabilities
1 parent ce078cb commit d666f08

File tree

8 files changed

+307
-4
lines changed

8 files changed

+307
-4
lines changed

tableauserverclient/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
2-
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
2+
from .models import ConnectionCredentials, ConnectionItem, DataAlertItem, DatasourceItem,\
33
GroupItem, JobItem, BackgroundJobItem, PaginationItem, ProjectItem, ScheduleItem,\
44
SiteItem, TableauAuth, PersonalAccessTokenAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError,\
55
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem,\

tableauserverclient/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from .connection_item import ConnectionItem
33
from .column_item import ColumnItem
44
from .data_acceleration_report_item import DataAccelerationReportItem
5+
from .data_alert_item import DataAlertItem
56
from .datasource_item import DatasourceItem
67
from .database_item import DatabaseItem
78
from .exceptions import UnpopulatedPropertyError
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import xml.etree.ElementTree as ET
2+
3+
from .property_decorators import property_not_empty
4+
from .user_item import UserItem
5+
from .view_item import ViewItem
6+
7+
8+
class DataAlertItem(object):
9+
def __init__(self):
10+
self._id = None
11+
self._subject = None
12+
self._creatorId = None
13+
self._createdAt = None
14+
self._updatedAt = None
15+
self._frequency = None
16+
self._public = None
17+
self._owner_id = None
18+
self._owner_name = None
19+
self._view_id = None
20+
self._view_name = None
21+
self._workbook_id = None
22+
self._workbook_name = None
23+
self._project_id = None
24+
self._project_name = None
25+
self._recipients = None
26+
27+
def __repr__(self):
28+
return "<Data Alert {} subject={} frequency={} public={}>".format(self.id, self.subject,
29+
self.frequency, self.public)
30+
31+
@property
32+
def id(self):
33+
return self._id
34+
35+
@property
36+
def subject(self):
37+
return self._subject
38+
39+
@subject.setter
40+
@property_not_empty
41+
def subject(self, value):
42+
self._subject = value
43+
44+
@property
45+
def frequency(self):
46+
return self._frequency
47+
48+
@frequency.setter
49+
@property_not_empty
50+
def frequency(self, value):
51+
self._frequency = value
52+
53+
@property
54+
def public(self):
55+
return self._public
56+
57+
@public.setter
58+
@property_not_empty
59+
def public(self, value):
60+
self._public = value
61+
62+
@property
63+
def creatorId(self):
64+
return self._creatorId
65+
66+
@property
67+
def recipients(self):
68+
return self._recipients or list()
69+
70+
@property
71+
def createdAt(self):
72+
return self._createdAt
73+
74+
@property
75+
def updatedAt(self):
76+
return self._updatedAt
77+
78+
@property
79+
def owner_id(self):
80+
return self._owner_id
81+
82+
@property
83+
def owner_name(self):
84+
return self._owner_name
85+
86+
@property
87+
def view_id(self):
88+
return self._view_id
89+
90+
@property
91+
def view_name(self):
92+
return self._view_name
93+
94+
@property
95+
def workbook_id(self):
96+
return self._workbook_id
97+
98+
@property
99+
def workbook_name(self):
100+
return self._workbook_name
101+
102+
@property
103+
def project_id(self):
104+
return self._project_id
105+
106+
@property
107+
def project_name(self):
108+
return self._project_name
109+
110+
def _set_values(self, id, subject, creatorId, createdAt, updatedAt,
111+
frequency, public, recipients, owner_id, owner_name,
112+
view_id, view_name, workbook_id, workbook_name, project_id,
113+
project_name):
114+
if id is not None:
115+
self._id = id
116+
if subject:
117+
self._subject = subject
118+
if creatorId:
119+
self._creatorId = creatorId
120+
if createdAt:
121+
self._createdAt = createdAt
122+
if updatedAt:
123+
self._updatedAt = updatedAt
124+
if frequency:
125+
self._frequency = frequency
126+
if public:
127+
self._public = public
128+
if owner_id:
129+
self._owner_id = owner_id
130+
if owner_name:
131+
self._owner_name = owner_name
132+
if view_id:
133+
self._view_id = view_id
134+
if view_name:
135+
self._view_name = view_name
136+
if workbook_id:
137+
self._workbook_id = workbook_id
138+
if workbook_name:
139+
self._workbook_name = workbook_name
140+
if project_id:
141+
self._project_id = project_id
142+
if project_name:
143+
self._project_name = project_name
144+
if recipients:
145+
self._recipients = recipients
146+
147+
@classmethod
148+
def from_response(cls, resp, ns):
149+
all_alert_items = list()
150+
parsed_response = ET.fromstring(resp)
151+
all_alert_xml = parsed_response.findall('.//t:dataAlert', namespaces=ns)
152+
153+
for alert_xml in all_alert_xml:
154+
kwargs = cls._parse_element(alert_xml, ns)
155+
alert_item = cls()
156+
alert_item._set_values(**kwargs)
157+
all_alert_items.append(alert_item)
158+
159+
return all_alert_items
160+
161+
@staticmethod
162+
def _parse_element(alert_xml, ns):
163+
kwargs = dict()
164+
kwargs['id'] = alert_xml.get('id', None)
165+
kwargs['subject'] = alert_xml.get('subject', None)
166+
kwargs['creatorId'] = alert_xml.get('creatorId', None)
167+
kwargs['createdAt'] = alert_xml.get('createdAt', None)
168+
kwargs['updatedAt'] = alert_xml.get('updatedAt', None)
169+
kwargs['frequency'] = alert_xml.get('frequency', None)
170+
kwargs['public'] = alert_xml.get('public', None)
171+
172+
owner = alert_xml.findall('.//t:owner', namespaces=ns)[0]
173+
kwargs['owner_id'] = owner.get('id', None)
174+
kwargs['owner_name'] = owner.get('name', None)
175+
176+
view_response = alert_xml.findall('.//t:view', namespaces=ns)[0]
177+
kwargs['view_id'] = view_response.get('id', None)
178+
kwargs['view_name'] = view_response.get('name', None)
179+
180+
workbook_response = view_response.findall('.//t:workbook', namespaces=ns)[0]
181+
kwargs['workbook_id'] = workbook_response.get('id', None)
182+
kwargs['workbook_name'] = workbook_response.get('name', None)
183+
project_response = view_response.findall('.//t:project', namespaces=ns)[0]
184+
kwargs['project_id'] = project_response.get('id', None)
185+
kwargs['project_name'] = project_response.get('name', None)
186+
187+
recipients = alert_xml.findall('.//t:recipient', namespaces=ns)
188+
kwargs['recipients'] = [recipient.get('id', None) for recipient in recipients]
189+
190+
return kwargs

tableauserverclient/server/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from .request_options import CSVRequestOptions, ImageRequestOptions, PDFRequestOptions, RequestOptions
33
from .filter import Filter
44
from .sort import Sort
5-
from .. import ConnectionItem, DatasourceItem, DatabaseItem, JobItem, BackgroundJobItem, \
5+
from .. import ConnectionItem, DataAlertItem, DatasourceItem, DatabaseItem, JobItem, BackgroundJobItem, \
66
GroupItem, PaginationItem, ProjectItem, ScheduleItem, SiteItem, TableauAuth,\
77
UserItem, ViewItem, WorkbookItem, TableItem, TaskItem, SubscriptionItem, \
88
PermissionsRule, Permission, ColumnItem, FlowItem, WebhookItem
9-
from .endpoint import Auth, Datasources, Endpoint, Groups, Projects, Schedules, \
9+
from .endpoint import Auth, DataAlerts, Datasources, Endpoint, Groups, Projects, Schedules, \
1010
Sites, Tables, Users, Views, Workbooks, Subscriptions, ServerResponseError, \
1111
MissingRequiredFieldError, Flows, Favorites
1212
from .server import Server

tableauserverclient/server/endpoint/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .auth_endpoint import Auth
22
from .data_acceleration_report_endpoint import DataAccelerationReport
3+
from .data_alert_endpoint import DataAlerts
34
from .datasources_endpoint import Datasources
45
from .databases_endpoint import Databases
56
from .endpoint import Endpoint
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from .endpoint import api, Endpoint
2+
from .exceptions import MissingRequiredFieldError
3+
from .permissions_endpoint import _PermissionsEndpoint
4+
from .default_permissions_endpoint import _DefaultPermissionsEndpoint
5+
6+
from .. import RequestFactory, DataAlertItem, TableItem, PaginationItem, Permission
7+
8+
import logging
9+
10+
logger = logging.getLogger('tableau.endpoint.dataalerts')
11+
12+
13+
class DataAlerts(Endpoint):
14+
def __init__(self, parent_srv):
15+
super(DataAlerts, self).__init__(parent_srv)
16+
17+
@property
18+
def baseurl(self):
19+
return "{0}/sites/{1}/dataalerts".format(self.parent_srv.baseurl, self.parent_srv.site_id)
20+
21+
@api(version="3.2")
22+
def get(self, req_options=None):
23+
logger.info('Querying all dataalerts on site')
24+
url = self.baseurl
25+
server_response = self.get_request(url, req_options)
26+
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
27+
all_dataalert_items = DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)
28+
return all_dataalert_items, pagination_item
29+
30+
# Get 1 dataalert
31+
@api(version="3.2")
32+
def get_by_id(self, dataalert_id):
33+
if not dataalert_id:
34+
error = "dataalert ID undefined."
35+
raise ValueError(error)
36+
logger.info('Querying single dataalert (ID: {0})'.format(dataalert_id))
37+
url = "{0}/{1}".format(self.baseurl, dataalert_id)
38+
server_response = self.get_request(url)
39+
return DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)[0]
40+
41+
@api(version="3.2")
42+
def delete(self, dataalert):
43+
dataalert_id = getattr(dataalert, 'id', dataalert)
44+
if not dataalert_id:
45+
error = "Dataalert ID undefined."
46+
raise ValueError(error)
47+
# DELETE /api/api-version/sites/site-id/dataAlerts/data-alert-id/users/user-id
48+
url = "{0}/{1}".format(self.baseurl, dataalert_id)
49+
self.delete_request(url)
50+
logger.info('Deleted single dataalert (ID: {0})'.format(dataalert_id))
51+
52+
@api(version="3.2")
53+
def delete_user_from_alert(self, dataalert, user):
54+
dataalert_id = getattr(dataalert, 'id', dataalert)
55+
if not dataalert_id:
56+
error = "Dataalert ID undefined."
57+
raise ValueError(error)
58+
# DELETE /api/api-version/sites/site-id/dataAlerts/data-alert-id/users/user-id
59+
url = "{0}/{1}/users/{2}".format(self.baseurl, dataalert_id, user.id)
60+
self.delete_request(url)
61+
logger.info('Deleted single dataalert (ID: {0})'.format(dataalert_id))
62+
63+
@api(version="3.2")
64+
def add_user_to_alert(self, dataalert_item, user):
65+
if not dataalert_item.id:
66+
error = "Dataalert item missing ID."
67+
raise MissingRequiredFieldError(error)
68+
69+
url = "{0}/{1}/users".format(self.baseurl, dataalert_item.id)
70+
update_req = RequestFactory.DataAlert.update_req(dataalert_item)
71+
server_response = self.put_request(url, update_req)
72+
logger.info('Updated dataalert item (ID: {0})'.format(dataalert_item.id))
73+
updated_dataalert = DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)[0]
74+
return updated_dataalert
75+
76+
@api(version="3.2")
77+
def update(self, dataalert_item):
78+
if not dataalert_item.id:
79+
error = "Dataalert item missing ID."
80+
raise MissingRequiredFieldError(error)
81+
82+
url = "{0}/{1}".format(self.baseurl, dataalert_item.id)
83+
update_req = RequestFactory.DataAlert.update_req(dataalert_item)
84+
server_response = self.put_request(url, update_req)
85+
logger.info('Updated dataalert item (ID: {0})'.format(dataalert_item.id))
86+
updated_dataalert = DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)[0]
87+
return updated_dataalert

tableauserverclient/server/request_factory.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,28 @@ def update_req(self, column_item):
8686
return ET.tostring(xml_request)
8787

8888

89+
class DataAlertRequest(object):
90+
def add_user_to_alert(self, alert_item, user_item):
91+
xml_request = ET.Element('tsRequest')
92+
user_element = ET.SubElement(xml_request, 'user')
93+
user_element.attrib['id'] = user_item.id
94+
95+
return ET.tostring(xml_request)
96+
97+
98+
def update_req(self, alert_item):
< 10000 /code>99+
xml_request = ET.Element('tsRequest')
100+
dataAlert_element = ET.SubElement(xml_request, 'dataAlert')
101+
dataAlert_element.attrib['subject'] = alert_item.subject
102+
dataAlert_element.attrib['frequency'] = alert_item.frequency
103+
dataAlert_element.attrib['public'] = alert_item.public
104+
105+
owner = ET.SubElement(dataAlert_element, 'owner')
106+
owner.attrib['id'] = alert_item.owner_id
107+
108+
return ET.tostring(xml_request)
109+
110+
89111
class DatabaseRequest(object):
90112
def update_req(self, database_item):
91113
xml_request = ET.Element('tsRequest')
@@ -637,6 +659,7 @@ class RequestFactory(object):
637659
Auth = AuthRequest()
638660
Connection = Connection()
639661
Column = ColumnRequest()
662+
DataAlert = DataAlertRequest()
640663
Datasource = DatasourceRequest()
641664
Database = DatabaseRequest()
642665
Empty = EmptyRequest()

tableauserverclient/server/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from ..namespace import Namespace
55
from .endpoint import Sites, Views, Users, Groups, Workbooks, Datasources, Projects, Auth, \
66
Schedules, ServerInfo, Tasks, Subscriptions, Jobs, Metadata,\
7-
Databases, Tables, Flows, Webhooks, DataAccelerationReport, Favorites
7+
Databases, Tables, Flows, Webhooks, DataAccelerationReport, Favorites, DataAlerts
88
from .endpoint.exceptions import EndpointUnavailableError, ServerInfoEndpointNotFoundError
99

1010
import requests
@@ -58,6 +58,7 @@ def __init__(self, server_address, use_server_version=False):
5858
self.tables = Tables(self)
5959
self.webhooks = Webhooks(self)
6060
self.data_acceleration_report = DataAccelerationReport(self)
61+
self.data_alerts = DataAlerts(self)
6162
self._namespace = Namespace()
6263

6364
if use_server_version:

0 commit comments

Comments
 (0)
0