Skip to content

Commit

Permalink
[MIG] fastapi: Migration to 17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenminhchien committed May 24, 2024
1 parent 8cce6cf commit c231e78
Show file tree
Hide file tree
Showing 22 changed files with 3,546 additions and 3,380 deletions.
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ exclude: |
^datamodel/|
^extendable/|
^extendable_fastapi/|
^fastapi/|
^fastapi_auth_jwt/|
^fastapi_auth_jwt_demo/|
^graphql_base/|
Expand Down
2,607 changes: 1,330 additions & 1,277 deletions fastapi/README.rst

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions fastapi/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"name": "Odoo FastAPI",
"summary": """
Odoo FastAPI endpoint""",
"version": "16.0.1.2.5",
"version": "17.0.1.0.0",
"license": "LGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"maintainers": ["lmignon"],
Expand All @@ -30,5 +30,5 @@
]
},
"development_status": "Beta",
"installable": False,
# "installable": False,
}
34 changes: 18 additions & 16 deletions fastapi/models/fastapi_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL).

import logging
from collections.abc import Awaitable, Callable
from functools import partial
from itertools import chain
from typing import Any, Awaitable, Callable, Dict, List, Tuple, Type, Union
from typing import Any

from a2wsgi import ASGIMiddleware
from starlette.middleware import Middleware
Expand All @@ -20,7 +21,6 @@


class FastapiEndpoint(models.Model):

_name = "fastapi.endpoint"
_inherit = "endpoint.route.sync.mixin"
_description = "FastAPI Endpoint"
Expand Down Expand Up @@ -111,7 +111,7 @@ def _registered_endpoint_rule_keys(self):
return tuple(res)

@api.model
def _routing_impacting_fields(self) -> Tuple[str]:
def _routing_impacting_fields(self) -> tuple[str]:
"""The list of fields requiring to refresh the mount point of the pp
into odoo if modified"""
return ("root_path",)
Expand All @@ -134,11 +134,11 @@ def _handle_route_updates(self, vals):
if refresh_fastapi_app:
self._reset_app()
if "user_id" in vals:
self.get_uid.clear_cache(self)
self.env.registry.clear_cache()
return False

@api.model
def _fastapi_app_fields(self) -> List[str]:
def _fastapi_app_fields(self) -> list[str]:
"""The list of fields requiring to refresh the fastapi app if modified"""
return []

Expand Down Expand Up @@ -181,13 +181,13 @@ def _get_routing_info(self):
# csrf ?????
}

def _endpoint_registry_route_unique_key(self, routing: Dict[str, Any]):
def _endpoint_registry_route_unique_key(self, routing: dict[str, Any]):
route = "|".join(routing["routes"])
path = route.replace(self.root_path, "")
return f"{self._name}:{self.id}:{path}"

def _reset_app(self):
self.get_app.clear_cache(self)
self.env.registry.clear_cache()

@api.model
@tools.ormcache("root_path")
Expand Down Expand Up @@ -220,17 +220,17 @@ def _get_app(self) -> FastAPI:
app.add_exception_handler(exception, handler)
return app

def _get_app_dependencies_overrides(self) -> Dict[Callable, Callable]:
def _get_app_dependencies_overrides(self) -> dict[Callable, Callable]:
return {
dependencies.fastapi_endpoint_id: partial(lambda a: a, self.id),
dependencies.company_id: partial(lambda a: a, self.company_id.id),
}

