[REF] base_jsonify: review changes
parent
74a4c2c713
commit
d30ea05fcf
|
@ -80,7 +80,7 @@ Also the module provide a method "get_json_parser" on the ir.exports object
|
||||||
that generate a parser from an ir.exports configuration.
|
that generate a parser from an ir.exports configuration.
|
||||||
|
|
||||||
Further features are available for advanced uses.
|
Further features are available for advanced uses.
|
||||||
It defines a simple "resolver" model that has a "python_code" field and an eval
|
It defines a simple "resolver" model that has a "python_code" field and a resolve
|
||||||
function so that arbitrary functions can be configured to transform fields,
|
function so that arbitrary functions can be configured to transform fields,
|
||||||
or process the resulting dictionary.
|
or process the resulting dictionary.
|
||||||
It is also to specify a lang to extract the translation of any given field.
|
It is also to specify a lang to extract the translation of any given field.
|
||||||
|
@ -152,12 +152,12 @@ If the global resolver is given, then the json_dict goes through:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
resolver.eval(dict, record)
|
resolver.resolve(dict, record)
|
||||||
|
|
||||||
Which allows to add external data from the context or transform the dictionary
|
Which allows to add external data from the context or transform the dictionary
|
||||||
if necessary. Similarly if given for a field the resolver evaluates the result.
|
if necessary. Similarly if given for a field the resolver evaluates the result.
|
||||||
|
|
||||||
It is possible for a target to end with a '*':
|
It is possible for a target to have a marshaller by ending the target with '=list':
|
||||||
in that case the result is put into a list.
|
in that case the result is put into a list.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -165,8 +165,8 @@ in that case the result is put into a list.
|
||||||
parser = {
|
parser = {
|
||||||
fields: [
|
fields: [
|
||||||
{'name': 'name'},
|
{'name': 'name'},
|
||||||
{'name': 'field_1', 'target': 'customTags*'},
|
{'name': 'field_1', 'target': 'customTags=list'},
|
||||||
{'name': 'field_2', 'target': 'customTags*'},
|
{'name': 'field_2', 'target': 'customTags=list'},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from openupgradelib import openupgrade
|
||||||
|
|
||||||
def migrate(cr, version):
|
|
||||||
query = """ALTER TABLE "ir_exports_line" RENAME COLUMN "alias" TO "target";"""
|
@openupgrade.migrate()
|
||||||
cr.execute(query)
|
def migrate(env, version):
|
||||||
|
openupgrade.rename_columns(env.cr, {"ir_exports_line": [("alias", "target")]})
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from . import utils
|
||||||
from . import models
|
from . import models
|
||||||
from . import ir_export
|
from . import ir_export
|
||||||
from . import ir_exports_line
|
from . import ir_exports_line
|
||||||
|
|
|
@ -8,9 +8,9 @@ from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
def partition(l, accessor):
|
def partition(l, accessor):
|
||||||
"""Partition an iterable (e.g. a recordset) according to an accessor (e.g. a lambda)
|
"""Partition a recordset according to an accessor (e.g. a lambda).
|
||||||
Return a dictionary whose keys are the values obtained from accessor, and values
|
Returns a dictionary whose keys are the values obtained from accessor,
|
||||||
are the items that have this value.
|
and values are the items that have this value.
|
||||||
Example: partition([{"name": "ax"}, {"name": "by"}], lambda x: "x" in x["name"])
|
Example: partition([{"name": "ax"}, {"name": "by"}], lambda x: "x" in x["name"])
|
||||||
=> {True: [{"name": "ax"}], False: [{"name": "by"}]}
|
=> {True: [{"name": "ax"}], False: [{"name": "by"}]}
|
||||||
"""
|
"""
|
||||||
|
@ -61,6 +61,7 @@ def convert_dict(dict_parser):
|
||||||
|
|
||||||
|
|
||||||
def field_dict(field, options=None):
|
def field_dict(field, options=None):
|
||||||
|
"""Create a parser dict for the field field."""
|
||||||
result = {"name": field.split(":")[0]}
|
result = {"name": field.split(":")[0]}
|
||||||
if len(field.split(":")) > 1:
|
if len(field.split(":")) > 1:
|
||||||
result["target"] = field.split(":")[1]
|
result["target"] = field.split(":")[1]
|
||||||
|
@ -93,7 +94,7 @@ class IrExport(models.Model):
|
||||||
The final parser can be used to "jsonify" records of ir.export's model.
|
The final parser can be used to "jsonify" records of ir.export's model.
|
||||||
"""
|
"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
parser = {"language_agnostic": self.language_agnostic}
|
parser = {}
|
||||||
lang_to_lines = partition(self.export_fields, lambda l: l.lang_id.code)
|
lang_to_lines = partition(self.export_fields, lambda l: l.lang_id.code)
|
||||||
lang_parsers = {}
|
lang_parsers = {}
|
||||||
for lang in lang_to_lines:
|
for lang in lang_to_lines:
|
||||||
|
@ -102,7 +103,8 @@ class IrExport(models.Model):
|
||||||
names = line.name.split("/")
|
names = line.name.split("/")
|
||||||
if line.target:
|
if line.target:
|
||||||
names = line.target.split("/")
|
names = line.target.split("/")
|
||||||
options = {"resolver": line.resolver_id, "function": line.function}
|
function = line.instance_method_name
|
||||||
|
options = {"resolver": line.resolver_id, "function": function}
|
||||||
update_dict(dict_parser, names, options)
|
update_dict(dict_parser, names, options)
|
||||||
lang_parsers[lang] = convert_dict(dict_parser)
|
lang_parsers[lang] = convert_dict(dict_parser)
|
||||||
if list(lang_parsers.keys()) == [False]:
|
if list(lang_parsers.keys()) == [False]:
|
||||||
|
@ -111,4 +113,6 @@ class IrExport(models.Model):
|
||||||
parser["langs"] = lang_parsers
|
parser["langs"] = lang_parsers
|
||||||
if self.global_resolver_id:
|
if self.global_resolver_id:
|
||||||
parser["resolver"] = self.global_resolver_id
|
parser["resolver"] = self.global_resolver_id
|
||||||
|
if self.language_agnostic:
|
||||||
|
parser["language_agnostic"] = self.language_agnostic
|
||||||
return parser
|
return parser
|
||||||
|
|
|
@ -24,19 +24,18 @@ class IrExportsLine(models.Model):
|
||||||
string="Custom resolver",
|
string="Custom resolver",
|
||||||
help="If set, will apply the resolver on the field value",
|
help="If set, will apply the resolver on the field value",
|
||||||
)
|
)
|
||||||
function = fields.Char(
|
instance_method_name = fields.Char(
|
||||||
comodel_name="ir.exports.resolver",
|
comodel_name="ir.exports.resolver",
|
||||||
string="Function",
|
string="Function",
|
||||||
help="A method defined on the model that takes a record and a field_name",
|
help="A method defined on the model that takes a record and a field_name",
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.constrains("resolver_id", "function")
|
@api.constrains("resolver_id", "instance_method_name")
|
||||||
def _check_function_resolver(self):
|
def _check_function_resolver(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.resolver_id and rec.function:
|
if rec.resolver_id and rec.instance_method_name:
|
||||||
raise ValidationError(
|
msg = _("Either set a function or a resolver, not both.")
|
||||||
_("Either set a function or a resolver, not both.")
|
raise ValidationError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
@api.constrains("target", "name")
|
@api.constrains("target", "name")
|
||||||
def _check_target(self):
|
def _check_target(self):
|
||||||
|
|
|
@ -21,7 +21,7 @@ class FieldResolver(models.Model):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_name = "ir.exports.resolver"
|
_name = "ir.exports.resolver"
|
||||||
_description = "Resolver"
|
_description = "Export Resolver"
|
||||||
|
|
||||||
name = fields.Char()
|
name = fields.Char()
|
||||||
type = fields.Selection([("field", "Field"), ("global", "Global")])
|
type = fields.Selection([("field", "Field"), ("global", "Global")])
|
||||||
|
@ -31,7 +31,7 @@ class FieldResolver(models.Model):
|
||||||
help="\n".join(help_message),
|
help="\n".join(help_message),
|
||||||
)
|
)
|
||||||
|
|
||||||
def eval(self, param, records):
|
def resolve(self, param, records):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
result = []
|
result = []
|
||||||
context = records.env.context
|
context = records.env.context
|
||||||
|
|
|
@ -9,6 +9,8 @@ from odoo import api, fields, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
from odoo.tools.translate import _
|
from odoo.tools.translate import _
|
||||||
|
|
||||||
|
from .utils import convert_simple_to_full_parser
|
||||||
|
|
||||||
|
|
||||||
class Base(models.AbstractModel):
|
class Base(models.AbstractModel):
|
||||||
|
|
||||||
|
@ -19,32 +21,6 @@ class Base(models.AbstractModel):
|
||||||
"""Deduct how to handle a field from its parser."""
|
"""Deduct how to handle a field from its parser."""
|
||||||
return parser_field if isinstance(parser_field, tuple) else (parser_field, None)
|
return parser_field if isinstance(parser_field, tuple) else (parser_field, None)
|
||||||
|
|
||||||
@api.model
|
|
||||||
def convert_simple_to_full_parser(self, parser):
|
|
||||||
def _f(f, function=None):
|
|
||||||
field_split = f.split(":")
|
|
||||||
field_dict = {"name": field_split[0]}
|
|
||||||
if len(field_split) > 1:
|
|
||||||
field_dict["target"] = field_split[1]
|
|
||||||
if function:
|
|
||||||
field_dict["function"] = function
|
|
||||||
return field_dict
|
|
||||||
|
|
||||||
def _convert_parser(parser):
|
|
||||||
result = []
|
|
||||||
for line in parser:
|
|
||||||
if isinstance(line, str):
|
|
||||||
result.append(_f(line))
|
|
||||||
else:
|
|
||||||
f, sub = line
|
|
||||||
if callable(sub) or isinstance(sub, str):
|
|
||||||
result.append(_f(f, sub))
|
|
||||||
else:
|
|
||||||
result.append((_f(f), _convert_parser(sub)))
|
|
||||||
return result
|
|
||||||
|
|
||||||
return {"language_agnostic": False, "fields": _convert_parser(parser)}
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _jsonify_bad_parser_error(self, field_name):
|
def _jsonify_bad_parser_error(self, field_name):
|
||||||
raise UserError(_("Wrong parser configuration for field: `%s`") % field_name)
|
raise UserError(_("Wrong parser configuration for field: `%s`") % field_name)
|
||||||
|
@ -59,9 +35,8 @@ class Base(models.AbstractModel):
|
||||||
return self._jsonify_bad_parser_error(field_name)
|
return self._jsonify_bad_parser_error(field_name)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _jsonify_value(self, record, field, resolver):
|
def _jsonify_value(self, field, value):
|
||||||
# TODO: we should get default by field (eg: char field -> "")
|
"""Override this function to support new field types."""
|
||||||
value = record[field.name]
|
|
||||||
if value is False and field.type != "boolean":
|
if value is False and field.type != "boolean":
|
||||||
value = None
|
value = None
|
||||||
elif field.type == "date":
|
elif field.type == "date":
|
||||||
|
@ -71,18 +46,26 @@ class Base(models.AbstractModel):
|
||||||
value = fields.Datetime.to_datetime(value)
|
value = fields.Datetime.to_datetime(value)
|
||||||
# Get the timestamp converted to the client's timezone.
|
# Get the timestamp converted to the client's timezone.
|
||||||
# This call also add the tzinfo into the datetime object
|
# This call also add the tzinfo into the datetime object
|
||||||
value = fields.Datetime.context_timestamp(record, value)
|
value = fields.Datetime.context_timestamp(self, value)
|
||||||
value = value.isoformat()
|
value = value.isoformat()
|
||||||
return self._resolve(resolver, field, record)[0] if resolver else value
|
return value
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _resolve(self, resolver, *args):
|
def _add_json_key(self, values, json_key, value):
|
||||||
if isinstance(resolver, int):
|
"""To manage defaults, you can use a specific resolver."""
|
||||||
resolver = self.env["ir.exports.resolver"].browse(resolver)
|
key_marshaller = json_key.split("=")
|
||||||
return resolver.eval(*args)
|
key = key_marshaller[0]
|
||||||
|
marshaller = key_marshaller[1] if len(key_marshaller) > 1 else None
|
||||||
|
if marshaller == "list": # sublist field
|
||||||
|
if not values.get(key):
|
||||||
|
values[key] = []
|
||||||
|
values[key].append(value)
|
||||||
|
else:
|
||||||
|
values[key] = value
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _jsonify_record(self, parser, rec, root):
|
def _jsonify_record(self, parser, rec, root):
|
||||||
|
"""Jsonify one record (rec). Private function called by jsonify."""
|
||||||
for field in parser:
|
for field in parser:
|
||||||
field_dict, subparser = rec.__parse_field(field)
|
field_dict, subparser = rec.__parse_field(field)
|
||||||
field_name = field_dict["name"]
|
field_name = field_dict["name"]
|
||||||
|
@ -100,14 +83,11 @@ class Base(models.AbstractModel):
|
||||||
if field.type in ("many2one", "reference"):
|
if field.type in ("many2one", "reference"):
|
||||||
value = value[0] if value else None
|
value = value[0] if value else None
|
||||||
else:
|
else:
|
||||||
value = self._jsonify_value(rec, field, field_dict.get("resolver"))
|
resolver = field_dict.get("resolver")
|
||||||
if json_key.endswith("*"): # sublist field
|
value = rec._jsonify_value(field, rec[field.name])
|
||||||
key = json_key[:-1]
|
value = resolver.resolve(field, rec)[0] if resolver else value
|
||||||
if not root.get(key):
|
|
||||||
root[key] = []
|
self._add_json_key(root, json_key, value)
|
||||||
root[key].append(value)
|
|
||||||
else:
|
|
||||||
root[json_key] = value
|
|
||||||
return root
|
return root
|
||||||
|
|
||||||
def jsonify(self, parser, one=False):
|
def jsonify(self, parser, one=False):
|
||||||
|
@ -140,7 +120,7 @@ class Base(models.AbstractModel):
|
||||||
if one:
|
if one:
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
if isinstance(parser, list):
|
if isinstance(parser, list):
|
||||||
parser = self.convert_simple_to_full_parser(parser)
|
parser = convert_simple_to_full_parser(parser)
|
||||||
resolver = parser.get("resolver")
|
resolver = parser.get("resolver")
|
||||||
|
|
||||||
results = [{} for record in self]
|
results = [{} for record in self]
|
||||||
|
@ -151,5 +131,5 @@ class Base(models.AbstractModel):
|
||||||
for record, json in zip(records, results):
|
for record, json in zip(records, results):
|
||||||
self._jsonify_record(parsers[lang], record, json)
|
self._jsonify_record(parsers[lang], record, json)
|
||||||
|
|
||||||
results = self._resolve(resolver, results, self) if resolver else results
|
results = resolver.resolve(results, self) if resolver else results
|
||||||
return results[0] if one else results
|
return results[0] if one else results
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
def convert_simple_to_full_parser(parser):
|
||||||
|
"""Convert a simple API style parser to a full parser"""
|
||||||
|
assert isinstance(parser, list)
|
||||||
|
return {"fields": _convert_parser(parser)}
|
||||||
|
|
||||||
|
|
||||||
|
def _f(f, function=None):
|
||||||
|
"""Return a dict from the string encoding a field to export.
|
||||||
|
The : is used as a separator to specify a target, if any.
|
||||||
|
"""
|
||||||
|
field_split = f.split(":")
|
||||||
|
field_dict = {"name": field_split[0]}
|
||||||
|
if len(field_split) > 1:
|
||||||
|
field_dict["target"] = field_split[1]
|
||||||
|
if function:
|
||||||
|
field_dict["function"] = function
|
||||||
|
return field_dict
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_parser(parser):
|
||||||
|
"""Recursively process each list to replace encoding fields as string
|
||||||
|
by dicts specifying each attribute by its relevant key.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for line in parser:
|
||||||
|
if isinstance(line, str):
|
||||||
|
result.append(_f(line))
|
||||||
|
else:
|
||||||
|
f, sub = line
|
||||||
|
if callable(sub) or isinstance(sub, str):
|
||||||
|
result.append(_f(f, sub))
|
||||||
|
else:
|
||||||
|
result.append((_f(f), _convert_parser(sub)))
|
||||||
|
return result
|
|
@ -53,7 +53,7 @@ Also the module provide a method "get_json_parser" on the ir.exports object
|
||||||
that generate a parser from an ir.exports configuration.
|
that generate a parser from an ir.exports configuration.
|
||||||
|
|
||||||
Further features are available for advanced uses.
|
Further features are available for advanced uses.
|
||||||
It defines a simple "resolver" model that has a "python_code" field and an eval
|
It defines a simple "resolver" model that has a "python_code" field and a resolve
|
||||||
function so that arbitrary functions can be configured to transform fields,
|
function so that arbitrary functions can be configured to transform fields,
|
||||||
or process the resulting dictionary.
|
or process the resulting dictionary.
|
||||||
It is also to specify a lang to extract the translation of any given field.
|
It is also to specify a lang to extract the translation of any given field.
|
||||||
|
@ -125,12 +125,12 @@ If the global resolver is given, then the json_dict goes through:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
resolver.eval(dict, record)
|
resolver.resolve(dict, record)
|
||||||
|
|
||||||
Which allows to add external data from the context or transform the dictionary
|
Which allows to add external data from the context or transform the dictionary
|
||||||
if necessary. Similarly if given for a field the resolver evaluates the result.
|
if necessary. Similarly if given for a field the resolver evaluates the result.
|
||||||
|
|
||||||
It is possible for a target to end with a '*':
|
It is possible for a target to have a marshaller by ending the target with '=list':
|
||||||
in that case the result is put into a list.
|
in that case the result is put into a list.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -138,8 +138,8 @@ in that case the result is put into a list.
|
||||||
parser = {
|
parser = {
|
||||||
fields: [
|
fields: [
|
||||||
{'name': 'name'},
|
{'name': 'name'},
|
||||||
{'name': 'field_1', 'target': 'customTags*'},
|
{'name': 'field_1', 'target': 'customTags=list'},
|
||||||
{'name': 'field_2', 'target': 'customTags*'},
|
{'name': 'field_2', 'target': 'customTags=list'},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -411,7 +411,7 @@ you can pass a callable or the name of a method on the model:</p>
|
||||||
<p>Also the module provide a method “get_json_parser” on the ir.exports object
|
<p>Also the module provide a method “get_json_parser” on the ir.exports object
|
||||||
that generate a parser from an ir.exports configuration.</p>
|
that generate a parser from an ir.exports configuration.</p>
|
||||||
<p>Further features are available for advanced uses.
|
<p>Further features are available for advanced uses.
|
||||||
It defines a simple “resolver” model that has a “python_code” field and an eval
|
It defines a simple “resolver” model that has a “python_code” field and a resolve
|
||||||
function so that arbitrary functions can be configured to transform fields,
|
function so that arbitrary functions can be configured to transform fields,
|
||||||
or process the resulting dictionary.
|
or process the resulting dictionary.
|
||||||
It is also to specify a lang to extract the translation of any given field.</p>
|
It is also to specify a lang to extract the translation of any given field.</p>
|
||||||
|
@ -468,18 +468,18 @@ with the added benefit of being able to use resolvers.</p>
|
||||||
<p>A simple parser is simply translated into a full parser at export.</p>
|
<p>A simple parser is simply translated into a full parser at export.</p>
|
||||||
<p>If the global resolver is given, then the json_dict goes through:</p>
|
<p>If the global resolver is given, then the json_dict goes through:</p>
|
||||||
<pre class="code python literal-block">
|
<pre class="code python literal-block">
|
||||||
<span class="n">resolver</span><span class="o">.</span><span class="n">eval</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">record</span><span class="p">)</span>
|
<span class="n">resolver</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">record</span><span class="p">)</span>
|
||||||
</pre>
|
</pre>
|
||||||
<p>Which allows to add external data from the context or transform the dictionary
|
<p>Which allows to add external data from the context or transform the dictionary
|
||||||
if necessary. Similarly if given for a field the resolver evaluates the result.</p>
|
if necessary. Similarly if given for a field the resolver evaluates the result.</p>
|
||||||
<p>It is possible for a target to end with a ‘*’:
|
<p>It is possible for a target to have a marshaller by ending the target with ‘=list’:
|
||||||
in that case the result is put into a list.</p>
|
in that case the result is put into a list.</p>
|
||||||
<pre class="code python literal-block">
|
<pre class="code python literal-block">
|
||||||
<span class="n">parser</span> <span class="o">=</span> <span class="p">{</span>
|
<span class="n">parser</span> <span class="o">=</span> <span class="p">{</span>
|
||||||
<span class="n">fields</span><span class="p">:</span> <span class="p">[</span>
|
<span class="n">fields</span><span class="p">:</span> <span class="p">[</span>
|
||||||
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'name'</span><span class="p">},</span>
|
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'name'</span><span class="p">},</span>
|
||||||
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'field_1'</span><span class="p">,</span> <span class="s1">'target'</span><span class="p">:</span> <span class="s1">'customTags*'</span><span class="p">},</span>
|
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'field_1'</span><span class="p">,</span> <span class="s1">'target'</span><span class="p">:</span> <span class="s1">'customTags=list'</span><span class="p">},</span>
|
||||||
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'field_2'</span><span class="p">,</span> <span class="s1">'target'</span><span class="p">:</span> <span class="s1">'customTags*'</span><span class="p">},</span>
|
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'field_2'</span><span class="p">,</span> <span class="s1">'target'</span><span class="p">:</span> <span class="s1">'customTags=list'</span><span class="p">},</span>
|
||||||
<span class="p">]</span>
|
<span class="p">]</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
|
@ -5,6 +5,8 @@ from odoo import fields
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
from odoo.tests.common import SavepointCase
|
from odoo.tests.common import SavepointCase
|
||||||
|
|
||||||
|
from ..models.utils import convert_simple_to_full_parser
|
||||||
|
|
||||||
|
|
||||||
def jsonify_custom(self, field_name):
|
def jsonify_custom(self, field_name):
|
||||||
return "yeah!"
|
return "yeah!"
|
||||||
|
@ -113,7 +115,7 @@ class TestParser(SavepointCase):
|
||||||
|
|
||||||
exporter = self.env.ref("base_jsonify.ir_exp_partner")
|
exporter = self.env.ref("base_jsonify.ir_exp_partner")
|
||||||
parser = exporter.get_json_parser()
|
parser = exporter.get_json_parser()
|
||||||
expected_full_parser = exporter.convert_simple_to_full_parser(expected_parser)
|
expected_full_parser = convert_simple_to_full_parser(expected_parser)
|
||||||
self.assertEqual(parser, expected_full_parser)
|
self.assertEqual(parser, expected_full_parser)
|
||||||
|
|
||||||
# modify an ir.exports_line to put a target for a field
|
# modify an ir.exports_line to put a target for a field
|
||||||
|
@ -122,7 +124,7 @@ class TestParser(SavepointCase):
|
||||||
)
|
)
|
||||||
expected_parser[4] = ("category_id:category", ["name"])
|
expected_parser[4] = ("category_id:category", ["name"])
|
||||||
parser = exporter.get_json_parser()
|
parser = exporter.get_json_parser()
|
||||||
expected_full_parser = exporter.convert_simple_to_full_parser(expected_parser)
|
expected_full_parser = convert_simple_to_full_parser(expected_parser)
|
||||||
self.assertEqual(parser, expected_full_parser)
|
self.assertEqual(parser, expected_full_parser)
|
||||||
|
|
||||||
def test_json_export(self):
|
def test_json_export(self):
|
||||||
|
@ -251,8 +253,8 @@ class TestParser(SavepointCase):
|
||||||
)
|
)
|
||||||
resolver = self.env["ir.exports.resolver"].create({"python_code": code})
|
resolver = self.env["ir.exports.resolver"].create({"python_code": code})
|
||||||
lang_parser = [
|
lang_parser = [
|
||||||
{"target": "customTags*", "name": "name", "resolver": resolver.id},
|
{"target": "customTags=list", "name": "name", "resolver": resolver},
|
||||||
{"target": "customTags*", "name": "id", "resolver": resolver.id},
|
{"target": "customTags=list", "name": "id", "resolver": resolver},
|
||||||
]
|
]
|
||||||
parser = {"language_agnostic": True, "langs": {False: lang_parser}}
|
parser = {"language_agnostic": True, "langs": {False: lang_parser}}
|
||||||
expected_json = {
|
expected_json = {
|
||||||
|
@ -275,7 +277,7 @@ class TestParser(SavepointCase):
|
||||||
export = self.env["ir.exports"].create(
|
export = self.env["ir.exports"].create(
|
||||||
{
|
{
|
||||||
"export_fields": [
|
"export_fields": [
|
||||||
(0, 0, {"name": "name", "function": "jsonify_custom"}),
|
(0, 0, {"name": "name", "instance_method_name": "jsonify_custom"}),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,6 +62,6 @@ class TestIrExportsLine(TransactionCase):
|
||||||
"export_id": self.ir_export.id,
|
"export_id": self.ir_export.id,
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"resolver_id": resolver.id,
|
"resolver_id": resolver.id,
|
||||||
"function": "function_name",
|
"instance_method_name": "function_name",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<field name="target" />
|
<field name="target" />
|
||||||
<field name="lang_id" />
|
<field name="lang_id" />
|
||||||
<field name="resolver_id" />
|
<field name="resolver_id" />
|
||||||
<field name="function" />
|
<field name="instance_method_name" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</group>
|
</group>
|
||||||
|
|
Loading…
Reference in New Issue