Use _query_scalar_to_str for multipart booleans, add tuple passthrough test

Reuse existing boolean serialization (true/false not True/False) for
multipart form fields. Add test for file-like tuple passthrough.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
William Easton 2026-04-14 10:23:40 -05:00
commit ea1439a009
2 changed files with 32 additions and 3 deletions

View file

@ -94,11 +94,12 @@ class RequestDirector:
if declared_content_type == "multipart/form-data" and isinstance(
body, dict
):
# Wrap plain values as (None, str(value)) tuples so httpx
# Wrap plain values as (None, stringified) tuples so httpx
# treats them as form fields. Scalars must be stringified
# because httpx rejects non-string/bytes values in files=.
# Use _query_scalar_to_str for booleans (true/false, not True/False).
files = {
k: v if isinstance(v, tuple) else (None, str(v))
k: v if isinstance(v, tuple) else (None, _query_scalar_to_str(v))
for k, v in body.items()
}
elif (

View file

@ -1292,7 +1292,35 @@ class TestContentTypeDispatch:
request.read()
body = request.content.decode("utf-8")
assert "42" in body
assert "True" in body
assert "true" in body
def test_multipart_preserves_tuple_values(self, director):
"""Tuple values (file-like) are passed through unchanged to httpx files=."""
route = HTTPRoute(
path="/upload",
method="POST",
operation_id="upload",
request_body=RequestBodyInfo(
required=True,
content_schema={
"multipart/form-data": {
"type": "object",
"properties": {"file": {"type": "string"}},
}
},
),
parameter_map={
"file": {"location": "body", "openapi_name": "file"},
},
)
# Tuple values represent file-like objects for httpx
request = director.build(route, {"file": ("report.csv", b"a,b,c")})
content_type = request.headers.get("content-type", "")
assert "multipart/form-data" in content_type
request.read()
body = request.content.decode("utf-8", errors="replace")
assert "report.csv" in body
assert "a,b,c" in body
def test_json_body_still_works(self, director, json_route):
"""application/json bodies should still be sent as JSON (regression)."""