From a01863529bade9ab76ccd374c674e85320c10a6b Mon Sep 17 00:00:00 2001 From: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Date: Wed, 9 Jul 2025 17:38:31 -0500 Subject: [PATCH 1/3] fix: handle parameters for view filters Closes #1632 Parameters need to be prefixed with "vf_Parameters." in order to be properly registered as setting a parameter value. This PR adds that prefix where it was missing, but leaves parameter names that already included the prefix unmodified. --- tableauserverclient/server/request_options.py | 9 ++++++++- test/test_request_option.py | 14 ++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index 45a4f6df0..70c85d140 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -387,7 +387,14 @@ def parameter(self, name: str, value: str) -> Self: Self The current object """ - self.view_parameters.append((name, value)) + prefix = "vf_Parameters." + if name.startswith(prefix): + proper_name = name + elif name.startswith("Parameters."): + proper_name = f"vf_{name}" + else: + proper_name = f"{prefix}{name}" + self.view_parameters.append((proper_name, value)) return self def _append_view_filters(self, params) -> None: diff --git a/test/test_request_option.py b/test/test_request_option.py index dbf6dc996..bbf06bdc8 100644 --- a/test/test_request_option.py +++ b/test/test_request_option.py @@ -321,14 +321,20 @@ def test_filtering_parameters(self) -> None: opts = TSC.PDFRequestOptions() opts.parameter("name1@", "value1") opts.parameter("name2$", "value2") + opts.parameter("Parameters.name3", "value3") + opts.parameter("vf_Parameters.name4", "value4") opts.page_type = TSC.PDFRequestOptions.PageType.Tabloid resp = self.server.workbooks.get_request(url, request_object=opts) query_params = parse_qs(resp.request.query) - self.assertIn("name1@", query_params) - self.assertIn("value1", query_params["name1@"]) - self.assertIn("name2$", query_params) - self.assertIn("value2", query_params["name2$"]) + self.assertIn("vf_parameters.name1@", query_params) + self.assertIn("value1", query_params["vf_parameters.name1@"]) + self.assertIn("vf_parameters.name2$", query_params) + self.assertIn("value2", query_params["vf_parameters.name2$"]) + self.assertIn("vf_parameters.name3", query_params) + self.assertIn("value3", query_params["vf_parameters.name3"]) + self.assertIn("vf_parameters.name4", query_params) + self.assertIn("value4", query_params["vf_parameters.name4"]) self.assertIn("type", query_params) self.assertIn("tabloid", query_params["type"]) From a74b9e3de4b772ef12935cb28afc55660aec9388 Mon Sep 17 00:00:00 2001 From: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Date: Sat, 1 Nov 2025 06:24:07 -0500 Subject: [PATCH 2/3] docs: case sensitivity in the test's query string --- test/test_request_option.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_request_option.py b/test/test_request_option.py index bbf06bdc8..dc3491df9 100644 --- a/test/test_request_option.py +++ b/test/test_request_option.py @@ -325,6 +325,11 @@ def test_filtering_parameters(self) -> None: opts.parameter("vf_Parameters.name4", "value4") opts.page_type = TSC.PDFRequestOptions.PageType.Tabloid + # While Tableau Server side IS case sensitive with the query string, + # requiring the prefix to be "vf_Parameters", requests does not end + # up preserving the case sensitivity with the Response.Request + # object. It also shows up lowercased in the requests_mock request + # history. resp = self.server.workbooks.get_request(url, request_object=opts) query_params = parse_qs(resp.request.query) self.assertIn("vf_parameters.name1@", query_params) From 248e16acacd1b112859382127596651dae28bf01 Mon Sep 17 00:00:00 2001 From: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:02:13 -0600 Subject: [PATCH 3/3] chore: pytest style asserts --- test/test_request_option.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/test_request_option.py b/test/test_request_option.py index dc3491df9..d0ba5c770 100644 --- a/test/test_request_option.py +++ b/test/test_request_option.py @@ -332,16 +332,16 @@ def test_filtering_parameters(self) -> None: # history. resp = self.server.workbooks.get_request(url, request_object=opts) query_params = parse_qs(resp.request.query) - self.assertIn("vf_parameters.name1@", query_params) - self.assertIn("value1", query_params["vf_parameters.name1@"]) - self.assertIn("vf_parameters.name2$", query_params) - self.assertIn("value2", query_params["vf_parameters.name2$"]) - self.assertIn("vf_parameters.name3", query_params) - self.assertIn("value3", query_params["vf_parameters.name3"]) - self.assertIn("vf_parameters.name4", query_params) - self.assertIn("value4", query_params["vf_parameters.name4"]) - self.assertIn("type", query_params) - self.assertIn("tabloid", query_params["type"]) + assert "vf_parameters.name1@" in query_params + assert "value1" in query_params["vf_parameters.name1@"] + assert "vf_parameters.name2$" in query_params + assert "value2" in query_params["vf_parameters.name2$"] + assert "vf_parameters.name3" in query_params + assert "value3" in query_params["vf_parameters.name3"] + assert "vf_parameters.name4" in query_params + assert "value4" in query_params["vf_parameters.name4"] + assert "type" in query_params + assert "tabloid" in query_params["type"] def test_queryset_endpoint_pagesize_all(self) -> None: for page_size in (1, 10, 100, 1000):