-
-
Notifications
You must be signed in to change notification settings - Fork 329
[18.0][MIG] graphql_base: Migration to 18.0 #474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ajay-odoogap
wants to merge
36
commits into
OCA:18.0
Choose a base branch
from
odoogap:18.0-mig-graphql_base
base: 18.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
0df45fb
[ADD] graphql_base and graphql_demo
sbidoul b99a1b0
graphql: more documentation
sbidoul d4d46ad
graphql: add development_status and maintainers
sbidoul 16fda01
graphql: improve and test error handling
sbidoul 8c3fce2
graphql: fix typos in documentation
sbidoul ae882d3
[UPD] README.rst
OCA-git-bot 38ef684
[FIX] graphql: controller must rollback in case of error
sbidoul 5c61249
[FIX] graphql: readme lint
sbidoul 2085e7b
[UPD] README.rst
OCA-git-bot d338f26
[UPD] README.rst
OCA-git-bot eb370ff
black, isort pre-commit
lmignon 6175f19
[MIG] 13.0 branch creation
lmignon db35360
[MIG] graphql_base, graphql_demo from 12 to 13
sbidoul 52ef411
[UPD] README.rst
OCA-git-bot d386c63
[UPD] README.rst
OCA-git-bot 5ba5577
Initialize 14.0 branch
lmignon 6cc1d06
[MIG] Migration to version 14.0: graphql_base
qgroulard 8f959ef
[UPD] Update graphql_base.pot
oca-travis 803ec42
[UPD] README.rst
OCA-git-bot b281e60
Forward port from 14.0
lmignon 8c84eb3
[MIG] [16.0] base_graphql
28180f2
[UPD] Update graphql_base.pot
7716184
[UPD] README.rst
OCA-git-bot 1b7b4a8
graphql_base 16.0.1.0.1
OCA-git-bot 6aedbc8
[UPD] README.rst
OCA-git-bot 44c73f0
[MIG] mark all modules installable=False
sbidoul 5f46cd0
Added translation using Weblate (Italian)
mymage 7193bdf
Translated using Weblate (Italian)
mymage 7b1c6b3
[MIG] graphql_base: Migration to 17.0
dduarte-odoogap fb24d97
[FIX] graphql_base: rename types.py
sbidoul 5962125
[UPD] Update graphql_base.pot
ecc1c99
[BOT] post-merge updates
OCA-git-bot 088fb2f
[IMP] graphql_base: pre-commit auto fixes
ajay-odoogap 3573975
[MIG] graphql_base: Migration to 18.0
ajay-odoogap 7a1bfa7
Merge branch '18.0' into 18.0-mig-graphql_base
ajay-odoogap 414242d
[IMP] graphql_base: pre-commit auto fixes
ajay-odoogap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
============ | ||
Graphql Base | ||
============ | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:7550bc59f47cae17ac3a8ac5e3340fd5e11cdefbc421215be6447377d282a85e | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Production/Stable | ||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||
:alt: License: LGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github | ||
:target: https://github.com/OCA/rest-framework/tree/18.0/graphql_base | ||
: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-18-0/rest-framework-18-0-graphql_base | ||
: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=18.0 | ||
:alt: Try me on Runboat | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
This modules enables the creation of `GraphQL <https://graphql.org/>`__ | ||
endpoints. In itself, it does nothing and must be used by a developer to | ||
create the GraphQL schema and resolvers using | ||
`graphene <https://graphene-python.org/>`__, and expose them through a | ||
controller. An example is available in the ``graphql_demo`` module. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Usage | ||
===== | ||
|
||
To use this module, you need to | ||
|
||
- create your graphene schema | ||
- create your controller to expose your GraphQL endpoint, and | ||
optionally a GraphiQL IDE. | ||
|
||
This module does not attempt to expose the whole Odoo object model. This | ||
could be the purpose of another module based on this one. We believe | ||
however that it is preferable to expose a specific well tested endpoint | ||
for each customer, so as to reduce coupling by knowing precisely what is | ||
exposed and needs to be tested when upgrading Odoo. | ||
|
||
To start working with this module, we recommend the following approach: | ||
|
||
- Learn `GraphQL basics <https://graphql.org/learn/>`__ | ||
- Learn `graphene <https://graphene-python.org/>`__, the python library | ||
used to create GraphQL schemas and resolvers. | ||
- Examine the ``graphql_demo`` module in this repo, copy it, adapt the | ||
controller to suit your needs (routes, authentication methods). | ||
- Start building your own schema and resolver. | ||
|
||
Building your schema | ||
-------------------- | ||
|
||
The schema can be built using native graphene types. An | ||
``odoo.addons.graphql_base.types.OdooObjectType`` is provided as a | ||
convenience. It is a graphene ``ObjectType`` with a default attribute | ||
resolver which: | ||
|
||
- converts False to None (except for Boolean types), to avoid Odoo's | ||
weird ``False`` strings being rendered as json ``"false"``; | ||
- adds the user timezone to Datetime fields; | ||
- raises an error if an attribute is absent to avoid field name typing | ||
errors. | ||
|
||
Creating GraphQL controllers | ||
---------------------------- | ||
|
||
The module provides an | ||
``odoo.addons.graphql_base.GraphQLControllerMixin`` class to help you | ||
build GraphQL controllers providing GraphiQL and/or GraphQL endpoints. | ||
|
||
.. code:: python | ||
|
||
from odoo import http | ||
from odoo.addons.graphql_base import GraphQLControllerMixin | ||
|
||
from ..schema import schema | ||
|
||
|
||
class GraphQLController(http.Controller, GraphQLControllerMixin): | ||
|
||
# The GraphiQL route, providing an IDE for developers | ||
@http.route("/graphiql/demo", auth="user") | ||
def graphiql(self, **kwargs): | ||
return self._handle_graphiql_request(schema) | ||
|
||
# The graphql route, for applications. | ||
# Note csrf=False: you may want to apply extra security | ||
# (such as origin restrictions) to this route. | ||
@http.route("/graphql/demo", auth="user", csrf=False) | ||
def graphql(self, **kwargs): | ||
return self._handle_graphql_request(schema) | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rest-framework/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 <https://github.com/OCA/rest-framework/issues/new?body=module:%20graphql_base%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
------- | ||
|
||
* ACSONE SA/NV | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* Ajay Javiya <[email protected]> | ||
|
||
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-sbidoul| image:: https://github.com/sbidoul.png?size=40px | ||
:target: https://github.com/sbidoul | ||
:alt: sbidoul | ||
|
||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__: | ||
|
||
|maintainer-sbidoul| | ||
|
||
This module is part of the `OCA/rest-framework <https://github.com/OCA/rest-framework/tree/18.0/graphql_base>`_ project on GitHub. | ||
|
||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Copyright 2018 ACSONE SA/NV | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from .controllers import GraphQLControllerMixin | ||
from .graphene_types import OdooObjectType, odoo_attr_resolver |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Copyright 2018 ACSONE SA/NV | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
{ | ||
"name": "Graphql Base", | ||
"summary": """ | ||
Base GraphQL/GraphiQL controller""", | ||
"version": "18.0.1.0.0", | ||
"license": "LGPL-3", | ||
"author": "ACSONE SA/NV,Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/rest-framework", | ||
"depends": ["base"], | ||
"data": ["views/graphiql.xml"], | ||
"external_dependencies": {"python": ["graphene", "graphql_server"]}, | ||
"development_status": "Production/Stable", | ||
"maintainers": ["sbidoul"], | ||
"installable": True, | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .main import GraphQLControllerMixin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Copyright 2018 ACSONE SA/NV | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from functools import partial | ||
|
||
from graphql_server import ( | ||
HttpQueryError, | ||
encode_execution_results, | ||
format_error_default, | ||
json_encode, | ||
load_json_body, | ||
run_http_query, | ||
) | ||
|
||
from odoo import http | ||
|
||
|
||
class GraphQLControllerMixin: | ||
def _parse_body(self): | ||
req = http.request.httprequest | ||
# We use mimetype here since we don't need the other | ||
# information provided by content_type | ||
content_type = req.mimetype | ||
if content_type == "application/graphql": | ||
return {"query": req.data.decode("utf8")} | ||
elif content_type == "application/json": | ||
return load_json_body(req.data.decode("utf8")) | ||
elif content_type in ( | ||
"application/x-www-form-urlencoded", | ||
"multipart/form-data", | ||
): | ||
return http.request.params | ||
return {} | ||
|
||
def _process_request(self, schema, data): | ||
try: | ||
request = http.request.httprequest | ||
execution_results, all_params = run_http_query( | ||
schema, | ||
request.method.lower(), | ||
data, | ||
query_data=request.args, | ||
batch_enabled=False, | ||
catch=False, | ||
context_value={"env": http.request.env}, | ||
) | ||
result, status_code = encode_execution_results( | ||
execution_results, | ||
is_batch=isinstance(data, list), | ||
format_error=format_error_default, | ||
encode=partial(json_encode, pretty=False), | ||
) | ||
headers = dict() | ||
headers["Content-Type"] = "application/json" | ||
response = http.request.make_response(result, headers=headers) | ||
response.status_code = status_code | ||
if any(er.errors for er in execution_results): | ||
env = http.request.env | ||
env.cr.rollback() | ||
env.clear() | ||
return response | ||
except HttpQueryError as e: | ||
result = json_encode({"errors": [{"message": str(e)}]}) | ||
headers = dict() | ||
headers["Content-Type"] = "application/json" | ||
response = http.request.make_response(result, headers=headers) | ||
response.status_code = e.status_code | ||
env = http.request.env | ||
env.cr.rollback() | ||
env.clear() | ||
return response | ||
|
||
def _handle_graphql_request(self, schema): | ||
data = self._parse_body() | ||
return self._process_request(schema, data) | ||
|
||
def _handle_graphiql_request(self, schema): | ||
req = http.request.httprequest | ||
if req.method == "GET" and req.accept_mimetypes.accept_html: | ||
return http.request.render("graphql_base.graphiql", {}) | ||
# this way of passing a GraphQL query over http is not spec compliant | ||
# (https://graphql.org/learn/serving-over-http/), but we use | ||
# this only for our GraphiQL UI, and it works with Odoo's way | ||
# of passing the csrf token | ||
return self._process_request(schema, http.request.params) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Copyright 2018 ACSONE SA/NV | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
import graphene | ||
|
||
from odoo import fields | ||
|
||
|
||
def odoo_attr_resolver(attname, default_value, root, info, **args): | ||
"""An attr resolver that is specialized for Odoo recordsets. | ||
|
||
It converts False to None, except for Odoo Boolean fields. | ||
This is necessary because Odoo null values are often represented | ||
as False, and graphene would convert a String field with value False | ||
to "false". | ||
|
||
It converts datetimes to the user timezone. | ||
|
||
It also raises an error if the attribute is not present, ignoring | ||
any default value, so as to return if the schema declares a field | ||
that is not present in the underlying Odoo model. | ||
""" | ||
value = getattr(root, attname) | ||
field = root._fields.get(attname) | ||
if value is False: | ||
if not isinstance(field, fields.Boolean): | ||
return None | ||
elif isinstance(field, fields.Datetime): | ||
return fields.Datetime.context_timestamp(root, value) | ||
return value | ||
|
||
|
||
class OdooObjectType(graphene.ObjectType): | ||
"""A graphene ObjectType with an Odoo aware default resolver.""" | ||
|
||
@classmethod | ||
def __init_subclass_with_meta__(cls, default_resolver=None, **options): | ||
if default_resolver is None: | ||
default_resolver = odoo_attr_resolver | ||
|
||
return super().__init_subclass_with_meta__( | ||
default_resolver=default_resolver, **options | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * graphql_base | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 17.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"Last-Translator: \n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" | ||
|
||
#. module: graphql_base | ||
#: model_terms:ir.ui.view,arch_db:graphql_base.graphiql | ||
msgid "Loading..." | ||
msgstr "" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * graphql_base | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 16.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"PO-Revision-Date: 2024-01-15 17:34+0000\n" | ||
"Last-Translator: mymage <[email protected]>\n" | ||
"Language-Team: none\n" | ||
"Language: it\n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: nplurals=2; plural=n != 1;\n" | ||
"X-Generator: Weblate 4.17\n" | ||
|
||
#. module: graphql_base | ||
#: model_terms:ir.ui.view,arch_db:graphql_base.graphiql | ||
msgid "Loading..." | ||
msgstr "Caricamento ..." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[build-system] | ||
requires = ["whool"] | ||
build-backend = "whool.buildapi" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This modules enables the creation of [GraphQL](https://graphql.org/) | ||
endpoints. In itself, it does nothing and must be used by a developer to | ||
create the GraphQL schema and resolvers using | ||
[graphene](https://graphene-python.org/), and expose them through a | ||
controller. An example is available in the `graphql_demo` module. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you change this line?