8000 Added datasource tagging functionality along with unit test and added… · SnarkyPapi/server-client-python@00e3015 · GitHub
[go: up one dir, main page]

Skip to content

Commit 00e3015

Browse files
lbrendanlRussell Hay
authored and
Russell Hay
committed
Added datasource tagging functionality along with unit test and added sample code.
For upcoming 2.6 REST API Version.
1 parent 590f130 commit 00e3015

File tree

5 files changed

+79
-9
lines changed

5 files changed

+79
-9
lines changed

samples/explore_datasource.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ def main():
6767
print(["{0}({1})".format(connection.id, connection.datasource_name)
6868
for connection in sample_datasource.connections])
6969

70+
# Add some tags to the datasource
71+
original_tag_set = set(sample_datasource.tags)
72+
sample_datasource.tags.update('a', 'b', 'c', 'd')
73+
server.datasources.update(sample_datasource)
74+
print("\nOld tag set: {}".format(original_tag_set))
75+
print("New tag set: {}".format(sample_datasource.tags))
76+
77+
# Delete all tags that were added by setting tags to original
78+
sample_datasource.tags = original_tag_set
79+
server.datasources.update(sample_datasource)
7080

7181
if __name__ == '__main__':
7282
main()

tableauserverclient/models/datasource_item.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .tag_item import TagItem
55
from .. import NAMESPACE
66
from ..datetime_helpers import parse_datetime
7+
import copy
78

89

910
class DatasourceItem(object):
@@ -12,13 +13,14 @@ def __init__(self, project_id, name=None):
1213
self._content_url = None
1314
self._created_at = None
1415
self._id = None
16+
self._initial_tags = set()
1517
self._project_name = None
16-
self._tags = set()
1718
self._datasource_type = None
1819
self._updated_at = None
1920
self.name = name
2021
self.owner_id = None
2122
self.project_id = project_id
23+
self.tags = set()
2224

2325
@property
2426
def connections(self):
@@ -52,10 +54,6 @@ def project_id(self, value):
5254
def project_name(self):
5355
return self._project_name
5456

55-
@property
56-
def tags(self):
57-
return self._tags
58-
5957
@property
6058
def datasource_type(self):
6159
return self._datasource_type
@@ -67,6 +65,12 @@ def updated_at(self):
6765
def _set_connections(self, connections):
6866
self._connections = connections
6967

68+
def _set_initial_tags(self, initial_tags):
69+
self._initial_tags = initial_tags
70+
71+
def _get_initial_tags(self):
72+
return self._initial_tags
73+
7074
def _parse_common_tags(self, datasource_xml):
7175
if not isinstance(datasource_xml, ET.Element):
7276
datasource_xml = ET.fromstring(datasource_xml).find('.//t:datasource', namespaces=NAMESPACE)
@@ -90,7 +94,8 @@ def _set_values(self, id, name, datasource_type, content_url, created_at,
9094
if updated_at:
9195
self._updated_at = updated_at
9296
if tags:
93-
self._tags = tags
97+
self.tags = tags
98+
self._initial_tags = copy.copy(tags)
9499
if project_id:
95100
self.project_id = project_id
96101
if project_name:

tableauserverclient/server/endpoint/datasources_endpoint.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .fileuploads_endpoint import Fileuploads
44
from .. import RequestFactory, DatasourceItem, PaginationItem, ConnectionItem
55
from ...filesys_helpers import to_filename
6+
from ...models.tag_item import TagItem
67
import os
78
import logging
89
import copy
@@ -22,6 +23,18 @@ class Datasources(Endpoint):
2223
def baseurl(self):
2324
return "{0}/sites/{1}/datasources".format(self.parent_srv.baseurl, self.parent_srv.site_id)
2425

< A3E2 /code>
26+
# Add new tags to datasource
27+
def _add_tags(self, datasource_id, tag_set):
28+
url = "{0}/{1}/tags".format(self.baseurl, datasource_id)
29+
add_req = RequestFactory.Tag.add_req(tag_set)
30+
server_response = self.put_request(url, add_req)
31+
return TagItem.from_response(server_response.content)
32+
33+
# Delete a datasources's tag by name
34+
def _delete_tag(self, datasource_id, tag_name):
35+
url = "{0}/{1}/tags/{2}".format(self.baseurl, datasource_id, tag_name)
36+
self.delete_request(url)
37+
2538
# Get all datasources
2639
@api(version="2.0")
2740
def get(self, req_options=None):
@@ -97,9 +110,24 @@ def update(self, datasource_item):
97110
if not datasource_item.id:
98111
error = 'Datasource item missing ID. Datasource must be retrieved from server first.'
99112
raise MissingRequiredFieldError(error)
113+
114+
# Remove and add tags to match the datasource item's tag set
115+
if datasource_item.tags != datasource_item._initial_tags:
116+
add_set = datasource_item.tags - datasource_item._initial_tags
117+
remove_set = datasource_item._initial_tags - datasource_item.tags
118+
for tag in remove_set:
119+
self._delete_tag(datasource_item.id, tag)
120+
if add_set:
121+
datasource_item.tags = self._add_tags(datasource_item.id, add_set)
122+
datasource_item._initial_tags = copy.copy(datasource_item.tags)
123+
logger.info('Updated datasource tags to {0}'.format(datasource_item.tags))
124+
125+
# Update the datasource itself
100126
url = "{0}/{1}".format(self.baseurl, datasource_item.id)
101127
update_req = RequestFactory.Datasource.update_req(datasource_item)
128+
print(update_req)
102129
server_response = self.put_request(url, update_req)
130+
print(server_response)
103131
logger.info('Updated datasource item (ID: {0})'.format(datasource_item.id))
104132
updated_datasource = copy.copy(datasource_item)
105133
return updated_datasource._parse_common_tags(server_response.content)

test/assets/datasource_add_tags.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.6.xsd">
3+
<tags>
4+
<tag label="a" />
5+
<tag label="b" />
6+
<tag label="c" />
7+
<tag label="d" />
8+
</tags>
9+
</tsResponse>

test/test_datasource.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), 'assets')
88

