From 39c10752557d53c6965720fc769d6a60189da63e Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 29 Jul 2026 15:57:03 -0700 Subject: [PATCH 1/5] docs: expand RequestOptions.vf() with vf_ wire-format rules 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) --- tableauserverclient/server/request_options.py | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index 5a8600908..4440ab94c 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -351,9 +351,37 @@ def get_query_params(self): def vf(self, name: str, value: str) -> Self: """Apply a filter based on a column within the view. - Note that when filtering on a boolean type field, the only valid values are 'true' and 'false' - For more detail see: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_filtering_and_sorting.htm#Filter-query-views + Serialized to the REST API as ``vf_=``. The rules below + describe how the server interprets the wire value; ``vf()`` itself + does not transform your input. + + Value syntax + ------------ + - **Exact match (default):** a single value matches rows where the + column equals that value exactly. Case-sensitivity follows the + underlying data source. + - **OR-list:** commas separate alternatives, so ``"East,West"`` + matches rows where the column is ``East`` OR ``West``. + - **Literal comma in a value:** escape with a backslash -- + ``"Rock\\, Paper\\, Scissors"`` matches the single value + ``Rock, Paper, Scissors``. URL-encoding the comma (``%2C``) + does NOT escape it. + - **Empty value** (``vf_=``) overrides any workbook-embedded + filter on that column, effectively widening it to all values. + This is undocumented but stable behavior that some users rely on. + - **Wildcards** (``*``) are NOT supported by the REST view-filter + layer. Wildcard matching is a viz-configured behavior on filter + controls inside a workbook; use ``.parameter()`` and design the + workbook accordingly if you need it. + - **Ranges, comparisons, operators** (``>``, ``<=``, ``BETWEEN``, + etc.) are NOT supported here. Use workbook-side filter design or + the ``filter=`` query parameter on list endpoints, which is a + separate syntax. + - **Booleans:** the only valid values are ``'true'`` and ``'false'``. + + For more detail see: + https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_filtering_and_sorting.htm#Filter-query-views Parameters ---------- From 8f3dc23ba4f13d4754b4619bb3f549a48f7e108c Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 29 Jul 2026 15:57:45 -0700 Subject: [PATCH 2/5] docs: drop irrelevant filter= reference from vf() docstring 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) --- tableauserverclient/server/request_options.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index 4440ab94c..b66f8aa0c 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -375,9 +375,8 @@ def vf(self, name: str, value: str) -> Self: controls inside a workbook; use ``.parameter()`` and design the workbook accordingly if you need it. - **Ranges, comparisons, operators** (``>``, ``<=``, ``BETWEEN``, - etc.) are NOT supported here. Use workbook-side filter design or - the ``filter=`` query parameter on list endpoints, which is a - separate syntax. + etc.) are NOT supported. Design the workbook's filters to expose + the shape you need at export time. - **Booleans:** the only valid values are ``'true'`` and ``'false'``. For more detail see: From c78f06033329d2c5df7671ca246093b490bd94db Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 29 Jul 2026 16:00:52 -0700 Subject: [PATCH 3/5] docs: document backslash as vf_ escape character 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) --- tableauserverclient/server/request_options.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index b66f8aa0c..1b7b6bc98 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -363,10 +363,12 @@ def vf(self, name: str, value: str) -> Self: underlying data source. - **OR-list:** commas separate alternatives, so ``"East,West"`` matches rows where the column is ``East`` OR ``West``. - - **Literal comma in a value:** escape with a backslash -- - ``"Rock\\, Paper\\, Scissors"`` matches the single value - ``Rock, Paper, Scissors``. URL-encoding the comma (``%2C``) - does NOT escape it. + - **Backslash is an escape character.** ``\\c`` in the wire value + means "literal ``c``, don't interpret it." To match a value + containing a literal ``,`` escape it: ``"Rock\\, Paper\\, Scissors"`` + matches ``Rock, Paper, Scissors``. To match a literal backslash, + double it: ``"C:\\\\temp\\\\file"`` matches ``C:\\temp\\file``. + URL-encoding (``%2C``, ``%5C``) does NOT escape either character. - **Empty value** (``vf_=``) overrides any workbook-embedded filter on that column, effectively widening it to all values. This is undocumented but stable behavior that some users rely on. From 98b4faf226c6b3db16309b686d326be036b32b94 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 29 Jul 2026 16:01:42 -0700 Subject: [PATCH 4/5] docs: rephrase vf_ backslash bullet to lead with examples 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) --- tableauserverclient/server/request_options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index 1b7b6bc98..ac4a1de4a 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -363,10 +363,10 @@ def vf(self, name: str, value: str) -> Self: underlying data source. - **OR-list:** commas separate alternatives, so ``"East,West"`` matches rows where the column is ``East`` OR ``West``. - - **Backslash is an escape character.** ``\\c`` in the wire value - means "literal ``c``, don't interpret it." To match a value - containing a literal ``,`` escape it: ``"Rock\\, Paper\\, Scissors"`` - matches ``Rock, Paper, Scissors``. To match a literal backslash, + - **Backslash escapes.** To match a value that contains a literal + comma, escape it: ``"Rock\\, Paper\\, Scissors"`` matches + ``Rock, Paper, Scissors`` (without escaping, the comma would be + treated as an OR-list separator). To match a literal backslash, double it: ``"C:\\\\temp\\\\file"`` matches ``C:\\temp\\file``. URL-encoding (``%2C``, ``%5C``) does NOT escape either character. - **Empty value** (``vf_=``) overrides any workbook-embedded From 6b7a41fa1b85923335c6825fc9e70e3afe8ef785 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 29 Jul 2026 16:08:00 -0700 Subject: [PATCH 5/5] docs: clarify vf_ escaping is only for ',' and '\' 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) --- tableauserverclient/server/request_options.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index ac4a1de4a..8ea4cba13 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -363,12 +363,16 @@ def vf(self, name: str, value: str) -> Self: underlying data source. - **OR-list:** commas separate alternatives, so ``"East,West"`` matches rows where the column is ``East`` OR ``West``. - - **Backslash escapes.** To match a value that contains a literal - comma, escape it: ``"Rock\\, Paper\\, Scissors"`` matches - ``Rock, Paper, Scissors`` (without escaping, the comma would be - treated as an OR-list separator). To match a literal backslash, - double it: ``"C:\\\\temp\\\\file"`` matches ``C:\\temp\\file``. - URL-encoding (``%2C``, ``%5C``) does NOT escape either character. + - **Escaping** applies to two characters only, comma and backslash; + all other characters (``&``, ``=``, ``/``, ``#``, ``%``, ``+``, + quotes, brackets, etc.) pass through untouched -- ``vf()`` URL- + encodes them for transport and the server treats them as literal + data. To match a value containing a literal comma, escape it: + ``"Rock\\, Paper\\, Scissors"`` matches ``Rock, Paper, Scissors`` + (without escaping, the comma starts an OR-list). To match a + literal backslash, double it: ``"C:\\\\temp\\\\file"`` matches + ``C:\\temp\\file``. URL-encoding (``%2C``, ``%5C``) does NOT + escape either character. - **Empty value** (``vf_=``) overrides any workbook-embedded filter on that column, effectively widening it to all values. This is undocumented but stable behavior that some users rely on.