8000 Data alert endpoint and item by jorwoods · Pull Request #667 · tableau/server-client-python · GitHub
[go: up one dir, main page]

Skip to content

Data alert endpoint and item #667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ ENV/
# Rope project settings
.ropeproject


# VSCode project settings
.vscode/

# macOS.gitignore from https://github.com/github/gitignore
*.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
from .models import ConnectionCredentials, ConnectionItem, DataAlertItem, DatasourceItem,\
GroupItem, JobItem, BackgroundJobItem, PaginationItem, ProjectItem, ScheduleItem,\
SiteItem, TableauAuth, PersonalAccessTokenAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError,\
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem,\
Expand Down
1 change: 1 addition & 0 deletions tableauserverclient/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .connection_item import ConnectionItem
from .column_item import ColumnItem
from .data_acceleration_report_item import DataAccelerationReportItem
from .data_alert_item import DataAlertItem
from .datasource_item import DatasourceItem
from .database_item import DatabaseItem
from .exceptions import UnpopulatedPropertyError
Expand Down
197 changes: 197 additions & 0 deletions tableauserverclient/models/data_alert_item.py
10000
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import xml.etree.ElementTree as ET

from .property_decorators import property_not_empty, property_is_enum, property_is_boolean
from .user_item import UserItem
from .view_item import ViewItem


class DataAlertItem(object):
class Frequency:
Once = 'Once'
Frequently = 'Frequently'
Hourly = 'Hourly'
Daily = 'Daily'
Weekly = 'Weekly'

def __init__(self):
self._id = None
self._subject = None
self._creatorId = None
self._createdAt = None
self._updatedAt = None
self._frequency = None
self._public = None
self._owner_id = None
self._owner_name = None
self._view_id = None
self._view_name = None
self._workbook_id = None
self._workbook_name = None
self._project_id = None
self._project_name = None
self._recipients = None

def __repr__(self):
return "<Data Alert {id} subject={subject} frequency={frequency} \
public={public}>".format(**self.__dict__)

@property
def id(self):
return self._id

@property
def subject(self):
return self._subject

@subject.setter
@property_not_empty
def subject(self, value):
self._subject = value

@property
def frequency(self):
return self._frequency

@frequency.setter
@property_is_enum(Frequency)
def frequency(self, value):
self._frequency = value

@property
def public(self):
return self._public

@public.setter
@property_is_boolean
def public(self, value):
self._public = value

@property
def creatorId(self):
return self._creatorId

@property
def recipients(self):
return self._recipients or list()

@property
def createdAt(self):
return self._createdAt

@property
def updatedAt(self):
return self._updatedAt

@property
def owner_id(self):
return self._owner_id

@property
def owner_name(self):
return self._owner_name

@property
def view_id(self):
return self._view_id

@property
def view_name(self):
return self._view_name

@property
def workbook_id(self):
return self._workbook_id

@property
def workbook_name(self):
return self._workbook_name

@property
def project_id(self):
return self._project_id

@property
def project_name(self):
return self._project_name

def _set_values(self, id, subject, creatorId, createdAt, updatedAt,
frequency, public, recipients, owner_id, owner_name,
view_id, view_name, workbook_id, workbook_name, project_id,
project_name):
if id is not None:
self._id = id
if subject:
self._subject = subject
if creatorId:
self._creatorId = creatorId
if createdAt:
self._createdAt = createdAt
if updatedAt:
self._updatedAt = updatedAt
if frequency:
self._frequency = frequency
if public:
self._public = public
if owner_id:
self._owner_id = owner_id
if owner_name:
self._owner_name = owner_name
if view_id:
self._view_id = view_id
if view_name:
self._view_name = view_name
if workbook_id:
self._workbook_id = workbook_id
if workbook_name:
self._workbook_name = workbook_name
if project_id:
self._project_id = project_id
if project_name:
self._project_name = project_name
if recipients:
self._recipients = recipients

@classmethod
def from_response(cls, resp, ns):
all_alert_items = list()
parsed_response = ET.fromstring(resp)
all_alert_xml = parsed_response.findall('.//t:dataAlert', namespaces=ns)

for alert_xml in all_alert_xml:
kwargs = cls._parse_element(alert_xml, ns)
alert_item = cls()
alert_item._set_values(**kwargs)
all_alert_items.append(alert_item)

return all_alert_items

