fix: preserve nullability for null-only anyOf/oneOf schemas (#3171)#3313
Closed
zen-agent wants to merge 1 commit into
Closed
fix: preserve nullability for null-only anyOf/oneOf schemas (#3171)#3313zen-agent wants to merge 1 commit into
zen-agent wants to merge 1 commit into
Conversation
`json_schema_to_pydantic_type` correctly maps a direct `{"type": "null"}`
schema to `Optional[Any]`, but a null-only `anyOf` (e.g.
`{"anyOf": [{"type": "null"}]}`) was collapsing to either `NoneType`
(via the underlying library) or `str` (via the manual fallback in
`_build_union_from_options`), erasing the nullable intent.
Fixes:
- `_build_union_from_options`: when `has_null=True` and no non-null
branches remain, return `Optional[Any]` instead of falling back to
`str`.
- `_handle_toplevel_combiner`: when the library successfully resolves
the combiner to bare `NoneType`, normalize it to `Optional[Any]`
for consistency with the direct `{"type": "null"}` mapping.
Adds regression tests covering null-only `anyOf`, null-only `oneOf`,
and repeated null branches.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Abhishek <abhishek@composio.dev>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Author
Post-PR status
Ready for review/merge. |
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.
Description
Fixes #3171.
json_schema_to_pydantic_type()inpython/composio/utils/schema_converter.pycorrectly maps a direct{"type": "null"}schema toOptional[Any](viaPYDANTIC_TYPE_TO_PYTHON_TYPE), but a null-onlyanyOflike{"anyOf": [{"type": "null"}]}was being downgraded — to bareNoneType(when the underlying library resolves the combiner) orstr(when execution reached the manual_build_union_from_optionsfallback). Both outcomes erase the nullable-but-untyped intent.Root cause
Two paths hit the same gap:
_handle_toplevel_combiner—json_schema_to_pydanticlibrary succeeds and returnstype(None)for a null-only combiner, so we never reach the manual fallback._build_union_from_options— when every option is filtered into thehas_null=Truebucket andpydantic_typesends up empty, the function falls through to the genericreturn strinstead of honoringhas_null.Fix
_build_union_from_options: whenhas_null=Trueand no non-null branches remain, returnOptional[Any]instead ofstr._handle_toplevel_combiner: when the library resolves the combiner to bareNoneType, normalize it toOptional[Any]so it matches the direct{"type": "null"}mapping.How did I test this PR
tests/test_schema_parser.py::TestJsonSchemaToPydanticType:test_anyof_null_only_preserves_nullability—{"anyOf": [{"type": "null"}]}→Optional[Any]test_oneof_null_only_preserves_nullability—{"oneOf": [{"type": "null"}]}→Optional[Any]test_anyof_repeated_null_branches— multiple null branches collapse cleanly{"anyOf": [{"type": "string"}, {"type": "null"}]}→Optional[str]✓{"anyOf": [{"type": "string"}, {"type": "integer"}]}→Union[str, int]✓{"type": "null"}→Optional[Any]✓ (unchanged)Triggered by: abhishek@composio.dev | Source: slack
Session: https://zen-api-production-4c98.up.railway.app/dashboard/#/chat/zen-e25dc264c721