Skip to content

Commit bcda7ee

Browse files
author
Prathyusha Gidugu
committed
Fix Workbook constructor silently returning empty workbooks (0.11.3)
Changes: - _prepare_datasources now uses xml_root.find('.//datasources'). - _prepare_worksheets's ds_index lookup is now tolerant of missing entries (uses `.get(...)` and `continue`) so a worksheet that references an un-indexed datasource doesn't abort the constructor. - Bumped wheel version 0.11.2 -> 0.11.3 in BUILD.bazel.
1 parent 30f0a58 commit bcda7ee

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,6 @@ py_wheel(
7676
requires = [
7777
"lxml",
7878
],
79-
version = "0.11.2",
79+
version = "0.11.3",
8080
deps = ["//tableaudocumentapi"],
8181
)

tableaudocumentapi/workbook.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,15 @@ def _prepare_datasource_index(datasources):
9797
def _prepare_datasources(xml_root):
9898
datasources = []
9999

100-
# loop through our datasources and append
101-
datasource_elements = xml_root.find('datasources')
100+
# Use descendant search (`.//`) so we find the <datasources> element
101+
# regardless of where it sits in the workbook XML. Newer Tableau
102+
# versions sometimes nest it below the top level, and matching only
103+
# the direct child here returned [], which in turn caused
104+
# _prepare_worksheets() to raise KeyError on ds_index lookups and
105+
# silently abort the whole Workbook() constructor. Aligned with the
106+
# sibling _prepare_dashboards / _prepare_worksheets methods which
107+
# already use `.//`.
108+
datasource_elements = xml_root.find('.//datasources')
102109
if datasource_elements is None:
103110
return []
104111

@@ -137,7 +144,14 @@ def _prepare_worksheets(xml_root, ds_index):
137144

138145
for dependency in dependencies:
139146
datasource_name = dependency.attrib['datasource']
140-
datasource = ds_index[datasource_name]
147+
# Defensive: a worksheet may reference a datasource that
148+
# isn't in the index (e.g. a parameter-only datasource).
149+
# Previously this raised KeyError, aborting the Workbook
150+
# constructor and leaving worksheets/dashboards/datasources
151+
# all empty.
152+
datasource = ds_index.get(datasource_name)
153+
if datasource is None:
154+
continue
141155
for column in dependency.findall('.//column'):
142156
column_name = column.attrib['name']
143157
if column_name in datasource.fields:

0 commit comments

Comments
 (0)