|
5 | 5 | # pyright: reportUnknownLambdaType=false |
6 | 6 | from collections.abc import Callable |
7 | 7 | from dataclasses import dataclass |
8 | | -from typing import Annotated, Any, TypedDict |
| 8 | +from typing import Annotated, Any, Optional, TypedDict |
9 | 9 |
|
10 | 10 | import annotated_types |
11 | 11 | import pytest |
@@ -1094,3 +1094,52 @@ def func_with_reserved_json( |
1094 | 1094 | assert result["json"] == {"nested": "data"} |
1095 | 1095 | assert result["model_dump"] == [1, 2, 3] |
1096 | 1096 | assert result["normal"] == "plain string" |
| 1097 | + |
| 1098 | + |
| 1099 | +def test_optional_parameters_not_required(): |
| 1100 | + """Test that Optional parameters are not marked as required in JSON schema.""" |
| 1101 | + |
| 1102 | + def func_with_optional_params( |
| 1103 | + required: str = Field(description="This should be required"), |
| 1104 | + optional: str | None = Field(description="This should be optional"), |
| 1105 | + optional_with_default: str | None = Field(default="hello", description="This should be optional with default"), |
| 1106 | + optional_with_union_type: Optional[str] = Field(description="This should be optional"), # noqa: UP045 |
| 1107 | + optional_with_union_type_and_default: Optional[str] | None = Field( # noqa: UP045 |
| 1108 | + default="hello", description="This should be optional with default" |
| 1109 | + ), |
| 1110 | + ) -> str: |
| 1111 | + return f"{required}|{optional}|{optional_with_default}|{optional_with_union_type}|{optional_with_union_type_and_default}" |
| 1112 | + |
| 1113 | + meta = func_metadata(func_with_optional_params) |
| 1114 | + assert meta.arg_model.model_json_schema() == { |
| 1115 | + "properties": { |
| 1116 | + "required": {"description": "This should be required", "title": "Required", "type": "string"}, |
| 1117 | + "optional": { |
| 1118 | + "anyOf": [{"type": "string"}, {"type": "null"}], |
| 1119 | + "default": None, |
| 1120 | + "description": "This should be optional", |
| 1121 | + "title": "Optional", |
| 1122 | + }, |
| 1123 | + "optional_with_default": { |
| 1124 | + "anyOf": [{"type": "string"}, {"type": "null"}], |
| 1125 | + "default": "hello", |
| 1126 | + "description": "This should be optional with default", |
| 1127 | + "title": "Optional With Default", |
| 1128 | + }, |
| 1129 | + "optional_with_union_type": { |
| 1130 | + "anyOf": [{"type": "string"}, {"type": "null"}], |
| 1131 | + "default": None, |
| 1132 | + "description": "This should be optional", |
| 1133 | + "title": "Optional With Union Type", |
| 1134 | + }, |
| 1135 | + "optional_with_union_type_and_default": { |
| 1136 | + "anyOf": [{"type": "string"}, {"type": "null"}], |
| 1137 | + "default": "hello", |
| 1138 | + "description": "This should be optional with default", |
| 1139 | + "title": "Optional With Union Type And Default", |
| 1140 | + }, |
| 1141 | + }, |
| 1142 | + "required": ["required"], |
| 1143 | + "title": "func_with_optional_paramsArguments", |
| 1144 | + "type": "object", |
| 1145 | + } |
0 commit comments