GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — docs: expand RequestOptions.vf() with vf_ wire-format rules by jacalata · Pull Request #1840 · tableau/server-client-python

Conversation

@jacalata

@jacalata jacalata commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

The vf_ REST view filter has several server-side quirks that aren't obvious from the current one-line vf() docstring. This expands it to document what values actually mean on the wire: exact-match by default, , as OR-list, \, for a literal comma, the empty-value override behavior, no wildcards, no operators, boolean 'true'/'false' only.

Callers who build vf_ requests through TSC no longer have to reverse-engineer server behavior to figure out why their filter returned zero rows.

Why now

Working through --filter parsing bugs in tabcmd, I verified the wire-format behavior end-to-end against Tableau Cloud. Recording those findings in the library the tabcmd (and other callers) build on top of, so the next person doesn't have to redo the experiment.

Notable server-side behaviors documented:

  • Rock\, Paper\, Scissors — backslash-escape works for a literal comma. %2C does NOT.
  • vf_Region= (empty value) — overrides any workbook-embedded filter on that column. Undocumented but stable and useful.
  • * — NOT a wildcard on vf_. It's a wildcard on the filter= list-endpoint syntax, which is a different query parameter.

Test plan

  • help(PDFRequestOptions.vf) renders the expanded docstring cleanly
  • mypy passes (pre-commit hook)
  • No behavior change; docstring-only

🤖 Generated with Claude Code

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
jacalata and others added 2 commits July 29, 2026 15:57
@jacalata @claude
docs: expand RequestOptions.vf() with vf_ wire-format rules
39c1075
The vf_ view filter has several server-side quirks that aren't obvious
from the current one-line docstring. Document what values actually mean
on the wire: exact match by default, comma as OR-list, backslash-escape
for literal comma, empty-value override behavior, no wildcards, no
operators, boolean 'true'/'false' only.

