Skip to content

Commit 6e3e43e

Browse files
committed
Merge PR #505 into 18.0
Signed-off-by lmignon
2 parents fe25007 + 8e21d8f commit 6e3e43e

20 files changed

+1089
-53
lines changed

base_rest/restapi.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from cerberus import Validator
99

10-
from odoo import _, http
10+
from odoo import http
1111
from odoo.exceptions import UserError, ValidationError
1212

1313
from .tools import ROUTING_DECORATOR_ATTR, cerberus_to_json
@@ -218,13 +218,13 @@ def from_params(self, service, params):
218218
validator = self.get_cerberus_validator(service, "input")
219219
if validator.validate(params):
220220
return validator.document
221-
raise UserError(_("BadRequest %s") % validator.errors)
221+
raise UserError(service.env._("BadRequest %s") % validator.errors)
222222

223223
def to_response(self, service, result):
224224
validator = self.get_cerberus_validator(service, "output")
225225
if validator.validate(result):
226226
return validator.document
227-
raise SystemError(_("Invalid Response %s") % validator.errors)
227+
raise SystemError(service.env._("Invalid Response %s") % validator.errors)
228228

229229
def to_openapi_query_parameters(self, service, spec):
230230
json_schema = self.to_json_schema(service, spec, "input")
@@ -275,7 +275,9 @@ def get_cerberus_validator(self, service, direction):
275275
return schema
276276
if isinstance(schema, dict):
277277
return Validator(schema, purge_unknown=True)
278-
raise Exception(_("Unable to get cerberus schema from %s") % self._schema)
278+
raise Exception(
279+
service.env._("Unable to get cerberus schema from %s") % self._schema
280+
)
279281

