From b1ce46d3c8668804fc651bfae1b9b0240e2c6e18 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Mon, 15 Dec 2025 17:03:57 +0100 Subject: [PATCH] [ADD] fastapi_endpoint_context --- fastapi_endpoint_context/README.rst | 103 ++++ fastapi_endpoint_context/__init__.py | 1 + fastapi_endpoint_context/__manifest__.py | 17 + fastapi_endpoint_context/dependencies.py | 28 ++ fastapi_endpoint_context/models/__init__.py | 1 + .../models/fastapi_endpoint.py | 25 + .../readme/CONTRIBUTORS.md | 1 + .../readme/DESCRIPTION.md | 9 + fastapi_endpoint_context/readme/USAGE.md | 3 + .../static/description/index.html | 441 ++++++++++++++++++ fastapi_endpoint_context/tests/__init__.py | 1 + .../tests/test_fastapi_endpoint_context.py | 51 ++ .../odoo/addons/fastapi_endpoint_context | 1 + setup/fastapi_endpoint_context/setup.py | 6 + 14 files changed, 688 insertions(+) create mode 100644 fastapi_endpoint_context/README.rst create mode 100644 fastapi_endpoint_context/__init__.py create mode 100644 fastapi_endpoint_context/__manifest__.py create mode 100644 fastapi_endpoint_context/dependencies.py create mode 100644 fastapi_endpoint_context/models/__init__.py create mode 100644 fastapi_endpoint_context/models/fastapi_endpoint.py create mode 100644 fastapi_endpoint_context/readme/CONTRIBUTORS.md create mode 100644 fastapi_endpoint_context/readme/DESCRIPTION.md create mode 100644 fastapi_endpoint_context/readme/USAGE.md create mode 100644 fastapi_endpoint_context/static/description/index.html create mode 100644 fastapi_endpoint_context/tests/__init__.py create mode 100644 fastapi_endpoint_context/tests/test_fastapi_endpoint_context.py create mode 120000 setup/fastapi_endpoint_context/odoo/addons/fastapi_endpoint_context create mode 100644 setup/fastapi_endpoint_context/setup.py diff --git a/fastapi_endpoint_context/README.rst b/fastapi_endpoint_context/README.rst new file mode 100644 index 000000000..73bf620d4 --- /dev/null +++ b/fastapi_endpoint_context/README.rst @@ -0,0 +1,103 @@ +======================== +fastapi_endpoint_context +======================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:088fe199709796fff2a016b1442b64d18d60b0aee7af68c52ad5a15f2137da50 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github + :target: https://github.com/OCA/rest-framework/tree/16.0/fastapi_endpoint_context + :alt: OCA/rest-framework +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi_endpoint_context + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module provides an overridable request context for FastAPI +endpoints. + +It allows to customize the behavior of requests deep in the odoo call +stack according to the current request context without having to +override routers that may come from external modules. + +This context contains by default the current endpoint app and id, +respectively accessible via +``self.env.context.get('fastapi_endpoint_app')`` and +``self.env.context.get('fastapi_endpoint_id')``. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +odoo_env dependency is automatically overridden to include FastAPI +endpoint context values. + +You can override the ``fastapi.endpoint``->\ ``_get_app_context()`` +method to add custom values to the context for your applications. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion + +Contributors +------------ + +- Florian Mounier florian.mounier@akretion.com + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-paradoxxxzero| image:: https://github.com/paradoxxxzero.png?size=40px + :target: https://github.com/paradoxxxzero + :alt: paradoxxxzero + +Current `maintainer `__: + +|maintainer-paradoxxxzero| + +This module is part of the `OCA/rest-framework `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fastapi_endpoint_context/__init__.py b/fastapi_endpoint_context/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/fastapi_endpoint_context/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/fastapi_endpoint_context/__manifest__.py b/fastapi_endpoint_context/__manifest__.py new file mode 100644 index 000000000..efa4a77b4 --- /dev/null +++ b/fastapi_endpoint_context/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2025 Akretion (http://www.akretion.com). +# @author Florian Mounier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "fastapi_endpoint_context", + "version": "16.0.1.0.0", + "author": "Akretion, Odoo Community Association (OCA)", + "summary": "Provides an overridable request context for FastAPI endpoints", + "depends": ["fastapi"], + "website": "https://github.com/OCA/rest-framework", + "data": [], + "maintainers": ["paradoxxxzero"], + "demo": [], + "installable": True, + "license": "AGPL-3", +} diff --git a/fastapi_endpoint_context/dependencies.py b/fastapi_endpoint_context/dependencies.py new file mode 100644 index 000000000..5060ed2b3 --- /dev/null +++ b/fastapi_endpoint_context/dependencies.py @@ -0,0 +1,28 @@ +# Copyright 2025 Akretion (http://www.akretion.com). +# @author Florian Mounier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from typing import Annotated + +from odoo.api import Environment + +from odoo.addons.fastapi import context, dependencies + +from fastapi import Depends + + +def odoo_env_with_context( + company_id: Annotated[int | None, Depends(dependencies.company_id)], + fastapi_endpoint_id: Annotated[int, Depends(dependencies.fastapi_endpoint_id)], +) -> Environment: + # Add a per endpoint customizable odoo environment context + env = context.odoo_env_ctx.get() + endpoint = env["fastapi.endpoint"].browse(fastapi_endpoint_id) + env = env( + context=dict( + env.context, + **endpoint._get_app_context(), + **({"allow_company_ids": [company_id]} if company_id else {}), + ) + ) + yield env diff --git a/fastapi_endpoint_context/models/__init__.py b/fastapi_endpoint_context/models/__init__.py new file mode 100644 index 000000000..b825fab92 --- /dev/null +++ b/fastapi_endpoint_context/models/__init__.py @@ -0,0 +1 @@ +from . import fastapi_endpoint diff --git a/fastapi_endpoint_context/models/fastapi_endpoint.py b/fastapi_endpoint_context/models/fastapi_endpoint.py new file mode 100644 index 000000000..1368c362b --- /dev/null +++ b/fastapi_endpoint_context/models/fastapi_endpoint.py @@ -0,0 +1,25 @@ +# Copyright 2025 Akretion (http://www.akretion.com). +# @author Florian Mounier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + +from odoo.addons.fastapi import dependencies + +from ..dependencies import odoo_env_with_context + + +class FastapiEndpoint(models.Model): + _inherit = "fastapi.endpoint" + + def _get_app_context(self): + """Add the fastapi app and endpoint id to the odoo env context""" + return { + "fastapi_app": self.app, + "fastapi_endpoint_id": self.id, + } + + def _get_app_dependencies_overrides(self): + res = super()._get_app_dependencies_overrides() + res.update({dependencies.odoo_env: odoo_env_with_context}) + return res diff --git a/fastapi_endpoint_context/readme/CONTRIBUTORS.md b/fastapi_endpoint_context/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..328a37da8 --- /dev/null +++ b/fastapi_endpoint_context/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Florian Mounier diff --git a/fastapi_endpoint_context/readme/DESCRIPTION.md b/fastapi_endpoint_context/readme/DESCRIPTION.md new file mode 100644 index 000000000..a672fd672 --- /dev/null +++ b/fastapi_endpoint_context/readme/DESCRIPTION.md @@ -0,0 +1,9 @@ +This module provides an overridable request context for FastAPI endpoints. + +It allows to customize the behavior of requests deep in the odoo call stack +according to the current request context without having to override routers +that may come from external modules. + +This context contains by default the current endpoint app and id, respectively +accessible via `self.env.context.get('fastapi_endpoint_app')` and +`self.env.context.get('fastapi_endpoint_id')`. diff --git a/fastapi_endpoint_context/readme/USAGE.md b/fastapi_endpoint_context/readme/USAGE.md new file mode 100644 index 000000000..7368214f2 --- /dev/null +++ b/fastapi_endpoint_context/readme/USAGE.md @@ -0,0 +1,3 @@ +odoo_env dependency is automatically overridden to include FastAPI endpoint context values. + +You can override the `fastapi.endpoint`->`_get_app_context()` method to add custom values to the context for your applications. diff --git a/fastapi_endpoint_context/static/description/index.html b/fastapi_endpoint_context/static/description/index.html new file mode 100644 index 000000000..94bd842d1 --- /dev/null +++ b/fastapi_endpoint_context/static/description/index.html @@ -0,0 +1,441 @@ + + + + + +fastapi_endpoint_context + + + +
+

