-
-
Notifications
You must be signed in to change notification settings - Fork 298
/
field_converter.py
131 lines (95 loc) · 3.51 KB
/
field_converter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import logging
from marshmallow import fields
from odoo import fields as odoo_fields
from odoo.addons.datamodel.fields import NestedModel
_logger = logging.getLogger(__name__)
__all__ = ["convert_field"]
class Binary(fields.Raw):
def _serialize(self, value, attr, obj, **kwargs):
res = super()._serialize(value, attr, obj, **kwargs)
if isinstance(res, bytes):
res = res.decode("utf-8")
return res
class FieldConverter:
def __init__(self, odoo_field):
self.odoo_field = odoo_field
def _marshmallow_field_class(self):
pass
def _get_kwargs(self):
kwargs = {
"required": self.odoo_field.required,
"allow_none": not self.odoo_field.required,
}
if self.odoo_field.readonly:
kwargs["dump_only"] = True
return kwargs
def convert_to_marshmallow(self):
marshmallow_field_class = self._marshmallow_field_class()
kwargs = self._get_kwargs()
return marshmallow_field_class(**kwargs)
class BooleanConverter(FieldConverter):
def _get_kwargs(self):
kwargs = super()._get_kwargs()
kwargs["falsy"] = fields.Boolean.falsy.union({None})
return kwargs
def _marshmallow_field_class(self):
return fields.Boolean
class IntegerConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.Integer
class FloatConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.Float
class StringConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.String
class DateConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.Date
class DatetimeConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.DateTime
class RawConverter(FieldConverter):
def _marshmallow_field_class(self):
return fields.Raw
class BinaryConverter(FieldConverter):
def _marshmallow_field_class(self):
return Binary
class RelationalConverter(FieldConverter):
def _get_kwargs(self):
kwargs = super()._get_kwargs()
kwargs["many"] = isinstance(
self.odoo_field, (odoo_fields.One2many, odoo_fields.Many2many)
)
kwargs["nested"] = "generic.minimal.serializer"
kwargs["metadata"] = {"odoo_model": self.odoo_field.comodel_name}
return kwargs
def _marshmallow_field_class(self):
return NestedModel
FIELDS_CONV = {
odoo_fields.Boolean: BooleanConverter,
odoo_fields.Integer: IntegerConverter,
odoo_fields.Id: IntegerConverter,
odoo_fields.Float: FloatConverter,
odoo_fields.Monetary: FloatConverter, # should we use a Decimal instead?
odoo_fields.Char: StringConverter,
odoo_fields.Text: StringConverter,
odoo_fields.Html: StringConverter,
odoo_fields.Selection: RawConverter,
odoo_fields.Date: DateConverter,
odoo_fields.Datetime: DatetimeConverter,
odoo_fields.Binary: BinaryConverter,
odoo_fields.Image: BinaryConverter,
odoo_fields.One2many: RelationalConverter,
odoo_fields.Many2one: RelationalConverter,
odoo_fields.Many2many: RelationalConverter,
}
def convert_field(odoo_field):
field_cls = type(odoo_field)
if field_cls in FIELDS_CONV:
return FIELDS_CONV[field_cls](odoo_field).convert_to_marshmallow()
else:
_logger.warning(
"Not implemented: Odoo fields of type {} cannot be "
"translated into Marshmallow fields".format(field_cls)
)