← eval5_submission

fastapi_13207

failed LOOP NO_PATCH LOOP UNSUBMITTED empty_patch(budget) · 23 tool calls · 308 s · fastapi/fastapi

Task input

🐛 Fix OpenAPI schema support for computed fields when using `separate_input_output_schemas=False`

This demonstrates how the output schema differs when the FastAPI app runs with different values for `separate_input_output_schemas` - namely, the computed fields are omitted.

Initially reported here: https://github.com/fastapi/fastapi/discussions/10342

Tool calls (23)

#ToolArgumentsResult
1run_command
{
 "command": "grep -rn \"separate_input_output_schemas\" . | head -20"
}
{"status": "ok", "stdout": "./fastapi/_compat/may_v1.py:65: separate_input_output_schemas: bool = True,\n./fastapi/_compat/v1.py:243: separate_input_output_sche
full
{"status": "ok", "stdout": "./fastapi/_compat/may_v1.py:65:        separate_input_output_schemas: bool = True,\n./fastapi/_compat/v1.py:243:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/v1.py:259:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/main.py:271:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/main.py:284:            separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/_compat/main.py:295:                separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/_compat/main.py:309:            separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/_compat/main.py:322:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/main.py:331:            separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/_compat/main.py:341:            separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/_compat/v2.py:181:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/v2.py:184:        None if separate_input_output_schemas else \"validation\"\n./fastapi/_compat/v2.py:201:    separate_input_output_schemas: bool = True,\n./fastapi/_compat/v2.py:208:        None if separate_input_output_schemas else \"validation\"\n./fastapi/applications.py:791:        separate_input_output_schemas: Annotated[\n./fastapi/applications.py:875:        self.separate_input_output_schemas = separate_input_output_schemas\n./fastapi/applications.py:1078:                separate_input_output_schemas=self.separate_input_output_schemas,\n./fastapi/openapi/utils.py:102:    separate_input_output_schemas: bool = True,\n./fastapi/openapi/utils.py:133:                separate_input_output_schemas=separate_input_output_schemas,\n./fastapi/openapi/utils.py:175:    separate_input_output_schemas: bool = True,\n", "stderr": "grep: ./.git/index: binary file matches\n", "exit_code": 0}
2-4 ×3read_file
{
 "filepath": "fastapi/openapi/utils.py",
 "start_line": "100",
 "end_line": "200"
}
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
full
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
5read_file
{
 "filepath": "fastapi/openapi/utils.py"
}
{"status": "ok", "filepath": "fastapi/openapi/utils.py", "content": "import http.client\nimport inspect\nimport warnings\nfrom typing import Any, Dict, List, Op
full
{"status": "ok", "filepath": "fastapi/openapi/utils.py", "content": "import http.client\nimport inspect\nimport warnings\nfrom typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast\n\nfrom fastapi import routing\nfrom fastapi._compat import (\n    JsonSchemaValue,\n    ModelField,\n    Undefined,\n    get_compat_model_name_map,\n    get_definitions,\n    get_schema_from_model_field,\n    lenient_issubclass,\n)\nfrom fastapi.datastructures import DefaultPlaceholder\nfrom fastapi.dependencies.models import Dependant\nfrom fastapi.dependencies.utils import (\n    _get_flat_fields_from_params,\n    get_flat_dependant,\n    get_flat_params,\n)\nfrom fastapi.encoders import jsonable_encoder\nfrom fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX\nfrom fastapi.openapi.models import OpenAPI\nfrom fastapi.params import Body, ParamTypes\nfrom fastapi.responses import Response\nfrom fastapi.types import ModelNameMap\nfrom fastapi.utils import (\n    deep_dict_update,\n    generate_operation_id_for_path,\n    is_body_allowed_for_status_code,\n)\nfrom pydantic import BaseModel\nfrom starlette.responses import JSONResponse\nfrom starlette.routing import BaseRoute\nfrom typing_extensions import Literal\n\nfrom .._compat import _is_model_field\n\nvalidation_error_definition = {\n    \"title\": \"ValidationError\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"loc\": {\n            \"title\": \"Location\",\n            \"type\": \"array\",\n            \"items\": {\"anyOf\": [{\"type\": \"string\"}, {\"type\": \"integer\"}]},\n        },\n        \"msg\": {\"title\": \"Message\", \"type\": \"string\"},\n        \"type\": {\"title\": \"Error Type\", \"type\": \"string\"},\n    },\n    \"required\": [\"loc\", \"msg\", \"type\"],\n}\n\nvalidation_error_response_definition = {\n    \"title\": \"HTTPValidationError\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"detail\": {\n            \"title\": \"Detail\",\n       
6read_file
{
 "filepath": "fastapi/openapi/utils.py",
 "start_line": "151"
}
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
full
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
7run_command
{
 "command": "grep -n \"separate_input_output_schemas\" fastapi/openapi/utils.py"
}
{"status": "ok", "stdout": "102: separate_input_output_schemas: bool = True,\n133: separate_input_output_schemas=separate_input_output_schemas,\n175: separate_i
full
{"status": "ok", "stdout": "102:    separate_input_output_schemas: bool = True,\n133:                separate_input_output_schemas=separate_input_output_schemas,\n175:    separate_input_output_schemas: bool = True,\n184:        separate_input_output_schemas=separate_input_output_schemas,\n258:    separate_input_output_schemas: bool = True,\n288:                separate_input_output_schemas=separate_input_output_schemas,\n309:                    separate_input_output_schemas=separate_input_output_schemas,\n326:                            separate_input_output_schemas=separate_input_output_schemas,\n356:                            separate_input_output_schemas=separate_input_output_schemas,\n389:                            separate_input_output_schemas=separate_input_output_schemas,\n481:    separate_input_output_schemas: bool = True,\n507:        separate_input_output_schemas=separate_input_output_schemas,\n516:                separate_input_output_schemas=separate_input_output_schemas,\n535:                separate_input_output_schemas=separate_input_output_schemas,\n", "stderr": "", "exit_code": 0}
8read_file
{
 "filepath": "fastapi/openapi/utils.py",
 "start_line": "170",
 "end_line": "210"
}
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
full
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
9run_command
{
 "command": "cat fastapi/openapi/utils.py | sed -n '170,210p'"
}
{"status": "ok", "stdout": " body_field: Optional[ModelField],\n model_name_map: ModelNameMap,\n field_mapping: Dict[\n Tuple[ModelField, Literal[\"validation\"
full
{"status": "ok", "stdout": "    body_field: Optional[ModelField],\n    model_name_map: ModelNameMap,\n    field_mapping: Dict[\n        Tuple[ModelField, Literal[\"validation\", \"serialization\"]], JsonSchemaValue\n    ],\n    separate_input_output_schemas: bool = True,\n) -> Optional[Dict[str, Any]]:\n    if not body_field:\n        return None\n    assert _is_model_field(body_field)\n    body_schema = get_schema_from_model_field(\n        field=body_field,\n        model_name_map=model_name_map,\n        field_mapping=field_mapping,\n        separate_input_output_schemas=separate_input_output_schemas,\n    )\n    field_info = cast(Body, body_field.field_info)\n    request_media_type = field_info.media_type\n    required = body_field.required\n    request_body_oai: Dict[str, Any] = {}\n    if required:\n        request_body_oai[\"required\"] = required\n    request_media_content: Dict[str, Any] = {\"schema\": body_schema}\n    if field_info.openapi_examples:\n        request_media_content[\"examples\"] = jsonable_encoder(\n            field_info.openapi_examples\n        )\n    elif field_info.example != Undefined:\n        request_media_content[\"example\"] = jsonable_encoder(field_info.example)\n    request_body_oai[\"content\"] = {request_media_type: request_media_content}\n    return request_body_oai\n\n\ndef generate_operation_id(\n    *, route: routing.APIRoute, method: str\n) -> str:  # pragma: nocover\n    warnings.warn(\n        \"fastapi.openapi.utils.generate_operation_id() was deprecated, \"\n        \"it is not used internally, and will be removed soon\",\n        DeprecationWarning,\n        stacklevel=2,\n", "stderr": "", "exit_code": 0}
10run_command
{
 "command": "cat fastapi/openapi/utils.py | sed -n '250,300p'"
}
{"status": "ok", "stdout": "def get_openapi_path(\n *,\n route: routing.APIRoute,\n operation_ids: Set[str],\n model_name_map: ModelNameMap,\n field_mapping: Di
full
{"status": "ok", "stdout": "def get_openapi_path(\n    *,\n    route: routing.APIRoute,\n    operation_ids: Set[str],\n    model_name_map: ModelNameMap,\n    field_mapping: Dict[\n        Tuple[ModelField, Literal[\"validation\", \"serialization\"]], JsonSchemaValue\n    ],\n    separate_input_output_schemas: bool = True,\n) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:\n    path = {}\n    security_schemes: Dict[str, Any] = {}\n    definitions: Dict[str, Any] = {}\n    assert route.methods is not None, \"Methods must be a list\"\n    if isinstance(route.response_class, DefaultPlaceholder):\n        current_response_class: Type[Response] = route.response_class.value\n    else:\n        current_response_class = route.response_class\n    assert current_response_class, \"A response class is needed to generate OpenAPI\"\n    route_response_media_type: Optional[str] = current_response_class.media_type\n    if route.include_in_schema:\n        for method in route.methods:\n            operation = get_openapi_operation_metadata(\n                route=route, method=method, operation_ids=operation_ids\n            )\n            parameters: List[Dict[str, Any]] = []\n            flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True)\n            security_definitions, operation_security = get_openapi_security_definitions(\n                flat_dependant=flat_dependant\n            )\n            if operation_security:\n                operation.setdefault(\"security\", []).extend(operation_security)\n            if security_definitions:\n                security_schemes.update(security_definitions)\n            operation_parameters = _get_openapi_operation_parameters(\n                dependant=route.dependant,\n                model_name_map=model_name_map,\n                field_mapping=field_mapping,\n                separate_input_output_schemas=separate_input_output_schemas,\n            )\n            parameters.extend(operation_parameters)\
11run_command
{
 "command": "cat fastapi/openapi/utils.py | sed -n '300,350p'"
}
{"status": "ok", "stdout": " # Make sure required definitions of the same parameter take precedence\n # over non-required definitions\n all_parameters.update(re
full
{"status": "ok", "stdout": "                # Make sure required definitions of the same parameter take precedence\n                # over non-required definitions\n                all_parameters.update(required_parameters)\n                operation[\"parameters\"] = list(all_parameters.values())\n            if method in METHODS_WITH_BODY:\n                request_body_oai = get_openapi_operation_request_body(\n                    body_field=route.body_field,\n                    model_name_map=model_name_map,\n                    field_mapping=field_mapping,\n                    separate_input_output_schemas=separate_input_output_schemas,\n                )\n                if request_body_oai:\n                    operation[\"requestBody\"] = request_body_oai\n            if route.callbacks:\n                callbacks = {}\n                for callback in route.callbacks:\n                    if isinstance(callback, routing.APIRoute):\n                        (\n                            cb_path,\n                            cb_security_schemes,\n                            cb_definitions,\n                        ) = get_openapi_path(\n                            route=callback,\n                            operation_ids=operation_ids,\n                            model_name_map=model_name_map,\n                            field_mapping=field_mapping,\n                            separate_input_output_schemas=separate_input_output_schemas,\n                        )\n                        callbacks[callback.name] = {callback.path: cb_path}\n                operation[\"callbacks\"] = callbacks\n            if route.status_code is not None:\n                status_code = str(route.status_code)\n            else:\n                # It would probably make more sense for all response classes to have an\n                # explicit default status_code, and to extract it from them, instead of\n                # doing this inspection tricks, that would probably be i
12run_command
{
 "command": "cat fastapi/openapi/utils.py | sed -n '350,400p'"
}
{"status": "ok", "stdout": " if lenient_issubclass(current_response_class, JSONResponse):\n if route.response_field:\n response_schema = get_schema_from_model_f
full
{"status": "ok", "stdout": "                if lenient_issubclass(current_response_class, JSONResponse):\n                    if route.response_field:\n                        response_schema = get_schema_from_model_field(\n                            field=route.response_field,\n                            model_name_map=model_name_map,\n                            field_mapping=field_mapping,\n                            separate_input_output_schemas=separate_input_output_schemas,\n                        )\n                    else:\n                        response_schema = {}\n                operation.setdefault(\"responses\", {}).setdefault(\n                    status_code, {}\n                ).setdefault(\"content\", {}).setdefault(route_response_media_type, {})[\n                    \"schema\"\n                ] = response_schema\n            if route.responses:\n                operation_responses = operation.setdefault(\"responses\", {})\n                for (\n                    additional_status_code,\n                    additional_response,\n                ) in route.responses.items():\n                    process_response = additional_response.copy()\n                    process_response.pop(\"model\", None)\n                    status_code_key = str(additional_status_code).upper()\n                    if status_code_key == \"DEFAULT\":\n                        status_code_key = \"default\"\n                    openapi_response = operation_responses.setdefault(\n                        status_code_key, {}\n                    )\n                    assert isinstance(process_response, dict), (\n                        \"An additional response must be a dict\"\n                    )\n                    field = route.response_fields.get(additional_status_code)\n                    additional_field_schema: Optional[Dict[str, Any]] = None\n                    if field:\n                        additional_field_schema = get_schema_from_model_field(\n 
13run_command
{
 "command": "cat fastapi/openapi/utils.py | sed -n '480,540p'"
}
{"status": "ok", "stdout": " license_info: Optional[Dict[str, Union[str, Any]]] = None,\n separate_input_output_schemas: bool = True,\n external_docs: Optional[
full
{"status": "ok", "stdout": "    license_info: Optional[Dict[str, Union[str, Any]]] = None,\n    separate_input_output_schemas: bool = True,\n    external_docs: Optional[Dict[str, Any]] = None,\n) -> Dict[str, Any]:\n    info: Dict[str, Any] = {\"title\": title, \"version\": version}\n    if summary:\n        info[\"summary\"] = summary\n    if description:\n        info[\"description\"] = description\n    if terms_of_service:\n        info[\"termsOfService\"] = terms_of_service\n    if contact:\n        info[\"contact\"] = contact\n    if license_info:\n        info[\"license\"] = license_info\n    output: Dict[str, Any] = {\"openapi\": openapi_version, \"info\": info}\n    if servers:\n        output[\"servers\"] = servers\n    components: Dict[str, Dict[str, Any]] = {}\n    paths: Dict[str, Dict[str, Any]] = {}\n    webhook_paths: Dict[str, Dict[str, Any]] = {}\n    operation_ids: Set[str] = set()\n    all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or []))\n    model_name_map = get_compat_model_name_map(all_fields)\n    field_mapping, definitions = get_definitions(\n        fields=all_fields,\n        model_name_map=model_name_map,\n        separate_input_output_schemas=separate_input_output_schemas,\n    )\n    for route in routes or []:\n        if isinstance(route, routing.APIRoute):\n            result = get_openapi_path(\n                route=route,\n                operation_ids=operation_ids,\n                model_name_map=model_name_map,\n                field_mapping=field_mapping,\n                separate_input_output_schemas=separate_input_output_schemas,\n            )\n            if result:\n                path, security_schemes, path_definitions = result\n                if path:\n                    paths.setdefault(route.path_format, {}).update(path)\n                if security_schemes:\n                    components.setdefault(\"securitySchemes\", {}).update(\n                        security_schemes\n               
14run_command
{
 "command": "grep -rn \"get_definitions\" . | head -20"
}
{"status": "ok", "stdout": "./fastapi/_compat/may_v1.py:61: def get_definitions(\n./fastapi/_compat/may_v1.py:94: from .v1 import get_definitions as get_definit
full
{"status": "ok", "stdout": "./fastapi/_compat/may_v1.py:61:    def get_definitions(\n./fastapi/_compat/may_v1.py:94:    from .v1 import get_definitions as get_definitions\n./fastapi/_compat/__init__.py:21:from .main import get_definitions as get_definitions\n./fastapi/_compat/v1.py:255:def get_definitions(\n./fastapi/_compat/main.py:267:def get_definitions(\n./fastapi/_compat/main.py:281:        v1_field_maps, v1_definitions = may_v1.get_definitions(\n./fastapi/_compat/main.py:292:            v2_field_maps, v2_definitions = v2.get_definitions(\n./fastapi/_compat/main.py:306:        v2_field_maps, v2_definitions = v2.get_definitions(\n./fastapi/_compat/v2.py:197:def get_definitions(\n./fastapi/openapi/utils.py:12:    get_definitions,\n./fastapi/openapi/utils.py:504:    field_mapping, definitions = get_definitions(\n", "stderr": "", "exit_code": 0}
15read_file
{
 "filepath": "fastapi/_compat/v2.py"
}
{"status": "ok", "filepath": "fastapi/_compat/v2.py", "content": "import re\nimport warnings\nfrom copy import copy, deepcopy\nfrom dataclasses import dataclass
full
{"status": "ok", "filepath": "fastapi/_compat/v2.py", "content": "import re\nimport warnings\nfrom copy import copy, deepcopy\nfrom dataclasses import dataclass\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n    cast,\n)\n\nfrom fastapi._compat import may_v1, shared\nfrom fastapi.openapi.constants import REF_TEMPLATE\nfrom fastapi.types import IncEx, ModelNameMap\nfrom pydantic import BaseModel, TypeAdapter, create_model\nfrom pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError\nfrom pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation\nfrom pydantic import ValidationError as ValidationError\nfrom pydantic._internal._schema_generation_shared import (  # type: ignore[attr-defined]\n    GetJsonSchemaHandler as GetJsonSchemaHandler,\n)\nfrom pydantic._internal._typing_extra import eval_type_lenient\nfrom pydantic._internal._utils import lenient_issubclass as lenient_issubclass\nfrom pydantic.fields import FieldInfo as FieldInfo\nfrom pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema\nfrom pydantic.json_schema import JsonSchemaValue as JsonSchemaValue\nfrom pydantic_core import CoreSchema as CoreSchema\nfrom pydantic_core import PydanticUndefined, PydanticUndefinedType\nfrom pydantic_core import Url as Url\nfrom typing_extensions import Annotated, Literal, get_args, get_origin\n\ntry:\n    from pydantic_core.core_schema import (\n        with_info_plain_validator_function as with_info_plain_validator_function,\n    )\nexcept ImportError:  # pragma: no cover\n    from pydantic_core.core_schema import (\n        general_plain_validator_function as with_info_plain_validator_function,  # noqa: F401\n    )\n\nRequiredParam = PydanticUndefined\nUndefined = PydanticUndefined\nUndefinedType = PydanticUndefinedType\nevaluate_forwardref = eval_type_lenient\nValidator = Any\n\n\nclass BaseConfig:\n    pass\n\n\nclass ErrorWr
16run_command
{
 "command": "cat fastapi/_compat/v2.py | sed -n '197,300p'"
}
{"status": "ok", "stdout": "def get_definitions(\n *,\n fields: Sequence[ModelField],\n model_name_map: ModelNameMap,\n separate_input_output_schemas: bool = Tr
full
{"status": "ok", "stdout": "def get_definitions(\n    *,\n    fields: Sequence[ModelField],\n    model_name_map: ModelNameMap,\n    separate_input_output_schemas: bool = True,\n) -> Tuple[\n    Dict[Tuple[ModelField, Literal[\"validation\", \"serialization\"]], JsonSchemaValue],\n    Dict[str, Dict[str, Any]],\n]:\n    schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)\n    override_mode: Union[Literal[\"validation\"], None] = (\n        None if separate_input_output_schemas else \"validation\"\n    )\n    validation_fields = [field for field in fields if field.mode == \"validation\"]\n    serialization_fields = [field for field in fields if field.mode == \"serialization\"]\n    flat_validation_models = get_flat_models_from_fields(\n        validation_fields, known_models=set()\n    )\n    flat_serialization_models = get_flat_models_from_fields(\n        serialization_fields, known_models=set()\n    )\n    flat_validation_model_fields = [\n        ModelField(\n            field_info=FieldInfo(annotation=model),\n            name=model.__name__,\n            mode=\"validation\",\n        )\n        for model in flat_validation_models\n    ]\n    flat_serialization_model_fields = [\n        ModelField(\n            field_info=FieldInfo(annotation=model),\n            name=model.__name__,\n            mode=\"serialization\",\n        )\n        for model in flat_serialization_models\n    ]\n    flat_model_fields = flat_validation_model_fields + flat_serialization_model_fields\n    input_types = {f.type_ for f in fields}\n    unique_flat_model_fields = {\n        f for f in flat_model_fields if f.type_ not in input_types\n    }\n\n    inputs = [\n        (field, override_mode or field.mode, field._type_adapter.core_schema)\n        for field in list(fields) + list(unique_flat_model_fields)\n    ]\n    field_mapping, definitions = schema_generator.generate_definitions(inputs=inputs)\n    for item_def in cast(Dict[str, Dict[str, Any]], definitions).values():
17run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.get(\"/items\", response_model=Item)\ndef read_item():\n    return Item(name=\"Test\", price=10.0)\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    # We need to mock the app's separate_input_output_schemas\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    # Find the Item schema in definitions\n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    item_schema = None\n    for schema in definitions.values():\n        if schema.get(\"title\") == \"Item\":\n            item_schema = schema\n            break\n    \n    if item_schema is None:\n        print(f\"Item schema not found for separate_input_output_schemas={separate_input_output_schemas}\")\n        return False\n    \n    properties = item_schema.get(\"properties\", {})\n    has_total = \"total\" in properties\n    print(f\"separate_input_output_schemas={separate_input_output_schemas}, has_total={has_total}\")\n    return has_total\n\nif __name__ == \"__main__\":\n    res_true = check_computed_field(True)\n    res_false = check_computed_field(False)\n    if res_true and res_false:\n        print(\"SUCCESS\")\n    else:\n        print(\"FAILURE\")\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "ok", "stdout": "separate_input_output_schemas=True, has_total=True\nseparate_input_output_schemas=False, has_total=True\nSUCCESS\n", "stderr": "", "
full
{"status": "ok", "stdout": "separate_input_output_schemas=True, has_total=True\nseparate_input_output_schemas=False, has_total=True\nSUCCESS\n", "stderr": "", "exit_code": 0}
18run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    # When separate_input_output_schemas=True, we expect Item-in and Item-out\n    # When separate_input_output_schemas=False, we expect one Item schema\n    \n    item_schemas = [s for s in definitions.values() if s.get(\"title\") == \"Item\"]\n    \n    for schema in item_schemas:\n        properties = schema.get(\"properties\", {})\n        print(f\"separate_input_output_schemas={separate_input_output_schemas}, title={schema.get('title')}, has_total={'total' in properties}\")\n    \n    return item_schemas\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True, title=Item, has_total=False\nseparate_input_output_s
full
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True, title=Item, has_total=False\nseparate_input_output_schemas=True, title=Item, has_total=True\n\nTesting separate_input_output_schemas=False\nseparate_input_output_schemas=False, title=Item, has_total=False\nseparate_input_output_schemas=False, title=Item, has_total=True\n", "stderr": "", "exit_code": 0}
19run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    # Find the schema used for the request body\n    # /items POST requestBody -> content -> application/json -> schema -> $ref\n    request_body_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]\n    request_schema_name = request_body_ref.split(\"/\")[-1]\n    request_schema = definitions[request_schema_name]\n    \n    # Find the schema used for the response\n    response_body_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]\n    response_schema_name = response_body_ref.split(\"/\")[-1]\n    response_schema = definitions[response_schema_name]\n    \n    print(f\"separate_input_output_schemas={separate_input_output_schemas}\")\n    print(f\"  Request schema: {request_schema_name}, has_total={'total' in request_schema.get('properties', {})}\")\n    print(f\"  Response schema: {response_schema_name}, has_total={'total' in response_schema.get('properties', {})}\")\n    \n    return request_schema_name, response_schema_name\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"/tmp/repro.py\", line 50, in <module>\n check_co
full
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n  File \"/tmp/repro.py\", line 50, in <module>\n    check_computed_field(True)\n    ~~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/tmp/repro.py\", line 33, in check_computed_field\n    request_body_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"\"]\n                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^\nKeyError: ''\n", "details": {"stdout": "Testing separate_input_output_schemas=True\n", "stderr": "Traceback (most recent call last):\n  File \"/tmp/repro.py\", line 50, in <module>\n    check_computed_field(True)\n    ~~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/tmp/repro.py\", line 33, in check_computed_field\n    request_body_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"\"]\n                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^\nKeyError: ''\n", "exit_code": 1}}
20run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    # Find the schema used for the request body\n    request_body = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"requestBody\"]\n    request_schema = request_body[\"content\"][\"application/json\"][\"schema\"]\n    if \"$ref\" in request_schema:\n        request_schema_name = request_schema[\"$ref\"].split(\"/\")[-1]\n        request_schema = definitions[request_schema_name]\n    \n    # Find the schema used for the response\n    response_body = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n    response_schema = response_body[\"schema\"]\n    if \"$ref\" in response_schema:\n        response_schema_name = response_schema[\"$ref\"].split(\"/\")[-1]\n        response_schema = definitions[response_schema_name]\n    \n    print(f\"separate_input_output_schemas={separate_input_output_schemas}\")\n    print(f\"  Request schema has_total={'total' in request_schema.get('properties', {})}\")\n    print(f\"  Response schema has_total={'total' in response_schema.get('properties', {})}\")\n    \n    return request_schema\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n Request schema has_total=False\n Response schema ha
full
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n  Request schema has_total=False\n  Response schema has_total=False\n\nTesting separate_input_output_schemas=False\nseparate_input_output_schemas=False\n  Request schema has_total=False\n  Response schema has_total=False\n", "stderr": "", "exit_code": 0}
21run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    print(f\"separate_input_output_schemas={separate_input_output_schemas}\")\n    for name, schema in definitions.items():\n        print(f\"  Schema {name}: has_total={'total' in schema.get('properties', {})}\")\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n Schema HTTPValidationError: has_total=False\n Schem
full
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n  Schema HTTPValidationError: has_total=False\n  Schema Item-Input: has_total=False\n  Schema Item-Output: has_total=True\n  Schema ValidationError: has_total=False\n\nTesting separate_input_output_schemas=False\nseparate_input_output_schemas=False\n  Schema HTTPValidationError: has_total=False\n  Schema Item-Input: has_total=False\n  Schema Item-Output: has_total=True\n  Schema ValidationError: has_total=False\n", "stderr": "", "exit_code": 0}
22run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    print(f\"separate_input_output_schemas={separate_input_output_schemas}\")\n    for name, schema in definitions.items():\n        print(f\"  Schema {name}: has_total={'total' in schema.get('properties', {})}\")\n    \n    # Check if the response uses the schema with 'total'\n    response_schema_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]\n    print(f\"  Response uses: {response_schema_ref}\")\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"/tmp/repro.py\", line 41, in <module>\n check_co
full
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n  File \"/tmp/repro.py\", line 41, in <module>\n    check_computed_field(True)\n    ~~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/tmp/repro.py\", line 36, in check_computed_field\n    response_schema_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"][\"schema\"][\"\"]\n                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^\nKeyError: ''\n", "details": {"stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n  Schema HTTPValidationError: has_total=False\n  Schema Item-Input: has_total=False\n  Schema Item-Output: has_total=True\n  Schema ValidationError: has_total=False\n", "stderr": "Traceback (most recent call last):\n  File \"/tmp/repro.py\", line 41, in <module>\n    check_computed_field(True)\n    ~~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/tmp/repro.py\", line 36, in check_computed_field\n    response_schema_ref = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"][\"schema\"][\"\"]\n                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^\nKeyError: ''\n", "exit_code": 1}}
23run_command
{
 "command": "cat <<EOF > /tmp/repro.py\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, computed_field\nfrom fastapi.openapi.utils import get_openapi\n\napp = FastAPI()\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.price * 1.1\n\n@app.post(\"/items\", response_model=Item)\ndef create_item(item: Item):\n    return item\n\ndef check_computed_field(separate_input_output_schemas: bool):\n    app.separate_input_output_schemas = separate_input_output_schemas\n    openapi_schema = get_openapi(\n        title=\"Test\",\n        version=\"1.0.0\",\n        routes=app.routes,\n        webhooks=[],\n    )\n    \n    definitions = openapi_schema[\"components\"][\"schemas\"]\n    \n    print(f\"separate_input_output_schemas={separate_input_output_schemas}\")\n    for name, schema in definitions.items():\n        print(f\"  Schema {name}: has_total={'total' in schema.get('properties', {})}\")\n    \n    # Check if the response uses the schema with 'total'\n    response_schema = openapi_schema[\"paths\"][\"/items\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"][\"schema\"]\n    if \"$ref\" in response_schema:\n        print(f\"  Response uses: {response_schema['$ref']}\")\n\nif __name__ == \"__main__\":\n    print(\"Testing separate_input_output_schemas=True\")\n    check_computed_field(True)\n    print(\"\\nTesting separate_input_output_schemas=False\")\n    check_computed_field(False)\nEOF\npython3 /tmp/repro.py\n"
}
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n Schema HTTPValidationError: has_total=False\n Schem
full
{"status": "ok", "stdout": "Testing separate_input_output_schemas=True\nseparate_input_output_schemas=True\n  Schema HTTPValidationError: has_total=False\n  Schema Item-Input: has_total=False\n  Schema Item-Output: has_total=True\n  Schema ValidationError: has_total=False\n\nTesting separate_input_output_schemas=False\nseparate_input_output_schemas=False\n  Schema HTTPValidationError: has_total=False\n  Schema Item-Input: has_total=False\n  Schema Item-Output: has_total=True\n  Schema ValidationError: has_total=False\n", "stderr": "", "exit_code": 0}