fastapi_endpoint_context

+ + +

Beta License: AGPL-3 OCA/rest-framework Translate me on Weblate Try me on Runboat

+

This module provides an overridable request context for FastAPI +endpoints.

+

It allows to customize the behavior of requests deep in the odoo call +stack according to the current request context without having to +override routers that may come from external modules.

+

This context contains by default the current endpoint app and id, +respectively accessible via +self.env.context.get('fastapi_endpoint_app') and +self.env.context.get('fastapi_endpoint_id').

+

Table of contents

+ +
+

Usage

+

odoo_env dependency is automatically overridden to include FastAPI +endpoint context values.

+

You can override the fastapi.endpoint->_get_app_context() +method to add custom values to the context for your applications.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

paradoxxxzero

+

This module is part of the OCA/rest-framework project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/fastapi_endpoint_context/tests/__init__.py b/fastapi_endpoint_context/tests/__init__.py new file mode 100644 index 000000000..4758f65e6 --- /dev/null +++ b/fastapi_endpoint_context/tests/__init__.py @@ -0,0 +1 @@ +from . import test_fastapi_endpoint_context diff --git a/fastapi_endpoint_context/tests/test_fastapi_endpoint_context.py b/fastapi_endpoint_context/tests/test_fastapi_endpoint_context.py new file mode 100644 index 000000000..6488a94d2 --- /dev/null +++ b/fastapi_endpoint_context/tests/test_fastapi_endpoint_context.py @@ -0,0 +1,51 @@ +# Copyright 2025 Akretion (http://www.akretion.com). +# @author Florian Mounier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from typing import Annotated + +from requests import Response + +from odoo.api import Environment + +from odoo.addons.fastapi.dependencies import odoo_env +from odoo.addons.fastapi.routers import demo_router +from odoo.addons.fastapi.tests.common import FastAPITransactionCase + +from fastapi import Depends, status + + +# Extend the demo router to have an endpoint that returns the odoo env context +@demo_router.get("/demo/context") +async def get_context(env: Annotated[Environment, Depends(odoo_env)]) -> dict: + """Returns the odoo env context""" + return env.context + + +class FastAPIEndpointContextCase(FastAPITransactionCase): + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + cls.default_fastapi_router = demo_router + cls.default_fastapi_running_user = cls.env.ref("fastapi.my_demo_app_user") + cls.endpoint = cls.env.ref("fastapi.fastapi_endpoint_demo") + cls.default_fastapi_app = cls.endpoint._get_app() + cls.default_fastapi_dependency_overrides = { + k: v + for k, v in cls.default_fastapi_app.dependency_overrides.items() + if k.__name__ != "authenticated_partner_impl" + } + cls.default_fastapi_authenticated_partner = cls.env["res.partner"].create( + {"name": "FastAPI Demo"} + ) + + def test_context(self) -> None: + with self._create_test_client() as test_client: + response: Response = test_client.get("/demo/context") + self.assertEqual(response.status_code, status.HTTP_200_OK) + ctx = response.json() + self.assertEqual( + ctx.get("fastapi_endpoint_id"), + self.env.ref("fastapi.fastapi_endpoint_demo").id, + ) + self.assertEqual(ctx.get("fastapi_app"), "demo") diff --git a/setup/fastapi_endpoint_context/odoo/addons/fastapi_endpoint_context b/setup/fastapi_endpoint_context/odoo/addons/fastapi_endpoint_context new file mode 120000 index 000000000..8861f1c5b --- /dev/null +++ b/setup/fastapi_endpoint_context/odoo/addons/fastapi_endpoint_context @@ -0,0 +1 @@ +../../../../fastapi_endpoint_context \ No newline at end of file diff --git a/setup/fastapi_endpoint_context/setup.py b/setup/fastapi_endpoint_context/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/fastapi_endpoint_context/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)