Skip to content

Commit

Permalink
Merge PR #3206 into 18.0
Browse files Browse the repository at this point in the history
Signed-off-by simahawk
  • Loading branch information
OCA-git-bot committed Feb 24, 2025
2 parents e697148 + 05abf85 commit e11e694
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .oca/oca-port/blacklist/jsonifier.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"pull_requests": {
"OCA/server-tools#2762": "already ported"
}
}
5 changes: 3 additions & 2 deletions jsonifier/models/ir_exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,16 @@ def get_json_parser(self):
if line.target:
names = line.target.split("/")
function = line.instance_method_name
options = {"resolver": line.resolver_id, "function": function}
# resolver must be passed as ID to avoid cache issues
options = {"resolver": line.resolver_id.id, "function": function}
update_dict(dict_parser, names, options)
lang_parsers[lang] = convert_dict(dict_parser)
if list(lang_parsers.keys()) == [False]:
parser["fields"] = lang_parsers[False]
else:
parser["langs"] = lang_parsers
if self.global_resolver_id:
parser["resolver"] = self.global_resolver_id
parser["resolver"] = self.global_resolver_id.id
if self.language_agnostic:
parser["language_agnostic"] = self.language_agnostic
return parser
48 changes: 30 additions & 18 deletions jsonifier/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,19 @@ def _add_json_key(self, values, json_key, value):
def _jsonify_record(self, parser, rec, root):
"""JSONify one record (rec). Private function called by jsonify."""
strict = self.env.context.get("jsonify_record_strict", False)
for field in parser:
field_dict, subparser = rec.__parse_field(field)
for field_key in parser:
field_dict, subparser = rec.__parse_field(field_key)
function = field_dict.get("function")
try:
self._jsonify_record_validate_field(rec, field_dict, strict)
except SwallableException:
continue
if not function:
# If we have a function we can use it to get the value
# even if the field is not available.
# If not, well there's nothing we can do.
continue
json_key = field_dict.get("target", field_dict["name"])
if field_dict.get("function"):
if function:
try:
value = self._jsonify_record_handle_function(
rec, field_dict, strict
Expand All @@ -97,6 +102,9 @@ def _jsonify_record(self, parser, rec, root):
value = rec._jsonify_value(field, rec[field.name])
resolver = field_dict.get("resolver")
if resolver:
if isinstance(resolver, int):
# cached versions of the parser are stored as integer
resolver = self.env["ir.exports.resolver"].browse(resolver)
value, json_key = self._jsonify_record_handle_resolver(
rec, field, resolver, json_key
)
Expand All @@ -116,15 +124,15 @@ def _jsonify_record_validate_field(self, rec, field_dict, strict):
if strict:
# let it fail
rec._fields[field_name] # pylint: disable=pointless-statement
if not tools.config["test_enable"]:
# If running live, log proper error
# so that techies can track it down
_logger.error(
"%(model)s.%(fname)s not available",
{"model": self._name, "fname": field_name},
)
else:
if not tools.config["test_enable"]:
# If running live, log proper error
# so that techies can track it down
_logger.warning(
"%(model)s.%(fname)s not available",
{"model": self._name, "fname": field_name},
)
raise SwallableException()

return True

def _jsonify_record_handle_function(self, rec, field_dict, strict):
Expand Down Expand Up @@ -203,16 +211,20 @@ def jsonify(self, parser, one=False, with_fieldname=False):
if isinstance(parser, list):
parser = convert_simple_to_full_parser(parser)
resolver = parser.get("resolver")

if isinstance(resolver, int):
# cached versions of the parser are stored as integer
resolver = self.env["ir.exports.resolver"].browse(resolver)
results = [{} for record in self]
parsers = {False: parser["fields"]} if "fields" in parser else parser["langs"]
for lang in parsers:
translate = lang or parser.get("language_agnostic")
records = self.with_context(lang=lang) if translate else self
records = (
records.with_context(with_fieldname=True) if with_fieldname else records
)
for record, json in zip(records, results, strict=True):
new_ctx = {}
if translate:
new_ctx["lang"] = lang
if with_fieldname:
new_ctx["with_fieldname"] = True
records = self.with_context(**new_ctx) if new_ctx else self
for record, json in zip(records, results, strict=False):
self._jsonify_record(parsers[lang], record, json)

if resolver:
Expand Down
67 changes: 57 additions & 10 deletions jsonifier/tests/test_get_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# Simone Orsi <[email protected]>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from unittest import mock

from odoo import tools
from odoo.exceptions import UserError
Expand Down Expand Up @@ -214,6 +213,51 @@ def test_json_export(self):
"_fieldname_partner_latitude": "Geo Latitude",
"create_date": "2019-10-31T14:39:49",
}
expected_json_with_fieldname = {
"_fieldname_lang": "Language",
"lang": "en_US",
"_fieldname_comment": "Notes",
"comment": None,
"_fieldname_partner_latitude": "Geo Latitude",
"_fieldname_name": "Name",
"name": "Akretion",
"_fieldname_color": "Color Index",
"color": 0,
"_fieldname_children": "Contact",
"children": [
{
"_fieldname_children": "Contact",
"children": [],
"_fieldname_email": "Email",
"email": None,
"_fieldname_country": "Country",
"country": {
"_fieldname_code": "Country Code",
"code": "FR",
"_fieldname_name": "Country Name",
"name": "France",
},
"_fieldname_name": "Name",
"name": "Sebatien Beau",
"_fieldname_id": "ID",
"id": self.partner.child_ids.id,
}
],
"_fieldname_country": "Country",
"country": {
"_fieldname_code": "Country Code",
"code": "FR",
"_fieldname_name": "Country Name",
"name": "France",
},
"_fieldname_active": "Active",
"active": True,
"_fieldname_category_id": "Tags",
"category_id": [{"_fieldname_name": "Name", "name": "Inovator"}],
"_fieldname_create_date": "Created on",
"create_date": "2019-10-31T14:39:49",
"partner_latitude": 0.0,
}
json_partner = self.partner.jsonify(parser)
self.assertDictEqual(json_partner[0], expected_json)
json_partner_with_fieldname = self.partner.jsonify(
Expand Down Expand Up @@ -252,10 +296,12 @@ def test_json_export_callable_parser(self):
# callable subparser
("name", lambda rec, fname: rec[fname] + " rocks!"),
("name:custom", "jsonify_custom"),
("unknown_field", lambda rec, fname: "yeah again!"),
]
expected_json = {
"name": "Akretion rocks!",
"custom": "yeah!",
"unknown_field": "yeah again!",
}
json_partner = self.partner.jsonify(parser)
self.assertDictEqual(json_partner[0], expected_json)
Expand Down Expand Up @@ -378,24 +424,25 @@ def test_bad_parsers_strict(self):
def test_bad_parsers_fail_gracefully(self):
rec = self.category