This surfaces the behavior verified end-to-end against Tableau Cloud
while working through --filter parsing issues in tabcmd, so callers who
build vf_ requests through TSC know what the server will accept without
having to reverse-engineer it.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata @claude
docs: drop irrelevant filter= reference from vf() docstring
8f3dc23
The `filter=` list-endpoint syntax is unrelated to view-filter export
requests (it's for querying lists of workbooks/users/etc). Steering
readers there was scope creep. Just say ranges/operators aren't
supported and point at workbook-side design.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@github-actions

github-actions Bot commented Jul 29, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

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.py3231616 95%
   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.py731010 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.py2592424 91%
   exceptions.py7966 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%
TOTAL12065142488% 

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jacalata and others added 3 commits July 29, 2026 16:00
@jacalata @claude
docs: document backslash as vf_ escape character
c78f060
Empirically verified: '\' in a vf_ value is the escape character. To
match a literal backslash you must double it ('\\'). Consolidate the
comma-escape and backslash rules into a single "backslash escapes"
bullet, since it's one mechanism.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata @claude
docs: rephrase vf_ backslash bullet to lead with examples
98b4faf
Dropped the abstract "\c means literal c" phrasing (weird to read with
a random letter) and led with the two concrete cases -- escape a comma,
escape a backslash -- and noted why each escape matters (comma would
otherwise start an OR-list; backslash otherwise consumed as escape).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata @claude
docs: clarify vf_ escaping is only for ',' and '\'
6b7a41f
Empirically tested 20+ candidate metacharacters (/ % + : ; { } [ ] ( )
? # * @ = & " ' < >) against a live server; every one passes through
untouched when URL-encoded. Only ',' and '\' are vf_ metacharacters
that need escaping in the wire value. Explicitly call that out so
readers don't assume everything URL-special needs a client-side
workaround.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata
jacalata requested a lite review from Copilot August 6, 2026 21:23
@jacalata
jacalata enabled auto-merge (squash) August 6, 2026 21:23
Copilot AI reviewed Aug 6, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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

Note

Copilot was unable to run its full agentic suite in this review.

Expands the RequestOptions.vf() docstring to more thoroughly document Tableau REST view-filter (vf_) query semantics.

Changes:

  • Adds detailed vf_<name>=<value> serialization and parsing rules (OR-lists, escaping, empty value behavior).
  • Clarifies unsupported patterns (wildcards, range/comparison operators) and boolean value constraints.
  • Improves formatting and provides a direct link to Tableau REST filtering documentation.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread tableauserverclient/server/request_options.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread tableauserverclient/server/request_options.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread tableauserverclient/server/request_options.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@jacalata
docs: clarify vf() percent-encoding vs escaping (Copilot review)
e7b6c3f
Copilot flagged the vf() docstring as internally inconsistent: it said
'vf() does not transform your input' and later 'vf() URL-encodes them
for transport' -- both true, but confusing side-by-side.

Rewrite to distinguish (a) no Tableau-specific escaping/semantic transforms
(b) percent-encoding for HTTP transport. Also fold in a note that
percent-encoding is transport-layer only: %2C reaches the server as ','
and gets processed as a comma delimiter, so URL-encoding does NOT escape
a literal comma or backslash.

Also softened the 'empty value' bullet from 'undocumented but stable
behavior' (reads as a compat promise the library can't make) to
'observed... may change without notice.'

No behavior change.
@jacalata
jacalata requested a lite review from Copilot August 17, 2026 20:01
Copilot started reviewing on behalf of jacalata August 17, 2026 20:02
View session
Copilot AI reviewed Aug 17, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

tableauserverclient/server/request_options.py:359

  • The docstring says vf() “only percent-encodes the value for HTTP transport”, but vf() just appends (name, value) to self.view_filters and does not perform any encoding. Query-string percent-encoding (when it happens) is done later by the HTTP client/request construction, so attributing it to vf() is misleading and can be incorrect for code paths that build URLs manually.
        Serialized to the REST API as ``vf_<name>=<value>``. The rules below
        describe how the server interprets the wire value. ``vf()`` itself
        does not apply any Tableau-specific escaping or semantic transforms
        to your value; it only percent-encodes the value for HTTP transport,
        which the server decodes back before applying the rules below.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
jacalata and others added 4 commits August 17, 2026 13:20
@jacalata @claude
docs: label empirical vf() claims and tighten wildcard note
b0fc0d4
Fresh-eyes review noted two nits on the expanded docstring:

- The percent-encoding-does-not-escape claim (that %2C/%5C reach the
  server as literal comma/backslash and are then processed by the
  escaping rules like any other) is not on the public REST API doc page
  -- it was verified end-to-end against Tableau Cloud. Mark it as
  empirical with a verification date so a future maintainer knows to
  re-check if the wire behavior changes. Note that only the \, escape
  is documented; \ and the percent-encoding claim are empirical.

- The wildcard note previously suggested "use .parameter() and design
  the workbook accordingly" as a workaround. That conflates two
  mechanisms (workbook filter controls' wildcard behavior vs.
  parameters) and doesn't cleanly work around vf_'s exact-match limit.
  Reworded to just state the fact: vf_ is exact-match / OR-list only,
  no contains/starts-with/ends-with.

Docstring-only change; 41 request_option tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata @claude
docs: don't make a categorical negative claim about vf_ wildcards
4c503f3
Previous wording said wildcards, ranges, and operators are "NOT
supported" -- but I don't have live verification that `*` or `%` are
inert in a vf_ value. The public filtering docs describe only exact
match and OR-lists; behavior of other characters is undocumented, not
verifiably absent. Rephrase to say what we know (docs don't cover it,
TSC doesn't emit operator prefixes) and tell callers to verify against
their target server before relying on the outcome.

This is intentionally less prescriptive than the previous version.
The related open PR #1854 was flagged by the same fresh-eyes pass for
making an unverified `*`-as-wildcard claim in the opposite direction
-- both PRs should stay in "docs describe X; other behaviors are
untested" territory until we run the experiments.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jacalata
docs: verify vf_ wildcard behavior against a live server
adc4fad
The prior wording ('not documented, verify against your target') was
correct but weakly stated. Ran the actual experiments against Tableau
Server 3.30: vf_ passes * and % through as literal data, so a value of
'Widget*' matches only a product literally named 'Widget*', 'META
/star*/' matches its one row, and '*' or '%' on their own return zero
rows. Docstring now states that outcome directly and cites the
verification date.
@jacalata
Address opus-5 review on vf() docstring: heading + labels + version
fc6a9e7
Three findings from a post-push opus-5 pass:

- Bold "**Value syntax**" instead of an underlined RST section header.
  Sitting an underlined heading above the Napoleon Parameters block
  can render weirdly depending on Sphinx config.
- Label the escape examples explicitly as "wire form" vs "data value"
  so a reader can't confuse a Python-literal reading with the wire
  interpretation the docstring is describing.
- Say "Tableau REST API 3.30" rather than "Tableau Server 3.30".
  Server versions are 2026.N-shaped; 3.30 is the REST API contract
  identifier, which is what actually determines the behavior. Also
  drops an unverified aside about Cloud/Server sharing the URL
  parser.
jacalata added a commit that referenced this pull request Aug 20, 2026
@jacalata
Drop the vf_ exact-match limitation entry
91c1b04
Opus-5 review found the entry's tracker link (#1431) points at a
closed-not-planned issue; the underlying gap was filed with the
Tableau REST API docs team internally and there's no realistic
timeline for it being tracked back in the TSC repo. Rather than
carry an untracked entry indefinitely, drop it. The behavior claim
(vf_ is exact-match / OR-list only) is now covered by the expanded
docstring on RequestOptions.vf() in #1840.
@jacalata

jacalata commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

docs only change, merging with AI review only

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jacalata
jacalata disabled auto-merge August 20, 2026 07:37
@jacalata
jacalata merged commit 51b3efc into development Aug 20, 2026
31 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@jacalata
jacalata deleted the jac/vf-docs branch August 20, 2026 07:39
jacalata added a commit that referenced this pull request Aug 20, 2026
@jacalata @claude
docs: add Known server-side limitations section to api-ref.md (#1842)
3b3548a
* docs: add Known server-side limitations section

Add a new user-facing section to docs/api-ref.md that lists behaviors
users may hit that are constrained by the Tableau Server REST API
rather than by TSC. Each entry links its tracking issue and notes
where the fix is expected to land. Cross-link the new section from
the top-of-page note, and point at the `Server-Side Enhancement`
label as the live tracker maintained by this repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* docs: drop internal work-item IDs and per-bullet fix-scope tag

Public docs on gh-pages will be indexed, so remove the internal
work-item numbers (W-...) from the Known server-side limitations
section along with the paragraph that described what they were.
Also strip the redundant per-bullet "Fix expected: server-side"
tag: the section title already scopes the whole list to server-side
gaps.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* Drop On Extract Refresh entry, soften intro and daily-schedule wording

Three fresh-eyes findings:
- Remove the "Subscriptions cannot use On Extract Refresh" entry. The
  REST API's refreshExtractTriggered attribute does support this, and
  TSC support is landing in #1861 (which closes the tracker #1658). The
  entry is about to be factually wrong on both counts.
- Soften the intro: it promised "follow the appropriate issues" for
  every item, but the vf_-silently-dropped entry has no tracker filed.
  New wording says "where filed" so the doc doesn't overpromise.
- Reword the daily-schedules note to describe behavior neutrally
  ("currently runs daily schedules hourly instead") rather than calling
  it a "bug", which reads punchy on a public docs page.

* Drop the vf_ exact-match limitation entry

Opus-5 review found the entry's tracker link (#1431) points at a
closed-not-planned issue; the underlying gap was filed with the
Tableau REST API docs team internally and there's no realistic
timeline for it being tracked back in the TSC repo. Rather than
carry an untracked entry indefinitely, drop it. The behavior claim
(vf_ is exact-match / OR-list only) is now covered by the expanded
docstring on RequestOptions.vf() in #1840.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@jacalata
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.