Repository navigation
Conversation
Object bodies without named properties currently lose all dictionary entries. Expose one body argument for open dictionary schemas and send it whole, while retaining flattened arguments for named-property objects. Cover typed and free-form maps, empty and omitted bodies, parameter-name collisions, and named or closed-object compatibility. Fixes google#8037
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
Problem:
An OpenAPI request body with
type: object, no named properties, andadditionalProperties: {type: string}generates no body arguments. The senderthen reconstructs
{}, silently discarding the supplied dictionary.Solution:
Represent a pure dictionary body as one
bodyargument and send that argumentwhole. A pure dictionary has
type: object, absent or emptyproperties, andadditionalPropertiesother thanfalse, including the default when omitted.The parser and sender share this classification.
requestBody.requiredto the dictionary argument. An omitted optionalargument sends no payload; an explicitly supplied empty dictionary sends
{}.body_0when a queryparameter is already named
body.mixed named properties plus
additionalProperties. Closed empty objects keeptheir existing zero-argument interface.
No new dependencies or downstream changes are required.
Testing Plan
Unit Tests:
Added 14 regression/control cases covering typed and free-form dictionaries,
empty
properties, requiredness, name collisions, omitted/empty payloads, andnamed/mixed/closed objects. The existing open-object expectation is corrected to
expose
body.Full configured
toxmatrix, using pristineuv-venv-lock-runnerenvironmentswith the original
testextra, Python 3.11.15/3.12.13/3.13.15/3.14.7:The same 14 test IDs fail on unchanged main
(
1cb926d5b8d702261ec82a26d3f1c4296e0db7d7) in each matching interpreter,dependency environment, and host-access context. Each baseline re-run selected
those 14 failed tests; the full main suite was not re-run. No new failing IDs
were introduced in these runs.
OpenAPI request/SSRF tests, 3
load_web_pagetests, and the MCP Google-authasync-transport test. Clearing proxy environment variables still leaves the
system proxy visible in that context. The separate isolated source and clean
wheel OpenAPI runs above do not detect that proxy and both pass all 446 tests.
test_inclusive_upper_bounds_name_an_installed_release: the generatedlock selected
opentelemetry-api/opentelemetry-sdk1.45.1, while the declaredinclusive upper bounds name 1.45.2. This dependency-validation test also fails
unchanged on main. No dependency ranges or test expectations were changed.
The generated lock was resolved with
--exclude-newer=2026-10-24; key testversions were google-genai 2.33.0, google-cloud-agentplatform/aiplatform 2.6.0,
Pydantic 2.14.1, and pytest 9.1.1. The full test command was equivalent to:
Full-suite failure IDs reproduced on main in all four environments
Manual End-to-End (E2E) Tests:
Used the public
OpenAPIToolsetAPI with real HTTP connections to an ephemeral127.0.0.1server. The source baseline, fixed source, and clean installed wheeleach sent two requests: a pure dictionary and the
bodyquery-name collision.Standalone reviewer reproduction
With the checkout's dependencies installed, save this as
e2e_map_body.pyand runPYTHONPATH=src python e2e_map_body.py. Compare baseline1cb926d5b8d702261ec82a26d3f1c4296e0db7d7with this branch. To verify packaging,build with
uv build, install that wheel in a clean environment, and run thesame script from outside the checkout without
PYTHONPATH.Observed server logs:
Each call returned
{"ok": true}. This verifies construction and HTTP transportwithout a mock transport, credentials, an external API, or a model call. Remote
Gemini behavior and enforcement of dictionary value constraints were not tested.
Checklist
Additional context
concrete object schema and leaves schema normalization to that separate fix.
oneOf/anyOf/allOf) or untyped bodiesfor which a body argument already exists. Here the explicit object schema
produces no argument; both parameter generation and object serialization need
the dictionary classification.