mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-15 19:06:50 +01:00
765 lines
26 KiB
Python
765 lines
26 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2014 Sébastien Alix
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
|
|
"""This module contains classes representing the fields supported by Odoo.
|
|
A field is a Python descriptor which defines getter/setter methods for
|
|
its related attribute.
|
|
"""
|
|
import datetime
|
|
import sys
|
|
|
|
# from odoorpc import error
|
|
from odoorpc.models import IncrementalRecords, Model
|
|
|
|
|
|
def is_int(value):
|
|
"""Return `True` if ``value`` is an integer."""
|
|
if isinstance(value, bool):
|
|
return False
|
|
try:
|
|
int(value)
|
|
return True
|
|
except (ValueError, TypeError):
|
|
return False
|
|
|
|
|
|
# Python 2
|
|
if sys.version_info[0] < 3:
|
|
|
|
def is_string(value):
|
|
"""Return `True` if ``value`` is a string."""
|
|
# noqa: F821
|
|
return isinstance(value, basestring) # noqa: F821
|
|
|
|
|
|
# Python >= 3
|
|
else:
|
|
|
|
def is_string(value):
|
|
"""Return `True` if ``value`` is a string."""
|
|
return isinstance(value, str)
|
|
|
|
|
|
def odoo_tuple_in(iterable):
|
|
"""Return `True` if `iterable` contains an expected tuple like
|
|
``(6, 0, IDS)`` (and so on).
|
|
|
|
>>> odoo_tuple_in([0, 1, 2]) # Simple list
|
|
False
|
|
>>> odoo_tuple_in([(6, 0, [42])]) # List of tuples
|
|
True
|
|
>>> odoo_tuple_in([[1, 42]]) # List of lists
|
|
True
|
|
"""
|
|
if not iterable:
|
|
return False
|
|
|
|
def is_odoo_tuple(elt):
|
|
"""Return `True` if `elt` is a Odoo special tuple."""
|
|
try:
|
|
return elt[:1][0] in [1, 2, 3, 4, 5] or elt[:2] in [
|
|
(6, 0),
|
|
[6, 0],
|
|
(0, 0),
|
|
[0, 0],
|
|
]
|
|
except (TypeError, IndexError):
|
|
return False
|
|
|
|
return any(is_odoo_tuple(elt) for elt in iterable)
|
|
|
|
|
|
def tuples2ids(tuples, ids):
|
|
"""Update `ids` according to `tuples`, e.g. (3, 0, X), (4, 0, X)..."""
|
|
for value in tuples:
|
|
if value[0] == 6 and value[2]:
|
|
ids = value[2]
|
|
elif value[0] == 5:
|
|
ids[:] = []
|
|
elif value[0] == 4 and value[1] and value[1] not in ids:
|
|
ids.append(value[1])
|
|
elif value[0] == 3 and value[1] and value[1] in ids:
|
|
ids.remove(value[1])
|
|
return ids
|
|
|
|
|
|
def records2ids(iterable):
|
|
"""Replace records contained in `iterable` with their corresponding IDs:
|
|
|
|
>>> groups = list(odoo.env.user.groups_id)
|
|
>>> records2ids(groups)
|
|
[1, 2, 3, 14, 17, 18, 19, 7, 8, 9, 5, 20, 21, 22, 23]
|
|
"""
|
|
|
|
def record2id(elt):
|
|
"""If `elt` is a record, return its ID."""
|
|
if isinstance(elt, Model):
|
|
return elt.id
|
|
return elt
|
|
|
|
return [record2id(elt) for elt in iterable]
|
|
|
|
|
|
class BaseField(object):
|
|
"""Field which all other fields inherit.
|
|
Manage common metadata.
|
|
"""
|
|
|
|
def __init__(self, name, data):
|
|
self.name = name
|
|
self.type = 'type' in data and data['type'] or False
|
|
self.string = 'string' in data and data['string'] or False
|
|
self.size = 'size' in data and data['size'] or False
|
|
self.required = 'required' in data and data['required'] or False
|
|
self.readonly = 'readonly' in data and data['readonly'] or False
|
|
self.help = 'help' in data and data['help'] or False
|
|
self.states = 'states' in data and data['states'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
pass
|
|
|
|
def __set__(self, instance, value):
|
|
"""Each time a record is modified, it is marked as dirty
|
|
in the environment.
|
|
"""
|
|
instance.env.dirty.add(instance)
|
|
if instance._odoo.config.get('auto_commit'):
|
|
instance.env.commit()
|
|
|
|
def __str__(self):
|
|
"""Return a human readable string representation of the field."""
|
|
attrs = [
|
|
'string',
|
|
'relation',
|
|
'required',
|
|
'readonly',
|
|
'size',
|
|
'domain',
|
|
]
|
|
attrs_rep = []
|
|
for attr in attrs:
|
|
if hasattr(self, attr):
|
|
value = getattr(self, attr)
|
|
if value:
|
|
if is_string(value):
|
|
attrs_rep.append("{}='{}'".format(attr, value))
|
|
else:
|
|
attrs_rep.append("{}={}".format(attr, value))
|
|
attrs_rep = ", ".join(attrs_rep)
|
|
return "{}({})".format(self.type, attrs_rep)
|
|
|
|
def check_required(self, value):
|
|
"""Check the value if the field is required.
|
|
|
|
Aim to be overridden by field classes.
|
|
|
|
:return: `True` if the value is accepted, `False` otherwise.
|
|
"""
|
|
return bool(value)
|
|
|
|
def check_value(self, value):
|
|
"""Check the validity of a value for the field."""
|
|
# if self.readonly:
|
|
# raise error.Error(
|
|
# "'{field_name}' field is readonly".format(
|
|
# field_name=self.name))
|
|
if value and self.size:
|
|
if not is_string(value):
|
|
raise ValueError("Value supplied has to be a string")
|
|
if len(value) > self.size:
|
|
raise ValueError(
|
|
"Lenght of the '{}' is limited to {}".format(
|
|
self.name, self.size
|
|
)
|
|
)
|
|
if self.required and not self.check_required(value):
|
|
raise ValueError("'{}' field is required".format(self.name))
|
|
return value
|
|
|
|
def store(self, record, value):
|
|
"""Store the value in the record."""
|
|
record._values[self.name][record.id] = value
|
|
|
|
|
|
class Binary(BaseField):
|
|
"""Equivalent of the `fields.Binary` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Binary, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name][instance.id]
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Binary, self).__set__(instance, value)
|
|
|
|
|
|
class Boolean(BaseField):
|
|
"""Equivalent of the `fields.Boolean` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Boolean, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name][instance.id]
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
value = bool(value)
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Boolean, self).__set__(instance, value)
|
|
|
|
|
|
class Char(BaseField):
|
|
"""Equivalent of the `fields.Char` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Char, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Char, self).__set__(instance, value)
|
|
|
|
|
|
class Date(BaseField):
|
|
"""Represent the OpenObject 'fields.data'"""
|
|
|
|
pattern = "%Y-%m-%d"
|
|
|
|
def __init__(self, name, data):
|
|
super(Date, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id) or False
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
try:
|
|
res = datetime.datetime.strptime(value, self.pattern).date()
|
|
except (ValueError, TypeError):
|
|
res = value
|
|
return res
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Date, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
super(Date, self).check_value(value)
|
|
if isinstance(value, datetime.date):
|
|
value = value.strftime("%Y-%m-%d")
|
|
elif is_string(value):
|
|
datetime.datetime.strptime(value, self.pattern)
|
|
elif isinstance(value, bool) or value is None:
|
|
return value
|
|
else:
|
|
raise ValueError("Expecting a datetime.date object or string")
|
|
return value
|
|
|
|
|
|
class Datetime(BaseField):
|
|
"""Represent the OpenObject 'fields.datetime'"""
|
|
|
|
pattern = "%Y-%m-%d %H:%M:%S"
|
|
|
|
def __init__(self, name, data):
|
|
super(Datetime, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
try:
|
|
res = datetime.datetime.strptime(value, self.pattern)
|
|
except (ValueError, TypeError):
|
|
res = value
|
|
return res
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Datetime, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
super(Datetime, self).check_value(value)
|
|
if isinstance(value, datetime.datetime):
|
|
value = value.strftime("%Y-%m-%d %H:%M:%S")
|
|
elif is_string(value):
|
|
datetime.datetime.strptime(value, self.pattern)
|
|
elif isinstance(value, bool):
|
|
return value
|
|
else:
|
|
raise ValueError("Expecting a datetime.datetime object or string")
|
|
return value
|
|
|
|
|
|
class Float(BaseField):
|
|
"""Equivalent of the `fields.Float` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Float, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
if value in [None, False]:
|
|
value = 0.0
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Float, self).__set__(instance, value)
|
|
|
|
def check_required(self, value):
|
|
# Accept 0 values
|
|
return super(Float, self).check_required() or value == 0
|
|
|
|
|
|
class Integer(BaseField):
|
|
"""Equivalent of the `fields.Integer` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Integer, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
if value in [None, False]:
|
|
value = 0
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Integer, self).__set__(instance, value)
|
|
|
|
def check_required(self, value):
|
|
# Accept 0 values
|
|
return super(Float, self).check_required() or value == 0
|
|
|
|
|
|
class Selection(BaseField):
|
|
"""Represent the OpenObject 'fields.selection'"""
|
|
|
|
def __init__(self, name, data):
|
|
super(Selection, self).__init__(name, data)
|
|
self.selection = 'selection' in data and data['selection'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id, False)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Selection, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
super(Selection, self).check_value(value)
|
|
selection = [val[0] for val in self.selection]
|
|
if value and value not in selection:
|
|
raise ValueError(
|
|
"The value '{}' supplied doesn't match with the possible "
|
|
"values '{}' for the '{}' field".format(
|
|
value, selection, self.name
|
|
)
|
|
)
|
|
return value
|
|
|
|
|
|
class Many2many(BaseField):
|
|
"""Represent the OpenObject 'fields.many2many'"""
|
|
|
|
def __init__(self, name, data):
|
|
super(Many2many, self).__init__(name, data)
|
|
self.relation = 'relation' in data and data['relation'] or False
|
|
self.context = 'context' in data and data['context'] or {}
|
|
self.domain = 'domain' in data and data['domain'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
"""Return a recordset."""
|
|
ids = None
|
|
if instance._values[self.name].get(instance.id):
|
|
ids = instance._values[self.name][instance.id][:]
|
|
# None value => get the value on the fly
|
|
if ids is None:
|
|
args = [[instance.id], [self.name]]
|
|
kwargs = {'context': self.context, 'load': '_classic_write'}
|
|
orig_ids = instance._odoo.execute_kw(
|
|
instance._name, 'read', args, kwargs
|
|
)[0][self.name]
|
|
instance._values[self.name][instance.id] = orig_ids
|
|
ids = orig_ids and orig_ids[:] or []
|
|
# Take updated values into account
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
values = instance._values_to_write[self.name][instance.id]
|
|
# Handle ODOO tuples to update 'ids'
|
|
ids = tuples2ids(values, ids or [])
|
|
# Handle the field context
|
|
Relation = instance.env[self.relation]
|
|
env = instance.env
|
|
if self.context:
|
|
context = instance.env.context.copy()
|
|
context.update(self.context)
|
|
env = instance.env(context=context)
|
|
return Relation._browse(env, ids, from_record=(instance, self))
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
if isinstance(value, IncrementalRecords):
|
|
value = value.tuples
|
|
else:
|
|
if value and not odoo_tuple_in(value):
|
|
value = [(6, 0, records2ids(value))]
|
|
elif not value:
|
|
value = [(5,)]
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Many2many, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
if value:
|
|
if (
|
|
not isinstance(value, list)
|
|
and not isinstance(value, Model)
|
|
and not isinstance(value, IncrementalRecords)
|
|
):
|
|
raise ValueError(
|
|
"The value supplied has to be a list, a recordset "
|
|
"or 'False'"
|
|
)
|
|
return super(Many2many, self).check_value(value)
|
|
|
|
def store(self, record, value):
|
|
"""Store the value in the record."""
|
|
if record._values[self.name].get(record.id):
|
|
tuples2ids(value, record._values[self.name][record.id])
|
|
else:
|
|
record._values[self.name][record.id] = tuples2ids(value, [])
|
|
|
|
|
|
class Many2one(BaseField):
|
|
"""Represent the OpenObject 'fields.many2one'"""
|
|
|
|
def __init__(self, name, data):
|
|
super(Many2one, self).__init__(name, data)
|
|
self.relation = 'relation' in data and data['relation'] or False
|
|
self.context = 'context' in data and data['context'] or {}
|
|
self.domain = 'domain' in data and data['domain'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
id_ = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
id_ = instance._values_to_write[self.name][instance.id]
|
|
# None value => get the value on the fly
|
|
if id_ is None:
|
|
args = [[instance.id], [self.name]]
|
|
kwargs = {'context': self.context, 'load': '_classic_write'}
|
|
id_ = instance._odoo.execute_kw(
|
|
instance._name, 'read', args, kwargs
|
|
)[0][self.name]
|
|
instance._values[self.name][instance.id] = id_
|
|
Relation = instance.env[self.relation]
|
|
if id_:
|
|
env = instance.env
|
|
if self.context:
|
|
context = instance.env.context.copy()
|
|
context.update(self.context)
|
|
env = instance.env(context=context)
|
|
return Relation._browse(env, id_, from_record=(instance, self))
|
|
return Relation.browse(False)
|
|
|
|
def __set__(self, instance, value):
|
|
if isinstance(value, Model):
|
|
o_rel = value
|
|
elif is_int(value):
|
|
rel_obj = instance.env[self.relation]
|
|
o_rel = rel_obj.browse(value)
|
|
elif value in [None, False]:
|
|
o_rel = False
|
|
else:
|
|
raise ValueError(
|
|
"Value supplied has to be an integer, "
|
|
"a record object or 'None/False'."
|
|
)
|
|
o_rel = self.check_value(o_rel)
|
|
# instance.__data__['updated_values'][self.name] = \
|
|
# o_rel and [o_rel.id, False]
|
|
instance._values_to_write[self.name][instance.id] = (
|
|
o_rel and o_rel.id or False
|
|
)
|
|
super(Many2one, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
super(Many2one, self).check_value(value)
|
|
if value and value._name != self.relation:
|
|
raise ValueError(
|
|
(
|
|
"Instance of '{model}' supplied doesn't match with the "
|
|
+ "relation '{relation}' of the '{field_name}' field."
|
|
).format(
|
|
model=value._name,
|
|
relation=self.relation,
|
|
field_name=self.name,
|
|
)
|
|
)
|
|
return value
|
|
|
|
|
|
class One2many(BaseField):
|
|
"""Represent the OpenObject 'fields.one2many'"""
|
|
|
|
def __init__(self, name, data):
|
|
super(One2many, self).__init__(name, data)
|
|
self.relation = 'relation' in data and data['relation'] or False
|
|
self.context = 'context' in data and data['context'] or {}
|
|
self.domain = 'domain' in data and data['domain'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
"""Return a recordset."""
|
|
ids = None
|
|
if instance._values[self.name].get(instance.id):
|
|
ids = instance._values[self.name][instance.id][:]
|
|
# None value => get the value on the fly
|
|
if ids is None:
|
|
args = [[instance.id], [self.name]]
|
|
kwargs = {'context': self.context, 'load': '_classic_write'}
|
|
orig_ids = instance._odoo.execute_kw(
|
|
instance._name, 'read', args, kwargs
|
|
)[0][self.name]
|
|
instance._values[self.name][instance.id] = orig_ids
|
|
ids = orig_ids and orig_ids[:] or []
|
|
# Take updated values into account
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
values = instance._values_to_write[self.name][instance.id]
|
|
# Handle ODOO tuples to update 'ids'
|
|
ids = tuples2ids(values, ids or [])
|
|
Relation = instance.env[self.relation]
|
|
env = instance.env
|
|
if self.context:
|
|
context = instance.env.context.copy()
|
|
context.update(self.context)
|
|
env = instance.env(context=context)
|
|
return Relation._browse(env, ids, from_record=(instance, self))
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
if isinstance(value, IncrementalRecords):
|
|
value = value.tuples
|
|
else:
|
|
if value and not odoo_tuple_in(value):
|
|
value = [(6, 0, records2ids(value))]
|
|
elif not value:
|
|
value = [(5,)]
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(One2many, self).__set__(instance, value)
|
|
|
|
def check_value(self, value):
|
|
if value:
|
|
if (
|
|
not isinstance(value, list)
|
|
and not isinstance(value, Model)
|
|
and not isinstance(value, IncrementalRecords)
|
|
):
|
|
raise ValueError(
|
|
"The value supplied has to be a list, a recordset "
|
|
"or 'False'"
|
|
)
|
|
return super(One2many, self).check_value(value)
|
|
|
|
def store(self, record, value):
|
|
"""Store the value in the record."""
|
|
if record._values[self.name].get(record.id):
|
|
tuples2ids(value, record._values[self.name][record.id])
|
|
else:
|
|
record._values[self.name][record.id] = tuples2ids(value, [])
|
|
|
|
|
|
class Reference(BaseField):
|
|
"""Represent the OpenObject 'fields.reference'."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Reference, self).__init__(name, data)
|
|
self.context = 'context' in data and data['context'] or {}
|
|
self.domain = 'domain' in data and data['domain'] or False
|
|
self.selection = 'selection' in data and data['selection'] or False
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id) or False
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
# None value => get the value on the fly
|
|
if value is None:
|
|
args = [[instance.id], [self.name]]
|
|
kwargs = {'context': self.context, 'load': '_classic_write'}
|
|
value = instance._odoo.execute_kw(
|
|
instance._name, 'read', args, kwargs
|
|
)[0][self.name]
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
if value:
|
|
parts = value.rpartition(',')
|
|
relation, o_id = parts[0], parts[2]
|
|
relation = relation.strip()
|
|
o_id = int(o_id.strip())
|
|
if relation and o_id:
|
|
Relation = instance.env[relation]
|
|
env = instance.env
|
|
if self.context:
|
|
context = instance.env.context.copy()
|
|
context.update(self.context)
|
|
env = instance.env(context=context)
|
|
return Relation._browse(
|
|
env, o_id, from_record=(instance, self)
|
|
)
|
|
return False
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Reference, self).__set__(instance, value)
|
|
|
|
def _check_relation(self, relation):
|
|
"""Raise a `ValueError` if `relation` is not allowed among
|
|
the possible values.
|
|
"""
|
|
selection = [val[0] for val in self.selection]
|
|
if relation not in selection:
|
|
raise ValueError(
|
|
(
|
|
"The value '{value}' supplied doesn't match with the possible"
|
|
" values '{selection}' for the '{field_name}' field"
|
|
).format(
|
|
value=relation, selection=selection, field_name=self.name
|
|
)
|
|
)
|
|
return relation
|
|
|
|
def check_value(self, value):
|
|
if isinstance(value, Model):
|
|
relation = value.__class__.__osv__['name']
|
|
self._check_relation(relation)
|
|
value = "{},{}".format(relation, value.id)
|
|
super(Reference, self).check_value(value)
|
|
elif is_string(value):
|
|
super(Reference, self).check_value(value)
|
|
parts = value.rpartition(',')
|
|
relation, o_id = parts[0], parts[2]
|
|
relation = relation.strip()
|
|
o_id = o_id.strip()
|
|
# o_rel = instance.__class__.__odoo__.browse(relation, o_id)
|
|
if not relation or not is_int(o_id):
|
|
raise ValueError(
|
|
"String not well formatted, expecting "
|
|
"'{relation},{id}' format"
|
|
)
|
|
self._check_relation(relation)
|
|
else:
|
|
raise ValueError(
|
|
"Value supplied has to be a string or"
|
|
" a browse_record object."
|
|
)
|
|
return value
|
|
|
|
|
|
class Text(BaseField):
|
|
"""Equivalent of the `fields.Text` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Text, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name].get(instance.id)
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
if value is None:
|
|
value = False
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Text, self).__set__(instance, value)
|
|
|
|
|
|
class Html(Text):
|
|
"""Equivalent of the `fields.Html` class."""
|
|
|
|
def __init__(self, name, data):
|
|
super(Html, self).__init__(name, data)
|
|
|
|
|
|
class Unknown(BaseField):
|
|
"""Represent an unknown field. This should not happen but this kind of
|
|
field only exists to avoid a blocking situation from a RPC point of view.
|
|
"""
|
|
|
|
def __init__(self, name, data):
|
|
super(Unknown, self).__init__(name, data)
|
|
|
|
def __get__(self, instance, owner):
|
|
value = instance._values[self.name][instance.id]
|
|
if instance.id in instance._values_to_write[self.name]:
|
|
value = instance._values_to_write[self.name][instance.id]
|
|
return value
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.check_value(value)
|
|
instance._values_to_write[self.name][instance.id] = value
|
|
super(Unknown, self).__set__(instance, value)
|
|
|
|
|
|
TYPES_TO_FIELDS = {
|
|
'binary': Binary,
|
|
'boolean': Boolean,
|
|
'char': Char,
|
|
'date': Date,
|
|
'datetime': Datetime,
|
|
'float': Float,
|
|
'html': Html,
|
|
'integer': Integer,
|
|
'many2many': Many2many,
|
|
'many2one': Many2one,
|
|
'one2many': One2many,
|
|
'reference': Reference,
|
|
'selection': Selection,
|
|
'text': Text,
|
|
}
|
|
|
|
|
|
def generate_field(name, data):
|
|
"""Generate a well-typed field according to the data dictionary supplied
|
|
(obtained via the `fields_get' method of any models).
|
|
"""
|
|
assert 'type' in data
|
|
field = TYPES_TO_FIELDS.get(data['type'], Unknown)(name, data)
|
|
return field
|