280282
def to_json_schema(self, service, spec, direction):
281283
schema = self.get_cerberus_validator(service, direction).schema
@@ -321,7 +323,7 @@ def _do_validate(self, service, data, direction):
321323
for idx, p in enumerate(data):
322324
if not validator.validate(p):
323325
raise ExceptionClass(
324-
_(
326+
service.env._(
325327
"BadRequest item %(idx)s :%(errors)s",
326328
idx=idx,
327329
errors=validator.errors,
@@ -330,7 +332,7 @@ def _do_validate(self, service, data, direction):
330332
values.append(validator.document)
331333
if self._min_items is not None and len(values) < self._min_items:
332334
raise ExceptionClass(
333-
_(
335+
service.env._(
334336
"BadRequest: Not enough items in the list (%(current)s "
335337
"< %(expected)s)",
336338
current=len(values),
@@ -339,7 +341,7 @@ def _do_validate(self, service, data, direction):
339341
)
340342
if self._max_items is not None and len(values) > self._max_items:
341343
raise ExceptionClass(
342-
_(
344+
service.env._(
343345
"BadRequest: Too many items in the list (%(current)s "
344346
"> %(expected)s)",
345347
current=len(values),
@@ -367,7 +369,7 @@ def __init__(self, parts):
367369
:param parts: list of RestMethodParam
368370
"""
369371
if not isinstance(parts, dict):
370-
raise ValidationError(_("You must provide a dict of RestMethodParam"))
372+
raise RuntimeError("You must provide a dict of RestMethodParam")
371373
self._parts = parts
372374

373375
def to_openapi_properties(self, service, spec, direction):
@@ -410,7 +412,7 @@ def from_params(self, service, params):
410412
) # multipart ony sends its parts as string
411413
except json.JSONDecodeError as error:
412414
raise ValidationError(
413-
_(f"{key}'s JSON content is malformed: {error}")
415+
service.env._(f"{key}'s JSON content is malformed: {error}")
414416
) from error
415417
param = part.from_params(service, json_param)
416418
params[key] = param

base_rest/tests/test_cerberus_list_validator.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# Copyright 2020 ACSONE SA/NV
22
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
33

4-
import logging
54
import unittest
65

76
from cerberus import Validator
87

98
from odoo.exceptions import UserError
10-
from odoo.tests.common import BaseCase, MetaCase
9+
from odoo.tests.common import TransactionCase
1110

1211
from ..components.cerberus_validator import BaseRestCerberusValidator
1312
from ..restapi import CerberusListValidator
1413

1514

16-
class TestCerberusListValidator(BaseCase, MetaCase("DummyCase", (object,), {})):
15+
class TestCerberusListValidator(TransactionCase):
1716
"""Test all the methods that must be implemented by CerberusListValidator to
1817
be a valid RestMethodParam"""
1918

@@ -47,18 +46,8 @@ def setUpClass(cls):
4746
schema=cls.nested_schema
4847
)
4948
cls.maxDiff = None
50-
51-
def setUp(self):
52-
super().setUp()
53-
# mute logger
54-
loggers = ["odoo.tools.translate"]
55-
for logger in loggers:
56-
logging.getLogger(logger).addFilter(self)
57-
58-
@self.addCleanup
59-
def un_mute_logger():
60-
for logger_ in loggers:
61-
logging.getLogger(logger_).removeFilter(self)
49+
cls.mock_service = unittest.mock.Mock()
50+
cls.mock_service.env = cls.env
6251

6352
def filter(self, record):
6453
# required to mute logger
@@ -203,15 +192,18 @@ def test_from_params_validation(self):
203192
# minItems / maxItems
204193
with self.assertRaises(UserError):
205194
# minItems = 1
206-
self.simple_schema_list_validator.from_params(None, params=[])
195+
self.simple_schema_list_validator.from_params(self.mock_service, params=[])
207196
with self.assertRaises(UserError):
208197
# maxItems = 2
209198
self.simple_schema_list_validator.from_params(
210-
None, params=[{"name": "test"}, {"name": "test"}, {"name": "test"}]
199+
self.mock_service,
200+
params=[{"name": "test"}, {"name": "test"}, {"name": "test"}],
211201
)
212202
with self.assertRaises(UserError):
213203
# name required
214-
self.simple_schema_list_validator.from_params(None, params=[{}])
204+
self.simple_schema_list_validator.from_params(
205+
self.mock_service, params=[{}]
206+
)
215207

216208
def test_to_response_ignore_unknown(self):
217209
result = [{"name": "test", "unknown": True}]
@@ -223,15 +215,18 @@ def test_to_response_validation(self):
223215
# as a programmatic error not a user error
224216
with self.assertRaises(SystemError):
225217
# minItems = 1
226-
self.simple_schema_list_validator.to_response(None, result=[])
218+
self.simple_schema_list_validator.to_response(self.mock_service, result=[])
227219
with self.assertRaises(SystemError):
228220
# maxItems = 2
229221
self.simple_schema_list_validator.to_response(
230-
None, result=[{"name": "test"}, {"name": "test"}, {"name": "test"}]
222+
self.mock_service,
223+
result=[{"name": "test"}, {"name": "test"}, {"name": "test"}],
231224
)
232225
with self.assertRaises(SystemError):
233226
# name required
234-
self.simple_schema_list_validator.to_response(None, result=[{}])
227+
self.simple_schema_list_validator.to_response(
228+
self.mock_service, result=[{}]
229+
)
235230

236231
def test_schema_lookup_from_string(self):
237232
class MyService:

base_rest/tests/test_cerberus_validator.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
# Copyright 2020 ACSONE SA/NV
22
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
33

4-
import logging
54
import unittest
65

76
from cerberus import Validator
87

98
from odoo.exceptions import UserError
10-
from odoo.tests.common import BaseCase, MetaCase
9+
from odoo.tests.common import TransactionCase
1110

1211
from ..components.cerberus_validator import BaseRestCerberusValidator
1312
from ..restapi import CerberusValidator
1413
from ..tools import cerberus_to_json
1514

1615

17-
class TestCerberusValidator(BaseCase, MetaCase("DummyCase", (object,), {})):
16+
class TestCerberusValidator(TransactionCase):
1817
"""Test all the methods that must be implemented by CerberusValidator to
1918
be a valid RestMethodParam"""
2019

@@ -50,22 +49,8 @@ def setUpClass(cls):
5049
cls.nested_schema_cerberus_validator = CerberusValidator(
5150
schema=cls.nested_schema
5251
)
53-
54-
def setUp(self):
55-
super().setUp()
56-
# mute logger
57-
loggers = ["odoo.tools.translate"]
58-
for logger in loggers:
59-
logging.getLogger(logger).addFilter(self)
60-
61-
@self.addCleanup
62-
def un_mute_logger():
63-
for logger_ in loggers:
64-
logging.getLogger(logger_).removeFilter(self)
65-
66-
def filter(self, record):
67-
# required to mute logger
68-
return 0
52+
cls.mock_service = unittest.mock.Mock()
53+
cls.mock_service.env = cls.env
6954

7055
def test_to_openapi_responses(self):
7156
res = self.simple_schema_cerberus_validator.to_openapi_responses(None, None)
@@ -271,7 +256,9 @@ def test_from_params_ignore_unknown(self):
271256
def test_from_params_validation(self):
272257
# name is required
273258
with self.assertRaises(UserError):
274-
self.simple_schema_cerberus_validator.from_params(None, params={})
259+
self.simple_schema_cerberus_validator.from_params(
260+
self.mock_service, params={}
261+
)
275262

276263
def test_to_response_add_default(self):
277264
result = {"name": "test"}
@@ -288,7 +275,9 @@ def test_to_response_validation(self):
288275
# If a response is not conform to the expected schema it's considered
289276
# as a programmatic error not a user error
290277
with self.assertRaises(SystemError):
291-
self.simple_schema_cerberus_validator.to_response(None, result={})
278+
self.simple_schema_cerberus_validator.to_response(
279+
self.mock_service, result={}
280+
)
292281

293282
def test_schema_lookup_from_string(self):
294283
class MyService:

base_rest_pydantic/README.rst

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
===================
2+
Base Rest Datamodel
3+
===================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:ed7868cc1a1d1a63a8b53b8e25e19ed162638e6f7eb3246bcc6cad2c5c0ca1a6
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
18+
:alt: License: LGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github
20+
:target: https://github.com/OCA/rest-framework/tree/18.0/base_rest_pydantic
21+
:alt: OCA/rest-framework
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/rest-framework-18-0/rest-framework-18-0-base_rest_pydantic
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=18.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This addon allows you to use Pydantic objects as params and/or response
32+
with your REST API methods.
33+
34+
**Table of contents**
35+
36+
.. contents::
37+
:local:
38+
39+
Usage
40+
=====
41+
42+
To use Pydantic instances as request and/or response of a REST service
43+
endpoint you must:
44+
45+
- Define your Pydantic classes;
46+
- Provides the information required to the
47+
``odoo.addons.base_rest.restapi.method`` decorator;
48+
49+
.. code:: python
50+
51+
from odoo.addons.base_rest import restapi
52+
from odoo.addons.component.core import Component
53+
from odoo.addons.pydantic.models import BaseModel
54+
55+
class PingMessage(BaseModel):
56+
message: str
57+
58+
59+
class PingService(Component):
60+
_inherit = 'base.rest.service'
61+
_name = 'ping.service'
62+
_usage = 'ping'
63+
_collection = 'my_module.services'
64+
65+
66+
@restapi.method(
67+
[(["/pong"], "GET")],
68+
input_param=restapi.PydanticModel(PingMessage),
69+
output_param=restapi.PydanticModel(PingMessage),
70+
auth="public",
71+
)
72+
def pong(self, ping_message):
73+
return PingMessage(message = "Received: " + ping_message.message)
74+
75+
Bug Tracker
76+
===========
77+
78+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rest-framework/issues>`_.
79+
In case of trouble, please check there if your issue has already been reported.
80+
If you spotted it first, help us to smash it by providing a detailed and welcomed
81+
`feedback <https://github.com/OCA/rest-framework/issues/new?body=module:%20base_rest_pydantic%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
82+
83+
Do not contact contributors directly about support or help with technical issues.
84+
85+
Credits
86+
=======
87+
88+
Authors
89+
-------
90+
91+
* ACSONE SA/NV
92+
93+
Contributors
94+
------------
95+
96+
- Laurent Mignon <[email protected]>
97+
98+
Maintainers
99+
-----------
100+
101+
This module is maintained by the OCA.
102+
103+
.. image:: https://odoo-community.org/logo.png
104+
:alt: Odoo Community Association
105+
:target: https://odoo-community.org
106+
107+
OCA, or the Odoo Community Association, is a nonprofit organization whose
108+
mission is to support the collaborative development of Odoo features and
109+
promote its widespread use.
110+
111+
This module is part of the `OCA/rest-framework <https://github.com/OCA/rest-framework/tree/18.0/base_rest_pydantic>`_ project on GitHub.
112+
113+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

base_rest_pydantic/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import restapi

base_rest_pydantic/__manifest__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021 ACSONE SA/NV
2+
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
3+
4+
{
5+
"name": "Base Rest Datamodel",
6+
"summary": """
7+
Pydantic binding for base_rest""",
8+
"version": "18.0.1.0.0",
9+
"license": "LGPL-3",
10+
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
11+
"website": "https://github.com/OCA/rest-framework",
12+
"depends": ["base_rest"],
13+
"external_dependencies": {
14+
"python": [
15+
"pydantic>=2.0.0",
16+
]
17+
},
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * base_rest_datamodel
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 14.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"Last-Translator: \n"
10+
"Language-Team: \n"
11+
"MIME-Version: 1.0\n"
12+
"Content-Type: text/plain; charset=UTF-8\n"
13+
"Content-Transfer-Encoding: \n"
14+
"Plural-Forms: \n"
15+
16+
#. module: base_rest_datamodel
17+
#: code:addons/base_rest_datamodel/restapi.py:0
18+
#, python-format
19+
msgid "BadRequest %s"
20+
msgstr ""
21+
22+
#. module: base_rest_datamodel
23+
#: code:addons/base_rest_datamodel/restapi.py:0
24+
#, python-format
25+
msgid "Invalid Response %s"
26+
msgstr ""

0 commit comments

Comments
 (0)