Skip to content
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
92 changes: 82 additions & 10 deletions tableauserverclient/models/subscription_item.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import xml.etree.ElementTree as ET
from .target import Target
from .property_decorators import property_is_boolean


class SubscriptionItem(object):

def __init__(self, subject, schedule_id, user_id, target):
self.id = None
self.subject = subject
self._id = None
self.attach_image = True
self.attach_pdf = False
self.message = None
self.page_orientation = None
self.page_size_option = None
self.schedule_id = schedule_id
self.user_id = user_id
self.send_if_view_empty = True
self.subject = subject
self.suspended = False
self.target = target
self.user_id = user_id

def __repr__(self):
if self.id is not None:
Expand All @@ -19,8 +27,45 @@ def __repr__(self):
return "<Subscription subject({subject}) schedule_id({schedule_id}) user_id({user_id}) \
target({target})".format(**self.__dict__)

def _set_id(self, id_):
self.id = id_
@property
def id(self):
return self._id

@property
def attach_image(self):
return self._attach_image

@attach_image.setter
@property_is_boolean
def attach_image(self, value):
self._attach_image = value

@property
def attach_pdf(self):
return self._attach_pdf

@attach_pdf.setter
@property_is_boolean
def attach_pdf(self, value):
self._attach_pdf = value

@property
def send_if_view_empty(self):
return self._send_if_view_empty

@send_if_view_empty.setter
@property_is_boolean
def send_if_view_empty(self, value):
self._send_if_view_empty = value

@property
def suspended(self):
return self._suspended

@suspended.setter
@property_is_boolean
def suspended(self, value):
self._suspended = value

@classmethod
def from_response(cls, xml, ns):
Expand All @@ -33,24 +78,51 @@ def from_response(cls, xml, ns):

@classmethod
def _parse_element(cls, element, ns):
schedule_id = None
target = None

schedule_element = element.find('.//t:schedule', namespaces=ns)
content_element = element.find('.//t:content', namespaces=ns)
user_element = element.find('.//t:user', namespaces=ns)

# Schedule element
schedule_id = None
if schedule_element is not None:
schedule_id = schedule_element.get('id', None)

# Content element
target = None
send_if_view_empty = None
if content_element is not None:
target = Target(content_element.get('id', None), content_element.get('type'))
send_if_view_empty = string_to_bool(content_element.get('sendIfViewEmpty', ''))

# User element
user_id = None
if user_element is not None:
user_id = user_element.get('id')
user_id = user_element.get('id', None)

# Main attributes
id_ = element.get('id', None)
subject = element.get('subject', None)
attach_image = string_to_bool(element.get('attachImage', ''))
attach_pdf = string_to_bool(element.get('attachPdf', ''))
message = element.get('message', None)
page_orientation = element.get('pageOrientation', None)
page_size_option = element.get('pageSizeOption', None)
suspended = string_to_bool(element.get('suspended', ''))

# Create SubscriptionItem and set fields
sub = cls(subject, schedule_id, user_id, target)
sub._set_id(id_)
sub._id = id_
sub.attach_image = attach_image
sub.attach_pdf = attach_pdf
sub.message = message
sub.page_orientation = page_orientation
sub.page_size_option = page_size_option
sub.send_if_view_empty = send_if_view_empty
sub.suspended = suspended

return sub


# Used to convert string represented boolean to a boolean type
def string_to_bool(s):
return s.lower() == 'true'
12 changes: 12 additions & 0 deletions tableauserverclient/server/endpoint/subscriptions_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .endpoint import Endpoint, api
from .exceptions import MissingRequiredFieldError
from .. import RequestFactory, SubscriptionItem, PaginationItem

import logging
Expand Down Expand Up @@ -51,3 +52,14 @@ def delete(self, subscription_id):
url = "{0}/{1}".format(self.baseurl, subscription_id)
self.delete_request(url)
logger.info('Deleted subscription (ID: {0})'.format(subscription_id))

