Skip to content

Remove pre-8.3 XML namespace fallback - #1863

Draft
jacalata wants to merge 2 commits into
developmentfrom
jac/1046-remove-old-namespace
Draft

Remove pre-8.3 XML namespace fallback#1863
jacalata wants to merge 2 commits into
developmentfrom
jac/1046-remove-old-namespace

Conversation

@jacalata

Copy link
Copy Markdown
Contributor

Draft -- opening for discussion. Happy to add a deprecation cycle instead of an outright removal if that's preferred.

Summary

Removes the runtime XML namespace detection that let TSC accept responses from Tableau Server versions predating 8.3 (2013, http://tableausoftware.com/api). The library's minimum_supported_server_version has been 2.3 for years (Tableau Server 10.0, 2016), so the detection has been unreachable for a decade.

Fixes #1046.

What changes

Removed:

  • tableauserverclient/namespace.py (the whole module) and the symbols it exported: Namespace, UnknownNamespaceError, OLD_NAMESPACE, NEW_NAMESPACE, NAMESPACE_RE.
  • Server._namespace and the per-response .detect(...) call in Endpoint._make_request and both sign-in paths in Auth.

Kept:

  • Public TSC.DEFAULT_NAMESPACE re-export -- now sourced from tableauserverclient.server.server.NAMESPACE. Same string value.
  • Server.namespace property -- still returns the {"t": NAMESPACE} dict callers pass to ElementTree's namespaces= kwarg. Same shape.

Compatibility

Callers who imported directly from tableauserverclient.namespace (rather than the documented TSC.DEFAULT_NAMESPACE) will break. The CHANGELOG entry calls this out. Given the module was internal in every sense except being top-level, I opted for outright removal, but a deprecation shim (namespace.py becomes a warning-emitting alias, removed one minor release later) is easy to add if that's the house style.

Why now

Discussion in #1039 (2022) already noted the fallback was safe to drop; the issue has been open since. Nothing in the diff is complicated -- the code is simply dead.

Test plan

  • Full test suite: 868 pass locally.
  • Grep for from tableauserverclient.namespace, UnknownNamespaceError, _namespace.detect, OLD_NAMESPACE, NEW_NAMESPACE, namespace.Namespace inside the repo -- only remaining reference is the CHANGELOG entry.
  • mypy and black clean via pre-commit.

🤖 Generated with Claude Code

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>
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
tableauserverclient
   __init__.py50100% 
   config.py150100% 
   datetime_helpers.py2511 96%
   exponential_backoff.py200100% 
   filesys_helpers.py310100% 
tableauserverclient/bin
   __init__.py20100% 
   _version.py358212212 41%
tableauserverclient/helpers
   __init__.py10100% 
   logging.py20100% 
   strings.py3111 97%
tableauserverclient/models
   __init__.py460100% 
   collection_item.py4177 83%
   column_item.py553232 42%
   connection_credentials.py351111 69%
   connection_item.py941414 85%
   custom_view_item.py1442121 85%
   data_acceleration_report_item.py5411 98%
   data_alert_item.py15844 97%
   data_freshness_policy_item.py1551515 90%
   database_item.py2073636 83%
   datasource_item.py3001212 96%
   dqw_item.py10455 95%
   exceptions.py40100% 
   extensions_item.py13244 97%
   extract_item.py4444 91%
   favorites_item.py6988 88%
   fileupload_item.py190100% 
   flow_item.py1491010 93%
   flow_run_item.py710100% 
   group_item.py8966 93%
   groupset_item.py4977 86%
   interval_item.py1823232 82%
   job_item.py1921010 95%
   linked_tasks_item.py7911 99%
   location_item.py2922 93%
   metric_item.py1291313 90%
   oidc_item.py6333 95%
   pagination_item.py3411 97%
   permissions_item.py1111212 89%
   project_item.py2073131 85%
   property_decorators.py1001818 82%
   reference_item.py2622 92%
   revision_item.py5911 98%
   schedule_item.py20966 97%
   server_info_item.py3777 81%
   site_item.py6361313 98%
   subscription_item.py10122 98%
   table_item.py1191818 85%
   tableau_auth.py612525 59%
   tableau_types.py2711 96%
   tag_item.py150100% 
   target.py60100% 
   task_item.py5622 96%
   user_item.py3101818 94%
   view_item.py2201616 93%
   virtual_connection_item.py6488 88%
   webhook_item.py6911 99%
   workbook_item.py3621616 96%
tableauserverclient/server
   __init__.py90100% 
   exceptions.py40100% 
   filter.py2911 97%
   pager.py3311 97%
   query.py1431515 90%
   request_factory.py1335195195 85%
   request_options.py38655 99%
   server.py1882323 88%
   sort.py60100% 
tableauserverclient/server/endpoint
   __init__.py350100% 
   auth_endpoint.py751111 85%
   custom_views_endpoint.py1521212 92%
   data_acceleration_report_endpoint.py210100% 
   data_alert_endpoint.py942323 76%
   databases_endpoint.py1113030 73%
   datasources_endpoint.py3233333 90%
   default_permissions_endpoint.py4433 93%
   dqw_endpoint.py451616 64%
   endpoint.py2101919 91%
   exceptions.py7766 92%
   extensions_endpoint.py310100% 
   favorites_endpoint.py942222 77%
   fileuploads_endpoint.py510100% 
   flow_runs_endpoint.py6299 85%
   flow_task_endpoint.py2122 90%
   flows_endpoint.py1985353 73%
   groups_endpoint.py12699 93%
   groupsets_endpoint.py7277 90%
   jobs_endpoint.py6799 87%
   linked_tasks_endpoint.py370100% 
   metadata_endpoint.py881414 84%
   metrics_endpoint.py5566 89%
   oidc_endpoint.py4211 98%
   permissions_endpoint.py4433 93%
   projects_endpoint.py1782424 87%
   resource_tagger.py1273535 72%
   schedules_endpoint.py1191111 91%
   server_info_endpoint.py361010 72%
   sites_endpoint.py1302727 79%
   subscriptions_endpoint.py561414 75%
   tables_endpoint.py1103636 67%
   tasks_endpoint.py6366 90%
   users_endpoint.py18388 96%
   views_endpoint.py15099 94%
   virtual_connections_endpoint.py1131010 91%
   webhooks_endpoint.py5499 83%
   workbooks_endpoint.py3382222 93%
TOTAL11977141988% 

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes runtime XML namespace detection that allowed parsing legacy (pre-Tableau Server 8.3) REST API XML responses, standardizing the client on the modern http://tableau.com/api namespace in line with the library’s long-standing minimum supported server/API versions.

Changes:

  • Removed the tableauserverclient.namespace module and eliminated per-response namespace detection calls.
  • Centralized the namespace constant in server.server and updated TSC.DEFAULT_NAMESPACE to keep the public re-export working.
  • Updated server/endpoint code paths to always use the fixed namespace map.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tableauserverclient/server/server.py Removes per-instance namespace detector and introduces fixed namespace constants/map.
tableauserverclient/server/endpoint/endpoint.py Removes the XML-response namespace detection hook in _make_request.
tableauserverclient/server/endpoint/auth_endpoint.py Removes namespace detection during sign-in and site switching flows.
tableauserverclient/namespace.py Deletes the legacy namespace detection module and exported symbols.
tableauserverclient/init.py Updates DEFAULT_NAMESPACE re-export to come from the new namespace source.
CHANGELOG.md Documents the breaking removal of legacy namespace fallback and module exports.
Suppressed comments (2)

tableauserverclient/server/endpoint/auth_endpoint.py:159

  • With namespace auto-detection removed, a legacy-namespace (or otherwise unexpected) XML response can make find(...).get(...) raise AttributeError. Adding an explicit check and raising ServerResponseError produces a clearer, user-facing failure mode for unsupported namespaces/servers.
        parsed_response = fromstring(server_response.content)
        site_id = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("id", None)
        site_url = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("contentUrl", None)

tableauserverclient/server/endpoint/auth_endpoint.py:86

  • With namespace auto-detection removed, a legacy-namespace (or otherwise unexpected) XML response will make find(...).get(...) raise an AttributeError, which is hard to diagnose. It’s better to explicitly check that the expected elements are present and raise ServerResponseError with a message that points to a likely namespace / server-version mismatch.

This issue also appears on line 157 of the same file.

        parsed_response = fromstring(server_response.content)
        site_id = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("id", None)
        site_url = parsed_response.find(".//t:site", namespaces=self.parent_srv.namespace).get("contentUrl", None)

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tableauserverclient/server/server.py Outdated
Comment on lines +295 to +296
def namespace(self):
return self._namespace()
return _NAMESPACE_MAP
@@ -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
…hared state

Copilot flagged that Server.namespace returned the module-level
_NAMESPACE_MAP directly, so a caller mutating the returned dict would
have polluted every other Server instance in the process. Old namespace-
handling code returned a per-instance dict, so no cross-instance
pollution was possible. Wrap in dict(...) to restore that behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop supporting old namespaces

2 participants