@staticmethod
def _parse_element(alert_xml, ns):
kwargs = dict()
kwargs['id'] = alert_xml.get('id', None)
kwargs['subject'] = alert_xml.get('subject', None)
kwargs['creatorId'] = alert_xml.get('creatorId', None)
kwargs['createdAt'] = alert_xml.get('createdAt', None)
kwargs['updatedAt'] = alert_xml.get('updatedAt', None)
kwargs['frequency'] = alert_xml.get('frequency', None)
kwargs['public'] = alert_xml.get('public', None)

owner = alert_xml.findall('.//t:owner', namespaces=ns)[0]
kwargs['owner_id'] = owner.get('id', None)
kwargs['owner_name'] = owner.get('name', None)

view_response = alert_xml.findall('.//t:view', namespaces=ns)[0]
kwargs['view_id'] = view_response.get('id', None)
kwargs['view_name'] = view_response.get('name', None)

workbook_response = view_response.findall('.//t:workbook', namespaces=ns)[0]
kwargs['workbook_id'] = workbook_response.get('id', None)
kwargs['workbook_name'] = workbook_response.get('name', None)
project_response = view_response.findall('.//t:project', namespaces=ns)[0]
kwargs['project_id'] = project_response.get('id', None)
kwargs['project_name'] = project_response.get('name', None)

recipients = alert_xml.findall('.//t:recipient', namespaces=ns)
kwargs['recipients'] = [recipient.get('id', None) for recipient in recipients]

return kwargs
10000
4 changes: 2 additions & 2 deletions tableauserverclient/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
from .request_options import CSVRequestOptions, ImageRequestOptions, PDFRequestOptions, RequestOptions
from .filter import Filter
from .sort import Sort
from .. import ConnectionItem, DatasourceItem, DatabaseItem, JobItem, BackgroundJobItem, \
from .. import ConnectionItem, DataAlertItem, DatasourceItem, DatabaseItem, JobItem, BackgroundJobItem, \
GroupItem, PaginationItem, ProjectItem, ScheduleItem, SiteItem, TableauAuth,\
UserItem, ViewItem, WorkbookItem, TableItem, TaskItem, SubscriptionItem, \
PermissionsRule, Permission, ColumnItem, FlowItem, WebhookItem
from .endpoint import Auth, Datasources, Endpoint, Groups, Projects, Schedules, \
from .endpoint import Auth, DataAlerts, Datasources, Endpoint, Groups, Projects, Schedules, \
Sites, Tables, Users, Views, Workbooks, Subscriptions, ServerResponseError, \
MissingRequiredFieldError, Flows, Favorites
from .server import Server
Expand Down
1 change: 1 addition & 0 deletions tableauserverclient/server/endpoint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .auth_endpoint import Auth
from .data_acceleration_report_endpoint import DataAccelerationReport
from .data_alert_endpoint import DataAlerts
from .datasources_endpoint import Datasources
from .databases_endpoint import Databases
from .endpoint import Endpoint
Expand Down
94 changes: 94 additions & 0 deletions tableauserverclient/server/endpoint/data_alert_endpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from .endpoint import api, Endpoint
from .exceptions import MissingRequiredFieldError
from .permissions_endpoint import _PermissionsEndpoint
from .default_permissions_endpoint import _DefaultPermissionsEndpoint

from .. import RequestFactory, DataAlertItem, PaginationItem, UserItem

import logging

logger = logging.getLogger('tableau.endpoint.dataAlerts')


class DataAlerts(Endpoint):
def __init__(self, parent_srv):
super(DataAlerts, self).__init__(parent_srv)

@property
def baseurl(self):
return "{0}/sites/{1}/dataAlerts".format(self.parent_srv.baseurl, self.parent_srv.site_id)

@api(version="3.2")
def get(self, req_options=None):
logger.info('Querying all dataAlerts on site')
url = self.baseurl
server_response = self.get_request(url, req_options)
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
all_dataAlert_items = DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)
return all_dataAlert_items, pagination_item

# Get 1 dataAlert
@api(version="3.2")
def get_by_id(self, dataAlert_id):
if not dataAlert_id:
error = "dataAlert ID undefined."
raise ValueError(error)
logger.info('Querying single dataAlert (ID: {0})'.format(dataAlert_id))
url = "{0}/{1}".format(self.baseurl, dataAlert_id)
server_response = self.get_request(url)
return DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)[0]

@api(version="3.2")
def delete(self, dataAlert):
dataAlert_id = getattr(dataAlert, 'id', dataAlert)
if not dataAlert_id:
error = "Dataalert ID undefined."
raise ValueError(error)
# DELETE /api/api-version/sites/site-id/dataAlerts/data-alert-id/users/user-id
url = "{0}/{1}".format(self.baseurl, dataAlert_id)
self.delete_request(url)
logger.info('Deleted single dataAlert (ID: {0})'.format(dataAlert_id))

