Skip to content

fix(openapi): honor query parameter style and explode - #7208

Open
1aifanatic wants to merge 1 commit into
google:mainfrom
1aifanatic:fix/openapi-query-param-style-explode
Open

1aifanatic wants to merge 1 commit into
google:mainfrom
1aifanatic:fix/openapi-query-param-style-explode

Conversation

@1aifanatic

Copy link
Copy Markdown

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:

RestApiTool passed query values to httpx as the model produced them, and ApiParameter did not record the spec's style/explode. httpx repeats the key for a list, which only matches the default for arrays, and sends a dict as its Python repr. So every object-typed query parameter went out as filter={'status': 'open'}, and non-exploded or delimited arrays were exploded.

Solution:

  • ApiParameter gets optional style and explode fields (default None, so serialized ParsedOperations still load), and OperationParser copies them from the spec's Parameter.
  • A small _serialize_query_param() applies them to query values, following OpenAPI 3:
    • objects are spread (form, exploded, the default), bracketed (deepObject), or k,v,... (form, not exploded);
    • non-exploded arrays are joined with , (form), (spaceDelimited), or | (pipeDelimited);
    • scalars and default arrays are passed through unchanged, so existing behavior for them doesn't change.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.

  • All unit tests pass locally.

  • test_rest_api_tool.py::TestRestApiTool::test_prepare_request_params_query_style_and_explode, parametrized over the style/explode/type combinations above. The 6 serialization cases fail on main; the default-array and scalar cases are controls and pass on both.

  • test_operation_parser.py::test_process_operation_parameters_keeps_style_and_explode fails on main.

$ pytest tests/unittests/tools/openapi_tool
350 passed

$ pytest tests/unittests -n 8   # Python 3.12, Windows 11
44 failed, 15152 passed, 102 skipped, 27 xfailed, 2 xpassed

Every failure outside the new tests also fails on an unmodified origin/main (3f4bb8f) on the same machine, where the same run gives 47 failed. Most are deterministic Windows-specific tests (cli/ deploy, conformance, scripts/check_new_py_files, path normalization, the unsafe local code executor, the import allowlist, yaml). The remainder differ between runs: telemetry functional/node-functional schema cases, and streaming/test_streaming_tool_events.py::test_delivered_event_carries_the_message_and_nothing_else, which failed 1/10 in isolation on clean main versus 2/10 on this branch. I ran on Python 3.12 only, not the full tox matrix.

Manual End-to-End (E2E) Tests:

A real Runner + LlmAgent + OpenAPIToolset whose spec has a default-style object param, a deepObject param, and a form/explode: false array, with a mocked model and an httpx.MockTransport backend. The script is in #7204.

Before (main @ 3f4bb8f):

query sent: match={'status':+'open',+'priority':+'P1'}&filter={'assignee':+'me'}&fields=id&fields=title

After:

query sent: status=open&priority=P1&filter[assignee]=me&fields=id,title

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

🤖 Generated with Claude Code

https://claude.ai/code/session_013vXxD1ga1hnCq2uFRwNks7

RestApiTool passed query values to httpx as the model produced them and
ApiParameter did not record the spec's style/explode. httpx repeats the
key for a list, which only matches the default for arrays, and sends a
dict as its Python repr, so every object-typed query parameter went out
as e.g. filter={'status': 'open'}. Non-exploded and delimited arrays
were exploded as well.

Carry style and explode from the spec's Parameter into ApiParameter
(optional fields, so serialized parameters still load) and serialize
query values per OpenAPI: objects are spread (form, exploded, the
default), bracketed (deepObject) or k,v-joined (form, not exploded), and
non-exploded arrays are joined with ",", " " or "|". Scalars and default
arrays are unchanged.

Fixes google#7204

Claude-Session: https://claude.ai/code/session_013vXxD1ga1hnCq2uFRwNks7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RestApiTool ignores query parameter style/explode: object query params are sent as a Python dict repr

2 participants