failed CONTEXT UNSUBMITTED agent_error · 50 tool calls · 226 s · fastapi/fastapi
🚸 Improve tracebacks by adding endpoint metadata
Today, when validation errors occur, error messages don't indicate what endpoint caused the problem, which can make debugging difficult.
This PR adds endpoint context metadata to validation error messages to show the filepath (clickable in IDEs!) and line number, function name and HTTP method and route where applicable. The endpoint context is extracted once per endpoint and then cached to avoid any additional performance overhead on subsequent requests. Just to double check, I also ran a rough benchmark (100k requests):
```
Baseline (without changes): 0.0006s
Uncached: 1.3281s (13.28µs per request)
**Cached**: 0.0060s (0.06µs per request)
```
Endpoint context only appears in the exception's string representation (server logs). It is **not** exposed to clients in HTTP responses. Clients still receive the standard 422 response with validation error details.
## Examples
### ResponseValidationError
**Before:**
```
fastapi.exceptions.ResponseValidationError: 1 validation error:
{'type': 'missing', 'loc': ('response', 'id'), 'msg': 'Field required', 'input': {'name': 'Widget'}}
```
**After:**
```
fastapi.exceptions.ResponseValidationError: 1 validation error:
{'type': 'missing', 'loc': ('response', 'id'), 'msg': 'Field required', 'input': {'name': 'Widget'}}
File "/Users/savannah/work/fastapi/capture_real_examples.py", line 43, in create_item
POST /items/
```
### RequestValidationError
**Before:**
```
fastapi.exceptions.RequestValidationError: 1 validation error:
{'type': 'int_parsing', 'loc': ('path', 'user_id'), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'invalid'}
```
**After:**
```
fastapi.exceptions.RequestValidationError: 1 validation error:
{'type': 'int_parsing', 'loc': ('path', 'user_id'), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'invalid'}
File "/Users/savannah/work/fastapi/capture_real_examples.py", line 38, in get_user
GET /users/{user_id}
```
### WebSocketRequestValidationError
**Before:**
```
fastapi.exceptions.WebSocketRequestValidationError: 1 validation error:
{'type': 'int_parsing', 'loc': ('path', 'item_id'), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'invalid'}
```
**After:**
```
fastapi.exceptions.WebSocketRequestValidationError: 1 validation error:
{'type': 'int_parsing', 'loc': ('path', 'item_id'), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'invalid'}
File "/Users/savannah/work/fastapi/capture_real_examples.py", line 48, in websocket_endpoint
WS /ws/{item_id}
```| # | Tool | Arguments | Result |
|---|---|---|---|
| 1 | run_command | {
"command": "grep -rn \"RequestValidationError\" fastapi/exceptions.py"
} | {"status": "ok", "stdout": "fastapi/exceptions.py:165:class RequestValidationError(ValidationException):\nfastapi/exceptions.py:171:class WebSocketRequestValidafull{"status": "ok", "stdout": "fastapi/exceptions.py:165:class RequestValidationError(ValidationException):\nfastapi/exceptions.py:171:class WebSocketRequestValidationError(ValidationException):\n", "stderr": "", "exit_code": 0} |
| 2 | run_command | {
"command": "grep -rn \"ResponseValidationError\" fastapi/exceptions.py"
} | {"status": "ok", "stdout": "fastapi/exceptions.py:175:class ResponseValidationError(ValidationException):\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "fastapi/exceptions.py:175:class ResponseValidationError(ValidationException):\n", "stderr": "", "exit_code": 0} |
| 3 | run_command | {
"command": "sed -n '150,185p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": "class DependencyScopeError(FastAPIError):\n \"\"\"\n A dependency declared that it depends on another dependency with an invalid\n (full{"status": "ok", "stdout": "class DependencyScopeError(FastAPIError):\n \"\"\"\n A dependency declared that it depends on another dependency with an invalid\n (narrower) scope.\n \"\"\"\n\n\nclass ValidationException(Exception):\n def __init__(self, errors: Sequence[Any]) -> None:\n self._errors = errors\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n\nclass RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n\nclass WebSocketRequestValidationError(ValidationException):\n pass\n\n\nclass ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\n", "stderr": "", "exit_code": 0} |
| 4 | run_command | {
"command": "grep -rn \"RequestValidationError\" fastapi/ | grep -v \"exceptions.py\" | head -20"
} | {"status": "ok", "stdout": "fastapi/exception_handlers.py:2:from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError\nfastapi/excefull{"status": "ok", "stdout": "fastapi/exception_handlers.py:2:from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError\nfastapi/exception_handlers.py:21: request: Request, exc: RequestValidationError\nfastapi/exception_handlers.py:30: websocket: WebSocket, exc: WebSocketRequestValidationError\nfastapi/applications.py:24:from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError\nfastapi/applications.py:988: RequestValidationError, request_validation_exception_handler\nfastapi/applications.py:991: WebSocketRequestValidationError,\nfastapi/routing.py:50: RequestValidationError,\nfastapi/routing.py:52: WebSocketRequestValidationError,\nfastapi/routing.py:347: validation_error = RequestValidationError(\nfastapi/routing.py:423: validation_error = RequestValidationError(\nfastapi/routing.py:453: raise WebSocketRequestValidationError(\n", "stderr": "", "exit_code": 0} |
| 5 | run_command | {
"command": "sed -n '330,360p' fastapi/routing.py"
} | {"status": "ok", "stdout": " if body_bytes:\n json_body: Any = Undefined\n content_type_value = request.headers.get(\"content-type\")\n if not content_type_valufull{"status": "ok", "stdout": " if body_bytes:\n json_body: Any = Undefined\n content_type_value = request.headers.get(\"content-type\")\n if not content_type_value:\n json_body = await request.json()\n else:\n message = email.message.Message()\n message[\"content-type\"] = content_type_value\n if message.get_content_maintype() == \"application\":\n subtype = message.get_content_subtype()\n if subtype == \"json\" or subtype.endswith(\"+json\"):\n json_body = await request.json()\n if json_body != Undefined:\n body = json_body\n else:\n body = body_bytes\n except json.JSONDecodeError as e:\n validation_error = RequestValidationError(\n [\n {\n \"type\": \"json_invalid\",\n \"loc\": (\"body\", e.pos),\n \"msg\": \"JSON decode error\",\n \"input\": {},\n \"ctx\": {\"error\": e.msg},\n }\n ],\n body=e.doc,\n )\n raise validation_error from e\n except HTTPException:\n", "stderr": "", "exit_code": 0} |
| 6 | run_command | {
"command": "sed -n '340,430p' fastapi/routing.py"
} | {"status": "ok", "stdout": " if subtype == \"json\" or subtype.endswith(\"+json\"):\n json_body = await request.json()\n if json_body != Undefined:\n body = jsofull{"status": "ok", "stdout": " if subtype == \"json\" or subtype.endswith(\"+json\"):\n json_body = await request.json()\n if json_body != Undefined:\n body = json_body\n else:\n body = body_bytes\n except json.JSONDecodeError as e:\n validation_error = RequestValidationError(\n [\n {\n \"type\": \"json_invalid\",\n \"loc\": (\"body\", e.pos),\n \"msg\": \"JSON decode error\",\n \"input\": {},\n \"ctx\": {\"error\": e.msg},\n }\n ],\n body=e.doc,\n )\n raise validation_error from e\n except HTTPException:\n # If a middleware raises an HTTPException, it should be raised again\n raise\n except Exception as e:\n http_error = HTTPException(\n status_code=400, detail=\"There was an error parsing the body\"\n )\n raise http_error from e\n\n # Solve dependencies and run path operation function, auto-closing dependencies\n errors: List[Any] = []\n async_exit_stack = request.scope.get(\"fastapi_inner_astack\")\n assert isinstance(async_exit_stack, AsyncExitStack), (\n \"fastapi_inner_astack not found in request scope\"\n )\n solved_result = await solve_dependencies(\n request=request,\n dependant=dependant,\n body=body,\n dependency_overrides_provider=dependency_overrides_provider,\n async_exit_stack=async_exit_stack,\n embed_body_fields=embed_body_fields,\n )\n errors = solved_result.errors\n if not errors:\n raw_response = await run_endpoint_functi |
| 7 | run_command | {
"command": "grep -rn \"ResponseValidationError\" fastapi/routing.py"
} | {"status": "ok", "stdout": "fastapi/routing.py:51: ResponseValidationError,\nfastapi/routing.py:248: raise ResponseValidationError(\n", "stderr": "", "exit_codefull{"status": "ok", "stdout": "fastapi/routing.py:51: ResponseValidationError,\nfastapi/routing.py:248: raise ResponseValidationError(\n", "stderr": "", "exit_code": 0} |
| 8 | run_command | {
"command": "sed -n '230,260p' fastapi/routing.py"
} | {"status": "ok", "stdout": " # pydantic v1\n response_content = _prepare_response_content(\n response_content,\n exclude_unset=exclude_unset,\n exclude_defaultsfull{"status": "ok", "stdout": " # pydantic v1\n response_content = _prepare_response_content(\n response_content,\n exclude_unset=exclude_unset,\n exclude_defaults=exclude_defaults,\n exclude_none=exclude_none,\n )\n if is_coroutine:\n value, errors_ = field.validate(response_content, {}, loc=(\"response\",))\n else:\n value, errors_ = await run_in_threadpool(\n field.validate, response_content, {}, loc=(\"response\",)\n )\n if isinstance(errors_, list):\n errors.extend(errors_)\n elif errors_:\n errors.append(errors_)\n if errors:\n raise ResponseValidationError(\n errors=_normalize_errors(errors), body=response_content\n )\n\n if hasattr(field, \"serialize\"):\n return field.serialize(\n value,\n include=include,\n exclude=exclude,\n by_alias=by_alias,\n exclude_unset=exclude_unset,\n exclude_defaults=exclude_defaults,\n exclude_none=exclude_none,\n", "stderr": "", "exit_code": 0} |
| 9 | run_command | {
"command": "sed -n '440,460p' fastapi/routing.py"
} | {"status": "ok", "stdout": " async def app(websocket: WebSocket) -> None:\n async_exit_stack = websocket.scope.get(\"fastapi_inner_astack\")\n assert isinstancefull{"status": "ok", "stdout": " async def app(websocket: WebSocket) -> None:\n async_exit_stack = websocket.scope.get(\"fastapi_inner_astack\")\n assert isinstance(async_exit_stack, AsyncExitStack), (\n \"fastapi_inner_astack not found in request scope\"\n )\n solved_result = await solve_dependencies(\n request=websocket,\n dependant=dependant,\n dependency_overrides_provider=dependency_overrides_provider,\n async_exit_stack=async_exit_stack,\n embed_body_fields=embed_body_fields,\n )\n if solved_result.errors:\n raise WebSocketRequestValidationError(\n _normalize_errors(solved_result.errors)\n )\n assert dependant.call is not None, \"dependant.call must be a function\"\n await dependant.call(**solved_result.values)\n\n return app\n\n", "stderr": "", "exit_code": 0} |
| 10 | run_command | {
"command": "grep -rn \"dependant\" fastapi/routing.py | head -20"
} | {"status": "ok", "stdout": "fastapi/routing.py:41: get_dependant,\nfastapi/routing.py:42: get_flat_dependant,\nfastapi/routing.py:43: get_parameterless_sub_depefull{"status": "ok", "stdout": "fastapi/routing.py:41: get_dependant,\nfastapi/routing.py:42: get_flat_dependant,\nfastapi/routing.py:43: get_parameterless_sub_dependant,\nfastapi/routing.py:277: *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool\nfastapi/routing.py:281: assert dependant.call is not None, \"dependant.call must be a function\"\nfastapi/routing.py:284: return await dependant.call(**values)\nfastapi/routing.py:286: return await run_in_threadpool(dependant.call, **values)\nfastapi/routing.py:290: dependant: Dependant,\nfastapi/routing.py:304: assert dependant.call is not None, \"dependant.call must be a function\"\nfastapi/routing.py:305: is_coroutine = dependant.is_coroutine_callable\nfastapi/routing.py:377: dependant=dependant,\nfastapi/routing.py:386: dependant=dependant,\nfastapi/routing.py:436: dependant: Dependant,\nfastapi/routing.py:447: dependant=dependant,\nfastapi/routing.py:456: assert dependant.call is not None, \"dependant.call must be a function\"\nfastapi/routing.py:457: await dependant.call(**solved_result.values)\nfastapi/routing.py:477: self.dependant = get_dependant(\nfastapi/routing.py:481: self.dependant.dependencies.insert(\nfastapi/routing.py:483: get_parameterless_sub_dependant(depends=depends, path=self.path_format),\nfastapi/routing.py:485: self._flat_dependant = get_flat_dependant(self.dependant)\n", "stderr": "", "exit_code": 0} |
| 11 | run_command | {
"command": "grep -rn \"class Dependant\" fastapi/ | head -20"
} | {"status": "ok", "stdout": "fastapi/dependencies/models.py:32:class Dependant:\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "fastapi/dependencies/models.py:32:class Dependant:\n", "stderr": "", "exit_code": 0} |
| 12 | run_command | {
"command": "sed -n '30,60p' fastapi/dependencies/models.py"
} | {"status": "ok", "stdout": "\n@dataclass\nclass Dependant:\n path_params: List[ModelField] = field(default_factory=list)\n query_params: List[ModelField] = fielfull{"status": "ok", "stdout": "\n@dataclass\nclass Dependant:\n path_params: List[ModelField] = field(default_factory=list)\n query_params: List[ModelField] = field(default_factory=list)\n header_params: List[ModelField] = field(default_factory=list)\n cookie_params: List[ModelField] = field(default_factory=list)\n body_params: List[ModelField] = field(default_factory=list)\n dependencies: List[\"Dependant\"] = field(default_factory=list)\n name: Optional[str] = None\n call: Optional[Callable[..., Any]] = None\n request_param_name: Optional[str] = None\n websocket_param_name: Optional[str] = None\n http_connection_param_name: Optional[str] = None\n response_param_name: Optional[str] = None\n background_tasks_param_name: Optional[str] = None\n security_scopes_param_name: Optional[str] = None\n own_oauth_scopes: Optional[List[str]] = None\n parent_oauth_scopes: Optional[List[str]] = None\n use_cache: bool = True\n path: Optional[str] = None\n scope: Union[Literal[\"function\", \"request\"], None] = None\n\n @cached_property\n def oauth_scopes(self) -> List[str]:\n scopes = self.parent_oauth_scopes.copy() if self.parent_oauth_scopes else []\n # This doesn't use a set to preserve order, just in case\n for scope in self.own_oauth_scopes or []:\n if scope not in scopes:\n scopes.append(scope)\n return scopes\n", "stderr": "", "exit_code": 0} |
| 13 | run_command | {
"command": "grep -rn \"class APIRoute\" fastapi/ | head -20"
} | {"status": "ok", "stdout": "fastapi/routing.py:504:class APIRoute(routing.Route):\nfastapi/routing.py:673:class APIRouter(routing.Router):\n", "stderr": "", "exfull{"status": "ok", "stdout": "fastapi/routing.py:504:class APIRoute(routing.Route):\nfastapi/routing.py:673:class APIRouter(routing.Router):\n", "stderr": "", "exit_code": 0} |
| 14 | run_command | {
"command": "sed -n '500,550p' fastapi/routing.py"
} | {"status": "ok", "stdout": " child_scope[\"route\"] = self\n return match, child_scope\n\n\nclass APIRoute(routing.Route):\n def __init__(\n self,\n path: str,\full{"status": "ok", "stdout": " child_scope[\"route\"] = self\n return match, child_scope\n\n\nclass APIRoute(routing.Route):\n def __init__(\n self,\n path: str,\n endpoint: Callable[..., Any],\n *,\n response_model: Any = Default(None),\n status_code: Optional[int] = None,\n tags: Optional[List[Union[str, Enum]]] = None,\n dependencies: Optional[Sequence[params.Depends]] = None,\n summary: Optional[str] = None,\n description: Optional[str] = None,\n response_description: str = \"Successful Response\",\n responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,\n deprecated: Optional[bool] = None,\n name: Optional[str] = None,\n methods: Optional[Union[Set[str], List[str]]] = None,\n operation_id: Optional[str] = None,\n response_model_include: Optional[IncEx] = None,\n response_model_exclude: Optional[IncEx] = None,\n response_model_by_alias: bool = True,\n response_model_exclude_unset: bool = False,\n response_model_exclude_defaults: bool = False,\n response_model_exclude_none: bool = False,\n include_in_schema: bool = True,\n response_class: Union[Type[Response], DefaultPlaceholder] = Default(\n JSONResponse\n ),\n dependency_overrides_provider: Optional[Any] = None,\n callbacks: Optional[List[BaseRoute]] = None,\n openapi_extra: Optional[Dict[str, Any]] = None,\n generate_unique_id_function: Union[\n Callable[[\"APIRoute\"], str], DefaultPlaceholder\n ] = Default(generate_unique_id),\n ) -> None:\n self.path = path\n self.endpoint = endpoint\n if isinstance(response_model, DefaultPlaceholder):\n return_annotation = get_typed_return_annotation(endpoint)\n if lenient_issubclass(return_annotation, Response):\n response_model = None\n else: |
| 15 | run_command | {
"command": "sed -n '550,600p' fastapi/routing.py"
} | {"status": "ok", "stdout": " self.deprecated = deprecated\n self.operation_id = operation_id\n self.response_model_include = response_model_include\n self.respofull{"status": "ok", "stdout": " self.deprecated = deprecated\n self.operation_id = operation_id\n self.response_model_include = response_model_include\n self.response_model_exclude = response_model_exclude\n self.response_model_by_alias = response_model_by_alias\n self.response_model_exclude_unset = response_model_exclude_unset\n self.response_model_exclude_defaults = response_model_exclude_defaults\n self.response_model_exclude_none = response_model_exclude_none\n self.include_in_schema = include_in_schema\n self.response_class = response_class\n self.dependency_overrides_provider = dependency_overrides_provider\n self.callbacks = callbacks\n self.openapi_extra = openapi_extra\n self.generate_unique_id_function = generate_unique_id_function\n self.tags = tags or []\n self.responses = responses or {}\n self.name = get_name(endpoint) if name is None else name\n self.path_regex, self.path_format, self.param_convertors = compile_path(path)\n if methods is None:\n methods = [\"GET\"]\n self.methods: Set[str] = {method.upper() for method in methods}\n if isinstance(generate_unique_id_function, DefaultPlaceholder):\n current_generate_unique_id: Callable[[APIRoute], str] = (\n generate_unique_id_function.value\n )\n else:\n current_generate_unique_id = generate_unique_id_function\n self.unique_id = self.operation_id or current_generate_unique_id(self)\n # normalize enums e.g. http.HTTPStatus\n if isinstance(status_code, IntEnum):\n status_code = int(status_code)\n self.status_code = status_code\n if self.response_model:\n assert is_body_allowed_for_status_code(status_code), (\n f\"Status code {status_code} must not have a response body\"\n )\n response_name = \"Response_\" + |
| 16 | run_command | {
"command": "sed -n '600,650p' fastapi/routing.py"
} | {"status": "ok", "stdout": " self.secure_cloned_response_field: Optional[ModelField] = (\n create_cloned_field(self.response_field)\n )\n else:\n self.response_full{"status": "ok", "stdout": " self.secure_cloned_response_field: Optional[ModelField] = (\n create_cloned_field(self.response_field)\n )\n else:\n self.response_field = None # type: ignore\n self.secure_cloned_response_field = None\n self.dependencies = list(dependencies or [])\n self.description = description or inspect.cleandoc(self.endpoint.__doc__ or \"\")\n # if a \"form feed\" character (page break) is found in the description text,\n # truncate description text to the content preceding the first \"form feed\"\n self.description = self.description.split(\"\\f\")[0].strip()\n response_fields = {}\n for additional_status_code, response in self.responses.items():\n assert isinstance(response, dict), \"An additional response must be a dict\"\n model = response.get(\"model\")\n if model:\n assert is_body_allowed_for_status_code(additional_status_code), (\n f\"Status code {additional_status_code} must not have a response body\"\n )\n response_name = f\"Response_{additional_status_code}_{self.unique_id}\"\n response_field = create_model_field(\n name=response_name, type_=model, mode=\"serialization\"\n )\n response_fields[additional_status_code] = response_field\n if response_fields:\n self.response_fields: Dict[Union[int, str], ModelField] = response_fields\n else:\n self.response_fields = {}\n\n assert callable(endpoint), \"An endpoint must be a callable\"\n self.dependant = get_dependant(\n path=self.path_format, call=self.endpoint, scope=\"function\"\n )\n for depends in self.dependencies[::-1]:\n self.dependant.dependencies.insert(\n 0,\n get_parameterless_sub_dependant(depends |
| 17 | run_command | {
"command": "grep -rn \"get_request_handler\" fastapi/ | head -20"
} | {"status": "ok", "stdout": "fastapi/routing.py:279: # Only called by get_request_handler. Has been split into its own function to\nfastapi/routing.py:289:def gefull{"status": "ok", "stdout": "fastapi/routing.py:279: # Only called by get_request_handler. Has been split into its own function to\nfastapi/routing.py:289:def get_request_handler(\nfastapi/routing.py:650: return get_request_handler(\n", "stderr": "", "exit_code": 0} |
| 18 | run_command | {
"command": "sed -n '289,330p' fastapi/routing.py"
} | {"status": "ok", "stdout": "def get_request_handler(\n dependant: Dependant,\n body_field: Optional[ModelField] = None,\n status_code: Optional[int] = None,\n rfull{"status": "ok", "stdout": "def get_request_handler(\n dependant: Dependant,\n body_field: Optional[ModelField] = None,\n status_code: Optional[int] = None,\n response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),\n response_field: Optional[ModelField] = None,\n response_model_include: Optional[IncEx] = None,\n response_model_exclude: Optional[IncEx] = None,\n response_model_by_alias: bool = True,\n response_model_exclude_unset: bool = False,\n response_model_exclude_defaults: bool = False,\n response_model_exclude_none: bool = False,\n dependency_overrides_provider: Optional[Any] = None,\n embed_body_fields: bool = False,\n) -> Callable[[Request], Coroutine[Any, Any, Response]]:\n assert dependant.call is not None, \"dependant.call must be a function\"\n is_coroutine = dependant.is_coroutine_callable\n is_body_form = body_field and isinstance(\n body_field.field_info, (params.Form, temp_pydantic_v1_params.Form)\n )\n if isinstance(response_class, DefaultPlaceholder):\n actual_response_class: Type[Response] = response_class.value\n else:\n actual_response_class = response_class\n\n async def app(request: Request) -> Response:\n response: Union[Response, None] = None\n file_stack = request.scope.get(\"fastapi_middleware_astack\")\n assert isinstance(file_stack, AsyncExitStack), (\n \"fastapi_middleware_astack not found in request scope\"\n )\n\n # Read body and auto-close files\n try:\n body: Any = None\n if body_field:\n if is_body_form:\n body = await request.form()\n file_stack.push_async_callback(body.close)\n else:\n body_bytes = await request.body()\n if body_bytes:\n", "stderr": "", "exit_code": 0} |
| 19 | run_command | {
"command": "sed -n '330,410p' fastapi/routing.py"
} | {"status": "ok", "stdout": " if body_bytes:\n json_body: Any = Undefined\n content_type_value = request.headers.get(\"content-type\")\n if not content_type_valufull{"status": "ok", "stdout": " if body_bytes:\n json_body: Any = Undefined\n content_type_value = request.headers.get(\"content-type\")\n if not content_type_value:\n json_body = await request.json()\n else:\n message = email.message.Message()\n message[\"content-type\"] = content_type_value\n if message.get_content_maintype() == \"application\":\n subtype = message.get_content_subtype()\n if subtype == \"json\" or subtype.endswith(\"+json\"):\n json_body = await request.json()\n if json_body != Undefined:\n body = json_body\n else:\n body = body_bytes\n except json.JSONDecodeError as e:\n validation_error = RequestValidationError(\n [\n {\n \"type\": \"json_invalid\",\n \"loc\": (\"body\", e.pos),\n \"msg\": \"JSON decode error\",\n \"input\": {},\n \"ctx\": {\"error\": e.msg},\n }\n ],\n body=e.doc,\n )\n raise validation_error from e\n except HTTPException:\n # If a middleware raises an HTTPException, it should be raised again\n raise\n except Exception as e:\n http_error = HTTPException(\n status_code=400, detail=\"There was an error parsing the body\"\n )\n raise http_error from e\n\n # Solve dependencies and run path operation function, auto-closing dependencies\n errors: List[Any] = []\n async_exit_stack = request.sc |
| 20 | run_command | {
"command": "sed -n '410,440p' fastapi/routing.py"
} | {"status": "ok", "stdout": " include=response_model_include,\n exclude=response_model_exclude,\n by_alias=response_model_by_alias,\n exclude_unset=response_modefull{"status": "ok", "stdout": " include=response_model_include,\n exclude=response_model_exclude,\n by_alias=response_model_by_alias,\n exclude_unset=response_model_exclude_unset,\n exclude_defaults=response_model_exclude_defaults,\n exclude_none=response_model_exclude_none,\n is_coroutine=is_coroutine,\n )\n response = actual_response_class(content, **response_args)\n if not is_body_allowed_for_status_code(response.status_code):\n response.body = b\"\"\n response.headers.raw.extend(solved_result.response.headers.raw)\n if errors:\n validation_error = RequestValidationError(\n _normalize_errors(errors), body=body\n )\n raise validation_error\n\n # Return response\n assert response\n return response\n\n return app\n\n\ndef get_websocket_app(\n dependant: Dependant,\n dependency_overrides_provider: Optional[Any] = None,\n embed_body_fields: bool = False,\n) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:\n async def app(websocket: WebSocket) -> None:\n", "stderr": "", "exit_code": 0} |
| 21 | run_command | {
"command": "sed -n '440,470p' fastapi/routing.py"
} | {"status": "ok", "stdout": " async def app(websocket: WebSocket) -> None:\n async_exit_stack = websocket.scope.get(\"fastapi_inner_astack\")\n assert isinstancefull{"status": "ok", "stdout": " async def app(websocket: WebSocket) -> None:\n async_exit_stack = websocket.scope.get(\"fastapi_inner_astack\")\n assert isinstance(async_exit_stack, AsyncExitStack), (\n \"fastapi_inner_astack not found in request scope\"\n )\n solved_result = await solve_dependencies(\n request=websocket,\n dependant=dependant,\n dependency_overrides_provider=dependency_overrides_provider,\n async_exit_stack=async_exit_stack,\n embed_body_fields=embed_body_fields,\n )\n if solved_result.errors:\n raise WebSocketRequestValidationError(\n _normalize_errors(solved_result.errors)\n )\n assert dependant.call is not None, \"dependant.call must be a function\"\n await dependant.call(**solved_result.values)\n\n return app\n\n\nclass APIWebSocketRoute(routing.WebSocketRoute):\n def __init__(\n self,\n path: str,\n endpoint: Callable[..., Any],\n *,\n name: Optional[str] = None,\n dependencies: Optional[Sequence[params.Depends]] = None,\n dependency_overrides_provider: Optional[Any] = None,\n", "stderr": "", "exit_code": 0} |
| 22 | run_command | {
"command": "sed -n '240,260p' fastapi/routing.py"
} | {"status": "ok", "stdout": " value, errors_ = await run_in_threadpool(\n field.validate, response_content, {}, loc=(\"response\",)\n )\n if isinstance(errors_, full{"status": "ok", "stdout": " value, errors_ = await run_in_threadpool(\n field.validate, response_content, {}, loc=(\"response\",)\n )\n if isinstance(errors_, list):\n errors.extend(errors_)\n elif errors_:\n errors.append(errors_)\n if errors:\n raise ResponseValidationError(\n errors=_normalize_errors(errors), body=response_content\n )\n\n if hasattr(field, \"serialize\"):\n return field.serialize(\n value,\n include=include,\n exclude=exclude,\n by_alias=by_alias,\n exclude_unset=exclude_unset,\n exclude_defaults=exclude_defaults,\n exclude_none=exclude_none,\n", "stderr": "", "exit_code": 0} |
| 23 | run_command | {
"command": "sed -n '160,180p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": "\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n\nclass RequestValidationError(ValidationException):\n def __init__(sfull{"status": "ok", "stdout": "\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n\nclass RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n\nclass WebSocketRequestValidationError(ValidationException):\n pass\n\n\nclass ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n def __str__(self) -> str:\n", "stderr": "", "exit_code": 0} |
| 24 | run_command | {
"command": "sed -n '180,200p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": " def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {efull{"status": "ok", "stdout": " def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\n", "stderr": "", "exit_code": 0} |
| 25 | run_command | {
"command": "grep -rn \"import inspect\" fastapi/ | head -20"
} | {"status": "ok", "stdout": "fastapi/dependencies/models.py:1:import inspect\nfastapi/dependencies/utils.py:2:import inspect\nfastapi/openapi/utils.py:2:import ifull{"status": "ok", "stdout": "fastapi/dependencies/models.py:1:import inspect\nfastapi/dependencies/utils.py:2:import inspect\nfastapi/openapi/utils.py:2:import inspect\nfastapi/routing.py:4:import inspect\n", "stderr": "", "exit_code": 0} |
| 26 | run_command | {
"command": "grep -rn \"from functools import cached_property\" fastapi/ | head -20"
} | {"status": "ok", "stdout": "fastapi/dependencies/models.py:4:from functools import cached_property, partial\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "fastapi/dependencies/models.py:4:from functools import cached_property, partial\n", "stderr": "", "exit_code": 0} |
| 27 | run_command | {
"command": "sed -n '1,10p' fastapi/dependencies/models.py"
} | {"status": "ok", "stdout": "import inspect\nimport sys\nfrom dataclasses import dataclass, field\nfrom functools import cached_property, partial\nfrom typing imfull{"status": "ok", "stdout": "import inspect\nimport sys\nfrom dataclasses import dataclass, field\nfrom functools import cached_property, partial\nfrom typing import Any, Callable, List, Optional, Union\n\nfrom fastapi._compat import ModelField\nfrom fastapi.security.base import SecurityBase\nfrom fastapi.types import DependencyCacheKey\nfrom typing_extensions import Literal\n", "stderr": "", "exit_code": 0} |
| 28 | run_command | {
"command": "sed -n '1,10p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": "from typing import Any, Dict, Optional, Sequence, Type, Union\n\nfrom annotated_doc import Doc\nfrom pydantic import BaseModel, creafull{"status": "ok", "stdout": "from typing import Any, Dict, Optional, Sequence, Type, Union\n\nfrom annotated_doc import Doc\nfrom pydantic import BaseModel, create_model\nfrom starlette.exceptions import HTTPException as StarletteHTTPException\nfrom starlette.exceptions import WebSocketException as StarletteWebSocketException\nfrom typing_extensions import Annotated\n\n\nclass HTTPException(StarletteHTTPException):\n", "stderr": "", "exit_code": 0} |
| 29 | run_command | {
"command": "sed -n '1,10p' fastapi/routing.py"
} | {"status": "ok", "stdout": "import dataclasses\nimport email.message\nimport functools\nimport inspect\nimport json\nfrom contextlib import AsyncExitStack, asynfull{"status": "ok", "stdout": "import dataclasses\nimport email.message\nimport functools\nimport inspect\nimport json\nfrom contextlib import AsyncExitStack, asynccontextmanager\nfrom enum import Enum, IntEnum\nfrom typing import (\n Any,\n AsyncIterator,\n", "stderr": "", "exit_code": 0} |
| 30 | run_command | {
"command": "sed -n '10,20p' fastapi/routing.py"
} | {"status": "ok", "stdout": " AsyncIterator,\n Awaitable,\n Callable,\n Collection,\n Coroutine,\n Dict,\n List,\n Mapping,\n Optional,\n Sequence,\n Set,\n", "sfull{"status": "ok", "stdout": " AsyncIterator,\n Awaitable,\n Callable,\n Collection,\n Coroutine,\n Dict,\n List,\n Mapping,\n Optional,\n Sequence,\n Set,\n", "stderr": "", "exit_code": 0} |
| 31 | run_command | {
"command": "sed -n '20,30p' fastapi/routing.py"
} | {"status": "ok", "stdout": " Set,\n Tuple,\n Type,\n Union,\n)\n\nfrom annotated_doc import Doc\nfrom fastapi import params, temp_pydantic_v1_params\nfrom fastafull{"status": "ok", "stdout": " Set,\n Tuple,\n Type,\n Union,\n)\n\nfrom annotated_doc import Doc\nfrom fastapi import params, temp_pydantic_v1_params\nfrom fastapi._compat import (\n ModelField,\n Undefined,\n", "stderr": "", "exit_code": 0} |
| 32 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\nold = \"\"\"class ValidationException(Exception):\n def __init__(self, errors: Sequence[Any]) -> None:\n self._errors = errors\n\n def errors(self) -> Sequence[Any]:\n return self._errors\"\"\"\nnew = \"\"\"class ValidationException(Exception):\n def __init__(self, errors: Sequence[Any]) -> None:\n self._errors = errors\n self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\"\"\"\nassert s.count(old) == 1, (\"old text found this many times:\", s.count(old))\nt = s.replace(old, new)\np.write_text(t)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 33 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\nold = \"\"\"class RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\"\"\"\nnew = \"\"\"class RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\"\"\"\n# No change needed here, but I'll check if I should add something.\n# Wait, I need to implement __str__ for RequestValidationError and WebSocketRequestValidationError too.\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 34 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\n\n# Add __str__ to RequestValidationError\n# Add __str__ to WebSocketRequestValidationError\n# Update ResponseValidationError.__str__\n\n# Let's do it in one go or separate.\n\n# Current ResponseValidationError.__str__:\n# def __str__(self) -> str:\n# message = f\"{len(self._errors)} validation errors:\\n\"\n# for err in self._errors:\n# message += f\" {err}\\n\"\n# return message\n\n# New __str__ for all of them:\n# def __str__(self) -> str:\n# message = f\"{len(self._errors)} validation errors:\\n\"\n# for err in self._errors:\n# message += f\" {err}\\n\"\n# if self.endpoint_context:\n# message += f\"\\n{self.endpoint_context}\"\n# return message\n\n# I'll implement this in ValidationException to avoid repetition.\n\n# Wait, ValidationException is just a base class.\n# Let's see if I can add __str__ to ValidationException.\n\n# Let's check if other exceptions use ValidationException.\n# RequestValidationError, WebSocketRequestValidationError, ResponseValidationError all inherit from it.\n\n# Let's try adding __str__ to ValidationException.\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 35 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\n\n# Remove ResponseValidationError.__str__ and add it to ValidationException\nold_response_str = \"\"\" def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\"\"\"\n\n# We need to find where it is in ResponseValidationError.\n# It's at the end of the file.\n\n# Let's just replace the whole ResponseValidationError class or just the __str__ method.\n\n# Actually, let's add __str__ to ValidationException and remove it from ResponseValidationError.\n\n# Find ValidationException and add __str__\n# Find ResponseValidationError and remove __str__\n\n# Let's do it carefully.\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 36 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\n\n# Add __str__ to ValidationException\nold_val_exc = \"\"\"class ValidationException(Exception):\n def __init__(self, errors: Sequence[Any]) -> None:\n self._errors = errors\n self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\"\"\"\n\nnew_val_exc = \"\"\"class ValidationException(Exception):\n def __init__(self, errors: Sequence[Any]) -> None:\n self._errors = errors\n self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\\\n\"\n for err in self._errors:\n message += f\" {err}\\\\n\"\n if self.endpoint_context:\n message += f\"\\\\n{self.endpoint_context}\"\n return message\"\"\"\n\nassert s.count(old_val_exc) == 1, (\"old text found this many times:\", s.count(old_val_exc))\ns = s.replace(old_val_exc, new_val_exc)\n\n# Remove __str__ from ResponseValidationError\nold_resp_val = \"\"\" def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\"\"\"\n\n# Note: the original file had \\n in the f-string.\n# Let's check the exact content again.\n# sed -n '180,200p' fastapi/exceptions.py\n# def __str__(self) -> str:\n# message = f\"{len(self._errors)} validation errors:\\n\"\n# for err in self._errors:\n# message += f\" {err}\\n\"\n# return message\n\n# The f-string in the file is:\n# message = f\"{len(self._errors)} validation errors:\\n\"\n# Let's use a more flexible replacement for ResponseValidationError.__str__.\n\n# I'll just replace the whole ResponseValidationError class.\nold_resp_class = \"\"\"class ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\"\"\"\n\nnew_resp_class = \"\"\"class ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\"\"\"\n\n# Let's check if old_resp_class is exactly in s.\n# The sed output showed:\n# class ResponseValidationError(ValidationException):\n# def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n# super().__init__(errors)\n# self.body = body\n#\n# def __str__(self) -> str:\n# message = f\"{len(self._errors)} validation errors:\\n\"\n# for err in self._errors:\n# message += f\" {err}\\n\"\n# return message\n\n# Let's try to replace it.\nif old_resp_class in s:\n s = s.replace(old_resp_class, new_resp_class)\nelse:\n # Try with different indentation or something.\n # Let's just use a regex or something.\n pass\n\np.write_text(s)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 37 | run_command | {
"command": "sed -n '160,200p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": " self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n def __str__(self) -> sfull{"status": "ok", "stdout": " self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n if self.endpoint_context:\n message += f\"\\n{self.endpoint_context}\"\n return message\n\n\nclass RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n\nclass WebSocketRequestValidationError(ValidationException):\n pass\n\n\nclass ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\n", "stderr": "", "exit_code": 0} |
| 38 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\n\n# It seems the previous replacement for ResponseValidationError failed because of the exact string.\n# Let's just remove the __str__ method from ResponseValidationError using a more robust way.\n\nimport re\ns = re.sub(\n r\"class ResponseValidationError\\(ValidationException\\):\\n def __init__\\(.*?\\)\\n super\\(\\)\\.__init__\\(errors\\)\\n self\\.body = body\\n\\n def __str__\\(self\\) -> str:\\n message = f\\\"{len\\(self\\._errors\\)} validation errors:\\n\\\"\\n for err in self._errors:\\n message += f\\\" {err}\\n\\\"\\n return message\",\n r\"class ResponseValidationError(ValidationException):\\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\\n super().__init__(errors)\\n self.body = body\",\n s,\n flags=re.DOTALL\n)\n# That regex is too complex. Let's just use a simple replace for the __str__ part.\n\n# Let's try this:\n# Find the start of ResponseValidationError and the end of its __str__ method.\n\n# Actually, I'll just use a python script to edit the file.\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 39 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/exceptions.py\")\ns = p.read_text()\n\n# Let's just replace the whole ResponseValidationError block.\n# I'll use the exact string from sed output.\n\nold_resp_block = \"\"\"class ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n return message\"\"\"\n\nnew_resp_block = \"\"\"class ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\"\"\"\n\nif old_resp_block in s:\n s = s.replace(old_resp_block, new_resp_block)\nelse:\n # Try with different line endings or something.\n # Let's just use a simple replacement for the __str__ method.\n # The __str__ method starts with ' def __str__(self) -> str:' and ends with ' return message'\n # and it's inside ResponseValidationError.\n \n # Let's try to find the line number and replace.\n lines = s.splitlines()\n start_line = -1\n for i, line in enumerate(lines):\n if \"class ResponseValidationError(ValidationException):\" in line:\n start_line = i\n break\n \n if start_line != -1:\n # Find the __str__ method within ResponseValidationError\n str_start = -1\n for i in range(start_line, len(lines)):\n if \"def __str__(self) -> str:\" in lines[i]:\n str_start = i\n break\n if lines[i].strip() == \"\" and i > start_line + 5: # probably end of class\n break\n \n if str_start != -1:\n # Find the end of the __str__ method\n str_end = -1\n for i in range(str_start, len(lines)):\n if \"return message\" in lines[i]:\n str_end = i\n break\n \n if str_end != -1:\n # Remove the lines from str_start to str_end\n # Also remove the empty line before it if it exists.\n if str_start > 0 and lines[str_start-1].strip() == \"\":\n del lines[str_start-1:str_end+1]\n else:\n del lines[str_start:str_end+1]\n s = \"\\n\".join(lines)\n\np.write_text(s)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 40 | run_command | {
"command": "sed -n '160,200p' fastapi/exceptions.py"
} | {"status": "ok", "stdout": " self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n def __str__(self) -> sfull{"status": "ok", "stdout": " self.endpoint_context: Optional[str] = None\n\n def errors(self) -> Sequence[Any]:\n return self._errors\n\n def __str__(self) -> str:\n message = f\"{len(self._errors)} validation errors:\\n\"\n for err in self._errors:\n message += f\" {err}\\n\"\n if self.endpoint_context:\n message += f\"\\n{self.endpoint_context}\"\n return message\n\n\nclass RequestValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body\n\n\nclass WebSocketRequestValidationError(ValidationException):\n pass\n\n\nclass ResponseValidationError(ValidationException):\n def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:\n super().__init__(errors)\n self.body = body", "stderr": "", "exit_code": 0} |
| 41 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\nimport inspect\n\ndef get_endpoint_context(dependant) -> str:\n # dependant.call is the endpoint function\n endpoint = dependant.call\n if endpoint is None:\n return \"\"\n \n try:\n # Get the file, line number, and function name\n frame = inspect.getframeinfo(endpoint)\n filename = frame.filename\n lineno = frame.lineno\n func_name = endpoint.__name__\n \n # We also need the HTTP method and route.\n # These are not in Dependant, but in APIRoute.\n # However, get_request_handler only has access to Dependant.\n # Wait, the problem statement says \"HTTP method and route where applicable\".\n # This means we might need to pass this info to the exception.\n \n return f\"File \\\"{filename}\\\", line {lineno}, in {func_name}\"\n except Exception:\n return \"\"\n\n# I need to integrate this into fastapi/routing.py.\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 42 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\nimport inspect\n\n# Let's define a helper to get the context.\n# I'll put it in fastapi/routing.py or a new utility file.\n# Since it's used in routing.py, let's put it there.\n\n# The context should be:\n# File \"/path/to/file.py\", line 43, in create_item\n# POST /items/\n\n# To get the method and route, we need the APIRoute instance.\n# But get_request_handler only gets the Dependant.\n# Let's check if APIRoute is available.\n# In APIRoute.get_route_handler, it calls get_request_handler(self.dependant, ...).\n# We should probably pass the route info to get_request_handler.\n\n# Let's see get_request_handler signature again.\n# def get_request_handler(\n# dependant: Dependant,\n# body_field: Optional[ModelField] = None,\n# ...\n# )\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 43 | run_command | {
"command": "sed -n '289,300p' fastapi/routing.py"
} | {"status": "ok", "stdout": "def get_request_handler(\n dependant: Dependant,\n body_field: Optional[ModelField] = None,\n status_code: Optional[int] = None,\n rfull{"status": "ok", "stdout": "def get_request_handler(\n dependant: Dependant,\n body_field: Optional[ModelField] = None,\n status_code: Optional[int] = None,\n response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),\n response_field: Optional[ModelField] = None,\n response_model_include: Optional[IncEx] = None,\n response_model_exclude: Optional[IncEx] = None,\n response_model_by_alias: bool = True,\n response_model_exclude_unset: bool = False,\n response_model_exclude_defaults: bool = False,\n response_model_exclude_none: bool = False,\n", "stderr": "", "exit_code": 0} |
| 44 | run_command | {
"command": "sed -n '640,655p' fastapi/routing.py"
} | {"status": "ok", "stdout": " self._flat_dependant.body_params\n )\n self.body_field = get_body_field(\n flat_dependant=self._flat_dependant,\n name=self.unique_full{"status": "ok", "stdout": " self._flat_dependant.body_params\n )\n self.body_field = get_body_field(\n flat_dependant=self._flat_dependant,\n name=self.unique_id,\n embed_body_fields=self._embed_body_fields,\n )\n self.app = request_response(self.get_route_handler())\n\n def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:\n return get_request_handler(\n dependant=self.dependant,\n body_field=self.body_field,\n status_code=self.status_code,\n response_class=self.response_class,\n response_field=self.secure_cloned_response_field,\n", "stderr": "", "exit_code": 0} |
| 45 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\nimport inspect\n\n# I will add a helper function to get the endpoint context.\n# And I will update get_request_handler to accept endpoint_context.\n\n# Let's first add the helper function to fastapi/routing.py.\np = Path(\"fastapi/routing.py\")\ns = p.read_text()\n\n# I'll add the helper function before get_request_handler.\n# get_request_handler starts at line 289.\n\n# Let's find the line number of get_request_handler.\nlines = s.splitlines()\nhandler_line = -1\nfor i, line in enumerate(lines):\n if \"def get_request_handler(\" in line:\n handler_line = i\n break\n\ncontext_helper = \"\"\"def _get_endpoint_context(\n dependant: \"Dependant\", method: str, path: str\n) -> str:\n try:\n endpoint = dependant.call\n if endpoint is None:\n return \"\"\n frame = inspect.getframeinfo(endpoint)\n return f'File \"{frame.filename}\", line {frame.lineno}, in {endpoint.__name__}\\\\n {method} {path}'\n except Exception:\n return \"\"\n\"\"\"\n\n# Insert the helper function.\nlines[handler_line:handler_line] = [context_helper, \"\"]\ns = \"\\\\n\".join(lines)\np.write_text(s)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 46 | run_command | {
"command": "sed -n '280,300p' fastapi/routing.py"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 47 | run_command | {
"command": "run_command: grep -n \"_get_endpoint_context\" fastapi/routing.py"
} | {"status": "error", "error_type": "CommandError", "error_message": "/bin/bash: run_command:: command not found\n", "details": {"stdout": "", "stderr": "/bin/basfull{"status": "error", "error_type": "CommandError", "error_message": "/bin/bash: run_command:: command not found\n", "details": {"stdout": "", "stderr": "/bin/bash: run_command:: command not found\n", "exit_code": 127}} |
| 48 | run_command | {
"command": "grep -n \"_get_endpoint_context\" fastapi/routing.py"
} | {"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStacfull{"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStack, asynccontextmanager\\nfrom enum import Enum, IntEnum\\nfrom typing import (\\n Any,\\n AsyncIterator,\\n Awaitable,\\n Callable,\\n Collection,\\n Coroutine,\\n Dict,\\n List,\\n Mapping,\\n Optional,\\n Sequence,\\n Set,\\n Tuple,\\n Type,\\n Union,\\n)\\n\\nfrom annotated_doc import Doc\\nfrom fastapi import params, temp_pydantic_v1_params\\nfrom fastapi._compat import (\\n ModelField,\\n Undefined,\\n _get_model_config,\\n _model_dump,\\n _normalize_errors,\\n lenient_issubclass,\\n)\\nfrom fastapi.datastructures import Default, DefaultPlaceholder\\nfrom fastapi.dependencies.models import Dependant\\nfrom fastapi.dependencies.utils import (\\n _should_embed_body_fields,\\n get_body_field,\\n get_dependant,\\n get_flat_dependant,\\n get_parameterless_sub_dependant,\\n get_typed_return_annotation,\\n solve_dependencies,\\n)\\nfrom fastapi.encoders import jsonable_encoder\\nfrom fastapi.exceptions import (\\n FastAPIError,\\n RequestValidationError,\\n ResponseValidationError,\\n WebSocketRequestValidationError,\\n)\\nfrom fastapi.types import DecoratedCallable, IncEx\\nfrom fastapi.utils import (\\n create_cloned_field,\\n create_model_field,\\n generate_unique_id,\\n get_value_or_default,\\n is_body_allowed_for_status_code,\\n)\\nfrom pydantic import BaseModel\\nfrom starlette import routing\\nfrom starlette._exception_handler import wrap_app_handling_exceptions\\nfrom starlette._utils import is_async_callable\\nfrom starlette.concurrency import run_in_threadpool\\nfrom starlette.exceptions import HTTPException\\nfrom starlette.requests import Request\\nfrom starlette.responses import JSONResponse, Response\\nfrom starlette.routing import (\\n BaseRoute,\\n Match,\\n compile_path,\\n |
| 49 | run_command | {
"command": "grep -n \"_get_endpoint_context\" fastapi/routing.py | tail -n 5"
} | {"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStacfull{"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStack, asynccontextmanager\\nfrom enum import Enum, IntEnum\\nfrom typing import (\\n Any,\\n AsyncIterator,\\n Awaitable,\\n Callable,\\n Collection,\\n Coroutine,\\n Dict,\\n List,\\n Mapping,\\n Optional,\\n Sequence,\\n Set,\\n Tuple,\\n Type,\\n Union,\\n)\\n\\nfrom annotated_doc import Doc\\nfrom fastapi import params, temp_pydantic_v1_params\\nfrom fastapi._compat import (\\n ModelField,\\n Undefined,\\n _get_model_config,\\n _model_dump,\\n _normalize_errors,\\n lenient_issubclass,\\n)\\nfrom fastapi.datastructures import Default, DefaultPlaceholder\\nfrom fastapi.dependencies.models import Dependant\\nfrom fastapi.dependencies.utils import (\\n _should_embed_body_fields,\\n get_body_field,\\n get_dependant,\\n get_flat_dependant,\\n get_parameterless_sub_dependant,\\n get_typed_return_annotation,\\n solve_dependencies,\\n)\\nfrom fastapi.encoders import jsonable_encoder\\nfrom fastapi.exceptions import (\\n FastAPIError,\\n RequestValidationError,\\n ResponseValidationError,\\n WebSocketRequestValidationError,\\n)\\nfrom fastapi.types import DecoratedCallable, IncEx\\nfrom fastapi.utils import (\\n create_cloned_field,\\n create_model_field,\\n generate_unique_id,\\n get_value_or_default,\\n is_body_allowed_for_status_code,\\n)\\nfrom pydantic import BaseModel\\nfrom starlette import routing\\nfrom starlette._exception_handler import wrap_app_handling_exceptions\\nfrom starlette._utils import is_async_callable\\nfrom starlette.concurrency import run_in_threadpool\\nfrom starlette.exceptions import HTTPException\\nfrom starlette.requests import Request\\nfrom starlette.responses import JSONResponse, Response\\nfrom starlette.routing import (\\n BaseRoute,\\n Match,\\n compile_path,\\n |
| 50 | run_command | {
"command": "grep -n \"_get_endpoint_context\" fastapi/routing.py"
} | {"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStacfull{"status": "ok", "stdout": "1:import dataclasses\\nimport email.message\\nimport functools\\nimport inspect\\nimport json\\nfrom contextlib import AsyncExitStack, asynccontextmanager\\nfrom enum import Enum, IntEnum\\nfrom typing import (\\n Any,\\n AsyncIterator,\\n Awaitable,\\n Callable,\\n Collection,\\n Coroutine,\\n Dict,\\n List,\\n Mapping,\\n Optional,\\n Sequence,\\n Set,\\n Tuple,\\n Type,\\n Union,\\n)\\n\\nfrom annotated_doc import Doc\\nfrom fastapi import params, temp_pydantic_v1_params\\nfrom fastapi._compat import (\\n ModelField,\\n Undefined,\\n _get_model_config,\\n _model_dump,\\n _normalize_errors,\\n lenient_issubclass,\\n)\\nfrom fastapi.datastructures import Default, DefaultPlaceholder\\nfrom fastapi.dependencies.models import Dependant\\nfrom fastapi.dependencies.utils import (\\n _should_embed_body_fields,\\n get_body_field,\\n get_dependant,\\n get_flat_dependant,\\n get_parameterless_sub_dependant,\\n get_typed_return_annotation,\\n solve_dependencies,\\n)\\nfrom fastapi.encoders import jsonable_encoder\\nfrom fastapi.exceptions import (\\n FastAPIError,\\n RequestValidationError,\\n ResponseValidationError,\\n WebSocketRequestValidationError,\\n)\\nfrom fastapi.types import DecoratedCallable, IncEx\\nfrom fastapi.utils import (\\n create_cloned_field,\\n create_model_field,\\n generate_unique_id,\\n get_value_or_default,\\n is_body_allowed_for_status_code,\\n)\\nfrom pydantic import BaseModel\\nfrom starlette import routing\\nfrom starlette._exception_handler import wrap_app_handling_exceptions\\nfrom starlette._utils import is_async_callable\\nfrom starlette.concurrency import run_in_threadpool\\nfrom starlette.exceptions import HTTPException\\nfrom starlette.requests import Request\\nfrom starlette.responses import JSONResponse, Response\\nfrom starlette.routing import (\\n BaseRoute,\\n Match,\\n compile_path,\\n |
diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py
index 0620428b..6505621f 100644
--- a/fastapi/exceptions.py
+++ b/fastapi/exceptions.py
@@ -157,10 +157,19 @@ class DependencyScopeError(FastAPIError):
class ValidationException(Exception):
def __init__(self, errors: Sequence[Any]) -> None:
self._errors = errors
+ self.endpoint_context: Optional[str] = None
def errors(self) -> Sequence[Any]:
return self._errors
+ def __str__(self) -> str:
+ message = f"{len(self._errors)} validation errors:\n"
+ for err in self._errors:
+ message += f" {err}\n"
+ if self.endpoint_context:
+ message += f"\n{self.endpoint_context}"
+ return message
+
class RequestValidationError(ValidationException):
def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:
@@ -175,10 +184,4 @@ class WebSocketRequestValidationError(ValidationException):
class ResponseValidationError(ValidationException):
def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:
super().__init__(errors)
- self.body = body
-
- def __str__(self) -> str:
- message = f"{len(self._errors)} validation errors:\n"
- for err in self._errors:
- message += f" {err}\n"
- return message
+ self.body = body
\ No newline at end of file
diff --git a/fastapi/routing.py b/fastapi/routing.py
index c10175b1..fde4fbf0 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -1,4517 +1,12 @@
-import dataclasses
-import email.message
-import functools
-import inspect
-import json
-from contextlib import AsyncExitStack, asynccontextmanager
-from enum import Enum, IntEnum
-from typing import (
- Any,
- AsyncIterator,
- Awaitable,
- Callable,
- Collection,
- Coroutine,
- Dict,
- List,
- Mapping,
- Optional,
- Sequence,
- Set,
- Tuple,
- Type,
- Union,
-)
-
-from annotated_doc import Doc
-from fastapi import params, temp_pydantic_v1_params
-from fastapi._compat import (
- ModelField,
- Undefined,
- _get_model_config,
- _model_dump,
- _normalize_errors,
- lenient_issubclass,
-)
-from fastapi.datastructures import Default, DefaultPlaceholder
-from fastapi.dependencies.models import Dependant
-from fastapi.dependencies.utils import (
- _should_embed_body_fields,
- get_body_field,
- get_dependant,
- get_flat_dependant,
- get_parameterless_sub_dependant,
- get_typed_return_annotation,
- solve_dependencies,
-)
-from fastapi.encoders import jsonable_encoder
-from fastapi.exceptions import (
- FastAPIError,
- RequestValidationError,
- ResponseValidationError,
- WebSocketRequestValidationError,
-)
-from fastapi.types import DecoratedCallable, IncEx
-from fastapi.utils import (
- create_cloned_field,
- create_model_field,
- generate_unique_id,
- get_value_or_default,
- is_body_allowed_for_status_code,
-)
-from pydantic import BaseModel
-from starlette import routing
-from starlette._exception_handler import wrap_app_handling_exceptions
-from starlette._utils import is_async_callable
-from starlette.concurrency import run_in_threadpool
-from starlette.exceptions import HTTPException
-from starlette.requests import Request
-from starlette.responses import JSONResponse, Response
-from starlette.routing import (
- BaseRoute,
- Match,
- compile_path,
- get_name,
-)
-from starlette.routing import Mount as Mount # noqa
-from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send
-from starlette.websockets import WebSocket
-from typing_extensions import Annotated, deprecated
-
-
-# Copy of starlette.routing.request_response modified to include the
-# dependencies' AsyncExitStack
-def request_response(
- func: Callable[[Request], Union[Awaitable[Response], Response]],
-) -> ASGIApp:
- """
- Takes a function or coroutine `func(request) -> response`,
- and returns an ASGI application.
- """
- f: Callable[[Request], Awaitable[Response]] = (
- func if is_async_callable(func) else functools.partial(run_in_threadpool, func) # type:ignore
- )
-
- async def app(scope: Scope, receive: Receive, send: Send) -> None:
- request = Request(scope, receive, send)
-
- async def app(scope: Scope, receive: Receive, send: Send) -> None:
- # Starts customization
- response_awaited = False
- async with AsyncExitStack() as request_stack:
- scope["fastapi_inner_astack"] = request_stack
- async with AsyncExitStack() as function_stack:
- scope["fastapi_function_astack"] = function_stack
- response = await f(request)
- await response(scope, receive, send)
- # Continues customization
- response_awaited = True
- if not response_awaited:
- raise FastAPIError(
- "Response not awaited. There's a high chance that the "
- "application code is raising an exception and a dependency with yield "
- "has a block with a bare except, or a block with except Exception, "
- "and is not raising the exception again. Read more about it in the "
- "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
- )
-
- # Same as in Starlette
- await wrap_app_handling_exceptions(app, request)(scope, receive, send)
-
- return app
-
-
-# Copy of starlette.routing.websocket_session modified to include the
-# dependencies' AsyncExitStack
-def websocket_session(
- func: Callable[[WebSocket], Awaitable[None]],
-) -> ASGIApp:
- """
- Takes a coroutine `func(session)`, and returns an ASGI application.
- """
- # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async"
-
- async def app(scope: Scope, receive: Receive, send: Send) -> None:
- session = WebSocket(scope, receive=receive, send=send)
-
- async def app(scope: Scope, receive: Receive, send: Send) -> None:
- async with AsyncExitStack() as request_stack:
- scope["fastapi_inner_astack"] = request_stack
- async with AsyncExitStack() as function_stack:
- scope["fastapi_function_astack"] = function_stack
- await func(session)
-
- # Same as in Starlette
- await wrap_app_handling_exceptions(app, session)(scope, receive, send)
-
- return app
-
-
-def _prepare_response_content(
- res: Any,
- *,
- exclude_unset: bool,
- exclude_defaults: bool = False,
- exclude_none: bool = False,
-) -> Any:
- if isinstance(res, BaseModel):
- read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None)
- if read_with_orm_mode:
- # Let from_orm extract the data from this model instead of converting
- # it now to a dict.
- # Otherwise, there's no way to extract lazy data that requires attribute
- # access instead of dict iteration, e.g. lazy relationships.
- return res
- return _model_dump(
- res,
- by_alias=True,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
- elif isinstance(res, list):
- return [
- _prepare_response_content(
- item,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
- for item in res
- ]
- elif isinstance(res, dict):
- return {
- k: _prepare_response_content(
- v,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
- for k, v in res.items()
- }
- elif dataclasses.is_dataclass(res):
- assert not isinstance(res, type)
- return dataclasses.asdict(res)
- return res
-
-
-def _merge_lifespan_context(
- original_context: Lifespan[Any], nested_context: Lifespan[Any]
-) -> Lifespan[Any]:
- @asynccontextmanager
- async def merged_lifespan(
- app: AppType,
- ) -> AsyncIterator[Optional[Mapping[str, Any]]]:
- async with original_context(app) as maybe_original_state:
- async with nested_context(app) as maybe_nested_state:
- if maybe_nested_state is None and maybe_original_state is None:
- yield None # old ASGI compatibility
- else:
- yield {**(maybe_nested_state or {}), **(maybe_original_state or {})}
-
- return merged_lifespan # type: ignore[return-value]
-
-
-async def serialize_response(
- *,
- field: Optional[ModelField] = None,
- response_content: Any,
- include: Optional[IncEx] = None,
- exclude: Optional[IncEx] = None,
- by_alias: bool = True,
- exclude_unset: bool = False,
- exclude_defaults: bool = False,
- exclude_none: bool = False,
- is_coroutine: bool = True,
-) -> Any:
- if field:
- errors = []
- if not hasattr(field, "serialize"):
- # pydantic v1
- response_content = _prepare_response_content(
- response_content,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
- if is_coroutine:
- value, errors_ = field.validate(response_content, {}, loc=("response",))
- else:
- value, errors_ = await run_in_threadpool(
- field.validate, response_content, {}, loc=("response",)
- )
- if isinstance(errors_, list):
- errors.extend(errors_)
- elif errors_:
- errors.append(errors_)
- if errors:
- raise ResponseValidationError(
- errors=_normalize_errors(errors), body=response_content
- )
-
- if hasattr(field, "serialize"):
- return field.serialize(
- value,
- include=include,
- exclude=exclude,
- by_alias=by_alias,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
-
- return jsonable_encoder(
- value,
- include=include,
- exclude=exclude,
- by_alias=by_alias,
- exclude_unset=exclude_unset,
- exclude_defaults=exclude_defaults,
- exclude_none=exclude_none,
- )
- else:
- return jsonable_encoder(response_content)
-
-
-async def run_endpoint_function(
- *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool
-) -> Any:
- # Only called by get_request_handler. Has been split into its own function to
- # facilitate profiling endpoints, since inner functions are harder to profile.
- assert dependant.call is not None, "dependant.call must be a function"
-
- if is_coroutine:
- return await dependant.call(**values)
- else:
- return await run_in_threadpool(dependant.call, **values)
-
-
-def get_request_handler(
- dependant: Dependant,
- body_field: Optional[ModelField] = None,
- status_code: Optional[int] = None,
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
- response_field: Optional[ModelField] = None,
- response_model_include: Optional[IncEx] = None,
- response_model_exclude: Optional[IncEx] = None,
- response_model_by_alias: bool = True,
- response_model_exclude_unset: bool = False,
- response_model_exclude_defaults: bool = False,
- response_model_exclude_none: bool = False,
- dependency_overrides_provider: Optional[Any] = None,
- embed_body_fields: bool = False,
-) -> Callable[[Request], Coroutine[Any, Any, Response]]:
- assert dependant.call is not None, "dependant.call must be a function"
- is_coroutine = dependant.is_coroutine_callable
- is_body_form = body_field and isinstance(
- body_field.field_info, (params.Form, temp_pydantic_v1_params.Form)
- )
- if isinstance(response_class, DefaultPlaceholder):
- actual_response_class: Type[Response] = response_class.value
- else:
- actual_response_class = response_class
-
- async def app(request: Request) -> Response:
- response: Union[Response, None] = None
- file_stack = request.scope.get("fastapi_middleware_astack")
- assert isinstance(file_stack, AsyncExitStack), (
- "fastapi_middleware_astack not found in request scope"
- )
-
- # Read body and auto-close files
- try:
- body: Any = None
- if body_field:
- if is_body_form:
- body = await request.form()
- file_stack.push_async_callback(body.close)
- else:
- body_bytes = await request.body()
- if body_bytes:
- json_body: Any = Undefined
- content_type_value = request.headers.get("content-type")
- if not content_type_value:
- json_body = await request.json()
- else:
- message = email.message.Message()
- message["content-type"] = content_type_value
- if message.get_content_maintype() == "application":
- subtype = message.get_content_subtype()
- if subtype == "json" or subtype.endswith("+json"):
- json_body = await request.json()
- if json_body != Undefined:
- body = json_body
- else:
- body = body_bytes
- except json.JSONDecodeError as e:
- validation_error = RequestValidationError(
- [
- {
- "type": "json_invalid",
- "loc": ("body", e.pos),
- "msg": "JSON decode error",
- "input": {},
- "ctx": {"error": e.msg},
- }
- ],
- body=e.doc,
- )
- raise validation_error from e
- except HTTPException:
- # If a middleware raises an HTTPException, it should be raised again
- raise
- except Exception as e:
- http_error = HTTPException(
- status_code=400, detail="There was an error parsing the body"
- )
- raise http_error from e
-
- # Solve dependencies and run path operation function, auto-closing dependencies
- errors: List[Any] = []
- async_exit_stack = request.scope.get("fastapi_inner_astack")
- assert isinstance(async_exit_stack, AsyncExitStack), (
- "fastapi_inner_astack not found in request scope"
- )
- solved_result = await solve_dependencies(
- request=request,
- dependant=dependant,
- body=body,
- dependency_overrides_provider=dependency_overrides_provider,
- async_exit_stack=async_exit_stack,
- embed_body_fields=embed_body_fields,
- )
- errors = solved_result.errors
- if not errors:
- raw_response = await run_endpoint_function(
- dependant=dependant,
- values=solved_result.values,
- is_coroutine=is_coroutine,
- )
- if isinstance(raw_response, Response):
- if raw_response.background is None:
- raw_response.background = solved_result.background_tasks
- response = raw_response
- else:
- response_args: Dict[str, Any] = {
- "background": solved_result.background_tasks
- }
- # If status_code was set, use it, otherwise use the default from the
- # response class, in the case of redirect it's 307
- current_status_code = (
- status_code if status_code else solved_result.response.status_code
- )
- if current_status_code is not None:
- response_args["status_code"] = current_status_code
- if solved_result.response.status_code:
- response_args["status_code"] = solved_result.response.status_code
- content = await serialize_response(
- field=response_field,
- response_content=raw_response,
- include=response_model_include,
- exclude=response_model_exclude,
- by_alias=response_model_by_alias,
- exclude_unset=response_model_exclude_unset,
- exclude_defaults=response_model_exclude_defaults,
- exclude_none=response_model_exclude_none,
- is_coroutine=is_coroutine,
- )
- response = actual_response_class(content, **response_args)
- if not is_body_allowed_for_status_code(response.status_code):
- response.body = b""
- response.headers.raw.extend(solved_result.response.headers.raw)
- if errors:
- validation_error = RequestValidationError(
- _normalize_errors(errors), body=body
- )
- raise validation_error
-
- # Return response
- assert response
- return response
-
- return app
-
-
-def get_websocket_app(
- dependant: Dependant,
- dependency_overrides_provider: Optional[Any] = None,
- embed_body_fields: bool = False,
-) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
- async def app(websocket: WebSocket) -> None:
- async_exit_stack = websocket.scope.get("fastapi_inner_astack")
- assert isinstance(async_exit_stack, AsyncExitStack), (
- "fastapi_inner_astack not found in request scope"
- )
- solved_result = await solve_dependencies(
- request=websocket,
- dependant=dependant,
- dependency_overrides_provider=dependency_overrides_provider,
- async_exit_stack=async_exit_stack,
- embed_body_fields=embed_body_fields,
- )
- if solved_result.errors:
- raise WebSocketRequestValidationError(
- _normalize_errors(solved_result.errors)
- )
- assert dependant.call is not None, "dependant.call must be a function"
- await dependant.call(**solved_result.values)
-
- return app
-
-
-class APIWebSocketRoute(routing.WebSocketRoute):
- def __init__(
- self,
- path: str,
- endpoint: Callable[..., Any],
- *,
- name: Optional[str] = None,
- dependencies: Optional[Sequence[params.Depends]] = None,
- dependency_overrides_provider: Optional[Any] = None,
- ) -> None:
- self.path = path
- self.endpoint = endpoint
- self.name = get_name(endpoint) if name is None else name
- self.dependencies = list(dependencies or [])
- self.path_regex, self.path_format, self.param_convertors = compile_path(path)
- self.dependant = get_dependant(
- path=self.path_format, call=self.endpoint, scope="function"
- )
- for depends in self.dependencies[::-1]:
- self.dependant.dependencies.insert(
- 0,
-
==================================== ERRORS ====================================
___________ ERROR collecting tests/test_validation_error_context.py ____________
/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/fastapi/lib/python3.13/site-packages/_pytest/python.py:508: in importtestmodule
mod = import_path(
/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/fastapi/lib/python3.13/site-packages/_pytest/pathlib.py:596: in import_path
importlib.import_module(module_name)
/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1395: in _gcd_import
???
<frozen importlib._bootstrap>:1360: in _find_and_load
???
<frozen importlib._bootstrap>:1331: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:935: in _load_unlocked
???
/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/fastapi/lib/python3.13/site-packages/_pytest/assertion/rewrite.py:188: in exec_module
exec(co, module.__dict__)
tests/test_validation_error_context.py:1: in <module>
from fastapi import FastAPI, Request, WebSocket
fastapi/__init__.py:7: in <module>
from .applications import FastAPI as FastAPI
fastapi/applications.py:17: in <module>
from fastapi import routing
E File "/private/tmp/swe_work/pod_r4_v1g/fastapi_14306/b/workspace/fastapi/routing.py", line 1
E import dataclasses\nimport email.message\nimport functools\nimport inspect\nimport json\nfrom contextlib import AsyncExitStack, asynccontextmanager\nfrom enum import Enum, IntEnum\nfrom typing import (\n Any,\n AsyncIterator,\n Awaitable,\n Callable,\n Collection,\n Coroutine,\n Dict,\n List,\n Mapping,\n Optional,\n Sequence,\n Set,\n Tuple,\n Type,\n Union,\n)\n\nfrom annotated_doc import Doc\nfrom fastapi import params, temp_pydantic_v1_params\nfrom fastapi._compat import (\n ModelField,\n Undefined,\n _get_model_config,\n _model_dump,\n _normalize_errors,\n lenient_issubclass,\n)\nfrom fastapi.datastructures import Default, DefaultPlaceholder\nfrom fastapi.dependencies.models import Dependant\nfrom fastapi.dependencies.utils import (\n _should_embed_body_fields,\n get_body_field,\n get_dependant,\n get_flat_dependant,\n get_parameterless_sub_dependant,\n get_typed_return_annotation,\n solve_depende
E ^
E SyntaxError: unexpected character after line continuation character
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 error in 0.16s