Spaces:
Running
Running
Martin Melka commited on
Fix nesting when making OpenAPI arrays and objects optional (#1178)
Browse files
src/fastmcp/utilities/openapi.py
CHANGED
|
@@ -1114,10 +1114,56 @@ def _make_optional_parameter_nullable(schema: dict[str, Any]) -> dict[str, Any]:
|
|
| 1114 |
# Create a new schema that allows null in addition to the original type
|
| 1115 |
if "type" in schema:
|
| 1116 |
original_type = schema["type"]
|
|
|
|
| 1117 |
if isinstance(original_type, str):
|
| 1118 |
# Single type - make it a union with null
|
| 1119 |
nullable_schema = schema.copy()
|
| 1120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1121 |
# Remove the original type since we're using anyOf
|
| 1122 |
del nullable_schema["type"]
|
| 1123 |
return nullable_schema
|
|
|
|
| 1114 |
# Create a new schema that allows null in addition to the original type
|
| 1115 |
if "type" in schema:
|
| 1116 |
original_type = schema["type"]
|
| 1117 |
+
|
| 1118 |
if isinstance(original_type, str):
|
| 1119 |
# Single type - make it a union with null
|
| 1120 |
nullable_schema = schema.copy()
|
| 1121 |
+
|
| 1122 |
+
nested_non_nullable_schema = {
|
| 1123 |
+
"type": original_type,
|
| 1124 |
+
}
|
| 1125 |
+
|
| 1126 |
+
# If the original type is an array, move the array-specific properties into the now-nested schema
|
| 1127 |
+
# https://json-schema.org/understanding-json-schema/reference/array
|
| 1128 |
+
if original_type == "array":
|
| 1129 |
+
for array_property in [
|
| 1130 |
+
"items",
|
| 1131 |
+
"prefixItems",
|
| 1132 |
+
"unevaluatedItems",
|
| 1133 |
+
"contains",
|
| 1134 |
+
"minContains",
|
| 1135 |
+
"maxContains",
|
| 1136 |
+
"minItems",
|
| 1137 |
+
"maxItems",
|
| 1138 |
+
"uniqueItems",
|
| 1139 |
+
]:
|
| 1140 |
+
if array_property in nullable_schema:
|
| 1141 |
+
nested_non_nullable_schema[array_property] = nullable_schema[
|
| 1142 |
+
array_property
|
| 1143 |
+
]
|
| 1144 |
+
del nullable_schema[array_property]
|
| 1145 |
+
|
| 1146 |
+
# If the original type is an object, move the object-specific properties into the now-nested schema
|
| 1147 |
+
# https://json-schema.org/understanding-json-schema/reference/object
|
| 1148 |
+
elif original_type == "object":
|
| 1149 |
+
for object_property in [
|
| 1150 |
+
"properties",
|
| 1151 |
+
"patternProperties",
|
| 1152 |
+
"additionalProperties",
|
| 1153 |
+
"unevaluatedProperties",
|
| 1154 |
+
"required",
|
| 1155 |
+
"propertyNames",
|
| 1156 |
+
"minProperties",
|
| 1157 |
+
"maxProperties",
|
| 1158 |
+
]:
|
| 1159 |
+
if object_property in nullable_schema:
|
| 1160 |
+
nested_non_nullable_schema[object_property] = nullable_schema[
|
| 1161 |
+
object_property
|
| 1162 |
+
]
|
| 1163 |
+
del nullable_schema[object_property]
|
| 1164 |
+
|
| 1165 |
+
nullable_schema["anyOf"] = [nested_non_nullable_schema, {"type": "null"}]
|
| 1166 |
+
|
| 1167 |
# Remove the original type since we're using anyOf
|
| 1168 |
del nullable_schema["type"]
|
| 1169 |
return nullable_schema
|
tests/server/openapi/test_optional_parameters.py
CHANGED
|
@@ -95,8 +95,6 @@ async def test_optional_parameter_allows_null_for_type(param_schema):
|
|
| 95 |
# Should have anyOf with the original type and null
|
| 96 |
assert "anyOf" in optional_param_schema
|
| 97 |
assert {"type": "null"} in optional_param_schema["anyOf"]
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
else:
|
| 102 |
-
assert param_schema in optional_param_schema["anyOf"]
|
|
|
|
| 95 |
# Should have anyOf with the original type and null
|
| 96 |
assert "anyOf" in optional_param_schema
|
| 97 |
assert {"type": "null"} in optional_param_schema["anyOf"]
|
| 98 |
+
|
| 99 |
+
# Check that original schema is fully preserved under anyOf
|
| 100 |
+
assert param_schema in optional_param_schema["anyOf"]
|
|
|
|
|
|