Skip to content

v0.41 - add SVG image generation#1772

Open
jacalata wants to merge 189 commits into
masterfrom
development
Open

v0.41 - add SVG image generation#1772
jacalata wants to merge 189 commits into
masterfrom
development

Conversation

@jacalata

@jacalata jacalata commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Changes

  • allow users to download sheet images as SVG as well as by PNG
  • recognize 409 errors and treat them as success, because the job the user wants to create is already created

vitorhonna and others added 30 commits May 15, 2025 16:07
Fix typo in update_datasource_data.py
PersonalAccessTokenAuth repr was malformed. Fixing it to be
more representative and show the actual class name used
in cases where the client user decides to subclass.
Also correct the type hints to clarify that it accepts any
Iterable.
chore: refactor XML payload into RequestFactory
…#1638)

Update multiple connections in a single workbook - Takes multiple connection, authType and credentials as input
Update multiple connections in a single datasource - Takes multiple connection, authType and credentials as input

---------

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
…nections

Minor fixes on update connections
* feat: enable toggling attribute capture for a site

According to https://help.tableau.com/current/api/embedding_api/en-us/docs/embedding_api_user_attributes.html#:~:text=For%20security%20purposes%2C%20user%20attributes,a%20site%20admin%20(on%20Tableau
setting this site setting to `true` is required to enable use of
user attributes with Tableau Server and embedding workflows.

* chore: fix mypy error

---------

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Closes #1620

Sorting the fields prior to putting them in the query string
assures that '_all_' and '_default_' appear first in the field
list, satisfying the criteria of Tableau Server/Cloud to process
those first. Order of other fields appeared to be irrelevant, so
the test simply ensures their presence.

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* feat: support OIDC endpoints

Add support for remaining OIDC endpoints, including getting an
OIDC configuration by ID, removing the configuration, creating,
and updating configurations.

* feat: add str and repr to oidc item

---------

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* feat: SiteAuthConfiguration str and repr

Gives SiteAuthConfiguration methods for str and repr calls
to ensure consistent display of the object.

* style: black

---------

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Co-authored-by: Jac <jacalata@users.noreply.github.com>
Closes #1626

VirtualConnections leverages the ConnectionItem object to parse
the database connections server response. Most of other endpoints
return "userName" and the VirtualConnections' "Get Database Connections"
endpoint returns "username." Resolves the issue by allowing the
ConnectionItem to read either. Update the test assets to reflect the
actual returned value.

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
According to the .xsd schema file, the tags:batchCreate and
tags:batchDelete need a "contentType" attribute on the "content"
elements. This PR adds the missing attribute and checks in the test that
the string is carried through in the request body.

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
jacalata and others added 6 commits February 3, 2026 11:48
…1740)

* Initial plan

* Fix assertion syntax in test_populate_data_quality_warning

Co-authored-by: jacalata <2009720+jacalata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jacalata <2009720+jacalata@users.noreply.github.com>
Co-authored-by: Jac <jacalata@users.noreply.github.com>
Co-authored-by: jacalata <2009720+jacalata@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* feat: add SVG format support for view and custom view images

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
vchavatapalli and others added 19 commits May 10, 2026 01:36
Update license information in pyproject.toml
- Fixes license specifiers according to https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license-and-license-files
- This allows automatic license inspection tools like pip-licenses to correctly categorize this package.
* Remove deprecated cgi module usage and clean up dead code

Agent-Logs-Url: https://github.com/tableau/server-client-python/sessions/453f920c-7857-4503-ad99-0ccef076d792

Co-authored-by: jacalata <2009720+jacalata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jacalata <2009720+jacalata@users.noreply.github.com>
Co-authored-by: Brian Cantoni <bcantoni@salesforce.com>
* chore: replace Union with modern syntax

* chore: modernize Optional type hints

* fix: bump required versions

* fix: typing on update_connections methods

* docs: make docstrings match function signature

* fix: clarify max_age can be None

* fix: docstring indent

* style: black

---------

Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* chore(deps-dev): bump black from 24.10 to 26.3.1