@api(version="3.2")
def delete_user_from_alert(self, dataAlert, user):
dataAlert_id = getattr(dataAlert, 'id', dataAlert)
user_id = getattr(user, 'id', user)
if not dataAlert_id:
error = "Dataalert ID undefined."
raise ValueError(error)
if not user_id:
error = "User ID undefined."
raise ValueError(error)
# DELETE /api/api-version/sites/site-id/dataAlerts/data-alert-id/users/user-id
url = "{0}/{1}/users/{2}".format(self.baseurl, dataAlert_id, user_id)
self.delete_request(url)
logger.info('Deleted User (ID {0}) from dataAlert (ID: {1})'.format(user_id, dataAlert_id))

@api(version="3.2")
def add_user_to_alert(self, dataAlert_item, user):
if not dataAlert_item.id:
error = "Dataalert item missing ID."
raise MissingRequiredFieldError(error)
user_id = getattr(user, 'id', user)
if not user_id:
error = "User ID undefined."
raise ValueError(error)
url = "{0}/{1}/users".format(self.baseurl, dataAlert_item.id)
update_req = RequestFactory.DataAlert.add_user_to_alert(dataAlert_item, user_id)
server_response = self.post_request(url, update_req)
logger.info('Added user (ID {0}) to dataAlert item (ID: {1})'.format(user_id, dataAlert_item.id))
user = UserItem.from_response(server_response.content, self.parent_srv.namespace)[0]
return user

@api(version="3.2")
def update(self, dataAlert_item):
if not dataAlert_item.id:
error = "Dataalert item missing ID."
raise MissingRequiredFieldError(error)

url = "{0}/{1}".format(self.baseurl, dataAlert_item.id)
update_req = RequestFactory.DataAlert.update_req(dataAlert_item)
server_response = self.put_request(url, update_req)
logger.info('Updated dataAlert item (ID: {0})'.format(dataAlert_item.id))
updated_dataAlert = DataAlertItem.from_response(server_response.content, self.parent_srv.namespace)[0]
return updated_dataAlert
22 changes: 22 additions & 0 deletions tableauserverclient/server/request_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,27 @@ def update_req(self, column_item):
return ET.tostring(xml_request)


class DataAlertRequest(object):
def add_user_to_alert(self, alert_item, user_id):
xml_request = ET.Element('tsRequest')
user_element = ET.SubElement(xml_request, 'user')
user_element.attrib['id'] = user_id

return ET.tostring(xml_request)

def update_req(self, alert_item):
xml_request = ET.Element('tsRequest')
dataAlert_element = ET.SubElement(xml_request, 'dataAlert')
dataAlert_element.attrib['subject'] = alert_item.subject
dataAlert_element.attrib['frequency'] = alert_item.frequency.lower()
dataAlert_element.attrib['public'] = alert_item.public

owner = ET.SubElement(dataAlert_element, 'owner')
owner.attrib['id'] = alert_item.owner_id

return ET.tostring(xml_request)


class DatabaseRequest(object):
def update_req(self, database_item):
xml_request = ET.Element('tsRequest')
Expand Down Expand Up @@ -637,6 +658,7 @@ class RequestFactory(object):
Auth = AuthRequest()
Connection = Connection()
Column = ColumnRequest()
DataAlert = DataAlertRequest()
Datasource = DatasourceRequest()
Database = DatabaseRequest()
Empty = EmptyRequest()
Expand Down
3 changes: 2 additions & 1 deletion tableauserverclient/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ..namespace import Namespace
from .endpoint import Sites, Views, Users, Groups, Workbooks, Datasources, Projects, Auth, \
Schedules, ServerInfo, Tasks, Subscriptions, Jobs, Metadata,\
Databases, Tables, Flows, Webhooks, DataAccelerationReport, Favorites
Databases, Tables, Flows, Webhooks, DataAccelerationReport, Favorites, DataAlerts
from .endpoint.exceptions import EndpointUnavailableError, ServerInfoEndpointNotFoundError

import requests
Expand Down Expand Up @@ -58,6 +58,7 @@ def __init__(self, server_address, use_server_version=False):
self.tables = Tables(self)
self.webhooks = Webhooks(self)
self.data_acceleration_report = DataAccelerationReport(self)
self.data_alerts = DataAlerts(self)
self._namespace = Namespace()

if use_server_version:
Expand Down
Loading
0