Skip to content

Commit 520fd03

Browse files
committed
feat: workbook support all fields
1 parent 007136f commit 520fd03

File tree

3 files changed

+244
-1
lines changed

3 files changed

+244
-1
lines changed

tableauserverclient/models/workbook_item.py

+93
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from defusedxml.ElementTree import fromstring
88

99
from tableauserverclient.datetime_helpers import parse_datetime
10+
from tableauserverclient.models.location_item import LocationItem
11+
from tableauserverclient.models.project_item import ProjectItem
12+
from tableauserverclient.models.user_item import UserItem
1013
from .connection_item import ConnectionItem
1114
from .exceptions import UnpopulatedPropertyError
1215
from .permissions_item import PermissionsRule
@@ -141,6 +144,13 @@ def __init__(
141144
self.thumbnails_group_id = thumbnails_group_id
142145
self._sheet_count: Optional[int] = None
143146
self._has_extracts: Optional[bool] = None
147+
self._project: Optional[ProjectItem] = None
148+
self._owner: Optional[UserItem] = None
149+
self._location: Optional[LocationItem] = None
150+
self._encrypt_extracts: Optional[bool] = None
151+
self._default_view_id: Optional[str] = None
152+
self._share_description: Optional[str] = None
153+
self._last_published_at: Optional[datetime.datetime] = None
144154

145155
return None
146156

@@ -310,6 +320,34 @@ def thumbnails_group_id(self) -> Optional[str]:
310320
def thumbnails_group_id(self, value: str):
311321
self._thumbnails_group_id = value
312322

323+
@property
324+
def project(self) -> Optional[ProjectItem]:
325+
return self._project
326+
327+
@property
328+
def owner(self) -> Optional[UserItem]:
329+
return self._owner
330+
331+
@property
332+
def location(self) -> Optional[LocationItem]:
333+
return self._location
334+
335+
@property
336+
def encrypt_extracts(self) -> Optional[bool]:
337+
return self._encrypt_extracts
338+
339+
@property
340+
def default_view_id(self) -> Optional[str]:
341+
return self._default_view_id
342+
343+
@property
344+
def share_description(self) -> Optional[str]:
345+
return self._share_description
346+
347+
@property
348+
def last_published_at(self) -> Optional[datetime.datetime]:
349+
return self._last_published_at
350+
313351
def _set_connections(self, connections):
314352
self._connections = connections
315353

@@ -354,6 +392,13 @@ def _parse_common_tags(self, workbook_xml, ns):
354392
data_freshness_policy,
355393
sheet_count,
356394
has_extracts,
395+
project,
396+
owner,
397+
location,
398+
encrypt_extracts,
399+
default_view_id,
400+
share_description,
401+
last_published_at,
357402
) = self._parse_element(workbook_xml, ns)
358403

359404
self._set_values(
@@ -375,6 +420,13 @@ def _parse_common_tags(self, workbook_xml, ns):
375420
data_freshness_policy,
376421
sheet_count,
377422
has_extracts,
423+
project,
424+
owner,
425+
location,
426+
encrypt_extracts,
427+
default_view_id,
428+
share_description,
429+
last_published_at,
378430
)
379431