Bumps [black](https://github.com/psf/black) from 24.10 to 26.3.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](psf/black@24.10.0...26.3.1)

---
updated-dependencies:
- dependency-name: black
  dependency-version: 26.3.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* style: apply black 26.3.1 formatting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jac Fitzgerald <jac.fitzgerald@salesforce.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds -n auto to pytest addopts so the test suite uses all available CPU
cores. Reduces local and CI run time from ~6 min to ~2 min.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: quote tag labels containing spaces or commas in XML request

The server's TagUtil.parseTags splits unquoted labels on spaces and
commas, causing tags like "Yearly Sales" to be stored as two separate
tags. Wrapping labels in double quotes prevents the split; the server
strips the quotes before storing.

Fixes #1738

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: quote tag labels containing spaces or commas; add e2e test suite

The Tableau server splits unquoted tag labels on spaces and commas
(via TagUtil.parseTags), so "Yearly Sales" becomes two tags "Yearly"
and "Sales". Wrapping labels in double quotes prevents the split; the
server strips the quotes before storing.

Also adds the first e2e test infrastructure to the repo:
- test_e2e/ directory with a session-scoped server fixture reading
  credentials from env vars (TABLEAU_SERVER, TABLEAU_SITE,
  TABLEAU_TOKEN, TABLEAU_TOKEN_NAME, TABLEAU_PROJECT)
- test_e2e/test_tagging.py validates the tag quoting fix against a
  real Tableau server
- contributing.md documents how to run unit and e2e tests

Fixes #1738

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: encode special characters in tag delete URL path

Fixes #675 #994

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: don't default authSetting to ServerDefault in bulk user add

ServerDefault is wrong for Tableau Cloud. Match the single-user add/update
behaviour and only send authSetting when explicitly set.

Fixes #1777

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: update test to match corrected bulk add authSetting behaviour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…1781)

* fix: improve timeout error messages and document TSC_CHUNK_SIZE_MB

When a 504 occurs during an async chunked upload, the error message now
hints at reducing TSC_CHUNK_SIZE_MB rather than suggesting async mode
(which the user is already using). Also document the env var in the
publish docstrings for workbooks and datasources.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* style: apply black formatting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add tests for async publish 504 timeout error message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…nd flows (#1785)

Fixes #1090

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #1571

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…1788)

* fix: use return instead of raise StopIteration in QuerySet.__iter__

Per PEP 479, StopIteration raised inside a generator is converted to
RuntimeError. QuerySet.__iter__ is a generator and was raising
StopIteration to handle 400006 (invalid page number) errors, causing
RuntimeError for callers iterating endpoints that don't support
pagination past the last page.

Fixes #1786

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: remove bare baseurl statements outside requests_mock context

server.workbooks.baseurl accessed outside a requests_mock context causes
DNS resolution of http://test on Linux, failing with a ConnectionError.
These statements were no-ops — baseurl is pure string formatting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: document email filter for users endpoint

Fixes #1562

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #1597

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: include description in workbook publish and update requests

The REST API has supported workbook description since v3.20 (2023.2).
Fixes #899

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: correct version gate and test style for workbook description update

- Restore version threshold to 3.21 (matching Tableau REST API docs)
- Restore parent_srv is None guard to exclude description (original behavior)
- Update tests to reflect 3.21 boundary
- Use re.search on multipart body for publish test, matching existing pattern
- Fix stale sample comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: replace no_extract with DeprecationWarning, document include_extract

no_extract was silently accepted but never documented as removed. Now
raises DeprecationWarning and maps to include_extract=False so existing
callers get a clear migration path rather than a silent no-op.

Fixes #1541

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #1083

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…1795)

* feat: add vizWidth/vizHeight to PDFRequestOptions

Fixes #1102

- PDFRequestOptions already inherited viz_width/viz_height from
  _ImagePDFCommonExportOptions (shared with ImageRequestOptions), which
  serialises them as vizWidth/vizHeight query params
- Added version guard in views.populate_pdf: raises UnsupportedAttributeError
  when viz_height or viz_width are used below API 3.26
- Added tests for the new version guard, the happy path (API 3.26+), unit-
  level query-param serialisation, and the existing XOR validation
