Skip to content

Commit fcd07ca

Browse files
jacalataclaude
andcommitted
refactor: remove pre-8.3 XML namespace fallback (#1046)
The `Namespace` class detected `http://tableausoftware.com/api` (the pre-8.3 namespace) at runtime on every XML response and let the parser silently switch namespaces if it saw the old one. That behavior has been unreachable for years: the library's `minimum_supported_server_version` is 2.3, which corresponds to Tableau Server 10.0 -- shipped in 2016, three years after the namespace changed. Every server TSC has ever admitted uses `http://tableau.com/api`. Removes: - `tableauserverclient/namespace.py` (the module) and everything it exported: `Namespace`, `UnknownNamespaceError`, `OLD_NAMESPACE`, `NEW_NAMESPACE`, `NAMESPACE_RE`. - `Server._namespace` instance and the per-response `.detect(...)` call in `Endpoint._make_request` and both sign-in paths in `Auth`. Keeps: - The public `TSC.DEFAULT_NAMESPACE` re-export -- now sourced from `tableauserverclient.server.server.NAMESPACE`, which is the canonical constant. Same string value. - `Server.namespace` property -- still returns the `{"t": NAMESPACE}` dict callers pass to ElementTree's `namespaces=` kwarg. Same shape. Callers who imported directly from `tableauserverclient.namespace` (rather than `TSC.DEFAULT_NAMESPACE`) will break; the CHANGELOG entry calls this out. Fixes #1046. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent aa9e3a0 commit fcd07ca

6 files changed

Lines changed: 14 additions & 46 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
`type` / `value` / `text`. The existing `notes: list[str]` attribute is
1313
unchanged (it parses the separate legacy `<notes>` element still emitted by
1414
some job types). Fixes #1850.
15+
* Removed the pre-Tableau-8.3 XML namespace fallback
16+
(`http://tableausoftware.com/api`). Every server TSC's `minimum_supported_server_version`
17+
guard has ever admitted uses the current namespace (`http://tableau.com/api`),
18+
and the runtime-detection code has been unreachable in practice for a
19+
decade. `tableauserverclient.namespace` module and `UnknownNamespaceError`
20+
are removed; the public `TSC.DEFAULT_NAMESPACE` re-export still works and
21+
now points at `tableauserverclient.server.server.NAMESPACE`. Fixes #1046.
1522

1623
## 0.18.0 (6 April 2022)
1724
* Switched to using defused_xml for xml attack protection

tableauserverclient/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from tableauserverclient.bin._version import get_versions
2-
from tableauserverclient.namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
2+
from tableauserverclient.server.server import NAMESPACE as DEFAULT_NAMESPACE
33
from tableauserverclient.models import (
44
BackgroundJobItem,
55
CollectionItem,

tableauserverclient/namespace.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

tableauserverclient/server/endpoint/auth_endpoint.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ def sign_in(self, auth_req: "Credentials") -> contextmgr:
8080
**self.parent_srv.http_options,
8181
allow_redirects=False,
8282
)
83-
self.parent_srv._namespace.detect(server_response.content)
8483
self._check_status(server_response, url)
8584
parsed_response = fromstring(server_response.content)
8685
site_id = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("id", None)
@@ -154,7 +153,6 @@ def switch_site(self, site_item: "SiteItem") -> contextmgr:
154153
return Auth.contextmgr(self.sign_out)
155154
else:
156155
raise e
157-
self.parent_srv._namespace.detect(server_response.content)
158156
self._check_status(server_response, url)
159157
parsed_response = fromstring(server_response.content)
160158
site_id = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("id", None)

tableauserverclient/server/endpoint/endpoint.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,6 @@ def _make_request(
152152
# BE CAREFUL WHEN SHARING THESE RESULTS - MAY CONTAIN YOUR SENSITIVE DATA
153153
# logger.debug(loggable_response)
154154

155-
if content_type == "application/xml":
156-
self.parent_srv._namespace.detect(server_response.content)
157-
158155
return server_response
159156

160157
def _check_status(self, server_response: "Response", url: str | None = None):

tableauserverclient/server/server.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
EndpointUnavailableError,
4747
)
4848
from tableauserverclient.server.endpoint.exceptions import NotSignedInError
49-
from tableauserverclient.namespace import Namespace
5049

5150
_PRODUCT_TO_REST_VERSION = {
5251
"10.0": "2.3",
@@ -59,6 +58,11 @@
5958
minimum_supported_server_version = "2.3"
6059
default_server_version = "2.4" # first version that dropped the legacy auth endpoint
6160

61+
# The REST API has used the "http://tableau.com/api" XML namespace since Tableau
62+
# Server 8.3 (2015). Callers on older servers are unsupported.
63+
NAMESPACE = "http://tableau.com/api"
64+
_NAMESPACE_MAP = {"t": NAMESPACE}
65+
6266

6367
class Server:
6468
"""
@@ -176,7 +180,6 @@ def __init__(self, server_address, use_server_version=False, http_options=None,
176180
self.data_acceleration_report = DataAccelerationReport(self)
177181
self.data_alerts = DataAlerts(self)
178182
self.fileuploads = Fileuploads(self)
179-
self._namespace = Namespace()
180183
self.flow_runs = FlowRuns(self)
181184
self.metrics = Metrics(self)
182185
self.custom_views = CustomViews(self)
@@ -290,7 +293,7 @@ def baseurl(self):
290293

291294
@property
292295
def namespace(self):
293-
return self._namespace()
296+
return _NAMESPACE_MAP
294297

295298
@property
296299
def auth_token(self):

0 commit comments

Comments
 (0)