Skip to content

Commit 5533192

Browse files
committed
Merge branch 'jorwoods/test_datasource_style' into jorwoods/pytestify_ssl
2 parents 515ea42 + 1061309 commit 5533192

File tree

5 files changed

+81
-1
lines changed

5 files changed

+81
-1
lines changed

CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#ECCN:Open Source
2+
#GUSINFO:Open Source,Open Source Workflow

tableauserverclient/models/datasource_item.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,15 @@ def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
535535

536536
project_id = None
537537
project_name = None
538+
project = None
538539
project_elem = datasource_xml.find(".//t:project", namespaces=ns)
539540
if project_elem is not None:
540541
project = ProjectItem.from_xml(project_elem, ns)
541542
project_id = project_elem.get("id", None)
542543
project_name = project_elem.get("name", None)
543544

544545
owner_id = None
546+
owner = None
545547
owner_elem = datasource_xml.find(".//t:owner", namespaces=ns)
546548
if owner_elem is not None:
547549
owner = UserItem.from_xml(owner_elem, ns)

tableauserverclient/server/request_factory.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ def _generate_xml(self, datasource_item: DatasourceItem, connection_credentials=
184184
project_element = ET.SubElement(datasource_element, "project")
185185
project_element.attrib["id"] = datasource_item.project_id
186186

187+
if datasource_item.description is not None:
188+
datasource_element.attrib["description"] = datasource_item.description
189+
187190
if connection_credentials is not None and connections is not None:
188191
raise RuntimeError("You cannot set both `connections` and `connection_credentials`")
189192

@@ -196,7 +199,7 @@ def _generate_xml(self, datasource_item: DatasourceItem, connection_credentials=
196199
_add_connections_element(connections_element, connection)
197200
return ET.tostring(xml_request)
198201

199-
def update_req(self, datasource_item):
202+
def update_req(self, datasource_item: DatasourceItem) -> bytes:
200203
xml_request = ET.Element("tsRequest")
201204
datasource_element = ET.SubElement(xml_request, "datasource")
202205
if datasource_item.name:
@@ -219,6 +222,8 @@ def update_req(self, datasource_item):
219222
datasource_element.attrib["certificationNote"] = str(datasource_item.certification_note)
220223
if datasource_item.encrypt_extracts is not None:
221224
datasource_element.attrib["encryptExtracts"] = str(datasource_item.encrypt_extracts).lower()
225+
if datasource_item.description is not None:
226+
datasource_element.attrib["description"] = datasource_item.description
222227

223228
return ET.tostring(xml_request)
224229

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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.3.xsd">
3+
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
4+
<datasources>
5+
<datasource id="e76a1461-3b1d-4588-bf1b-17551a879ad9" name="SampleDS" size="4096" contentUrl="SampleDS" description="SampleDsDescription" type="dataengine" createdAt="2016-08-11T21:22:40Z" updatedAt="2016-08-11T21:34:17Z" encryptExtracts="false" hasExtracts="true" useRemoteQueryAgent="false" webpageUrl="https://web.com">
6+
<tags />
7+
</datasource>
8+
<datasource id="9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" name="Sample datasource" description="description Sample" size="10240" contentUrl="Sampledatasource" type="dataengine" createdAt="2016-08-04T21:31:55Z" updatedAt="2016-08-04T21:31:55Z" encryptExtracts="true" hasExtracts="false" useRemoteQueryAgent="true" webpageUrl="https://page.com">
9+
<tags>
10+
<tag label="world" />
11+
<tag label="indicators" />
12+
<tag label="sample" />
13+
</tags>
14+
</datasource>
15+
</datasources>
16+
</tsResponse>

test/test_datasource.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
GET_EMPTY_XML = TEST_ASSET_DIR / "datasource_get_empty.xml"
2525
GET_BY_ID_XML = TEST_ASSET_DIR / "datasource_get_by_id.xml"
2626
GET_XML_ALL_FIELDS = TEST_ASSET_DIR / "datasource_get_all_fields.xml"
27+
GET_NO_OWNER = TEST_ASSET_DIR / "datasource_get_no_owner.xml"
2728
POPULATE_CONNECTIONS_XML = TEST_ASSET_DIR / "datasource_populate_connections.xml"
2829
POPULATE_PERMISSIONS_XML = TEST_ASSET_DIR / "datasource_populate_permissions.xml"
2930
PUBLISH_XML = TEST_ASSET_DIR / "datasource_publish.xml"
@@ -850,3 +851,57 @@ def test_get_datasource_all_fields(server) -> None:
850851
assert datasources[0].owner.last_login == parse_datetime("2025-02-04T06:39:20Z")
851852
assert datasources[0].owner.name == "[email protected]"
852853
assert datasources[0].owner.site_role == "SiteAdministratorCreator"
854+
855+
856+
def test_update_description(server: TSC.Server) -> None:
857+
response_xml = UPDATE_XML.read_text()
858+
with requests_mock.mock() as m:
859+
m.put(server.datasources.baseurl + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb", text=response_xml)
860+
single_datasource = TSC.DatasourceItem("1d0304cd-3796-429f-b815-7258370b9b74", "Sample datasource")
861+
single_datasource.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794"
862+
single_datasource._content_url = "Sampledatasource"
863+
single_datasource._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb"
864+
single_datasource.certified = True
865+
single_datasource.certification_note = "Warning, here be dragons."
866+
single_datasource.description = "Sample description"
867+
_ = server.datasources.update(single_datasource)
868+
869+
history = m.request_history[0]
870+
body = fromstring(history.body)
871+
ds_elem = body.find(".//datasource")
872+
assert ds_elem is not None
873+
assert ds_elem.attrib["description"] == "Sample description"
874+
875+
876+
def test_publish_description(server: TSC.Server) -> None:
877+
response_xml = PUBLISH_XML.read_text()
878+
with requests_mock.mock() as m:
879+
m.post(server.datasources.baseurl, text=response_xml)
880+
single_datasource = TSC.DatasourceItem("1d0304cd-3796-429f-b815-7258370b9b74", "Sample datasource")
881+
single_datasource.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794"
882+
single_datasource._content_url = "Sampledatasource"
883+
single_datasource._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb"
884+
single_datasource.certified = True
885+
single_datasource.certification_note = "Warning, here be dragons."
886+
single_datasource.description = "Sample description"
887+
_ = server.datasources.publish(single_datasource, TEST_ASSET_DIR / "SampleDS.tds", server.PublishMode.CreateNew)
888+
889+
history = m.request_history[0]
890+
boundary = history.body[: history.body.index(b"\r\n")].strip()
891+
parts = history.body.split(boundary)
892+
request_payload = next(part for part in parts if b"request_payload" in part)
893+
xml_payload = request_payload.strip().split(b"\r\n")[-1]
894+
body = fromstring(xml_payload)
895+
ds_elem = body.find(".//datasource")
896+
assert ds_elem is not None
897+
assert ds_elem.attrib["description"] == "Sample description"
898+
899+
900+
def test_get_datasource_no_owner(server: TSC.Server) -> None:
901+
with requests_mock.mock() as m:
902+
m.get(server.datasources.baseurl, text=GET_NO_OWNER.read_text())
903+
datasources, _ = server.datasources.get()
904+
905+
datasource = datasources[0]
906+
assert datasource.owner is None
907+
assert datasource.project is None

0 commit comments

Comments
 (0)