diff --git a/CHANGELOG.md b/CHANGELOG.md index fc1430d38..108c730f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ `type` / `value` / `text`. The existing `notes: list[str]` attribute is unchanged (it parses the separate legacy `` element still emitted by some job types). Fixes #1850. +* Removed the pre-Tableau-8.3 XML namespace fallback + (`http://tableausoftware.com/api`). Every server TSC's `minimum_supported_server_version` + guard has ever admitted uses the current namespace (`http://tableau.com/api`), + and the runtime-detection code has been unreachable in practice for a + decade. `tableauserverclient.namespace` module and `UnknownNamespaceError` + are removed; the public `TSC.DEFAULT_NAMESPACE` re-export still works and + now points at `tableauserverclient.server.server.NAMESPACE`. Fixes #1046. ## 0.18.0 (6 April 2022) * Switched to using defused_xml for xml attack protection diff --git a/tableauserverclient/__init__.py b/tableauserverclient/__init__.py index 7241f23ca..9b6ae5e34 100644 --- a/tableauserverclient/__init__.py +++ b/tableauserverclient/__init__.py @@ -1,5 +1,5 @@ from tableauserverclient.bin._version import get_versions -from tableauserverclient.namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE +from tableauserverclient.server.server import NAMESPACE as DEFAULT_NAMESPACE from tableauserverclient.models import ( BackgroundJobItem, CollectionItem, diff --git a/tableauserverclient/namespace.py b/tableauserverclient/namespace.py deleted file mode 100644 index 54ac46d8d..000000000 --- a/tableauserverclient/namespace.py +++ /dev/null @@ -1,37 +0,0 @@ -import re - -from defusedxml.ElementTree import fromstring - -OLD_NAMESPACE = "http://tableausoftware.com/api" -NEW_NAMESPACE = "http://tableau.com/api" -NAMESPACE_RE = re.compile(r"\{(.*?)\}") - - -class UnknownNamespaceError(Exception): - pass - - -class Namespace: - def __init__(self): - self._namespace = {"t": NEW_NAMESPACE} - self._detected = False - - def __call__(self): - return self._namespace - - def detect(self, xml): - if self._detected: - return - - if not xml.startswith(b" contextmgr: **self.parent_srv.http_options, allow_redirects=False, ) - self.parent_srv._namespace.detect(server_response.content) self._check_status(server_response, url) parsed_response = fromstring(server_response.content) 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: return Auth.contextmgr(self.sign_out) else: raise e - self.parent_srv._namespace.detect(server_response.content) self._check_status(server_response, url) parsed_response = fromstring(server_response.content) site_id = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("id", None) diff --git a/tableauserverclient/server/endpoint/endpoint.py b/tableauserverclient/server/endpoint/endpoint.py index 31a0806dc..a6adf830d 100644 --- a/tableauserverclient/server/endpoint/endpoint.py +++ b/tableauserverclient/server/endpoint/endpoint.py @@ -152,9 +152,6 @@ def _make_request( # BE CAREFUL WHEN SHARING THESE RESULTS - MAY CONTAIN YOUR SENSITIVE DATA # logger.debug(loggable_response) - if content_type == "application/xml": - self.parent_srv._namespace.detect(server_response.content) - return server_response def _check_status(self, server_response: "Response", url: str | None = None): diff --git a/tableauserverclient/server/server.py b/tableauserverclient/server/server.py index 6b0338970..d28e3723e 100644 --- a/tableauserverclient/server/server.py +++ b/tableauserverclient/server/server.py @@ -46,7 +46,6 @@ EndpointUnavailableError, ) from tableauserverclient.server.endpoint.exceptions import NotSignedInError -from tableauserverclient.namespace import Namespace _PRODUCT_TO_REST_VERSION = { "10.0": "2.3", @@ -59,6 +58,11 @@ minimum_supported_server_version = "2.3" default_server_version = "2.4" # first version that dropped the legacy auth endpoint +# The REST API has used the "http://tableau.com/api" XML namespace since Tableau +# Server 8.3 (2015). Callers on older servers are unsupported. +NAMESPACE = "http://tableau.com/api" +_NAMESPACE_MAP = {"t": NAMESPACE} + class Server: """ @@ -176,7 +180,6 @@ def __init__(self, server_address, use_server_version=False, http_options=None, self.data_acceleration_report = DataAccelerationReport(self) self.data_alerts = DataAlerts(self) self.fileuploads = Fileuploads(self) - self._namespace = Namespace() self.flow_runs = FlowRuns(self) self.metrics = Metrics(self) self.custom_views = CustomViews(self) @@ -290,7 +293,7 @@ def baseurl(self): @property def namespace(self): - return self._namespace() + return dict(_NAMESPACE_MAP) @property def auth_token(self):