Skip to content

docs+feat: VirtualConnections docstrings, tag parsing, id workaround - #1858

Open
jacalata wants to merge 3 commits into
developmentfrom
jac/docstrings-virtual-connections
Open

docs+feat: VirtualConnections docstrings, tag parsing, id workaround#1858
jacalata wants to merge 3 commits into
developmentfrom
jac/docstrings-virtual-connections

Conversation

@jacalata

@jacalata jacalata commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Closes #1569.

Motivation

Virtual Connections is the largest remaining chunk in the
needs-docstring bucket per the api-ref migration audit: 14 of the 27
remaining public endpoint methods without docstrings, once the 15
Favorites methods from #1855 land.

While backfilling the docstrings I confirmed via server code + a live
test that the REST endpoint now returns tags on virtual-connection
responses (added server-side in W-21424436, shipping in Tableau Server
2026.2 / Cloud April 2026 / REST API 3.30). VirtualConnectionItem
wasn't parsing them, so the diff-based update_tags couldn't work and
had a NotImplementedError override. Extending the PR to close that
gap now that the server side is available.

Also uncovered two adjacent server-side gaps while implementing this;
both filed on the server team:

  • W-23806318 (Tableau CX-DevDocs): public REST API docs still
    describe the pre-2026.2 response schema, without <tags>.
  • W-23806343 (TDP - VConns): Get Virtual Connection REST response
    omits the id attribute on the <virtualConnection> element even
    though List Virtual Connections includes it. Working around
    client-side in this PR by stamping the id back from the request path.

Behavior change