@api(version='2.3')
def update(self, subscription_item):
if not subscription_item.id:
error = "Subscription item missing ID. Subscription must be retrieved from server first."
raise MissingRequiredFieldError(error)
url = "{0}/{1}".format(self.baseurl, subscription_item.id)
update_req = RequestFactory.Subscription.update_req(subscription_item)
server_response = self.put_request(url, update_req)
logger.info('Updated subscription item (ID: {0})'.format(subscription_item.id))
return SubscriptionItem.from_response(server_response.content, self.parent_srv.namespace)[0]
52 changes: 49 additions & 3 deletions tableauserverclient/server/request_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,22 +827,68 @@ def run_req(self, xml_request, task_item):


class SubscriptionRequest(object):
def create_req(self, subscription_item):
xml_request = ET.Element('tsRequest')
@_tsrequest_wrapped
def create_req(self, xml_request, subscription_item):
subscription_element = ET.SubElement(xml_request, 'subscription')
subscription_element.attrib['subject'] = subscription_item.subject

# Main attributes
subscription_element.attrib['subject'] = subscription_item.subject
if subscription_item.attach_image is not None:
subscription_element.attrib['attachImage'] = str(subscription_item.attach_image).lower()
if subscription_item.attach_pdf is not None:
subscription_element.attrib['attachPdf'] = str(subscription_item.attach_pdf).lower()
if subscription_item.message is not None:
subscription_element.attrib['message'] = subscription_item.message
if subscription_item.page_orientation is not None:
subscription_element.attrib['pageOrientation'] = subscription_item.page_orientation
if subscription_item.page_size_option is not None:
subscription_element.attrib['pageSizeOption'] = subscription_item.page_size_option

# Content element
content_element = ET.SubElement(subscription_element, 'content')
content_element.attrib['id'] = subscription_item.target.id
content_element.attrib['type'] = subscription_item.target.type
if subscription_item.send_if_view_empty is not None:
content_element.attrib['sendIfViewEmpty'] = str(subscription_item.send_if_view_empty).lower()

# Schedule element
schedule_element = ET.SubElement(subscription_element, 'schedule')
schedule_element.attrib['id'] = subscription_item.schedule_id

# User element
user_element = ET.SubElement(subscription_element, 'user')
user_element.attrib['id'] = subscription_item.user_id
return ET.tostring(xml_request)

@_tsrequest_wrapped
def update_req(self, xml_request, subscription_item):
subscription = ET.SubElement(xml_request, 'subscription')

# Main attributes
if subscription_item.subject is not None:
subscription.attrib['subject'] = subscription_item.subject
if subscription_item.attach_image is not None:
subscription.attrib['attachImage'] = str(subscription_item.attach_image).lower()
if subscription_item.attach_pdf is not None:
subscription.attrib['attachPdf'] = str(subscription_item.attach_pdf).lower()
if subscription_item.page_orientation is not None:
subscription.attrib['pageOrientation'] = subscription_item.page_orientation
if subscription_item.page_size_option is not None:
subscription.attrib['pageSizeOption'] = subscription_item.page_size_option
if subscription_item.suspended is not None:
subscription.attrib['suspended'] = str(subscription_item.suspended).lower()

# Schedule element
schedule = ET.SubElement(subscription, 'schedule')
if subscription_item.schedule_id is not None:
schedule.attrib['id'] = subscription_item.schedule_id

# Content element
content = ET.SubElement(subscription, 'content')
if subscription_item.send_if_view_empty is not None:
content.attrib['sendIfViewEmpty'] = str(subscription_item.send_if_view_empty).lower()
return ET.tostring(xml_request)


