diff --git a/.oca/oca-port/blacklist/fastapi.json b/.oca/oca-port/blacklist/fastapi.json index 8cbdd039c..88279ef5a 100644 --- a/.oca/oca-port/blacklist/fastapi.json +++ b/.oca/oca-port/blacklist/fastapi.json @@ -7,6 +7,7 @@ "OCA/rest-framework#440": "(auto) Nothing to port from PR #440", "OCA/rest-framework#476": "(auto) Nothing to port from PR #476", "OCA/rest-framework#364": "(auto) Nothing to port from PR #364", - "OCA/rest-framework#486": "(auto) Nothing to port from PR #486" + "OCA/rest-framework#486": "(auto) Nothing to port from PR #486", + "OCA/rest-framework#607": "(auto) Nothing to port from PR #607" } } diff --git a/fastapi/dependencies.py b/fastapi/dependencies.py index 5c24d40e6..4dd93053a 100644 --- a/fastapi/dependencies.py +++ b/fastapi/dependencies.py @@ -1,7 +1,7 @@ # Copyright 2022 ACSONE SA/NV # License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL). -from typing import TYPE_CHECKING, Annotated +from typing import Annotated from odoo.api import Environment from odoo.exceptions import AccessDenied @@ -13,11 +13,9 @@ from fastapi.security import HTTPBasic, HTTPBasicCredentials from .context import odoo_env_ctx +from .models.fastapi_endpoint import FastapiEndpoint from .schemas import Paging -if TYPE_CHECKING: - from .models.fastapi_endpoint import FastapiEndpoint - def company_id() -> int | None: """This method may be overriden by the FastAPI app to set the allowed company diff --git a/fastapi/error_handlers.py b/fastapi/error_handlers.py index 0c67a52e9..1f19bd567 100644 --- a/fastapi/error_handlers.py +++ b/fastapi/error_handlers.py @@ -29,7 +29,10 @@ def convert_exception_to_status_body(exc: Exception) -> tuple[int, dict]: status_code = exc.status_code details = exc.detail elif isinstance(exc, RequestValidationError): - status_code = status.HTTP_422_UNPROCESSABLE_CONTENT + # Use integer status code to supress starlette >= 0.48 deprecation warning + # See: https://github.com/fastapi/fastapi/pull/14077 + # status_code = status.HTTP_422_UNPROCESSABLE_CONTENT + status_code = 422 details = jsonable_encoder(exc.errors()) elif isinstance(exc, WebSocketRequestValidationError): status_code = status.WS_1008_POLICY_VIOLATION diff --git a/fastapi/models/fastapi_endpoint.py b/fastapi/models/fastapi_endpoint.py index 39b3ee6f1..c55d7ebd6 100644 --- a/fastapi/models/fastapi_endpoint.py +++ b/fastapi/models/fastapi_endpoint.py @@ -15,7 +15,6 @@ from fastapi import APIRouter, Depends, FastAPI -from .. import dependencies from ..middleware import ASGIMiddleware _logger = logging.getLogger(__name__) @@ -311,9 +310,12 @@ def _get_app(self) -> FastAPI: return app def _get_app_dependencies_overrides(self) -> dict[Callable, Callable]: + # Import here to avoid circular import while waiting for lazy imports + from ..dependencies import company_id, fastapi_endpoint_id + return { - dependencies.fastapi_endpoint_id: partial(lambda a: a, self.id), - dependencies.company_id: partial(lambda a: a, self.company_id.id), + fastapi_endpoint_id: partial(lambda a: a, self.id), + company_id: partial(lambda a: a, self.company_id.id), } def _prepare_fastapi_app_params(self) -> dict[str, Any]: @@ -338,7 +340,10 @@ def _get_fastapi_app_middlewares(self) -> list[Middleware]: def _get_fastapi_app_dependencies(self) -> list[Depends]: """Return the dependencies to use for the fastapi app.""" - return [Depends(dependencies.accept_language)] + # Import here to avoid circular import too + from ..dependencies import accept_language + + return [Depends(accept_language)] # test utility @api.model diff --git a/fastapi/static/description/icon.png b/fastapi/static/description/icon.png index e09b3918c..6154f7ea3 100644 Binary files a/fastapi/static/description/icon.png and b/fastapi/static/description/icon.png differ diff --git a/fastapi/static/description/icon.svg b/fastapi/static/description/icon.svg new file mode 100644 index 000000000..b991f80cd --- /dev/null +++ b/fastapi/static/description/icon.svg @@ -0,0 +1,71 @@ + + diff --git a/fastapi/tests/test_fastapi.py b/fastapi/tests/test_fastapi.py index 9008f09bd..e074325e0 100644 --- a/fastapi/tests/test_fastapi.py +++ b/fastapi/tests/test_fastapi.py @@ -157,9 +157,7 @@ def test_request_validation_error(self) -> None: route = "/fastapi_demo/demo/exception?exception_type=BAD&error_message=" response = self.url_open(route, timeout=200) mocked_commit.assert_not_called() - self.assertEqual( - response.status_code, status.HTTP_422_UNPROCESSABLE_CONTENT - ) + self.assertEqual(response.status_code, 422) def test_no_commit_on_exception(self) -> None: # this test check that the way we mock the cursor is working as expected