Skip to content

Commit 7f1bf85

Browse files
committed
feat: run linked task now
1 parent 100cb6d commit 7f1bf85

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

tableauserverclient/models/linked_tasks_item.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import datetime as dt
12
from typing import List, Optional
3+
24
from defusedxml.ElementTree import fromstring
35

6+
from tableauserverclient.datetime_helpers import parse_datetime
47
from tableauserverclient.models.schedule_item import ScheduleItem
58

69

@@ -74,5 +77,26 @@ def _parse_element(cls, xml, namespace) -> List["LinkedTaskFlowRunItem"]:
7477
return all_tasks
7578

7679

80+
class LinkedTaskJobItem:
81+
def __init__(self) -> None:
82+
self.id: Optional[str] = None
83+
self.linked_task_id: Optional[str] = None
84+
self.status: Optional[str] = None
85+
self.created_at: Optional[dt.datetime] = None
86+
87+
@classmethod
88+
def from_response(cls, resp: bytes, namespace) -> "LinkedTaskJobItem":
89+
parsed_response = fromstring(resp)
90+
job = cls()
91+
job_xml = parsed_response.find(".//t:linkedTaskJob[@id]", namespaces=namespace)
92+
if job_xml is None:
93+
raise ValueError("No linked task job found in response")
94+
job.id = job_xml.get("id")
95+
job.linked_task_id = job_xml.get("linkedTaskId")
96+
job.status = job_xml.get("status")
97+
job.created_at = parse_datetime(job_xml.get("createdAt"))
98+
return job
99+
100+
77101
def string_to_bool(s: str) -> bool:
78102
return s.lower() == "true"

tableauserverclient/server/endpoint/linked_tasks_endpoint.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import List, Optional, Tuple, Union
22

33
from tableauserverclient.helpers.logging import logger
4-
from tableauserverclient.models.linked_tasks_item import LinkedTaskItem
4+
from tableauserverclient.models.linked_tasks_item import LinkedTaskItem, LinkedTaskJobItem
55
from tableauserverclient.models.pagination_item import PaginationItem
66
from tableauserverclient.server.endpoint.endpoint import QuerysetEndpoint, api
7+
from tableauserverclient.server.request_factory import RequestFactory
78
from tableauserverclient.server.request_options import RequestOptions
89

910

@@ -33,3 +34,12 @@ def get_by_id(self, linked_task: Union[LinkedTaskItem, str]) -> LinkedTaskItem:
3334
server_response = self.get_request(url)
3435
all_group_items = LinkedTaskItem.from_response(server_response.content, self.parent_srv.namespace)
3536
return all_group_items[0]
37+
38+
@api(version="3.15")
39+
def run_now(self, linked_task: Union[LinkedTaskItem, str]) -> LinkedTaskJobItem:
40+
task_id = getattr(linked_task, "id", linked_task)
41+
logger.info(f"Running linked task {task_id} now")
42+
url = f"{self.baseurl}/{task_id}/runNow"
43+
empty_req = RequestFactory.Empty.empty_req()
44+
server_response = self.post_request(url, empty_req)
45+
return LinkedTaskJobItem.from_response(server_response.content, self.parent_srv.namespace)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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-3.5.xsd">
3+
<linkedTaskJob id="269a1e5a-1220-4a13-ac01-704982693dd8"
4+
linkedTaskId="1b8211dc-51a8-45ce-a831-b5921708e03e"
5+
status="InProgress"
6+
createdAt="2022-02-15T00:22:22Z"/>
7+
</tsResponse>

test/test_linked_tasks.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
import requests_mock
77

88
import tableauserverclient as TSC
9+
from tableauserverclient.datetime_helpers import parse_datetime
910
from tableauserverclient.models.linked_tasks_item import LinkedTaskItem, LinkedTaskStepItem, LinkedTaskFlowRunItem
1011

1112
asset_dir = (Path(__file__).parent / "assets").resolve()
1213

1314
GET_LINKED_TASKS = asset_dir / "linked_tasks_get.xml"
15+
RUN_LINKED_TASK_NOW = asset_dir / "linked_tasks_run_now.xml"
1416

1517

1618
class TestLinkedTasks(unittest.TestCase):
@@ -99,3 +101,29 @@ def test_get_by_id_obj_linked_task(self):
99101
assert task.num_steps == 1
100102
assert task.schedule is not None
101103
assert task.schedule.id == "be077332-d01d-481b-b2f3-917e463d4dca"
104+
105+
def test_run_now_str_linked_task(self):
106+
id_ = "1b8211dc-51a8-45ce-a831-b5921708e03e"
107+
108+
with requests_mock.mock() as m:
109+
m.post(f"{self.baseurl}/{id_}/runNow", text=RUN_LINKED_TASK_NOW.read_text())
110+
job = self.server.linked_tasks.run_now(id_)
111+
112+
assert job.id == "269a1e5a-1220-4a13-ac01-704982693dd8"
113+
assert job.status == "InProgress"
114+
assert job.created_at == parse_datetime("2022-02-15T00:22:22Z")
115+
assert job.linked_task_id == id_
116+
117+
def test_run_now_obj_linked_task(self):
118+
id_ = "1b8211dc-51a8-45ce-a831-b5921708e03e"
119+
in_task = LinkedTaskItem()
120+
in_task.id = id_
121+
122+
with requests_mock.mock() as m:
123+
m.post(f"{self.baseurl}/{id_}/runNow", text=RUN_LINKED_TASK_NOW.read_text())
124+
job = self.server.linked_tasks.run_now(in_task)
125+
126+
assert job.id == "269a1e5a-1220-4a13-ac01-704982693dd8"
127+
assert job.status == "InProgress"
128+
assert job.created_at == parse_datetime("2022-02-15T00:22:22Z")
129+
assert job.linked_task_id == id_

0 commit comments

Comments
 (0)