def _get_app_exception_handlers(
self,
) -> Dict[
Union[int, Type[Exception]],
Callable[[Request, Exception], Union[Response, Awaitable[Response]]],
) -> dict[
(int | type[Exception]),
Callable[[Request, Exception], (Response | Awaitable[Response])],
]:
"""Return a dict of exception handlers to register on the app
Expand All @@ -255,10 +255,12 @@ def _get_app_exception_handlers(
odoo.exceptions.UserError: error_handlers._odoo_user_error_handler,
odoo.exceptions.AccessError: error_handlers._odoo_access_error_handler,
odoo.exceptions.MissingError: error_handlers._odoo_missing_error_handler,
odoo.exceptions.ValidationError: error_handlers._odoo_validation_error_handler,
odoo.exceptions.ValidationError: (
error_handlers._odoo_validation_error_handler
),
}

def _prepare_fastapi_app_params(self) -> Dict[str, Any]:
def _prepare_fastapi_app_params(self) -> dict[str, Any]:
"""Return the params to pass to the Fast API app constructor"""
return {
"title": self.name,
Expand All @@ -267,17 +269,17 @@ def _prepare_fastapi_app_params(self) -> Dict[str, Any]:
"dependencies": self._get_fastapi_app_dependencies(),
}

def _get_fastapi_routers(self) -> List[APIRouter]:
def _get_fastapi_routers(self) -> list[APIRouter]:
"""Return the api routers to use for the instance.
This method must be implemented when registering a new api type.
"""
return []

def _get_fastapi_app_middlewares(self) -> List[Middleware]:
def _get_fastapi_app_middlewares(self) -> list[Middleware]:
"""Return the middlewares to use for the fastapi app."""
return []

def _get_fastapi_app_dependencies(self) -> List[Depends]:
def _get_fastapi_app_dependencies(self) -> list[Depends]:
"""Return the dependencies to use for the fastapi app."""
return [Depends(dependencies.accept_language)]
7 changes: 3 additions & 4 deletions fastapi/models/fastapi_endpoint_demo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright 2022 ACSONE SA/NV
# License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL).
from typing import Annotated, Any, List
from typing import Annotated, Any

from odoo import _, api, fields, models
from odoo.api import Environment
Expand All @@ -20,7 +20,6 @@


class FastapiEndpoint(models.Model):

_inherit = "fastapi.endpoint"

app: str = fields.Selection(
Expand All @@ -31,7 +30,7 @@ class FastapiEndpoint(models.Model):
string="Authenciation method",
)

def _get_fastapi_routers(self) -> List[APIRouter]:
def _get_fastapi_routers(self) -> list[APIRouter]:
if self.app == "demo":
return [demo_router]
return super()._get_fastapi_routers()
Expand All @@ -48,7 +47,7 @@ def _valdiate_demo_auth_method(self):
)

@api.model
def _fastapi_app_fields(self) -> List[str]:
def _fastapi_app_fields(self) -> list[str]:
fields = super()._fastapi_app_fields()
fields.append("demo_auth_method")
return fields
Expand Down
3 changes: 3 additions & 0 deletions fastapi/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
1 change: 1 addition & 0 deletions fastapi/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Laurent Mignon \<<[email protected]>\>
1 change: 0 additions & 1 deletion fastapi/readme/CONTRIBUTORS.rst

This file was deleted.

41 changes: 41 additions & 0 deletions fastapi/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
This addon provides the basis to smoothly integrate the
[FastAPI](https://fastapi.tiangolo.com/) framework into Odoo.

This integration allows you to use all the goodies from
[FastAPI](https://fastapi.tiangolo.com/) to build custom APIs for your
Odoo server based on standard Python type hints.

**What is building an API?**

An API is a set of functions that can be called from the outside world.
The goal of an API is to provide a way to interact with your application
from the outside world without having to know how it works internally. A
common mistake when you are building an API is to expose all the
internal functions of your application and therefore create a tight
coupling between the outside world and your internal datamodel and
business logic. This is not a good idea because it makes it very hard to
change your internal datamodel and business logic without breaking the
outside world.

When you are building an API, you define a contract between the outside
world and your application. This contract is defined by the functions
that you expose and the parameters that you accept. This contract is the
API. When you change your internal datamodel and business logic, you can
still keep the same API contract and therefore you don't break the
outside world. Even if you change your implementation, as long as you
keep the same API contract, the outside world will still work. This is
the beauty of an API and this is why it is so important to design a good
API.

A good API is designed to be stable and to be easy to use. It's designed
to provide high-level functions related to a specific use case. It's
designed to be easy to use by hiding the complexity of the internal
datamodel and business logic. A common mistake when you are building an
API is to expose all the internal functions of your application and let
the oustide world deal with the complexity of your internal datamodel
and business logic. Don't forget that on a transactional point of view,
each call to an API function is a transaction. This means that if a
specific use case requires multiple calls to your API, you should
provide a single function that does all the work in a single
transaction. This why APIs methods are called high-level and atomic
functions.
38 changes: 0 additions & 38 deletions fastapi/readme/DESCRIPTION.rst

This file was deleted.

61 changes: 61 additions & 0 deletions fastapi/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
## 16.0.1.2.5 (2024-01-17)

**Bugfixes**

- Odoo has done an update and now, it checks domains of ir.rule on creation and modification.

The ir.rule 'Fastapi: Running user rule' uses a field (authenticate_partner_id) that comes from the context.
This field wasn't always set and this caused an error when Odoo checked the domain.
So now it is set to *False* by default. (`#410 <https://github.com/OCA/rest-framework/issues/410>`_)

## 16.0.1.2.3 (2023-12-21)

**Bugfixes**

- In case of exception in endpoint execution, close the database cursor
after rollback.

This is to ensure that the *retrying* method in *service/model.py*
does not try to flush data to the database.
([\#405](https://github.com/OCA/rest-framework/issues/405))

## 16.0.1.2.2 (2023-12-12)

**Bugfixes**

- When using the 'FastAPITransactionCase' class, allows to specify a
specific override of the 'authenticated_partner_impl' method into the
list of overrides to apply. Before this change, the
'authenticated_partner_impl' override given in the 'overrides'
parameter was always overridden in the '\_create_test_client' method
of the 'FastAPITransactionCase' class. It's now only overridden if the
'authenticated_partner_impl' method is not already present in the list
of overrides to apply and no specific partner is given. If a specific
partner is given at same time of an override for the
'authenticated_partner_impl' method, an error is raised.
([\#396](https://github.com/OCA/rest-framework/issues/396))

## 16.0.1.2.1 (2023-11-03)

**Bugfixes**

- Fix a typo in the Field declaration of the 'count' attribute of the
'PagedCollection' schema.

Misspelt parameter was triggering a deprecation warning due to recent
versions of Pydantic seeing it as an arbitrary parameter.
([\#389](https://github.com/OCA/rest-framework/issues/389))

## 16.0.1.2.0 (2023-10-13)

**Features**

- The field *total* in the *PagedCollection* schema is replaced by the
field *count*. The field *total* is now deprecated and will be removed
in the next major version. This change is backward compatible. The
json document returned will now contain both fields *total* and
*count* with the same value. In your python code the field *total*, if
used, will fill the field *count* with the same value. You are
encouraged to use the field *count* instead of *total* and adapt your
code accordingly.
([\#380](https://github.com/OCA/rest-framework/issues/380))
61 changes: 0 additions & 61 deletions fastapi/readme/HISTORY.rst

This file was deleted.

Loading

0 comments on commit c231e78

Please sign in to comment.