- Removed stray bare literal '44' from test_request_option.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove incorrect version gate on vizWidth/vizHeight for PDF export

The REST API docs claimed vizHeight/vizWidth required API 3.26 and were
Cloud-only, but server-side code shows these params have been accepted
unconditionally since at least 2021.4 with no platform distinction.
Remove the 3.26 guard; the endpoint's own minimum version is sufficient.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #876 and #959 by auto-detecting and use the server's current REST API version *after* signin. This gives cleaner error scenarios when something goes wrong connecting/signing in.

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 extends the Tableau Server Client Python library to support exporting sheet images as SVG (in addition to PNG) and adjusts refresh behavior to treat the “duplicate extract job already queued” error as a non-fatal success. It also modernizes typing across endpoints/models, adds regression/unit/E2E tests for the new behaviors, and updates project packaging/test configuration.

Changes:

  • Add format support to image export request options and enforce API-version gating (SVG requires 3.29+).
  • Treat Tableau error code 409093 (duplicate extract refresh job) as a warning and return None from refresh methods instead of raising.
  • Expand tests (unit + E2E) for webhook event naming, tagging encoding/quoting, query iteration behavior, image export formats, and new filter fields; update packaging to Python 3.10+ and pytest defaults.

Reviewed changes

Copilot reviewed 106 out of 110 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/test_webhook.py Adds unit tests for webhook event setter/getter behavior, including new-style webhook-event-* names.
test/test_view.py Adds tests for image export format (SVG/PNG) and unsupported-version behavior; renames a PDF test for clarity.
test/test_user.py Adjusts bulk-add expectations and adds tests for filtering users by email / email__in.
test/test_tagging.py Expands tagging tests (quoting tags with spaces; URL encoding for special characters) and typing tweaks in helpers/protocols.
test/test_server_info.py Updates expectations for deferred server version detection when use_server_version=True.
test/test_request_option.py Removes stray content and adds tests for PDF viz dimension query params and request behavior.
test/test_pager.py Adds regression test ensuring QuerySet iteration ends cleanly on 400006 (PEP 479).
test/test_job.py Cleans up formatting (whitespace-only change).
test/test_flow.py Adds test asserting duplicate refresh (HTTP 409 / error code 409093) is treated as a non-error (None).
test/test_extensions.py Cleans up formatting (whitespace-only change).
test/test_endpoint.py Adds tests for robust XML error parsing for ServerResponseError/FailedSignInError when <error> is missing.
test/test_datasource.py Adds tests for update_connections without auth type, duplicate refresh handling, deprecation warning mapping, and async publish timeout.
test/test_database.py Fixes assertion to validate exact DQW message text.
test/test_custom_view.py Adds SVG/PNG image export tests and unsupported-version behavior for custom views.
test/test_connection_.py Adds tests for new database_name connection attribute and its XML round-trip behavior.
test/http/test_http_requests.py Updates expectations for deferred server version detection at construction time.
test/assets/workbook_update_connections_no_auth.xml Adds test asset for workbook connections update response without auth type in request.
test/assets/workbook_refresh_duplicate.xml Adds test asset for duplicate refresh job response (409093).
test/assets/webhook_get_new_event.xml Adds test asset to validate parsing of new-style webhook event element names.
test/assets/flow_refresh_duplicate.xml Adds test asset for duplicate flow refresh job response (409093).
test/assets/datasource_refresh_duplicate.xml Adds test asset for duplicate datasource refresh job response (409093).
test/assets/datasource_populate_connections.xml Updates asset to include dbName attribute to test database_name parsing.
test/assets/datasource_connections_update_no_auth.xml Adds test asset for datasource connections update response without auth type in request.
test/_utils.py Removes unused Optional import (typing modernization).
test_e2e/test_tagging.py Introduces E2E coverage for tag add/delete round-tripping (spaces/commas/multiple tags).
test_e2e/conftest.py Adds E2E server fixture + e2e marker configuration and environment-variable gating.
test_e2e/init.py Adds package marker for E2E tests.
tableauserverclient/server/server.py Defers use_server_version network call; stores flag for use during sign-in.
tableauserverclient/server/request_options.py Adds email field; modernizes typing; adds ImageRequestOptions.format (SVG/PNG) and wires it into query params.
tableauserverclient/server/query.py Fixes QuerySet iteration termination on 400006 by returning instead of raising StopIteration.
tableauserverclient/server/pager.py Typing modernization for endpoints/callables and optional request options.
tableauserverclient/server/endpoint/webhooks_endpoint.py Typing modernization for get() and parameter docs.
tableauserverclient/server/endpoint/virtual_connections_endpoint.py Typing modernization and union simplifications across methods.
tableauserverclient/server/endpoint/views_endpoint.py Adds version gating for format param (3.29+) alongside existing viz dimension gating; typing/doc updates.
tableauserverclient/server/endpoint/users_endpoint.py Adds filter docs for email/email__in and modernizes typing in signatures/docs.
tableauserverclient/server/endpoint/tasks_endpoint.py Typing modernization for get() signature.
tableauserverclient/server/endpoint/tables_endpoint.py Typing modernization for get/populate/add/delete tags APIs.
tableauserverclient/server/endpoint/subscriptions_endpoint.py Typing modernization for get() signature.
tableauserverclient/server/endpoint/sites_endpoint.py Typing modernization for get() signature.
tableauserverclient/server/endpoint/server_info_endpoint.py Typing modernization for get() return type.
tableauserverclient/server/endpoint/schedules_endpoint.py Typing modernization + doc typo fixes in batch update.
tableauserverclient/server/endpoint/resource_tagger.py Fixes tag name URL encoding by quoting with safe="" (encodes /, +, #, spaces, etc.).
tableauserverclient/server/endpoint/projects_endpoint.py Typing modernization for get() and filter().
tableauserverclient/server/endpoint/permissions_endpoint.py Typing modernization for union types and request options.
tableauserverclient/server/endpoint/oidc_endpoint.py Typing modernization for union types in OIDC APIs.
tableauserverclient/server/endpoint/metrics_endpoint.py Typing modernization for get() signature.
tableauserverclient/server/endpoint/linked_tasks_endpoint.py Typing modernization and cleanup of imports.
tableauserverclient/server/endpoint/jobs_endpoint.py Typing modernization for overloads and union parameters.
tableauserverclient/server/endpoint/groupsets_endpoint.py Typing modernization for unions and filter paging.
tableauserverclient/server/endpoint/groups_endpoint.py Typing modernization for unions and return types in docs.
tableauserverclient/server/endpoint/flows_endpoint.py Handles duplicate refresh job code as a warning and returns None; removes filename helper usage in download path logic.
tableauserverclient/server/endpoint/flow_runs_endpoint.py Typing modernization for unions and optional timeouts.
tableauserverclient/server/endpoint/favorites_endpoint.py Typing modernization for request options.
tableauserverclient/server/endpoint/exceptions.py Adds DUPLICATE_EXTRACT_JOB_CODE; makes XML error parsing robust when <error>/children are absent.
tableauserverclient/server/endpoint/endpoint.py Typing modernization and minor signature updates.
tableauserverclient/server/endpoint/dqw_endpoint.py Typing modernization for HasId protocol and request options.
tableauserverclient/server/endpoint/default_permissions_endpoint.py Typing modernization for unions in permissions APIs.
tableauserverclient/server/endpoint/databases_endpoint.py Typing modernization for tagging and request options.
tableauserverclient/server/endpoint/data_alert_endpoint.py Typing modernization for unions and request options.
tableauserverclient/server/endpoint/custom_views_endpoint.py Adds version gating for image format (3.29+) and modernizes typing across methods.
tableauserverclient/server/endpoint/auth_endpoint.py Calls use_server_version() after successful sign-in when configured to do so.
tableauserverclient/models/webhook_item.py Supports None, short names, full webhook-source-event-*, and new webhook-event-* event naming.
tableauserverclient/models/virtual_connection_item.py Typing modernization for nullable attributes/callables.
tableauserverclient/models/view_item.py Typing modernization for nullable fields and callable-backed properties.
tableauserverclient/models/user_item.py Typing modernization for nullable user fields and parsing helpers.
tableauserverclient/models/task_item.py Typing modernization for nullable schedule/target fields.
tableauserverclient/models/tableau_types.py Typing modernization for plural_type() union parameter.
tableauserverclient/models/tableau_auth.py Typing modernization for optional IDs and impersonation fields.
tableauserverclient/models/table_item.py Typing modernization for id property.
tableauserverclient/models/subscription_item.py Reformatting/whitespace normalization of file content (no functional change apparent).
tableauserverclient/models/site_item.py Typing modernization across site fields and auth configuration model.
tableauserverclient/models/schedule_item.py Typing modernization for interval unions and nullable datetimes/IDs.
tableauserverclient/models/revision_item.py Typing modernization for nullable revision fields.
tableauserverclient/models/project_item.py Typing modernization for nullable fields and XML parsing signatures.
tableauserverclient/models/permissions_item.py Typing modernization for nullable namespace parameters.
tableauserverclient/models/oidc_item.py Typing modernization for nullable OIDC configuration fields.
tableauserverclient/models/metric_item.py Typing modernization for nullable metric fields and permissions.
tableauserverclient/models/location_item.py Typing modernization for nullable location fields and XML parsing signature.
tableauserverclient/models/linked_tasks_item.py Typing modernization for nullable linked-task fields.
tableauserverclient/models/job_item.py Typing modernization for nullable job fields and background job item fields.
tableauserverclient/models/groupset_item.py Typing modernization for nullable group set fields.
tableauserverclient/models/group_item.py Typing modernization for nullable group fields.
tableauserverclient/models/flow_run_item.py Typing modernization for nullable flow run fields and XML parsing signature.
tableauserverclient/models/flow_item.py Typing modernization and import cleanup for Iterable.
tableauserverclient/models/favorites_item.py Typing modernization for from_response input type.
tableauserverclient/models/extract_item.py Typing modernization for nullable IDs and list return types.
tableauserverclient/models/data_freshness_policy_item.py Typing modernization for nullable schedule fields.
tableauserverclient/models/data_alert_item.py Typing modernization for nullable alert fields and repr formatting.
tableauserverclient/models/custom_view_item.py Typing modernization for nullable fields and parsing helpers.
tableauserverclient/models/connection_item.py Adds database_name (maps GET dbName and publish databaseName) and updates parsing logic accordingly.
tableauserverclient/models/column_item.py Reformatting/whitespace normalization of file content (no functional change apparent).
tableauserverclient/models/collection_item.py Typing modernization for nullable collection fields.
tableauserverclient/helpers/strings.py Reformatting/whitespace normalization of file content (no functional change apparent).
tableauserverclient/helpers/headers.py Removes filename-fixing helper module.
tableauserverclient/datetime_helpers.py Reformatting/whitespace normalization of file content (no functional change apparent).
tableauserverclient/bin/_version.py Typing modernization for dict/list/tuple annotations.
samples/update_connections_auth.py Makes datasource credential arguments optional via CLI flags.
samples/smoke_test.py Reformatting/whitespace normalization of file content (no functional change apparent).
samples/export.py Reformatting/whitespace normalization; minor assignment unpacking style change.
samples/explore_workbook.py Updates sample workbook description text.
pyproject.toml Bumps Python requirement to 3.10+, updates test tooling versions, enables xdist by default, adds E2E marker, adjusts setuptools package discovery/data.
contributing.md Adds test-running instructions and E2E setup guidance.
.gitignore Adds .claude/ and normalizes formatting.
Comments suppressed due to low confidence (1)

tableauserverclient/server/request_options.py:346

  • _DataExportOptions.get_query_params() now allows max_age=None, but the current check (self.max_age != -1) will include maxAge=None in the query string. That results in sending an invalid REST query parameter value when callers pass maxage=None.

Consider treating None like the default (omit the parameter).


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +501 to +503
format: str, optional
The format of the image to export. Use Format.PNG, Format.SVG, Format.png, or Format.svg.
Default is "PNG". Available in API version 3.29+.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.