From 65faa0a4228415c6286f62fd35ed388f01f8ec37 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 8 Jul 2026 13:09:19 -0700 Subject: [PATCH] feat: add operator parameter to vf() for range filters Exposes comparison operators (GreaterThan, LessThan, etc.) on the vf() method of _DataExportOptions. The REST API accepts operator:value encoding for view filters; previously callers had to hand-craft the string themselves. Fixes #1752 Co-Authored-By: Claude Sonnet 4.6 --- tableauserverclient/server/request_options.py | 10 ++++++++-- test/test_request_option.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index 5a8600908..9b6f9e0fe 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -349,7 +349,7 @@ def get_query_params(self): self._append_view_filters(params) return params - def vf(self, name: str, value: str) -> Self: + def vf(self, name: str, value: str, operator: str | None = None) -> 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' @@ -363,12 +363,18 @@ def vf(self, name: str, value: str) -> Self: value: str The value to filter on + operator: str, optional + A comparison operator from RequestOptions.Operator (e.g. 'gt', 'lte'). + When provided the filter is encoded as ``operator:value``. + Defaults to an exact-match filter when omitted. + Returns ------- Self The current object """ - self.view_filters.append((name, value)) + encoded_value = f"{operator}:{value}" if operator else value + self.view_filters.append((name, encoded_value)) return self def parameter(self, name: str, value: str) -> Self: diff --git a/test/test_request_option.py b/test/test_request_option.py index 3709e18d3..b9bb0afa6 100644 --- a/test/test_request_option.py +++ b/test/test_request_option.py @@ -238,6 +238,23 @@ def test_vf(server: TSC.Server) -> None: assert "tabloid" in query_string["type"] +def test_vf_with_operator(server: TSC.Server) -> None: + server.version = "3.23" + with requests_mock.mock() as m: + m.get(requests_mock.ANY) + url = server.workbooks.baseurl + "/456/data" + opts = TSC.PDFRequestOptions() + opts.vf("Sales", "1000", operator=TSC.RequestOptions.Operator.GreaterThan) + opts.vf("Region", "West") + + resp = server.workbooks.get_request(url, request_object=opts) + query_string = parse_qs(resp.request.query) + assert "vf_sales" in query_string + assert "gt:1000" in query_string["vf_sales"] + assert "vf_region" in query_string + assert "west" in query_string["vf_region"] + + # Test req_options for versions below 3.7 def test_vf_legacy(server: TSC.Server) -> None: server.version = "3.6"