diff --git a/tableauserverclient/models/datasource_item.py b/tableauserverclient/models/datasource_item.py index 498f4e277..f481e3b10 100644 --- a/tableauserverclient/models/datasource_item.py +++ b/tableauserverclient/models/datasource_item.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as ET from .exceptions import UnpopulatedPropertyError -from .property_decorators import property_not_nullable +from .property_decorators import property_not_nullable, property_is_boolean from .tag_item import TagItem from .. import NAMESPACE from ..datetime_helpers import parse_datetime @@ -17,6 +17,8 @@ def __init__(self, project_id, name=None): self._initial_tags = set() self._project_name = None self._updated_at = None + self._certified = None + self._certification_note = None self.name = name self.owner_id = None self.project_id = project_id @@ -37,6 +39,24 @@ def content_url(self): def created_at(self): return self._created_at + @property + def certified(self): + return self._certified + + @certified.setter + @property_not_nullable + @property_is_boolean + def certified(self, value): + self._certified = value + + @property + def certification_note(self): + return self._certification_note + + @certification_note.setter + def certification_note(self, value): + self._certification_note = value + @property def id(self): return self._id @@ -65,16 +85,18 @@ def updated_at(self): def _set_connections(self, connections): self._connections = connections - def _parse_common_tags(self, datasource_xml): + def _parse_common_elements(self, datasource_xml): if not isinstance(datasource_xml, ET.Element): datasource_xml = ET.fromstring(datasource_xml).find('.//t:datasource', namespaces=NAMESPACE) if datasource_xml is not None: - (_, _, _, _, _, updated_at, _, project_id, project_name, owner_id) = self._parse_element(datasource_xml) - self._set_values(None, None, None, None, None, updated_at, None, project_id, project_name, owner_id) + (_, _, _, _, _, updated_at, _, project_id, project_name, owner_id, + certified, certification_note) = self._parse_element(datasource_xml) + self._set_values(None, None, None, None, None, updated_at, None, project_id, + project_name, owner_id, certified, certification_note) return self def _set_values(self, id, name, datasource_type, content_url, created_at, - updated_at, tags, project_id, project_name, owner_id): + updated_at, tags, project_id, project_name, owner_id, certified, certification_note): if id is not None: self._id = id if name: @@ -96,6 +118,9 @@ def _set_values(self, id, name, datasource_type, content_url, created_at, self._project_name = project_name if owner_id: self.owner_id = owner_id + if certification_note: + self.certification_note = certification_note + self.certified = certified # Always True/False, not conditional @classmethod def from_response(cls, resp): @@ -104,22 +129,25 @@ def from_response(cls, resp): all_datasource_xml = parsed_response.findall('.//t:datasource', namespaces=NAMESPACE) for datasource_xml in all_datasource_xml: - (id, name, datasource_type, content_url, created_at, updated_at, - tags, project_id, project_name, owner_id) = cls._parse_element(datasource_xml) + (id_, name, datasource_type, content_url, created_at, updated_at, + tags, project_id, project_name, owner_id, + certified, certification_note) = cls._parse_element(datasource_xml) datasource_item = cls(project_id) - datasource_item._set_values(id, name, datasource_type, content_url, created_at, updated_at, - tags, None, project_name, owner_id) + datasource_item._set_values(id_, name, datasource_type, content_url, created_at, updated_at, + tags, None, project_name, owner_id, certified, certification_note) all_datasource_items.append(datasource_item) return all_datasource_items @staticmethod def _parse_element(datasource_xml): - id = datasource_xml.get('id', None) + id_ = datasource_xml.get('id', None) name = datasource_xml.get('name', None) datasource_type = datasource_xml.get('type', None) content_url = datasource_xml.get('contentUrl', None) created_at = parse_datetime(datasource_xml.get('createdAt', None)) updated_at = parse_datetime(datasource_xml.get('updatedAt', None)) + certification_note = datasource_xml.get('certificationNote', None) + certified = str(datasource_xml.get('isCertified', None)).lower() == 'true' tags = None tags_elem = datasource_xml.find('.//t:tags', namespaces=NAMESPACE) @@ -138,4 +166,5 @@ def _parse_element(datasource_xml): if owner_elem is not None: owner_id = owner_elem.get('id', None) - return id, name, datasource_type, content_url, created_at, updated_at, tags, project_id, project_name, owner_id + return (id_, name, datasource_type, content_url, created_at, updated_at, tags, project_id, + project_name, owner_id, certified, certification_note) diff --git a/tableauserverclient/server/endpoint/datasources_endpoint.py b/tableauserverclient/server/endpoint/datasources_endpoint.py index 3d4c070fb..c18639b62 100644 --- a/tableauserverclient/server/endpoint/datasources_endpoint.py +++ b/tableauserverclient/server/endpoint/datasources_endpoint.py @@ -112,7 +112,7 @@ def update(self, datasource_item): server_response = self.put_request(url, update_req) logger.info('Updated datasource item (ID: {0})'.format(datasource_item.id)) updated_datasource = copy.copy(datasource_item) - return updated_datasource._parse_common_tags(server_response.content) + return updated_datasource._parse_common_elements(server_response.content) # Publish datasource @api(version="2.0") diff --git a/tableauserverclient/server/request_factory.py b/tableauserverclient/server/request_factory.py index 1762cd3bd..9dbaaacba 100644 --- a/tableauserverclient/server/request_factory.py +++ b/tableauserverclient/server/request_factory.py @@ -65,6 +65,12 @@ def update_req(self, datasource_item): if datasource_item.owner_id: owner_element = ET.SubElement(datasource_element, 'owner') owner_element.attrib['id'] = datasource_item.owner_id + + datasource_element.attrib['isCertified'] = str(datasource_item.certified).lower() + + if datasource_item.certification_note: + datasource_element.attrib['certificationNote'] = str(datasource_item.certification_note) + return ET.tostring(xml_request) def publish_req(self, datasource_item, filename, file_contents, connection_credentials=None): diff --git a/test/assets/datasource_update.xml b/test/assets/datasource_update.xml index 637bc0187..3b4c36e58 100644 --- a/test/assets/datasource_update.xml +++ b/test/assets/datasource_update.xml @@ -1,6 +1,6 @@ - + diff --git a/test/test_datasource.py b/test/test_datasource.py index d75a29d85..80e61159e 100644 --- a/test/test_datasource.py +++ b/test/test_datasource.py @@ -93,11 +93,15 @@ def test_update(self): single_datasource = TSC.DatasourceItem('test', '1d0304cd-3796-429f-b815-7258370b9b74') single_datasource.owner_id = 'dd2239f6-ddf1-4107-981a-4cf94e415794' single_datasource._id = '9dbd2263-16b5-46e1-9c43-a76bb8ab65fb' + single_datasource.certified = True + single_datasource.certification_note = "Warning, here be dragons." single_datasource = self.server.datasources.update(single_datasource) self.assertEqual('9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', single_datasource.id) self.assertEqual('1d0304cd-3796-429f-b815-7258370b9b74', single_datasource.project_id) self.assertEqual('dd2239f6-ddf1-4107-981a-4cf94e415794', single_datasource.owner_id) + self.assertEqual(True, single_datasource.certified) + self.assertEqual("Warning, here be dragons.", single_datasource.certification_note) def test_update_copy_fields(self): with open(UPDATE_XML, 'rb') as f: