Skip to content

Commit 73c2b02

Browse files
jorwoodsjacalata
authored andcommitted
Add powerpoint export functionality to TSC (#1012)
1 parent 634ff90 commit 73c2b02

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

tableauserverclient/models/workbook_item.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import copy
22
import uuid
33
import xml.etree.ElementTree as ET
4-
from typing import Dict, List, Optional, Set, TYPE_CHECKING
4+
from typing import Callable, Dict, List, Optional, Set, TYPE_CHECKING
55

66
from defusedxml.ElementTree import fromstring
77

@@ -33,6 +33,7 @@ def __init__(self, project_id: str, name: str = None, show_tabs: bool = False) -
3333
self._id: Optional[str] = None
3434
self._initial_tags: set = set()
3535
self._pdf = None
36+
self._powerpoint = None
3637
self._preview_image = None
3738
self._project_name = None
3839
self._revisions = None
@@ -91,14 +92,21 @@ def id(self) -> Optional[str]:
9192
return self._id
9293

9394
@property
94-
def pdf(self):
95+
def powerpoint(self) -> bytes:
96+
if self._powerpoint is None:
97+
error = "Workbook item must be populated with its powerpoint first."
98+
raise UnpopulatedPropertyError(error)
99+
return self._powerpoint()
100+
101+
@property
102+
def pdf(self) -> bytes:
95103
if self._pdf is None:
96104
error = "Workbook item must be populated with its pdf first."
97105
raise UnpopulatedPropertyError(error)
98106
return self._pdf()
99107

100108
@property
101-
def preview_image(self):
109+
def preview_image(self) -> bytes:
102110
if self._preview_image is None:
103111
error = "Workbook item must be populated with its preview image first."
104112
raise UnpopulatedPropertyError(error)
@@ -173,13 +181,16 @@ def _set_connections(self, connections):
173181
def _set_permissions(self, permissions):
174182
self._permissions = permissions
175183

176-
def _set_views(self, views):
184+
def _set_views(self, views: Callable[[], List[ViewItem]]) -> None:
177185
self._views = views
178186

179-
def _set_pdf(self, pdf):
187+
def _set_pdf(self, pdf: Callable[[], bytes]) -> None:
180188
self._pdf = pdf
181189

182-
def _set_preview_image(self, preview_image):
190+
def _set_powerpoint(self, pptx: Callable[[], bytes]) -> None:
191+
self._powerpoint = pptx
192+
193+
def _set_preview_image(self, preview_image: Callable[[], bytes]) -> None:
183194
self._preview_image = preview_image
184195

185196
def _set_revisions(self, revisions):

tableauserverclient/server/endpoint/workbooks_endpoint.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def populate_views(self, workbook_item: WorkbookItem, usage: bool = False) -> No
206206
error = "Workbook item missing ID. Workbook must be retrieved from server first."
207207
raise MissingRequiredFieldError(error)
208208

209-
def view_fetcher():
209+
def view_fetcher() -> List[ViewItem]:
210210
return self._get_views_for_workbook(workbook_item, usage)
211211

212212
workbook_item._set_views(view_fetcher)
@@ -252,32 +252,50 @@ def populate_pdf(self, workbook_item: WorkbookItem, req_options: "RequestOptions
252252
error = "Workbook item missing ID."
253253
raise MissingRequiredFieldError(error)
254254

255-
def pdf_fetcher():
255+
def pdf_fetcher() -> bytes:
256256
return self._get_wb_pdf(workbook_item, req_options)
257257

258258
workbook_item._set_pdf(pdf_fetcher)
259259
logger.info("Populated pdf for workbook (ID: {0})".format(workbook_item.id))
260260

261-
def _get_wb_pdf(self, workbook_item, req_options):
261+
def _get_wb_pdf(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"]) -> bytes:
262262
url = "{0}/{1}/pdf".format(self.baseurl, workbook_item.id)
263263
server_response = self.get_request(url, req_options)
264264
pdf = server_response.content
265265
return pdf
266266

267+
@api(version="3.8")
268+
def populate_powerpoint(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"] = None) -> None:
269+
if not workbook_item.id:
270+
error = "Workbook item missing ID."
271+
raise MissingRequiredFieldError(error)
272+
273+
def pptx_fetcher() -> bytes:
274+
return self._get_wb_pptx(workbook_item, req_options)
275+
276+
workbook_item._set_powerpoint(pptx_fetcher)
277+
logger.info("Populated powerpoint for workbook (ID: {0})".format(workbook_item.id))
278+
279+
def _get_wb_pptx(self, workbook_item: WorkbookItem, req_options: Optional["RequestOptions"]) -> bytes:
280+
url = "{0}/{1}/powerpoint".format(self.baseurl, workbook_item.id)
281+
server_response = self.get_request(url, req_options)
282+
pptx = server_response.content
283+
return pptx
284+
267285
# Get preview image of workbook
268286
@api(version="2.0")
269287
def populate_preview_image(self, workbook_item: WorkbookItem) -> None:
270288
if not workbook_item.id:
271289
error = "Workbook item missing ID. Workbook must be retrieved from server first."
272290
raise MissingRequiredFieldError(error)
273291

274-
def image_fetcher():
292+
def image_fetcher() -> bytes:
275293
return self._get_wb_preview_image(workbook_item)
276294

277295
workbook_item._set_preview_image(image_fetcher)
278296
logger.info("Populated preview image for workbook (ID: {0})".format(workbook_item.id))
279297

280-
def _get_wb_preview_image(self, workbook_item):
298+
def _get_wb_preview_image(self, workbook_item: WorkbookItem) -> bytes:
281299
url = "{0}/{1}/previewImage".format(self.baseurl, workbook_item.id)
282300
server_response = self.get_request(url)
283301
preview_image = server_response.content
355 KB
Binary file not shown.

test/test_workbook.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
GET_XML = os.path.join(TEST_ASSET_DIR, "workbook_get.xml")
2828
POPULATE_CONNECTIONS_XML = os.path.join(TEST_ASSET_DIR, "workbook_populate_connections.xml")
2929
POPULATE_PDF = os.path.join(TEST_ASSET_DIR, "populate_pdf.pdf")
30+
POPULATE_POWERPOINT = os.path.join(TEST_ASSET_DIR, "populate_powerpoint.pptx")
3031
POPULATE_PERMISSIONS_XML = os.path.join(TEST_ASSET_DIR, "workbook_populate_permissions.xml")
3132
POPULATE_PREVIEW_IMAGE = os.path.join(TEST_ASSET_DIR, "RESTAPISample Image.png")
3233
POPULATE_VIEWS_XML = os.path.join(TEST_ASSET_DIR, "workbook_populate_views.xml")
@@ -439,6 +440,22 @@ def test_populate_pdf(self) -> None:
439440
self.server.workbooks.populate_pdf(single_workbook, req_option)
440441
self.assertEqual(response, single_workbook.pdf)
441442

443+
def test_populate_powerpoint(self) -> None:
444+
self.server.version = "3.8"
445+
self.baseurl = self.server.workbooks.baseurl
446+
with open(POPULATE_POWERPOINT, "rb") as f:
447+
response = f.read()
448+
with requests_mock.mock() as m:
449+
m.get(
450+
self.baseurl + "/1f951daf-4061-451a-9df1-69a8062664f2/powerpoint",
451+
content=response,
452+
)
453+
single_workbook = TSC.WorkbookItem("test")
454+
single_workbook._id = "1f951daf-4061-451a-9df1-69a8062664f2"
455+
456+
self.server.workbooks.populate_powerpoint(single_workbook)
457+
self.assertEqual(response, single_workbook.powerpoint)
458+
442459
def test_populate_preview_image(self) -> None:
443460
with open(POPULATE_PREVIEW_IMAGE, "rb") as f:
444461
response = f.read()

0 commit comments

Comments
 (0)