9+
ADD_TAGS_XML = os.path.join(TEST_ASSET_DIR, 'datasource_add_tags.xml')
910
GET_XML = os.path.join(TEST_ASSET_DIR, 'datasource_get.xml')
1011
GET_EMPTY_XML = os.path.join(TEST_ASSET_DIR, 'datasource_get_empty.xml')
1112
GET_BY_ID_XML = os.path.join(TEST_ASSET_DIR, 'datasource_get_by_id.xml')
12-
UPDATE_XML = os.path.join(TEST_ASSET_DIR, 'datasource_update.xml')
1313
PUBLISH_XML = os.path.join(TEST_ASSET_DIR, 'datasource_publish.xml')
14-
14+
UPDATE_XML = os.path.join(TEST_ASSET_DIR, 'datasource_update.xml')
1515

1616
class DatasourceTests(unittest.TestCase):
1717
def setUp(self):
@@ -105,13 +105,31 @@ def test_update_copy_fields(self):
105105
m.put(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', text=response_xml)
106106
single_datasource = TSC.DatasourceItem('test', '1d0304cd-3796-429f-b815-7258370b9b74')
107107
single_datasource._id = '9dbd2263-16b5-46e1-9c43-a76bb8ab65fb'
108-
single_datasource._tags = ['a', 'b', 'c']
109108
single_datasource._project_name = 'Tester'
110109
updated_datasource = self.server.datasources.update(single_datasource)
111110

112111
self.assertEqual(single_datasource.tags, updated_datasource.tags)
113112
self.assertEqual(single_datasource._project_name, updated_datasource._project_name)
114113

114+
def test_update_tags(self):
115+
with open(ADD_TAGS_XML, 'rb') as f:
116+
add_tags_xml = f.read().decode('utf-8')
117+
with open(UPDATE_XML, 'rb') as f:
118+
update_xml = f.read().decode('utf-8')
119+
with requests_mock.mock() as m:
120+
m.put(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/tags', text=add_tags_xml)
121+
m.delete(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/tags/b', status_code=204)
122+
m.delete(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/tags/d', status_code=204)
123+
m.put(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', text=update_xml)
124+
single_datasource = TSC.DatasourceItem('1d0304cd-3796-429f-b815-7258370b9b74')
125+
single_datasource._id = '9dbd2263-16b5-46e1-9c43-a76bb8ab65fb'
126+
single_datasource._initial_tags.update(['a', 'b', 'c', 'd'])
127+
single_datasource.tags.update(['a', 'c', 'e'])
128+
updated_datasource = self.server.datasources.update(single_datasource)
129+
130+
self.assertEqual(single_datasource.tags, updated_datasource.tags)
131+
self.assertEqual(single_datasource._initial_tags, updated_datasource._initial_tags)
132+
115133
def test_publish(self):
116134
with open(PUBLISH_XML, 'rb') as f:
117135
response_xml = f.read().decode('utf-8')

0 commit comments

Comments
 (0)
0