class EmptyRequest(object):
@_tsrequest_wrapped
Expand Down
8 changes: 4 additions & 4 deletions test/assets/subscription_get.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.6.xsd">
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
<subscriptions>
<subscription id="382e9a6e-0c08-4a95-b6c1-c14df7bac3e4" subject="Not Found Alert">
<content id="cdd716ca-5818-470e-8bec-086885dbadee" type="View" />
<subscription id="382e9a6e-0c08-4a95-b6c1-c14df7bac3e4" subject="Not Found Alert" message="NOT FOUND!" attachImage="true" attachPdf="false" suspended="false">
<content id="cdd716ca-5818-470e-8bec-086885dbadee" type="View" sendIfViewEmpty="false" />
<schedule id="7617c389-cdca-4940-a66e-69956fcebf3e" name="Subscribe daily [00:00 - 04:00, Pacific US] [migrated at 1490824351877]" />
<user id="c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e" name="[email protected]" />
</subscription>
<subscription id="23cb7630-afc8-4c8e-b6cd-83ae0322ec66" subject="Last 7 Days">
<content id="2e6b4e8f-22dd-4061-8f75-bf33703da7e5" type="View" />
<subscription id="23cb7630-afc8-4c8e-b6cd-83ae0322ec66" subject="Last 7 Days" message="overview" attachImage="false" attachPdf="true" suspended="true" pageOrientation="PORTRAIT" pageSizeOption="A5">
<content id="2e6b4e8f-22dd-4061-8f75-bf33703da7e5" type="Workbook" sendIfViewEmpty="true"/>
<schedule id="3407cd38-7b39-4983-86a6-67a1506a5e3f" name="SSS_27212a85-6b28-41f6-8c69-29b02043d7a5" />
<user id="c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e" name="[email protected]" />
</subscription>
Expand Down
27 changes: 25 additions & 2 deletions test/test_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,37 @@ def test_get_subscriptions(self):
m.get(self.baseurl, text=response_xml)
all_subscriptions, pagination_item = self.server.subscriptions.get()

self.assertEqual(2, pagination_item.total_available)
subscription = all_subscriptions[0]
self.assertEqual('382e9a6e-0c08-4a95-b6c1-c14df7bac3e4', subscription.id)
self.assertEqual('View', subscription.target.type)
self.assertEqual('NOT FOUND!', subscription.message)
self.assertTrue(subscription.attach_image)
self.assertFalse(subscription.attach_pdf)
self.assertFalse(subscription.suspended)
self.assertFalse(subscription.send_if_view_empty)
self.assertIsNone(subscription.page_orientation)
self.assertIsNone(subscription.page_size_option)
self.assertEqual('Not Found Alert', subscription.subject)
self.assertEqual('cdd716ca-5818-470e-8bec-086885dbadee', subscription.target.id)
self.assertEqual('View', subscription.target.type)
self.assertEqual('c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e', subscription.user_id)
self.assertEqual('Not Found Alert', subscription.subject)
self.assertEqual('7617c389-cdca-4940-a66e-69956fcebf3e', subscription.schedule_id)

subscription = all_subscriptions[1]
self.assertEqual('23cb7630-afc8-4c8e-b6cd-83ae0322ec66', subscription.id)
self.assertEqual('overview', subscription.message)
self.assertFalse(subscription.attach_image)
self.assertTrue(subscription.attach_pdf)
self.assertTrue(subscription.suspended)
self.assertTrue(subscription.send_if_view_empty)
self.assertEqual('PORTRAIT', subscription.page_orientation)
self.assertEqual('A5', subscription.page_size_option)
self.assertEqual('Last 7 Days', subscription.subject)
self.assertEqual('2e6b4e8f-22dd-4061-8f75-bf33703da7e5', subscription.target.id)
self.assertEqual('Workbook', subscription.target.type)
self.assertEqual('c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e', subscription.user_id)
self.assertEqual('3407cd38-7b39-4983-86a6-67a1506a5e3f', subscription.schedule_id)

def test_get_subscription_by_id(self):
with open(GET_XML_BY_ID, "rb") as f:
response_xml = f.read().decode("utf-8")
Expand Down