-
Notifications
You must be signed in to change notification settings - Fork 446
release v0.39 #1737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
release v0.39 #1737
Conversation
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.
fix: repr for auth objects
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>
* fix: black ci errors * chore: pytestify wb_model --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify webhooks --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify virtuall connections --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify ssl_config --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify filesys helpers --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify metrics --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify http_requests --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify test_site * chore: pytestify test_site_model --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * chore: pytestify file uploads --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Update pyproject.toml
* fix: black ci errors * chore: pytestify views * chore: pytestify view acceleration * feat: delete_view Starting in Server 2025.3, views can be deleted. --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* chore: pytestify schedule * chore: remove unused imports * feat: batch update schedule state --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: black ci errors * feat: enable bulk adding users * feat: ensure domain name is included if provided * style: black * chore: test missing user name * feat: implement users bulk_remove * chore: suppress deprecation warning in test * chore: split csv add creation to own test * chore: use subTests in remove_users * chore: user factory function in make_user * docs: bulk_add docstring * fix: assert on warning instead of ignore * chore: missed an absolute import * docs: bulk_add docstring * docs: create_users_csv docstring * chore: deprecate add_all method * test: test add_all and check DeprecationWarning * docs: docstring updates for bulk add operations * docs: add examples to docstrings * chore: update deprecated version # * feat: enable idp_configuration_id in bulk_add * chore: remove outdated docstring text * test: remove_users_csv * chore: update deprecated version number * chore: pytestify test_user * chore: pytestify test_user_model * style: black --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Running locally on my Mac: - pytest: 1min 20sec - pytest -n auto: 15sec https://pypi.org/project/pytest-xdist/ Co-authored-by: Jac <jacalata@users.noreply.github.com>
Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* fix: add workbook and view setter for custom view * chore: use workbook setter in tests Closes #1729 --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
Adding support for the REST APIs which provide access to Tableau Extensions configuration. --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Co-authored-by: Brian Cantoni <bcantoni@salesforce.com>
* fix: black ci errors * chore: pytestify request_option * fix: encoding error * fix: handle parameters for view filters Closes #1632 Parameters need to be prefixed with "vf_Parameters." in order to be properly registered as setting a parameter value. This PR adds that prefix where it was missing, but leaves parameter names that already included the prefix unmodified. * docs: case sensitivity in the test's query string * chore: pytest style asserts * fix: black ci errors --------- Co-authored-by: Jordan Woods <13803242+jorwoods@users.noreply.github.com>
* update publish workflow * Update pyproject.toml and setup * add init files to find test_repr, fix it to pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request delivers a major release (v0.39) focused on modernizing the Python testing infrastructure, expanding API coverage, and improving package configuration. The changes transition the entire test suite from unittest to pytest, add support for newer Python versions, and introduce new endpoints for OIDC authentication and dashboard extensions.
Changes:
- Migrated all test files from
unittest.TestCaseto pytest-style functions and fixtures - Added OIDC and Extensions endpoints for enhanced Tableau Server configuration
- Updated build configuration with improved dependency management and package discovery
Reviewed changes
Copilot reviewed 127 out of 131 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| test/*.py | Converted 20+ test files from unittest to pytest with fixtures |
| tableauserverclient/server/endpoint/oidc_endpoint.py | Added new OIDC configuration endpoint |
| tableauserverclient/server/endpoint/extensions_endpoint.py | Added dashboard extensions management endpoint |
| tableauserverclient/models/oidc_item.py | Created OIDC configuration model |
| tableauserverclient/models/extensions_item.py | Created extensions settings models |
| pyproject.toml | Updated dependencies and build requirements |
| .github/workflows/*.yml | Extended CI matrix to Python 3.14 with parallel testing |
| samples/*.py | Added utility scripts for connection updates and user creation |
| tableauserverclient/server/endpoint/*_endpoint.py | Added bulk connection updates and view deletion methods |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| with mocked_time() as mock_time: | ||
| exponentialBackoff = ExponentialBackoffTimer() | ||
| # The creation of our mock shouldn't sleep | ||
| pytest.approx(mock_time(), 0) |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pytest.approx function returns a comparison object but is not being used in an assertion. This should be assert mock_time() == pytest.approx(0) to actually perform the comparison.
| pytest.approx(mock_time(), 0.5) | ||
| exponentialBackoff.sleep() | ||
| pytest.approx(mock_time(), 1.2) | ||
| exponentialBackoff.sleep() | ||
| pytest.approx(mock_time(), 2.18) | ||
| exponentialBackoff.sleep() | ||
| pytest.approx(mock_time(), 3.552) | ||
| exponentialBackoff.sleep() | ||
| pytest.approx(mock_time(), 5.4728) |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the previous issue, pytest.approx is being called but not used in assertions. These should all be assert mock_time() == pytest.approx(value) to properly verify the timing values.
| exponentialBackoff.sleep() | ||
| self.assertAlmostEqual(mock_time(), 2.18) | ||
| slept = mock_time() - s | ||
| pytest.approx(slept, 30) |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pytest.approx calls are not being used in assertions. These should be assert slept == pytest.approx(30) and assert mock_time() == pytest.approx(value) respectively.
| for _ in range(4): | ||
| exponentialBackoff.sleep() | ||
| self.assertAlmostEqual(mock_time(), 3.552) | ||
| pytest.approx(mock_time(), 3.552) |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pytest.approx calls are not being used in assertions. These should be assert slept == pytest.approx(30) and assert mock_time() == pytest.approx(value) respectively.
| # the timeout we wait less; thereby we make sure to take the timeout | ||
| # into account as good as possible | ||
| exponentialBackoff.sleep() | ||
| pytest.approx(mock_time(), 4.5) |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pytest.approx calls are not being used in assertions. These should be assert slept == pytest.approx(30) and assert mock_time() == pytest.approx(value) respectively.
| first_dqw = dqws.pop() | ||
| assert first_dqw.id == "c2e0e406-84fb-4f4e-9998-f20dd9306710" | ||
| assert first_dqw.warning_type == "WARNING" | ||
| assert first_dqw.message, "Hello == World!" |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion appears to have incorrect syntax. The comma should likely be == to check equality: assert first_dqw.message == \"Hello, World!\"
| def get_unimplemented_models(): | ||
| return [ | ||
| # these items should have repr , please fix |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spacing in comment: 'repr , please' should be 'repr, please'
| @api(version="3.27") | ||
| def batch_update_state(self, schedules, state, update_all=False) -> list[str]: | ||
| """ | ||
| Batch update the status of one or more scheudles. If update_all is set, |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'schedules' in docstring.
| Parameters | ||
| ---------- | ||
| schedules: Iterable[ScheudleItem | str] | Any |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'ScheduleItem' in type annotation.
| "pytest-xdist", "requests-mock>=1.0,<2.0", "types-requests>=2.32.4.20250913"] | ||
|
|
||
| [tool.setuptools.packages.find] | ||
| where = ["tableauserverclient", "tableauserverclient.helpers", "tableauserverclient.models", "tableauserverclient.server", "tableauserverclient.server.endpoint"] |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The where parameter in [tool.setuptools.packages.find] should typically be set to the root directory (e.g., [\".\"]), not individual package paths. The current configuration may not correctly discover packages. Consider using where = [\".\"] with include to specify packages, or rely on automatic discovery.
|
New feature work
|
[Copilot summary]
This pull request introduces several improvements and updates across the codebase, focusing on modernizing Python support, enhancing packaging and build configuration, updating CI workflows, and adding new sample scripts. It also brings in new model imports and improves project metadata management.
Build & Packaging Improvements:
pyproject.tomlto requiresetuptools>=77.0, changedlicensetolicense-files, expandedurllib3version range, and added new test dependencies includingpytest-xdistandtypes-requests. Also, added explicit package discovery and dynamic version configuration. [1] [2] [3]setup.pyand ensuredcmdclassfromversioneeris used for versioning..gitattributesandMANIFEST.into better manage version files and package data. [1] [2] [3]publish.shscript.CI/CD Workflow Updates:
New Sample Scripts:
samples/create_user.pyfor creating a user via TSC.samples/metadata_paginated_query.pydemonstrating paginated metadata queries.samples/update_connection_auth.pyfor updating a single connection's authentication.samples/update_connections_auth.pyfor bulk updating connection authentication.Model & API Surface Enhancements:
tableauserverclient/__init__.py, includingCollectionItem,ExtensionsServer,ExtensionsSiteSettings,SafeExtension, andSiteOIDCConfiguration, and updated__all__accordingly. [1] [2] [3] [4] [5]Other Improvements:
samples/update_datasource_data.py.CODEOWNERS.Let me know if you want to discuss any of these changes in more detail!
References:
Build & Packaging: [1] [2] [3] [4] [5] [6] [7] [8]
CI/CD: [1] [2] [3] [4] [5]
Samples: [1] [2] [3] [4]
API Surface: [1] [2] [3] [4] [5]
Other: [1] [2]