380432
return self
@@ -399,6 +451,13 @@ def _set_values(
399451
data_freshness_policy,
400452
sheet_count,
401453
has_extracts,
454+
project,
455+
owner,
456+
location,
457+
encrypt_extracts,
458+
default_view_id,
459+
share_description,
460+
last_published_at,
402461
):
403462
if id is not None:
404463
self._id = id
@@ -437,6 +496,20 @@ def _set_values(
437496
self._sheet_count = sheet_count
438497
if has_extracts is not None:
439498
self._has_extracts = has_extracts
499+
if project:
500+
self._project = project
501+
if owner:
502+
self._owner = owner
503+
if location:
504+
self._location = location
505+
if encrypt_extracts is not None:
506+
self._encrypt_extracts = encrypt_extracts
507+
if default_view_id is not None:
508+
self._default_view_id = default_view_id
509+
if share_description is not None:
510+
self._share_description = share_description
511+
if last_published_at is not None:
512+
self._last_published_at = last_published_at
440513

441514
@classmethod
442515
def from_response(cls, resp: str, ns: dict[str, str]) -> list["WorkbookItem"]:
@@ -465,6 +538,10 @@ def _parse_element(workbook_xml, ns):
465538
updated_at = parse_datetime(workbook_xml.get("updatedAt", None))
466539
sheet_count = string_to_int(workbook_xml.get("sheetCount", None))
467540
has_extracts = string_to_bool(workbook_xml.get("hasExtracts", ""))
541+
encrypt_extracts = string_to_bool(e) if (e := workbook_xml.get("encryptExtracts", None)) is not None else None
542+
default_view_id = workbook_xml.get("defaultViewId", None)
543+
share_description = workbook_xml.get("shareDescription", None)
544+
last_published_at = parse_datetime(workbook_xml.get("lastPublishedAt", None))
468545

469546
size = workbook_xml.get("size", None)
470547
if size:
@@ -474,14 +551,18 @@ def _parse_element(workbook_xml, ns):
474551

475552
project_id = None
476553
project_name = None
554+
project = None
477555
project_tag = workbook_xml.find(".//t:project", namespaces=ns)
478556
if project_tag is not None:
557+
project = ProjectItem.from_xml(project_tag, ns)
479558
project_id = project_tag.get("id", None)
480559
project_name = project_tag.get("name", None)
481560

482561
owner_id = None
562+
owner = None
483563
owner_tag = workbook_xml.find(".//t:owner", namespaces=ns)
484564
if owner_tag is not None:
565+
owner = UserItem.from_xml(owner_tag, ns)
485566
owner_id = owner_tag.get("id", None)
486567

487568
tags = None
@@ -495,6 +576,11 @@ def _parse_element(workbook_xml, ns):
495576
if views_elem is not None:
496577
views = ViewItem.from_xml_element(views_elem, ns)
497578

579+
location = None
580+
location_elem = workbook_xml.find(".//t:location", namespaces=ns)
581+
if location_elem is not None:
582+
location = LocationItem.from_xml(location_elem, ns)
583+
498584
data_acceleration_config = {
499585
"acceleration_enabled": None,
500586
"accelerate_now": None,
@@ -529,6 +615,13 @@ def _parse_element(workbook_xml, ns):
529615
data_freshness_policy,
530616
sheet_count,
531617
has_extracts,
618+
project,
619+
owner,
620+
location,
621+
encrypt_extracts,
622+
default_view_id,
623+
share_description,
624+
last_published_at,
532625
)
533626

534627

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<ns0:tsResponse xmlns:ns0="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api https://help.tableau.com/samples/en-us/rest_api/ts-api_3_25.xsd">
2+
<ns0:pagination pageNumber="1" pageSize="100" totalAvailable="6" />
3+
<ns0:workbooks>
4+
<ns0:workbook id="9df3e2d1-070e-497a-9578-8cc557ced9df" name="Superstore" contentUrl="Superstore" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/265605" showTabs="true" size="2" createdAt="2024-02-14T04:42:09Z" updatedAt="2024-02-14T04:42:10Z" sheetCount="9" hasExtracts="false" encryptExtracts="false" defaultViewId="2bdcd787-dcc6-4a5d-bc61-2846f1ef4534" shareDescription="Superstore" lastPublishedAt="2024-02-14T04:42:09Z">
5+
<ns0:project id="669ca36b-492e-4ccf-bca1-3614fe6a9d7a" name="Samples" description="This project includes automatically uploaded samples." />
6+
<ns0:location id="669ca36b-492e-4ccf-bca1-3614fe6a9d7a" type="Project" name="Samples" />
7+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
8+
<ns0:tags />
9+
<ns0:dataAccelerationConfig />
10+
</ns0:workbook>
11+
<ns0:workbook id="6693cb26-9507-4174-ad3e-9de81a18c971" name="World Indicators" contentUrl="WorldIndicators" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/265606" showTabs="true" size="1" createdAt="2024-02-14T04:42:11Z" updatedAt="2024-02-14T04:42:12Z" sheetCount="8" hasExtracts="false" encryptExtracts="false" defaultViewId="3d10dbcf-a206-47c7-91ba-ebab3ab33d7c" shareDescription="World Indicators" lastPublishedAt="2024-02-14T04:42:11Z">
12+
<ns0:project id="669ca36b-492e-4ccf-bca1-3614fe6a9d7a" name="Samples" description="This project includes automatically uploaded samples." />
13+
<ns0:location id="669ca36b-492e-4ccf-bca1-3614fe6a9d7a" type="Project" name="Samples" />
14+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
15+
<ns0:tags />
16+
<ns0:dataAccelerationConfig />
17+
</ns0:workbook>
18+
<ns0:workbook id="dbc0f162-909f-4edf-8392-0d12a80af955" name="Superstore" description="This is a superstore workbook" contentUrl="Superstore_17078880698360" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/265621" showTabs="false" size="1" createdAt="2024-02-14T05:21:09Z" updatedAt="2024-07-02T02:19:59Z" sheetCount="7" hasExtracts="true" encryptExtracts="false" defaultViewId="8c4b1d3e-3f31-4d2a-8b9f-492b92f27987" shareDescription="Superstore" lastPublishedAt="2024-07-02T02:19:58Z">
19+
<ns0:project id="9836791c-9468-40f0-b7f3-d10b9562a046" name="default" description="The default project that was automatically created by Tableau." />
20+
<ns0:location id="9836791c-9468-40f0-b7f3-d10b9562a046" type="Project" name="default" />
21+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
22+
<ns0:tags />
23+
<ns0:dataAccelerationConfig />
24+
</ns0:workbook>
25+
<ns0:workbook id="6f86152e-f50d-441c-99f3-ab3accaf7e9e" name="Odata book" description="" contentUrl="Odatabook" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/417497" showTabs="false" size="1" createdAt="2024-06-11T02:29:17Z" updatedAt="2024-06-11T02:29:18Z" sheetCount="1" hasExtracts="true" encryptExtracts="false" defaultViewId="ab8dd9f4-22d1-4d35-8b87-594d9dc7e74f" shareDescription="Odata book" lastPublishedAt="2024-06-11T02:29:17Z">
26+
<ns0:project id="9836791c-9468-40f0-b7f3-d10b9562a046" name="default" description="The default project that was automatically created by Tableau." />
27+
<ns0:location id="9836791c-9468-40f0-b7f3-d10b9562a046" type="Project" name="default" />
28+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
29+
<ns0:tags />
30+
<ns0:dataAccelerationConfig />
31+
</ns0:workbook>
32+
<ns0:workbook id="b69fc30b-64c3-4c2f-a2a2-2eb15b9abaee" name="test" contentUrl="test" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/613582" showTabs="false" size="1" createdAt="2024-08-07T23:02:29Z" updatedAt="2024-08-07T23:03:27Z" sheetCount="8" hasExtracts="false" encryptExtracts="false" defaultViewId="c894fa66-6fcb-4065-9c49-e1f6755dca4a" shareDescription="test" lastPublishedAt="2024-08-07T23:03:27Z">
33+
<ns0:project id="9836791c-9468-40f0-b7f3-d10b9562a046" name="default" description="The default project that was automatically created by Tableau." />
34+
<ns0:location id="9836791c-9468-40f0-b7f3-d10b9562a046" type="Project" name="default" />
35+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
36+
<ns0:tags />
37+
<ns0:dataAccelerationConfig />
38+
</ns0:workbook>
39+
<ns0:workbook id="50b552b5-ef2b-4347-b4c7-9e011689c098" name="PersonalSpaceDemo" contentUrl="PersonalSpaceDemo" webpageUrl="https://10ax.online.tableau.com/#/site/exampledev/workbooks/941425" showTabs="false" size="1" createdAt="2025-02-04T04:22:05Z" updatedAt="2025-02-04T04:22:06Z" sheetCount="7" hasExtracts="true" encryptExtracts="false" defaultViewId="1d0d5323-73db-476e-9992-ac43a7789114" shareDescription="PersonalSpaceDemo" lastPublishedAt="2025-02-04T04:22:05Z">
40+
<ns0:location id="ea447ef3-18ae-4a00-a0b9-823ca18ec86c" type="PersonalSpace" name="Personal Space" />
41+
<ns0:owner email="[email protected]" fullName="Bob Smith" id="ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9" lastLogin="2025-02-04T06:39:20Z" name="[email protected]" siteRole="SiteAdministratorCreator" />
42+
<ns0:tags />
43+
<ns0:dataAccelerationConfig />
44+
</ns0:workbook>
45+
</ns0:workbooks>
46+
</ns0:tsResponse>

test/test_workbook.py

+105-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import pytest
1111

1212
import tableauserverclient as TSC
13-
from tableauserverclient.datetime_helpers import format_datetime
13+
from tableauserverclient.datetime_helpers import format_datetime, parse_datetime
1414
from tableauserverclient.models import UserItem, GroupItem, PermissionsRule
1515
from tableauserverclient.server.endpoint.exceptions import InternalServerError
1616
from tableauserverclient.server.request_factory import RequestFactory
@@ -24,6 +24,7 @@
2424
GET_EMPTY_XML = os.path.join(TEST_ASSET_DIR, "workbook_get_empty.xml")
2525
GET_INVALID_DATE_XML = os.path.join(TEST_ASSET_DIR, "workbook_get_invalid_date.xml")
2626
GET_XML = os.path.join(TEST_ASSET_DIR, "workbook_get.xml")
27+
GET_XML_ALL_FIELDS = os.path.join(TEST_ASSET_DIR, "workbook_get_all_fields.xml")
2728
ODATA_XML = os.path.join(TEST_ASSET_DIR, "odata_connection.xml")
2829
POPULATE_CONNECTIONS_XML = os.path.join(TEST_ASSET_DIR, "workbook_populate_connections.xml")
2930
POPULATE_PDF = os.path.join(TEST_ASSET_DIR, "populate_pdf.pdf")
@@ -933,3 +934,106 @@ def test_odata_connection(self) -> None:
933934

934935
assert xml_connection is not None
935936
self.assertEqual(xml_connection.get("serverAddress"), url)
937+
938+
def test_get_workbook_all_fields(self) -> None:
939+
self.server.version = "3.21"
940+
baseurl = self.server.workbooks.baseurl
941+
942+
with open(GET_XML_ALL_FIELDS) as f:
943+
response = f.read()
944+
945+
ro = TSC.RequestOptions()
946+
ro.all_fields = True
947+
948+
with requests_mock.mock() as m:
949+
m.get(f"{baseurl}?fields=_all_", text=response)
950+
workbooks, _ = self.server.workbooks.get(req_options=ro)
951+
952+
assert workbooks[0].id == "9df3e2d1-070e-497a-9578-8cc557ced9df"
953+
assert workbooks[0].name == "Superstore"
954+
assert workbooks[0].content_url == "Superstore"
955+
assert workbooks[0].webpage_url == "https://10ax.online.tableau.com/#/site/exampledev/workbooks/265605"
956+
assert workbooks[0].show_tabs
957+
assert workbooks[0].size == 2
958+
assert workbooks[0].created_at == parse_datetime("2024-02-14T04:42:09Z")
959+
assert workbooks[0].updated_at == parse_datetime("2024-02-14T04:42:10Z")
960+
assert workbooks[0].sheet_count == 9
961+
assert not workbooks[0].has_extracts
962+
assert not workbooks[0].encrypt_extracts
963+
assert workbooks[0].default_view_id == "2bdcd787-dcc6-4a5d-bc61-2846f1ef4534"
964+
assert workbooks[0].share_description == "Superstore"
965+
assert workbooks[0].last_published_at == parse_datetime("2024-02-14T04:42:09Z")
966+
assert isinstance(workbooks[0].project, TSC.ProjectItem)
967+
assert workbooks[0].project.id == "669ca36b-492e-4ccf-bca1-3614fe6a9d7a"
968+
assert workbooks[0].project.name == "Samples"
969+
assert workbooks[0].project.description == "This project includes automatically uploaded samples."
970+
assert isinstance(workbooks[0].location, TSC.LocationItem)
971+
assert workbooks[0].location.id == "669ca36b-492e-4ccf-bca1-3614fe6a9d7a"
972+
assert workbooks[0].location.type == "Project"
973+
assert workbooks[0].location.name == "Samples"
974+
assert isinstance(workbooks[0].owner, TSC.UserItem)
975+
assert workbooks[0].owner.email == "[email protected]"
976+
assert workbooks[0].owner.fullname == "Bob Smith"
977+
assert workbooks[0].owner.id == "ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9"
978+
assert workbooks[0].owner.last_login == parse_datetime("2025-02-04T06:39:20Z")
979+
assert workbooks[0].owner.name == "[email protected]"
980+
assert workbooks[0].owner.site_role == "SiteAdministratorCreator"
981+
assert workbooks[1].id == "6693cb26-9507-4174-ad3e-9de81a18c971"
982+
assert workbooks[1].name == "World Indicators"
983+
assert workbooks[1].content_url == "WorldIndicators"
984+
assert workbooks[1].webpage_url == "https://10ax.online.tableau.com/#/site/exampledev/workbooks/265606"
985+
assert workbooks[1].show_tabs
986+
assert workbooks[1].size == 1
987+
assert workbooks[1].created_at == parse_datetime("2024-02-14T04:42:11Z")
988+
assert workbooks[1].updated_at == parse_datetime("2024-02-14T04:42:12Z")
989+
assert workbooks[1].sheet_count == 8
990+
assert not workbooks[1].has_extracts
991+
assert not workbooks[1].encrypt_extracts
992+
assert workbooks[1].default_view_id == "3d10dbcf-a206-47c7-91ba-ebab3ab33d7c"
993+
assert workbooks[1].share_description == "World Indicators"
994+
assert workbooks[1].last_published_at == parse_datetime("2024-02-14T04:42:11Z")
995+
assert isinstance(workbooks[1].project, TSC.ProjectItem)
996+
assert workbooks[1].project.id == "669ca36b-492e-4ccf-bca1-3614fe6a9d7a"
997+
assert workbooks[1].project.name == "Samples"
998+
assert workbooks[1].project.description == "This project includes automatically uploaded samples."
999+
assert isinstance(workbooks[1].location, TSC.LocationItem)
1000+
assert workbooks[1].location.id == "669ca36b-492e-4ccf-bca1-3614fe6a9d7a"
1001+
assert workbooks[1].location.type == "Project"
1002+
assert workbooks[1].location.name == "Samples"
1003+
assert isinstance(workbooks[1].owner, TSC.UserItem)
1004+
assert workbooks[1].owner.email == "[email protected]"
1005+
assert workbooks[1].owner.fullname == "Bob Smith"
1006+
assert workbooks[1].owner.id == "ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9"
1007+
assert workbooks[1].owner.last_login == parse_datetime("2025-02-04T06:39:20Z")
1008+
assert workbooks[1].owner.name == "[email protected]"
1009+
assert workbooks[1].owner.site_role == "SiteAdministratorCreator"
1010+
assert workbooks[2].id == "dbc0f162-909f-4edf-8392-0d12a80af955"
1011+
assert workbooks[2].name == "Superstore"
1012+
assert workbooks[2].description == "This is a superstore workbook"
1013+
assert workbooks[2].content_url == "Superstore_17078880698360"
1014+
assert workbooks[2].webpage_url == "https://10ax.online.tableau.com/#/site/exampledev/workbooks/265621"
1015+
assert not workbooks[2].show_tabs
1016+
assert workbooks[2].size == 1
1017+
assert workbooks[2].created_at == parse_datetime("2024-02-14T05:21:09Z")
1018+
assert workbooks[2].updated_at == parse_datetime("2024-07-02T02:19:59Z")
1019+
assert workbooks[2].sheet_count == 7
1020+
assert workbooks[2].has_extracts
1021+
assert not workbooks[2].encrypt_extracts
1022+
assert workbooks[2].default_view_id == "8c4b1d3e-3f31-4d2a-8b9f-492b92f27987"
1023+
assert workbooks[2].share_description == "Superstore"
1024+
assert workbooks[2].last_published_at == parse_datetime("2024-07-02T02:19:58Z")
1025+
assert isinstance(workbooks[2].project, TSC.ProjectItem)
1026+
assert workbooks[2].project.id == "9836791c-9468-40f0-b7f3-d10b9562a046"
1027+
assert workbooks[2].project.name == "default"
1028+
assert workbooks[2].project.description == "The default project that was automatically created by Tableau."
1029+
assert isinstance(workbooks[2].location, TSC.LocationItem)
1030+
assert workbooks[2].location.id == "9836791c-9468-40f0-b7f3-d10b9562a046"
1031+
assert workbooks[2].location.type == "Project"
1032+
assert workbooks[2].location.name == "default"
1033+
assert isinstance(workbooks[2].owner, TSC.UserItem)
1034+
assert workbooks[2].owner.email == "[email protected]"
1035+
assert workbooks[2].owner.fullname == "Bob Smith"
1036+
assert workbooks[2].owner.id == "ee8bc9ca-77fe-4ae0-8093-cf77f0ee67a9"
1037+
assert workbooks[2].owner.last_login == parse_datetime("2025-02-04T06:39:20Z")
1038+
assert workbooks[2].owner.name == "[email protected]"
1039+
assert workbooks[2].owner.site_role == "SiteAdministratorCreator"

0 commit comments

Comments
 (0)