GeezerVison is showing github.com — docs: expand RequestOptions.vf() with vf_ wire-format rules by jacalata · Pull Request #1840 · tableau/server-client-python
Conversation
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.
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]>
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]>
|

Coverage Report
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
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]>
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]>
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]>
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
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.
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.
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]>
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]>
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.
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
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.
|
docs only change, merging with AI review only
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
jacalata
added a commit
that referenced
this pull request
Aug 20, 2026
* 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]>
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
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.
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.
|