From 5e26974f7a0b7847990cf050207d053acceb2ed7 Mon Sep 17 00:00:00 2001 From: adhavan18 Date: Thu, 10 Sep 2026 20:16:20 +0530 Subject: [PATCH] fix(qs): keep an explicit empty-string scalar distinct from None _stringify_item serialised both None and "" to the same "" string, then dropped the param on a truthiness check, so stringify({"a": ""}) produced "" instead of "a=". An explicit empty value in a query string is not the same as omitting the key. Check value is None before serialising, instead of checking the serialised string's truthiness after the fact. Array format ("comma") already handled this correctly since it filters on `item is not None`, only the scalar path had the bug. --- src/openai/_qs.py | 5 ++--- tests/test_qs.py | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/openai/_qs.py b/src/openai/_qs.py index 4127c19c62..d3c34ce6b0 100644 --- a/src/openai/_qs.py +++ b/src/openai/_qs.py @@ -112,10 +112,9 @@ def _stringify_item( f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" ) - serialised = self._primitive_value_to_str(value) - if not serialised: + if value is None: return [] - return [(key, serialised)] + return [(key, self._primitive_value_to_str(value))] def _primitive_value_to_str(self, value: PrimitiveData) -> str: # copied from httpx diff --git a/tests/test_qs.py b/tests/test_qs.py index 697b8a95ec..dc5fd979c6 100644 --- a/tests/test_qs.py +++ b/tests/test_qs.py @@ -22,6 +22,14 @@ def test_basic() -> None: assert stringify({"a": None}) == "" +def test_empty_string_scalar_is_kept_distinct_from_none() -> None: + # An explicit empty string is a real value ("a=") and must not be + # conflated with omitting the key entirely (None). + assert unquote(stringify({"a": ""})) == "a=" + assert stringify({"a": None}) == "" + assert unquote(stringify({"a": "", "b": 1})) == "a=&b=1" + + @pytest.mark.parametrize("method", ["class", "function"]) def test_nested_dotted(method: str) -> None: if method == "class":