logger_patch_path = "odoo.addons.jsonifier.models.models._logger.error"

# logging is disabled when testing as it's useless and makes build fail.
# logging is disabled when testing as it makes too much noise
tools.config["test_enable"] = False

logger_name = "odoo.addons.jsonifier.models.models"
bad_field_name = ["Name"]
with mock.patch(logger_patch_path) as mocked_logger:
with self.assertLogs(logger=logger_name, level="WARNING") as capt:
rec.jsonify(bad_field_name, one=True)
mocked_logger.assert_called()
self.assertIn("res.partner.category.Name not availabl", capt.output[0])

bad_function_name = {"fields": [{"name": "name", "function": "notafunction"}]}
with mock.patch(logger_patch_path) as mocked_logger:
with self.assertLogs(logger=logger_name, level="WARNING") as capt:
rec.jsonify(bad_function_name, one=True)
mocked_logger.assert_called()
self.assertIn(
"res.partner.category.notafunction not available", capt.output[0]
)

bad_subparser = {"fields": [({"name": "name"}, [{"name": "subparser_name"}])]}
with mock.patch(logger_patch_path) as mocked_logger:
with self.assertLogs(logger=logger_name, level="WARNING") as capt:
rec.jsonify(bad_subparser, one=True)
mocked_logger.assert_called()
self.assertIn("res.partner.category.name not relational", capt.output[0])

tools.config["test_enable"] = True

0 comments on commit e11e694

Please sign in to comment.