For users:

  • All 14 VirtualConnections methods now have numpy-style docstrings
    ported from api-ref.md, plus a class-level docstring. Content is
    unchanged; the generated Sphinx output (docs: set up Sphinx + ReadTheDocs pipeline for auto-generated API reference #1832) will cover what the
    handwritten api-ref.md page does today.
  • VirtualConnectionItem now parses <tags> from responses into
    tags: set[str] (populated) and _initial_tags: set[str]
    (immutable copy for diff purposes). On pre-2026.2 servers the
    response omits <tags> and both attributes are empty sets.
  • VirtualConnections.update_tags(vc) works for the standard
    mutate-and-push pattern: fetch a VC, add/remove entries from
    vc.tags, call update_tags. Gated on @api(version="3.30") so
    older servers (where _initial_tags would always be empty and
    removes would silently no-op) fail loudly at the version check
    instead.
  • VirtualConnections.get_by_id now returns an item with .id set
    even though the server response omits it. Downstream calls
    (add_tags, delete_tags, update_tags) require the id.

Also bundled (small):

  • add_permissions and delete_permission grow proper type hints so
    the docstring claims and the signatures agree.
  • Renamed permissions params to a consistent virtual_connection
    throughout the class.
  • Renamed delete_permission's second parameter from capability_item
    to permission_rule, matching what it actually is.
  • Fixed a pre-existing copy-paste error: permissions property error
    message said "Workbook item must be populated..." instead of
    "Virtual connection item...".

Test plan

  • Unit: test/test_virtual_connection.py 15 passed. New tests:
    test_from_xml_populated_tags (multi-item fixture, verifies parse
    • _initial_tags isolation from tags) and
      test_update_tags_diff_round_trip (mocks PUT/DELETE calls, asserts
      correct add/delete pattern from a synthetic diff).
  • Unit: test/test_tagging.py 134 passed after bumping the
    parametrized-test server version to 3.30.
  • Full suite: 864 passed, 1 skipped, 0 failed. mypy clean.
  • Live end-to-end against a Tableau server (build 2026-08-09,
    REST API 3.30): fetch a VC by id, add_tags(vc, ['a','b','c']),
    re-fetch, verify tags == {a,b,c} and _initial_tags == {a,b,c}.
    Then locally vc.tags.discard('b'); vc.tags.add('d'); update_tags(vc). Re-fetch confirms server state is {a,c,d}.
    Cleanup via delete_tags(vc, list(vc.tags)) succeeds.

🤖 Generated with Claude Code

Adds a class-level docstring plus 15 method docstrings (14 public
methods + the private _get_virtual_database_connections is unchanged).
Content ported from api-ref.md's Virtual Connections section on
gh-pages so once the Sphinx pipeline in #1832 is live the generated
output will cover what the handwritten page does today.

Virtual Connections was the largest remaining chunk in the
needs_docstring bucket per the api-ref migration audit (14 of the 41
remaining public endpoint methods without docstrings, after the 15
Favorites methods in #1855).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
tableauserverclient
   __init__.py50100% 
   config.py150100% 
   datetime_helpers.py2511 96%
   exponential_backoff.py200100% 
   filesys_helpers.py310100% 
   namespace.py2633 88%
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.py7288 89%
   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.py771111 86%
   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.py2122020 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.py1191111 91%
   webhooks_endpoint.py5499 83%
   workbooks_endpoint.py3382222 93%
TOTAL12021142488% 

jacalata and others added 2 commits August 10, 2026 18:59
- add_permissions and delete_permission grow proper type hints
  (VirtualConnectionItem, list[PermissionsRule], PermissionsRule) so the
  docstring claims and the signatures agree.
- Rename docstring/signature params to `virtual_connection` throughout
  the permissions methods; `item`, `resource`, `capability_item` were
  inconsistent with the rest of the class and with each other.
- Rename `delete_permission`'s second param from `capability_item` to
  `permission_rule` (which is what it actually is).
- Class docstring's REST API line now uses the same RST link style as
  every method's REST API line.
- update_tags docstring documents WHY it's not implemented: the REST
  API's virtual-connection response schema doesn't include tags, so
  there's no way to populate _initial_tags on the item and no diff
  basis for the mixin's update_tags. Tags exist server-side and are
  manipulated via the add-tags / delete-tag endpoints that add_tags /
  delete_tags already wrap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The `VirtualConnections` REST endpoints have carried tags on their
response bodies since Tableau Server 2026.2 / Cloud April 2026 (server
commit 2e687548e10, W-21424436, shipping in v262 with REST API 3.30+).
The public REST docs still don't reflect this (filed W-23806318);
`VirtualConnectionItem` previously didn't parse the <tags> element.

Changes:

- `VirtualConnectionItem.__init__` gains `tags: set[str]` and
  `_initial_tags: set[str]` matching every other taggable item.
- `VirtualConnectionItem.from_xml` parses <tags><tag label="..."/></tags>
  via the existing `TagItem.from_xml_element` helper. `_initial_tags`
  is a shallow copy of `tags` (strings are immutable so copy.copy is
  sufficient).
- `VirtualConnections.update_tags` drops the NotImplementedError
  override and delegates to `TaggingMixin.update_tags`. Bumped to
  `@api(version="3.30")` since older server responses don't carry
  <tags>, meaning `_initial_tags` would be empty and every locally-set
  tag would be treated as new -- silent no-op on removes.
- `VirtualConnections.get_by_id` stamps the id back onto the returned
  item. The `Get Virtual Connection` server response element omits the
  `id` attribute (separate server-side bug filed as W-23806343);
  downstream calls that need result.id (add_tags, delete_tags,
  update_tags) would fail with 'ID not found.' Client-side workaround
  until the server fix ships.
- Fixed pre-existing "Workbook item must be populated with permissions
  first" copy-paste error in the `permissions` property error message.
- Test fixture `virtual_connections_get.xml` grew a matching empty
  `<tags/>` element to reflect the current server response shape.
- `test_from_xml` and `test_virtual_connection_get_by_id` assert on the
  new tags/id shape.
- New `test_from_xml_populated_tags` covers the tag-parse path
  including no-back-propagation from `tags` to `_initial_tags`.
- New `test_update_tags_diff_round_trip` mocks the PUT/DELETE calls to
  verify the diff-based mixin end-to-end.
- `test_tagging.py` server version bumped from 3.28 to 3.30 so the
  parametrized virtual_connections update_tags case exercises the real
  code path.

Live-verified end-to-end against a Tableau server (build 2026-08-09,
REST API 3.30): fetch a VC, mutate .tags locally, call update_tags,
re-fetch, server state matches the local edit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jacalata jacalata changed the title docs: numpy-style docstrings on VirtualConnections endpoint (14 methods) docs+feat: VirtualConnections docstrings, tag parsing, id workaround Aug 11, 2026
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.

[TYPE 3] [Virtual Connection Tags]

1 participant