8000 Add subscriptions (#240) · rickyren/server-client-python@262d32f · GitHub
[go: up one dir, main page]

Skip to content

Commit 262d32f

Browse files
William Langt8y8
authored andcommitted
Add subscriptions (tableau#240)
Add support for Subscriptions
1 parent 728643e commit 262d32f

File tree

11 files changed

+216
-5
lines changed

11 files changed

+216
-5
lines changed

tableauserverclient/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
from .models import ConnectionCredentials, ConnectionItem, DatasourceItem,\
33
GroupItem, PaginationItem, ProjectItem, ScheduleItem, \
44
SiteItem, TableauAuth, UserItem, ViewItem, WorkbookItem, UnpopulatedPropertyError, \
5-
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem
5+
HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval, IntervalItem, TaskItem, \
6+
SubscriptionItem
67
from .server import RequestOptions, ImageRequestOptions, PDFRequestOptions, Filter, Sort, \
78
Server, ServerResponseError, MissingRequiredFieldError, NotSignedInError, Pager
8-
99
from ._version import get_versions
1010
__version__ = get_versions()['version']
1111
__VERSION__ = __version__

tableauserverclient/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
from .user_item import UserItem
1515
from .view_item import ViewItem
1616
from .workbook_item import WorkbookItem
17+
from .subscription_item import SubscriptionItem
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import xml.etree.ElementTree as ET
2+
from .exceptions import UnpopulatedPropertyError
3+
from .target import Target
4+
5+
6+
class SubscriptionItem(object):
7+
8+
def __init__(self, subject, schedule_id, user_id, target):
9+
self.id = None
10+
self.subject = subject
11+
self.schedule_id = schedule_id
12+
self.user_id = user_id
13+
self.target = target
14+
15+
def __repr__(self):
16+
if self.id is not None:
17+
return "<Subscription#{id} subject({subject}) schedule_id({schedule_id}) user_id({user_id}) \
18+
target({target})".format(**self.__dict__)
19+
else:
20+
return "<Subscription subject({subject}) schedule_id({schedule_id}) user_id({user_id}) \
21+
target({target})".format(**self.__dict__)
22+
23+
def _set_id(self, id_):
24+
self.id = id_
25+
26+
@classmethod
27+
def from_response(cls, xml, ns):
28+
parsed_response = ET.fromstring(xml)
29+
all_subscriptions_xml = parsed_response.findall(
30+
'.//t:subscription', namespaces=ns)
31+
32+
all_subscriptions = [SubscriptionItem._parse_element(x, ns) for x in all_subscriptions_xml]
33+
return all_subscriptions
34+
35+
@classmethod
36+
def _parse_element(cls, element, ns):
37+
schedule_id = None
38+
target = None
39+
40+
schedule_element = element.find('.//t:schedule', namespaces=ns)
41+
content_element = element.find('.//t:content', namespaces=ns)
42+
user_element = element.find('.//t:user', namespaces=ns)
43+
44+
if schedule_element is not None:
45+
schedule_id = schedule_element.get('id', None)
46+
47+
if content_element is not None:
48+
target = Target(content_element.get('id', None), content_element.get('type'))
49+
50+
if user_element is not None:
51+
user_id = user_element.get('id')
52+
53+
id_ = element.get('id', None)
54+
subject = element.get('subject', None)
55+
sub = cls(subject, schedule_id, user_id, target)
56+
sub._set_id(id_)
57+
return sub

tableauserverclient/server/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
from .sort import Sort
55
from .. import ConnectionItem, DatasourceItem,\
66
GroupItem, PaginationItem, ProjectItem, ScheduleItem, SiteItem, TableauAuth,\
7-
UserItem, ViewItem, WorkbookItem, TaskItem
7+
UserItem, ViewItem, WorkbookItem, TaskItem, SubscriptionItem
88
from .endpoint import Auth, Datasources, Endpoint, Groups, Projects, Schedules, \
9-
Sites, Users, Views, Workbooks, ServerResponseError, MissingRequiredFieldError
9+
Sites, Users, Views, Workbooks, Subscriptions, ServerResponseError, \
10+
MissingRequiredFieldError
1011
from .server import Server
1112
from .pager import Pager
1213
from .exceptions import NotSignedInError

tableauserverclient/server/endpoint/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
from .users_endpoint import Users
1212
from .views_endpoint import Views
1313
from .workbooks_endpoint import Workbooks
14+
from .subscriptions_endpoint import Subscriptions
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from .endpoint import Endpoint, api
2+
from .exceptions import MissingRequiredFieldError
3+
from .. import RequestFactory, SubscriptionItem, PaginationItem
4+
import logging
5+
6+
logger = logging.getLogger('tableau.endpoint.subscriptions')
7+
8+
9+
class Subscriptions(Endpoint):
10+
@property
11+
def baseurl(self):
12+
return "{0}/sites/{1}/subscriptions".format(self.parent_srv.baseurl,
13+
self.parent_srv.site_id)
14+
15+
@api(version='2.3')
16+
def get(self, req_options=None):
17+
logger.info('Querying all subscriptions for the site')
18+
url = self.baseurl
19+
server_response = self.get_request(url, req_options)
20+
21+
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
22+
all_subscriptions = SubscriptionItem.from_response(server_response.content, self.parent_srv.namespace)
23+
return all_subscriptions, pagination_item
24+
25+
@api(version='2.3')
26+
def get_by_id(self, subscription_id):
27+
if not subscription_id:
28+
error = "No Subscription ID provided"
29+
raise ValueError(error)
30+
logger.info("Querying a single subscription by id ({})".format(subscription_id))
31+
url = "{}/{}".format(self.baseurl, subscription_id)
32+
server_response = self.get_request(url)
33+
return SubscriptionItem.from_response(server_response.content, self.parent_srv.namespace)[0]
34+
35+
@api(version='2.3')
36+
def create(self, subscription_item):
37+
if not subscription_item:
38+
error = "No Susbcription provided"
39+
raise ValueError(error)
40+
logger.info("Creating a subscription ({})".format(subscription_item))
41+
url = self.baseurl
42+
create_req = RequestFactory.Subscription.create_req(subscription_item)
43+
server_response = self.post_request(url, create_req)
44+
return SubscriptionItem.from_response(server_response.content, self.parent_srv.namespace)[0]
45+
46+
@api(version='2.3')
47+
def delete(self, subscription_id):
48+
if not subscription_id:
49+
error = "Subscription ID undefined."
50+
raise ValueError(error)
51+
url = "{0}/{1}".format(self.baseurl, subscription_id)
52+
self.delete_request(url)
53+
logger.info('Deleted subscription (ID: {0})'.format(subscription_id))

tableauserverclient/server/request_factory.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,24 @@ def run_req(xml_request, task_item):
359359
pass
360360

361361

362+
class SubscriptionRequest(object):
363+
def create_req(self, subscription_item):
364+
xml_request = ET.Element('tsRequest')
365+
subscription_element = ET.SubElement(xml_request, 'subscription')
366+
subscription_element.attrib['subject'] = subscription_item.subject
367+
368+
content_element = ET.SubElement(subscription_element, 'content')
369+
content_element.attrib['id'] = subscription_item.target.id
370+
content_element.attrib['type'] = subscription_item.target.type
371+
372+
schedule_element = ET.SubElement(subscription_element, 'schedule')
373+
schedule_element.attrib['id'] = subscription_item.schedule_id
374+
375+
user_element = ET.SubElement(subscription_element, 'user')
376+
user_element.attrib['id'] = subscription_item.user_id
377+
return ET.tostring(xml_request)
378+
379+
362380
class RequestFactory(object):
363381
Auth = AuthRequest()
364382
Datasource = DatasourceRequest()
@@ -373,3 +391,4 @@ class RequestFactory(object):
373391
User = UserRequest()
374392
Workbook = WorkbookRequest()
375393
WorkbookConnection = WorkbookConnection()
394+
Subscription = SubscriptionRequest()

tableauserverclient/server/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .exceptions import NotSignedInError
44
from ..namespace import Namespace
55
from .endpoint import Sites, Views, Users, Groups, Workbooks, Datasources, Projects, Auth, \
6-
Schedules, ServerInfo, Tasks, ServerInfoEndpointNotFoundError
6+
Schedules, ServerInfo, Tasks, ServerInfoEndpointNotFoundError, Subscriptions
77

88
import requests
99

@@ -42,6 +42,7 @@ def __init__(self, server_address, use_server_version=False):
4242
self.schedules = Schedules(self)
4343
self.server_info = ServerInfo(self)
4444
self.tasks = Tasks(self)
45+
self.subscriptions = Subscriptions(self)
4546
self._namespace = Namespace()
4647

4748
if use_server_version:

test/assets/subscription_get.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<tsResponse
3+
xmlns="http://tableau.com/api"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.6.xsd">
5+
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
6+
<subscriptions>
7+
<subscription id="382e9a6e-0c08-4a95-b6c1-c14df7bac3e4" subject="Not Found Alert">
8+
<content id="cdd716ca-5818-470e-8bec-086885dbadee" type="View" />
9+
<schedule id="7617c389-cdca-4940-a66e-69956fcebf3e" name="Subscribe daily [00:00 - 04:00, Pacific US] [migrated at 1490824351877]" />
10+
<user id="c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e" name="jonsnow@winterfell.com" />
11+
</subscription>
12+
<subscription id="23cb7630-afc8-4c8e-b6cd-83ae0322ec66" subject="Last 7 Days">
13+
<content id="2e6b4e8f-22dd-4061-8f75-bf33703da7e5" type="View" />
14+
<schedule id="3407cd38-7b39-4983-86a6-67a1506a5e3f" name="SSS_27212a85-6b28-41f6-8c69-29b02043d7a5" />
15+
<user id="c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e" name="jonsnow@winterfell.com" />
16+
</subscription>
17+
</subscriptions>
18+
</tsResponse>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<tsResponse
3+
xmlns="http://tableau.com/api"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.6.xsd">
5+
<subscription id="382e9a6e-0c08-4a95-b6c1-c14df7bac3e4" subject="Not Found Alert">
6+
<content id="cdd716ca-5818-470e-8bec-086885dbadee" type="View" />
7+
<schedule id="7617c389-cdca-4940-a66e-69956fcebf3e" name="Subscribe daily [00:00 - 04:00, Pacific US] [migrated at 1490824351877]" />
8+
<user id="c0d5fc44-ad8c-4957-bec0-b70ed0f8df1e" name="jonsnow@winterfell.com" />
9+
</subscription>
10+
</tsResponse>

0 commit comments

Comments
 (0)
0