From 8a4ac5937a8e4a288337dbfac7fc63e5596c6f96 Mon Sep 17 00:00:00 2001 From: Jordan Woods Date: Sun, 29 May 2022 14:23:31 -0500 Subject: [PATCH] Extract refreshable item IDs from job XML response --- tableauserverclient/models/job_item.py | 26 +++++++++++++++++++ test/assets/job_get_by_id_failed_workbook.xml | 9 +++++++ test/test_job.py | 19 ++++++++++++-- 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 test/assets/job_get_by_id_failed_workbook.xml diff --git a/tableauserverclient/models/job_item.py b/tableauserverclient/models/job_item.py index e05c42e22..39562cd45 100644 --- a/tableauserverclient/models/job_item.py +++ b/tableauserverclient/models/job_item.py @@ -31,6 +31,8 @@ def __init__( finish_code: int = 0, notes: Optional[List[str]] = None, mode: Optional[str] = None, + workbook_id: Optional[str] = None, + datasource_id: Optional[str] = None, flow_run: Optional[FlowRunItem] = None, ): self._id = id_ @@ -42,6 +44,8 @@ def __init__( self._finish_code = finish_code self._notes: List[str] = notes or [] self._mode = mode + self._workbook_id = workbook_id + self._datasource_id = datasource_id self._flow_run = flow_run @property @@ -85,6 +89,22 @@ def mode(self, value: str) -> None: # check for valid data here self._mode = value + @property + def workbook_id(self) -> Optional[str]: + return self._workbook_id + + @workbook_id.setter + def workbook_id(self, value: Optional[str]) -> None: + self._workbook_id = value + + @property + def datasource_id(self) -> Optional[str]: + return self._datasource_id + + @datasource_id.setter + def datasource_id(self, value: Optional[str]) -> None: + self._datasource_id = value + @property def flow_run(self): return self._flow_run @@ -119,6 +139,10 @@ def _parse_element(cls, element, ns): finish_code = int(element.get("finishCode", -1)) notes = [note.text for note in element.findall(".//t:notes", namespaces=ns)] or None mode = element.get("mode", None) + workbook = element.find(".//t:workbook[@id]", namespaces=ns) + workbook_id = workbook.get("id") if workbook is not None else None + datasource = element.find(".//t:datasource[@id]", namespaces=ns) + datasource_id = datasource.get("id") if datasource is not None else None flow_run = None for flow_job in element.findall(".//t:runFlowJobType", namespaces=ns): flow_run = FlowRunItem() @@ -136,6 +160,8 @@ def _parse_element(cls, element, ns): finish_code, notes, mode, + workbook_id, + datasource_id, flow_run, ) diff --git a/test/assets/job_get_by_id_failed_workbook.xml b/test/assets/job_get_by_id_failed_workbook.xml new file mode 100644 index 000000000..bf81d896e --- /dev/null +++ b/test/assets/job_get_by_id_failed_workbook.xml @@ -0,0 +1,9 @@ + + + + + + java.lang.RuntimeException: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Login failed for user.\nIntegrated authentication failed. + + + diff --git a/test/test_job.py b/test/test_job.py index 6daa16afa..19a93e808 100644 --- a/test/test_job.py +++ b/test/test_job.py @@ -9,13 +9,12 @@ from tableauserverclient.server.endpoint.exceptions import JobFailedException from ._utils import read_xml_asset, mocked_time -TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "assets") - GET_XML = "job_get.xml" GET_BY_ID_XML = "job_get_by_id.xml" GET_BY_ID_FAILED_XML = "job_get_by_id_failed.xml" GET_BY_ID_CANCELLED_XML = "job_get_by_id_cancelled.xml" GET_BY_ID_INPROGRESS_XML = "job_get_by_id_inprogress.xml" +GET_BY_ID_WORKBOOK = "job_get_by_id_failed_workbook.xml" class JobTests(unittest.TestCase): @@ -103,3 +102,19 @@ def test_wait_for_job_timeout(self) -> None: m.get("{0}/{1}".format(self.baseurl, job_id), text=response_xml) with self.assertRaises(TimeoutError): self.server.jobs.wait_for_job(job_id, timeout=30) + + def test_get_job_datasource_id(self) -> None: + response_xml = read_xml_asset(GET_BY_ID_FAILED_XML) + job_id = "777bf7c4-421d-4b2c-a518-11b90187c545" + with requests_mock.mock() as m: + m.get(f"{self.baseurl}/{job_id}", text=response_xml) + job = self.server.jobs.get_by_id(job_id) + self.assertEqual(job.datasource_id, "03b9fbec-81f6-4160-ae49-5f9f6d412758") + + def test_get_job_workbook_id(self) -> None: + response_xml = read_xml_asset(GET_BY_ID_WORKBOOK) + job_id = "bb1aab79-db54-4e96-9dd3-461d8f081d08" + with requests_mock.mock() as m: + m.get(f"{self.baseurl}/{job_id}", text=response_xml) + job = self.server.jobs.get_by_id(job_id) + self.assertEqual(job.workbook_id, "5998aaaf-1abe-4d38-b4d9-bc53e85bdd13")