[IMP] fields: reuse column objects when possible, instead of recreating them
[odoo/odoo.git] / openerp / fields.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2013-2014 OpenERP (<http://www.openerp.com>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 """ High-level objects for fields. """
23
24 from copy import copy
25 from datetime import date, datetime
26 from functools import partial
27 from operator import attrgetter
28 from types import NoneType
29 import logging
30 import pytz
31 import xmlrpclib
32
33 from types import NoneType
34
35 from openerp.tools import float_round, ustr, html_sanitize
36 from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
37 from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
38
39 DATE_LENGTH = len(date.today().strftime(DATE_FORMAT))
40 DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT))
41
42 _logger = logging.getLogger(__name__)
43
44 class SpecialValue(object):
45     """ Encapsulates a value in the cache in place of a normal value. """
46     def __init__(self, value):
47         self.value = value
48     def get(self):
49         return self.value
50
51 class FailedValue(SpecialValue):
52     """ Special value that encapsulates an exception instead of a value. """
53     def __init__(self, exception):
54         self.exception = exception
55     def get(self):
56         raise self.exception
57
58 def _check_value(value):
59     """ Return `value`, or call its getter if `value` is a :class:`SpecialValue`. """
60     return value.get() if isinstance(value, SpecialValue) else value
61
62
63 def resolve_all_mro(cls, name, reverse=False):
64     """ Return the (successively overridden) values of attribute `name` in `cls`
65         in mro order, or inverse mro order if `reverse` is true.
66     """
67     klasses = reversed(cls.__mro__) if reverse else cls.__mro__
68     for klass in klasses:
69         if name in klass.__dict__:
70             yield klass.__dict__[name]
71
72
73 class MetaField(type):
74     """ Metaclass for field classes. """
75     by_type = {}
76
77     def __init__(cls, name, bases, attrs):
78         super(MetaField, cls).__init__(name, bases, attrs)
79         if cls.type:
80             cls.by_type[cls.type] = cls
81
82         # compute class attributes to avoid calling dir() on fields
83         cls.column_attrs = []
84         cls.related_attrs = []
85         cls.description_attrs = []
86         for attr in dir(cls):
87             if attr.startswith('_column_'):
88                 cls.column_attrs.append((attr[8:], attr))
89             elif attr.startswith('_related_'):
90                 cls.related_attrs.append((attr[9:], attr))
91             elif attr.startswith('_description_'):
92                 cls.description_attrs.append((attr[13:], attr))
93
94
95 class Field(object):
96     """ The field descriptor contains the field definition, and manages accesses
97         and assignments of the corresponding field on records. The following
98         attributes may be provided when instanciating a field:
99
100         :param string: the label of the field seen by users (string); if not
101             set, the ORM takes the field name in the class (capitalized).
102
103         :param help: the tooltip of the field seen by users (string)
104
105         :param readonly: whether the field is readonly (boolean, by default ``False``)
106
107         :param required: whether the value of the field is required (boolean, by
108             default ``False``)
109
110         :param index: whether the field is indexed in database (boolean, by
111             default ``False``)
112
113         :param default: the default value for the field; this is either a static
114             value, or a function taking a recordset and returning a value
115
116         :param states: a dictionary mapping state values to lists of UI attribute-value
117             pairs; possible attributes are: 'readonly', 'required', 'invisible'.
118             Note: Any state-based condition requires the ``state`` field value to be
119             available on the client-side UI. This is typically done by including it in
120             the relevant views, possibly made invisible if not relevant for the
121             end-user.
122
123         :param groups: comma-separated list of group xml ids (string); this
124             restricts the field access to the users of the given groups only
125
126         :param bool copy: whether the field value should be copied when the record
127             is duplicated (default: ``True`` for normal fields, ``False`` for
128             ``one2many`` and computed fields, including property fields and
129             related fields)
130
131         .. _field-computed:
132
133         .. rubric:: Computed fields
134
135         One can define a field whose value is computed instead of simply being
136         read from the database. The attributes that are specific to computed
137         fields are given below. To define such a field, simply provide a value
138         for the attribute `compute`.
139
140         :param compute: name of a method that computes the field
141
142         :param inverse: name of a method that inverses the field (optional)
143
144         :param search: name of a method that implement search on the field (optional)
145
146         :param store: whether the field is stored in database (boolean, by
147             default ``False`` on computed fields)
148
149         The methods given for `compute`, `inverse` and `search` are model
150         methods. Their signature is shown in the following example::
151
152             upper = fields.Char(compute='_compute_upper',
153                                 inverse='_inverse_upper',
154                                 search='_search_upper')
155
156             @api.depends('name')
157             def _compute_upper(self):
158                 for rec in self:
159                     self.upper = self.name.upper() if self.name else False
160
161             def _inverse_upper(self):
162                 for rec in self:
163                     self.name = self.upper.lower() if self.upper else False
164
165             def _search_upper(self, operator, value):
166                 if operator == 'like':
167                     operator = 'ilike'
168                 return [('name', operator, value)]
169
170         The compute method has to assign the field on all records of the invoked
171         recordset. The decorator :meth:`openerp.api.depends` must be applied on
172         the compute method to specify the field dependencies; those dependencies
173         are used to determine when to recompute the field; recomputation is
174         automatic and guarantees cache/database consistency. Note that the same
175         method can be used for several fields, you simply have to assign all the
176         given fields in the method; the method will be invoked once for all
177         those fields.
178
179         By default, a computed field is not stored to the database, and is
180         computed on-the-fly. Adding the attribute ``store=True`` will store the
181         field's values in the database. The advantage of a stored field is that
182         searching on that field is done by the database itself. The disadvantage
183         is that it requires database updates when the field must be recomputed.
184
185         The inverse method, as its name says, does the inverse of the compute
186         method: the invoked records have a value for the field, and you must
187         apply the necessary changes on the field dependencies such that the
188         computation gives the expected value. Note that a computed field without
189         an inverse method is readonly by default.
190
191         The search method is invoked when processing domains before doing an
192         actual search on the model. It must return a domain equivalent to the
193         condition: `field operator value`.
194
195         .. _field-related:
196
197         .. rubric:: Related fields
198
199         The value of a related field is given by following a sequence of
200         relational fields and reading a field on the reached model. The complete
201         sequence of fields to traverse is specified by the attribute
202
203         :param related: sequence of field names
204
205         The value of some attributes from related fields are automatically taken
206         from the source field, when it makes sense. Examples are the attributes
207         `string` or `selection` on selection fields.
208
209         By default, the values of related fields are not stored to the database.
210         Add the attribute ``store=True`` to make it stored, just like computed
211         fields. Related fields are automatically recomputed when their
212         dependencies are modified.
213
214         .. _field-company-dependent:
215
216         .. rubric:: Company-dependent fields
217
218         Formerly known as 'property' fields, the value of those fields depends
219         on the company. In other words, users that belong to different companies
220         may see different values for the field on a given record.
221
222         :param company_dependent: whether the field is company-dependent (boolean)
223
224         .. _field-incremental-definition:
225
226         .. rubric:: Incremental definition
227
228         A field is defined as class attribute on a model class. If the model
229         is extended (see :class:`~openerp.models.Model`), one can also extend
230         the field definition by redefining a field with the same name and same
231         type on the subclass. In that case, the attributes of the field are
232         taken from the parent class and overridden by the ones given in
233         subclasses.
234
235         For instance, the second class below only adds a tooltip on the field
236         ``state``::
237
238             class First(models.Model):
239                 _name = 'foo'
240                 state = fields.Selection([...], required=True)
241
242             class Second(models.Model):
243                 _inherit = 'foo'
244                 state = fields.Selection(help="Blah blah blah")
245
246     """
247     __metaclass__ = MetaField
248
249     _attrs = None               # dictionary with all field attributes
250     _free_attrs = None          # list of semantic-free attribute names
251
252     automatic = False           # whether the field is automatically created ("magic" field)
253     inherited = False           # whether the field is inherited (_inherits)
254     column = None               # the column interfaced by the field
255     setup_done = False          # whether the field has been set up
256
257     name = None                 # name of the field
258     type = None                 # type of the field (string)
259     relational = False          # whether the field is a relational one
260     model_name = None           # name of the model of this field
261     comodel_name = None         # name of the model of values (if relational)
262     inverse_fields = None       # list of inverse fields (objects)
263
264     store = True                # whether the field is stored in database
265     index = False               # whether the field is indexed in database
266     manual = False              # whether the field is a custom field
267     copy = True                 # whether the field is copied over by BaseModel.copy()
268     depends = ()                # collection of field dependencies
269     recursive = False           # whether self depends on itself
270     compute = None              # compute(recs) computes field on recs
271     inverse = None              # inverse(recs) inverses field on recs
272     search = None               # search(recs, operator, value) searches on self
273     related = None              # sequence of field names, for related fields
274     related_sudo = True         # whether related fields should be read as admin
275     company_dependent = False   # whether `self` is company-dependent (property field)
276     default = None              # default(recs) returns the default value
277
278     string = None               # field label
279     help = None                 # field tooltip
280     readonly = False
281     required = False
282     states = None
283     groups = False              # csv list of group xml ids
284     change_default = None       # whether the field may trigger a "user-onchange"
285     deprecated = None           # whether the field is ... deprecated
286
287     def __init__(self, string=None, **kwargs):
288         kwargs['string'] = string
289         self._attrs = {key: val for key, val in kwargs.iteritems() if val is not None}
290         self._free_attrs = []
291
292     def new(self, **kwargs):
293         """ Return a field of the same type as `self`, with its own parameters. """
294         return type(self)(**kwargs)
295
296     def set_class_name(self, cls, name):
297         """ Assign the model class and field name of `self`. """
298         self.model_name = cls._name
299         self.name = name
300
301         # determine all inherited field attributes
302         attrs = {}
303         for field in resolve_all_mro(cls, name, reverse=True):
304             if isinstance(field, type(self)):
305                 attrs.update(field._attrs)
306             else:
307                 attrs.clear()
308         attrs.update(self._attrs)       # necessary in case self is not in cls
309
310         # initialize `self` with `attrs`
311         if attrs.get('compute'):
312             # by default, computed fields are not stored, not copied and readonly
313             attrs['store'] = attrs.get('store', False)
314             attrs['copy'] = attrs.get('copy', False)
315             attrs['readonly'] = attrs.get('readonly', not attrs.get('inverse'))
316         if attrs.get('related'):
317             # by default, related fields are not stored
318             attrs['store'] = attrs.get('store', False)
319
320         for attr, value in attrs.iteritems():
321             if not hasattr(self, attr):
322                 self._free_attrs.append(attr)
323             setattr(self, attr, value)
324
325         if not self.string:
326             self.string = name.replace('_', ' ').capitalize()
327
328         # determine self.default and cls._defaults in a consistent way
329         self._determine_default(cls, name)
330
331         self.reset()
332
333     def _determine_default(self, cls, name):
334         """ Retrieve the default value for `self` in the hierarchy of `cls`, and
335             determine `self.default` and `cls._defaults` accordingly.
336         """
337         self.default = None
338
339         # traverse the class hierarchy upwards, and take the first field
340         # definition with a default or _defaults for self
341         for klass in cls.__mro__:
342             field = klass.__dict__.get(name, self)
343             if not isinstance(field, type(self)):
344                 return      # klass contains another value overridden by self
345
346             if 'default' in field._attrs:
347                 # take the default in field, and adapt it for cls._defaults
348                 value = field._attrs['default']
349                 if callable(value):
350                     self.default = value
351                     cls._defaults[name] = lambda model, cr, uid, context: \
352                         self.convert_to_write(value(model.browse(cr, uid, [], context)))
353                 else:
354                     self.default = lambda recs: value
355                     cls._defaults[name] = value
356                 return
357
358             defaults = klass.__dict__.get('_defaults') or {}
359             if name in defaults:
360                 # take the value from _defaults, and adapt it for self.default
361                 value = defaults[name]
362                 value_func = value if callable(value) else lambda *args: value
363                 self.default = lambda recs: self.convert_to_cache(
364                     value_func(recs._model, recs._cr, recs._uid, recs._context),
365                     recs, validate=False,
366                 )
367                 cls._defaults[name] = value
368                 return
369
370     def __str__(self):
371         return "%s.%s" % (self.model_name, self.name)
372
373     def __repr__(self):
374         return "%s.%s" % (self.model_name, self.name)
375
376     ############################################################################
377     #
378     # Field setup
379     #
380
381     def reset(self):
382         """ Prepare `self` for a new setup. """
383         self.setup_done = False
384         # self._triggers is a set of pairs (field, path) that represents the
385         # computed fields that depend on `self`. When `self` is modified, it
386         # invalidates the cache of each `field`, and registers the records to
387         # recompute based on `path`. See method `modified` below for details.
388         self._triggers = set()
389         self.inverse_fields = []
390
391     def setup(self, env):
392         """ Complete the setup of `self` (dependencies, recomputation triggers,
393             and other properties). This method is idempotent: it has no effect
394             if `self` has already been set up.
395         """
396         if not self.setup_done:
397             self._setup(env)
398             self.setup_done = True
399
400     def _setup(self, env):
401         """ Do the actual setup of `self`. """
402         if self.related:
403             self._setup_related(env)
404         else:
405             self._setup_regular(env)
406
407         # put invalidation/recomputation triggers on field dependencies
408         model = env[self.model_name]
409         for path in self.depends:
410             self._setup_dependency([], model, path.split('.'))
411
412         # put invalidation triggers on model dependencies
413         for dep_model_name, field_names in model._depends.iteritems():
414             dep_model = env[dep_model_name]
415             for field_name in field_names:
416                 field = dep_model._fields[field_name]
417                 field._triggers.add((self, None))
418
419     #
420     # Setup of related fields
421     #
422
423     def _setup_related(self, env):
424         """ Setup the attributes of a related field. """
425         # fix the type of self.related if necessary
426         if isinstance(self.related, basestring):
427             self.related = tuple(self.related.split('.'))
428
429         # determine the chain of fields, and make sure they are all set up
430         recs = env[self.model_name]
431         for name in self.related:
432             field = recs._fields[name]
433             field.setup(env)
434             recs = recs[name]
435
436         self.related_field = field
437
438         # check type consistency
439         if self.type != field.type:
440             raise Warning("Type of related field %s is inconsistent with %s" % (self, field))
441
442         # determine dependencies, compute, inverse, and search
443         self.depends = ('.'.join(self.related),)
444         self.compute = self._compute_related
445         self.inverse = self._inverse_related
446         if field._description_searchable(env):
447             # allow searching on self only if the related field is searchable
448             self.search = self._search_related
449
450         # copy attributes from field to self (string, help, etc.)
451         for attr, prop in self.related_attrs:
452             if not getattr(self, attr):
453                 setattr(self, attr, getattr(field, prop))
454
455     def _compute_related(self, records):
456         """ Compute the related field `self` on `records`. """
457         # when related_sudo, bypass access rights checks when reading values
458         others = records.sudo() if self.related_sudo else records
459         for record, other in zip(records, others):
460             if not record.id:
461                 # draft record, do not switch to another environment
462                 other = record
463             # traverse the intermediate fields; follow the first record at each step
464             for name in self.related[:-1]:
465                 other = other[name][:1]
466             record[self.name] = other[self.related[-1]]
467
468     def _inverse_related(self, records):
469         """ Inverse the related field `self` on `records`. """
470         for record in records:
471             other = record
472             # traverse the intermediate fields, and keep at most one record
473             for name in self.related[:-1]:
474                 other = other[name][:1]
475             if other:
476                 other[self.related[-1]] = record[self.name]
477
478     def _search_related(self, records, operator, value):
479         """ Determine the domain to search on field `self`. """
480         return [('.'.join(self.related), operator, value)]
481
482     # properties used by _setup_related() to copy values from related field
483     _related_comodel_name = property(attrgetter('comodel_name'))
484     _related_string = property(attrgetter('string'))
485     _related_help = property(attrgetter('help'))
486     _related_readonly = property(attrgetter('readonly'))
487     _related_groups = property(attrgetter('groups'))
488
489     #
490     # Setup of non-related fields
491     #
492
493     def _setup_regular(self, env):
494         """ Setup the attributes of a non-related field. """
495         recs = env[self.model_name]
496
497         def make_depends(deps):
498             return tuple(deps(recs) if callable(deps) else deps)
499
500         # convert compute into a callable and determine depends
501         if isinstance(self.compute, basestring):
502             # if the compute method has been overridden, concatenate all their _depends
503             self.depends = ()
504             for method in resolve_all_mro(type(recs), self.compute, reverse=True):
505                 self.depends += make_depends(getattr(method, '_depends', ()))
506             self.compute = getattr(type(recs), self.compute)
507         else:
508             self.depends = make_depends(getattr(self.compute, '_depends', ()))
509
510         # convert inverse and search into callables
511         if isinstance(self.inverse, basestring):
512             self.inverse = getattr(type(recs), self.inverse)
513         if isinstance(self.search, basestring):
514             self.search = getattr(type(recs), self.search)
515
516     def _setup_dependency(self, path0, model, path1):
517         """ Make `self` depend on `model`; `path0 + path1` is a dependency of
518             `self`, and `path0` is the sequence of field names from `self.model`
519             to `model`.
520         """
521         env = model.env
522         head, tail = path1[0], path1[1:]
523
524         if head == '*':
525             # special case: add triggers on all fields of model (except self)
526             fields = set(model._fields.itervalues()) - set([self])
527         else:
528             fields = [model._fields[head]]
529
530         for field in fields:
531             if field == self:
532                 _logger.debug("Field %s is recursively defined", self)
533                 self.recursive = True
534                 continue
535
536             field.setup(env)
537
538             #_logger.debug("Add trigger on %s to recompute %s", field, self)
539             field._triggers.add((self, '.'.join(path0 or ['id'])))
540
541             # add trigger on inverse fields, too
542             for invf in field.inverse_fields:
543                 #_logger.debug("Add trigger on %s to recompute %s", invf, self)
544                 invf._triggers.add((self, '.'.join(path0 + [head])))
545
546             # recursively traverse the dependency
547             if tail:
548                 comodel = env[field.comodel_name]
549                 self._setup_dependency(path0 + [head], comodel, tail)
550
551     @property
552     def dependents(self):
553         """ Return the computed fields that depend on `self`. """
554         return (field for field, path in self._triggers)
555
556     ############################################################################
557     #
558     # Field description
559     #
560
561     def get_description(self, env):
562         """ Return a dictionary that describes the field `self`. """
563         desc = {'type': self.type}
564         for attr, prop in self.description_attrs:
565             value = getattr(self, prop)
566             if callable(value):
567                 value = value(env)
568             if value is not None:
569                 desc[attr] = value
570
571         return desc
572
573     # properties used by get_description()
574
575     def _description_store(self, env):
576         if self.store:
577             # if the corresponding column is a function field, check the column
578             column = env[self.model_name]._columns.get(self.name)
579             return bool(getattr(column, 'store', True))
580         return False
581
582     def _description_searchable(self, env):
583         if self.store:
584             column = env[self.model_name]._columns.get(self.name)
585             return bool(getattr(column, 'store', True)) or \
586                    bool(getattr(column, '_fnct_search', False))
587         return bool(self.search)
588
589     def _description_sortable(self, env):
590         if self.store:
591             column = env[self.model_name]._columns.get(self.name)
592             return bool(getattr(column, 'store', True))
593         if self.inherited:
594             # self is sortable if the inherited field is itself sortable
595             return self.related_field._description_sortable(env)
596         return False
597
598     _description_manual = property(attrgetter('manual'))
599     _description_depends = property(attrgetter('depends'))
600     _description_related = property(attrgetter('related'))
601     _description_company_dependent = property(attrgetter('company_dependent'))
602     _description_readonly = property(attrgetter('readonly'))
603     _description_required = property(attrgetter('required'))
604     _description_states = property(attrgetter('states'))
605     _description_groups = property(attrgetter('groups'))
606     _description_change_default = property(attrgetter('change_default'))
607     _description_deprecated = property(attrgetter('deprecated'))
608
609     def _description_string(self, env):
610         if self.string and env.lang:
611             name = "%s,%s" % (self.model_name, self.name)
612             trans = env['ir.translation']._get_source(name, 'field', env.lang)
613             return trans or self.string
614         return self.string
615
616     def _description_help(self, env):
617         if self.help and env.lang:
618             name = "%s,%s" % (self.model_name, self.name)
619             trans = env['ir.translation']._get_source(name, 'help', env.lang)
620             return trans or self.help
621         return self.help
622
623     ############################################################################
624     #
625     # Conversion to column instance
626     #
627
628     def to_column(self):
629         """ return a low-level field object corresponding to `self` """
630         assert self.store
631
632         # determine column parameters
633         _logger.debug("Create fields._column for Field %s", self)
634         args = {}
635         for attr, prop in self.column_attrs:
636             args[attr] = getattr(self, prop)
637         for attr in self._free_attrs:
638             args[attr] = getattr(self, attr)
639
640         if self.company_dependent:
641             # company-dependent fields are mapped to former property fields
642             args['type'] = self.type
643             args['relation'] = self.comodel_name
644             return fields.property(**args)
645
646         if self.column:
647             # let the column provide a valid column for the given parameters
648             return self.column.new(**args)
649
650         return getattr(fields, self.type)(**args)
651
652     # properties used by to_column() to create a column instance
653     _column_copy = property(attrgetter('copy'))
654     _column_select = property(attrgetter('index'))
655     _column_manual = property(attrgetter('manual'))
656     _column_string = property(attrgetter('string'))
657     _column_help = property(attrgetter('help'))
658     _column_readonly = property(attrgetter('readonly'))
659     _column_required = property(attrgetter('required'))
660     _column_states = property(attrgetter('states'))
661     _column_groups = property(attrgetter('groups'))
662     _column_change_default = property(attrgetter('change_default'))
663     _column_deprecated = property(attrgetter('deprecated'))
664
665     ############################################################################
666     #
667     # Conversion of values
668     #
669
670     def null(self, env):
671         """ return the null value for this field in the given environment """
672         return False
673
674     def convert_to_cache(self, value, record, validate=True):
675         """ convert `value` to the cache level in `env`; `value` may come from
676             an assignment, or have the format of methods :meth:`BaseModel.read`
677             or :meth:`BaseModel.write`
678
679             :param record: the target record for the assignment, or an empty recordset
680
681             :param bool validate: when True, field-specific validation of
682                 `value` will be performed
683         """
684         return value
685
686     def convert_to_read(self, value, use_name_get=True):
687         """ convert `value` from the cache to a value as returned by method
688             :meth:`BaseModel.read`
689
690             :param bool use_name_get: when True, value's diplay name will
691                 be computed using :meth:`BaseModel.name_get`, if relevant
692                 for the field
693         """
694         return False if value is None else value
695
696     def convert_to_write(self, value, target=None, fnames=None):
697         """ convert `value` from the cache to a valid value for method
698             :meth:`BaseModel.write`.
699
700             :param target: optional, the record to be modified with this value
701             :param fnames: for relational fields only, an optional collection of
702                 field names to convert
703         """
704         return self.convert_to_read(value)
705
706     def convert_to_onchange(self, value):
707         """ convert `value` from the cache to a valid value for an onchange
708             method v7.
709         """
710         return self.convert_to_write(value)
711
712     def convert_to_export(self, value, env):
713         """ convert `value` from the cache to a valid value for export. The
714             parameter `env` is given for managing translations.
715         """
716         if env.context.get('export_raw_data'):
717             return value
718         return bool(value) and ustr(value)
719
720     def convert_to_display_name(self, value):
721         """ convert `value` from the cache to a suitable display name. """
722         return ustr(value)
723
724     ############################################################################
725     #
726     # Descriptor methods
727     #
728
729     def __get__(self, record, owner):
730         """ return the value of field `self` on `record` """
731         if record is None:
732             return self         # the field is accessed through the owner class
733
734         if not record:
735             # null record -> return the null value for this field
736             return self.null(record.env)
737
738         # only a single record may be accessed
739         record.ensure_one()
740
741         try:
742             return record._cache[self]
743         except KeyError:
744             pass
745
746         # cache miss, retrieve value
747         if record.id:
748             # normal record -> read or compute value for this field
749             self.determine_value(record)
750         else:
751             # draft record -> compute the value or let it be null
752             self.determine_draft_value(record)
753
754         # the result should be in cache now
755         return record._cache[self]
756
757     def __set__(self, record, value):
758         """ set the value of field `self` on `record` """
759         env = record.env
760
761         # only a single record may be updated
762         record.ensure_one()
763
764         # adapt value to the cache level
765         value = self.convert_to_cache(value, record)
766
767         if env.in_draft or not record.id:
768             # determine dependent fields
769             spec = self.modified_draft(record)
770
771             # set value in cache, inverse field, and mark record as dirty
772             record._cache[self] = value
773             if env.in_onchange:
774                 for invf in self.inverse_fields:
775                     invf._update(value, record)
776                 record._dirty = True
777
778             # determine more dependent fields, and invalidate them
779             if self.relational:
780                 spec += self.modified_draft(record)
781             env.invalidate(spec)
782
783         else:
784             # simply write to the database, and update cache
785             record.write({self.name: self.convert_to_write(value)})
786             record._cache[self] = value
787
788     ############################################################################
789     #
790     # Computation of field values
791     #
792
793     def _compute_value(self, records):
794         """ Invoke the compute method on `records`. """
795         # mark the computed fields failed in cache, so that access before
796         # computation raises an exception
797         exc = Warning("Field %s is accessed before being computed." % self)
798         for field in self.computed_fields:
799             records._cache[field] = FailedValue(exc)
800             records.env.computed[field].update(records._ids)
801         self.compute(records)
802         for field in self.computed_fields:
803             records.env.computed[field].difference_update(records._ids)
804
805     def compute_value(self, records):
806         """ Invoke the compute method on `records`; the results are in cache. """
807         with records.env.do_in_draft():
808             try:
809                 self._compute_value(records)
810             except (AccessError, MissingError):
811                 # some record is forbidden or missing, retry record by record
812                 for record in records:
813                     try:
814                         self._compute_value(record)
815                     except Exception as exc:
816                         record._cache[self.name] = FailedValue(exc)
817
818     def determine_value(self, record):
819         """ Determine the value of `self` for `record`. """
820         env = record.env
821
822         if self.store and not (self.depends and env.in_draft):
823             # this is a stored field
824             if self.depends:
825                 # this is a stored computed field, check for recomputation
826                 recs = record._recompute_check(self)
827                 if recs:
828                     # recompute the value (only in cache)
829                     self.compute_value(recs)
830                     # HACK: if result is in the wrong cache, copy values
831                     if recs.env != env:
832                         for source, target in zip(recs, recs.with_env(env)):
833                             try:
834                                 values = target._convert_to_cache({
835                                     f.name: source[f.name] for f in self.computed_fields
836                                 }, validate=False)
837                             except MissingError as e:
838                                 values = FailedValue(e)
839                             target._cache.update(values)
840                     # the result is saved to database by BaseModel.recompute()
841                     return
842
843             # read the field from database
844             record._prefetch_field(self)
845
846         elif self.compute:
847             # this is either a non-stored computed field, or a stored computed
848             # field in draft mode
849             if self.recursive:
850                 self.compute_value(record)
851             else:
852                 recs = record._in_cache_without(self)
853                 self.compute_value(recs)
854
855         else:
856             # this is a non-stored non-computed field
857             record._cache[self] = self.null(env)
858
859     def determine_draft_value(self, record):
860         """ Determine the value of `self` for the given draft `record`. """
861         if self.compute:
862             self._compute_value(record)
863         else:
864             record._cache[self] = SpecialValue(self.null(record.env))
865
866     def determine_inverse(self, records):
867         """ Given the value of `self` on `records`, inverse the computation. """
868         if self.inverse:
869             self.inverse(records)
870
871     def determine_domain(self, records, operator, value):
872         """ Return a domain representing a condition on `self`. """
873         if self.search:
874             return self.search(records, operator, value)
875         else:
876             return [(self.name, operator, value)]
877
878     ############################################################################
879     #
880     # Notification when fields are modified
881     #
882
883     def modified(self, records):
884         """ Notify that field `self` has been modified on `records`: prepare the
885             fields/records to recompute, and return a spec indicating what to
886             invalidate.
887         """
888         # invalidate the fields that depend on self, and prepare recomputation
889         spec = [(self, records._ids)]
890         for field, path in self._triggers:
891             if path and field.store:
892                 # don't move this line to function top, see log
893                 env = records.env(user=SUPERUSER_ID, context={'active_test': False})
894                 target = env[field.model_name].search([(path, 'in', records.ids)])
895                 if target:
896                     spec.append((field, target._ids))
897                     target.with_env(records.env)._recompute_todo(field)
898             else:
899                 spec.append((field, None))
900
901         return spec
902
903     def modified_draft(self, records):
904         """ Same as :meth:`modified`, but in draft mode. """
905         env = records.env
906
907         # invalidate the fields on the records in cache that depend on
908         # `records`, except fields currently being computed
909         spec = []
910         for field, path in self._triggers:
911             target = env[field.model_name]
912             computed = target.browse(env.computed[field])
913             if path == 'id':
914                 target = records - computed
915             elif path:
916                 target = (target.browse(env.cache[field]) - computed).filtered(
917                     lambda rec: rec._mapped_cache(path) & records
918                 )
919             else:
920                 target = target.browse(env.cache[field]) - computed
921
922             if target:
923                 spec.append((field, target._ids))
924
925         return spec
926
927
928 class Boolean(Field):
929     type = 'boolean'
930
931     def convert_to_cache(self, value, record, validate=True):
932         return bool(value)
933
934     def convert_to_export(self, value, env):
935         if env.context.get('export_raw_data'):
936             return value
937         return ustr(value)
938
939
940 class Integer(Field):
941     type = 'integer'
942
943     def convert_to_cache(self, value, record, validate=True):
944         if isinstance(value, dict):
945             # special case, when an integer field is used as inverse for a one2many
946             return value.get('id', False)
947         return int(value or 0)
948
949     def convert_to_read(self, value, use_name_get=True):
950         # Integer values greater than 2^31-1 are not supported in pure XMLRPC,
951         # so we have to pass them as floats :-(
952         if value and value > xmlrpclib.MAXINT:
953             return float(value)
954         return value
955
956     def _update(self, records, value):
957         # special case, when an integer field is used as inverse for a one2many
958         records._cache[self] = value.id or 0
959
960
961 class Float(Field):
962     """ The precision digits are given by the attribute
963
964     :param digits: a pair (total, decimal), or a function taking a database
965                    cursor and returning a pair (total, decimal)
966     """
967     type = 'float'
968     _digits = None              # digits argument passed to class initializer
969     digits = None               # digits as computed by setup()
970
971     def __init__(self, string=None, digits=None, **kwargs):
972         super(Float, self).__init__(string=string, _digits=digits, **kwargs)
973
974     def _setup_digits(self, env):
975         """ Setup the digits for `self` and its corresponding column """
976         self.digits = self._digits(env.cr) if callable(self._digits) else self._digits
977         if self.digits:
978             assert isinstance(self.digits, (tuple, list)) and len(self.digits) >= 2, \
979                 "Float field %s with digits %r, expecting (total, decimal)" % (self, self.digits)
980         if self.store:
981             column = env[self.model_name]._columns[self.name]
982             column.digits_change(env.cr)
983
984     def _setup_regular(self, env):
985         super(Float, self)._setup_regular(env)
986         self._setup_digits(env)
987
988     _related_digits = property(attrgetter('digits'))
989
990     _description_digits = property(attrgetter('digits'))
991
992     _column_digits = property(lambda self: not callable(self._digits) and self._digits)
993     _column_digits_compute = property(lambda self: callable(self._digits) and self._digits)
994
995     def convert_to_cache(self, value, record, validate=True):
996         # apply rounding here, otherwise value in cache may be wrong!
997         if self.digits:
998             return float_round(float(value or 0.0), precision_digits=self.digits[1])
999         else:
1000             return float(value or 0.0)
1001
1002
1003 class _String(Field):
1004     """ Abstract class for string fields. """
1005     translate = False
1006
1007     _column_translate = property(attrgetter('translate'))
1008     _related_translate = property(attrgetter('translate'))
1009     _description_translate = property(attrgetter('translate'))
1010
1011
1012 class Char(_String):
1013     """ Basic string field, can be length-limited, usually displayed as a
1014     single-line string in clients
1015
1016     :param int size: the maximum size of values stored for that field
1017     :param bool translate: whether the values of this field can be translated
1018     """
1019     type = 'char'
1020     size = None
1021
1022     def _setup(self, env):
1023         super(Char, self)._setup(env)
1024         assert isinstance(self.size, (NoneType, int)), \
1025             "Char field %s with non-integer size %r" % (self, self.size)
1026
1027     _column_size = property(attrgetter('size'))
1028     _related_size = property(attrgetter('size'))
1029     _description_size = property(attrgetter('size'))
1030
1031     def convert_to_cache(self, value, record, validate=True):
1032         if value is None or value is False:
1033             return False
1034         return ustr(value)[:self.size]
1035
1036 class Text(_String):
1037     """ Text field. Very similar to :class:`~.Char` but used for longer
1038      contents and displayed as a multiline text box
1039
1040     :param translate: whether the value of this field can be translated
1041     """
1042     type = 'text'
1043
1044     def convert_to_cache(self, value, record, validate=True):
1045         if value is None or value is False:
1046             return False
1047         return ustr(value)
1048
1049 class Html(_String):
1050     type = 'html'
1051     sanitize = True                     # whether value must be sanitized
1052
1053     _column_sanitize = property(attrgetter('sanitize'))
1054     _related_sanitize = property(attrgetter('sanitize'))
1055     _description_sanitize = property(attrgetter('sanitize'))
1056
1057     def convert_to_cache(self, value, record, validate=True):
1058         if value is None or value is False:
1059             return False
1060         if validate and self.sanitize:
1061             return html_sanitize(value)
1062         return value
1063
1064
1065 class Date(Field):
1066     type = 'date'
1067
1068     @staticmethod
1069     def today(*args):
1070         """ Return the current day in the format expected by the ORM.
1071             This function may be used to compute default values.
1072         """
1073         return date.today().strftime(DATE_FORMAT)
1074
1075     @staticmethod
1076     def context_today(record, timestamp=None):
1077         """ Return the current date as seen in the client's timezone in a format
1078             fit for date fields. This method may be used to compute default
1079             values.
1080
1081             :param datetime timestamp: optional datetime value to use instead of
1082                 the current date and time (must be a datetime, regular dates
1083                 can't be converted between timezones.)
1084             :rtype: str
1085         """
1086         today = timestamp or datetime.now()
1087         context_today = None
1088         tz_name = record._context.get('tz') or record.env.user.tz
1089         if tz_name:
1090             try:
1091                 today_utc = pytz.timezone('UTC').localize(today, is_dst=False)  # UTC = no DST
1092                 context_today = today_utc.astimezone(pytz.timezone(tz_name))
1093             except Exception:
1094                 _logger.debug("failed to compute context/client-specific today date, using UTC value for `today`",
1095                               exc_info=True)
1096         return (context_today or today).strftime(DATE_FORMAT)
1097
1098     @staticmethod
1099     def from_string(value):
1100         """ Convert an ORM `value` into a :class:`date` value. """
1101         value = value[:DATE_LENGTH]
1102         return datetime.strptime(value, DATE_FORMAT).date()
1103
1104     @staticmethod
1105     def to_string(value):
1106         """ Convert a :class:`date` value into the format expected by the ORM. """
1107         return value.strftime(DATE_FORMAT)
1108
1109     def convert_to_cache(self, value, record, validate=True):
1110         if not value:
1111             return False
1112         if isinstance(value, basestring):
1113             if validate:
1114                 # force parsing for validation
1115                 self.from_string(value)
1116             return value[:DATE_LENGTH]
1117         return self.to_string(value)
1118
1119     def convert_to_export(self, value, env):
1120         if value and env.context.get('export_raw_data'):
1121             return self.from_string(value)
1122         return bool(value) and ustr(value)
1123
1124
1125 class Datetime(Field):
1126     type = 'datetime'
1127
1128     @staticmethod
1129     def now(*args):
1130         """ Return the current day and time in the format expected by the ORM.
1131             This function may be used to compute default values.
1132         """
1133         return datetime.now().strftime(DATETIME_FORMAT)
1134
1135     @staticmethod
1136     def context_timestamp(record, timestamp):
1137         """Returns the given timestamp converted to the client's timezone.
1138            This method is *not* meant for use as a _defaults initializer,
1139            because datetime fields are automatically converted upon
1140            display on client side. For _defaults you :meth:`fields.datetime.now`
1141            should be used instead.
1142
1143            :param datetime timestamp: naive datetime value (expressed in UTC)
1144                                       to be converted to the client timezone
1145            :rtype: datetime
1146            :return: timestamp converted to timezone-aware datetime in context
1147                     timezone
1148         """
1149         assert isinstance(timestamp, datetime), 'Datetime instance expected'
1150         tz_name = record._context.get('tz') or record.env.user.tz
1151         if tz_name:
1152             try:
1153                 utc = pytz.timezone('UTC')
1154                 context_tz = pytz.timezone(tz_name)
1155                 utc_timestamp = utc.localize(timestamp, is_dst=False)  # UTC = no DST
1156                 return utc_timestamp.astimezone(context_tz)
1157             except Exception:
1158                 _logger.debug("failed to compute context/client-specific timestamp, "
1159                               "using the UTC value",
1160                               exc_info=True)
1161         return timestamp
1162
1163     @staticmethod
1164     def from_string(value):
1165         """ Convert an ORM `value` into a :class:`datetime` value. """
1166         value = value[:DATETIME_LENGTH]
1167         if len(value) == DATE_LENGTH:
1168             value += " 00:00:00"
1169         return datetime.strptime(value, DATETIME_FORMAT)
1170
1171     @staticmethod
1172     def to_string(value):
1173         """ Convert a :class:`datetime` value into the format expected by the ORM. """
1174         return value.strftime(DATETIME_FORMAT)
1175
1176     def convert_to_cache(self, value, record, validate=True):
1177         if not value:
1178             return False
1179         if isinstance(value, basestring):
1180             if validate:
1181                 # force parsing for validation
1182                 self.from_string(value)
1183             value = value[:DATETIME_LENGTH]
1184             if len(value) == DATE_LENGTH:
1185                 value += " 00:00:00"
1186             return value
1187         return self.to_string(value)
1188
1189     def convert_to_export(self, value, env):
1190         if value and env.context.get('export_raw_data'):
1191             return self.from_string(value)
1192         return bool(value) and ustr(value)
1193
1194
1195 class Binary(Field):
1196     type = 'binary'
1197
1198
1199 class Selection(Field):
1200     """
1201     :param selection: specifies the possible values for this field.
1202         It is given as either a list of pairs (`value`, `string`), or a
1203         model method, or a method name.
1204     :param selection_add: provides an extension of the selection in the case
1205         of an overridden field. It is a list of pairs (`value`, `string`).
1206
1207     The attribute `selection` is mandatory except in the case of
1208     :ref:`related fields <field-related>` or :ref:`field extensions
1209     <field-incremental-definition>`.
1210     """
1211     type = 'selection'
1212     selection = None        # [(value, string), ...], function or method name
1213     selection_add = None    # [(value, string), ...]
1214
1215     def __init__(self, selection=None, string=None, **kwargs):
1216         if callable(selection):
1217             from openerp import api
1218             selection = api.expected(api.model, selection)
1219         super(Selection, self).__init__(selection=selection, string=string, **kwargs)
1220
1221     def _setup(self, env):
1222         super(Selection, self)._setup(env)
1223         assert self.selection is not None, "Field %s without selection" % self
1224
1225     def _setup_related(self, env):
1226         super(Selection, self)._setup_related(env)
1227         # selection must be computed on related field
1228         field = self.related_field
1229         self.selection = lambda model: field._description_selection(model.env)
1230
1231     def set_class_name(self, cls, name):
1232         super(Selection, self).set_class_name(cls, name)
1233         # determine selection (applying 'selection_add' extensions)
1234         selection = None
1235         for field in resolve_all_mro(cls, name, reverse=True):
1236             if isinstance(field, type(self)):
1237                 # We cannot use field.selection or field.selection_add here
1238                 # because those attributes are overridden by `set_class_name`.
1239                 if 'selection' in field._attrs:
1240                     selection = field._attrs['selection']
1241                 if 'selection_add' in field._attrs:
1242                     selection = selection + field._attrs['selection_add']
1243             else:
1244                 selection = None
1245         self.selection = selection
1246
1247     def _description_selection(self, env):
1248         """ return the selection list (pairs (value, label)); labels are
1249             translated according to context language
1250         """
1251         selection = self.selection
1252         if isinstance(selection, basestring):
1253             return getattr(env[self.model_name], selection)()
1254         if callable(selection):
1255             return selection(env[self.model_name])
1256
1257         # translate selection labels
1258         if env.lang:
1259             name = "%s,%s" % (self.model_name, self.name)
1260             translate = partial(
1261                 env['ir.translation']._get_source, name, 'selection', env.lang)
1262             return [(value, translate(label) if label else label) for value, label in selection]
1263         else:
1264             return selection
1265
1266     @property
1267     def _column_selection(self):
1268         if isinstance(self.selection, basestring):
1269             method = self.selection
1270             return lambda self, *a, **kw: getattr(self, method)(*a, **kw)
1271         else:
1272             return self.selection
1273
1274     def get_values(self, env):
1275         """ return a list of the possible values """
1276         selection = self.selection
1277         if isinstance(selection, basestring):
1278             selection = getattr(env[self.model_name], selection)()
1279         elif callable(selection):
1280             selection = selection(env[self.model_name])
1281         return [value for value, _ in selection]
1282
1283     def convert_to_cache(self, value, record, validate=True):
1284         if not validate:
1285             return value or False
1286         if value in self.get_values(record.env):
1287             return value
1288         elif not value:
1289             return False
1290         raise ValueError("Wrong value for %s: %r" % (self, value))
1291
1292     def convert_to_export(self, value, env):
1293         if not isinstance(self.selection, list):
1294             # FIXME: this reproduces an existing buggy behavior!
1295             return value
1296         for item in self._description_selection(env):
1297             if item[0] == value:
1298                 return item[1]
1299         return False
1300
1301
1302 class Reference(Selection):
1303     type = 'reference'
1304     size = None
1305
1306     def __init__(self, selection=None, string=None, **kwargs):
1307         super(Reference, self).__init__(selection=selection, string=string, **kwargs)
1308
1309     def _setup(self, env):
1310         super(Reference, self)._setup(env)
1311         assert isinstance(self.size, (NoneType, int)), \
1312             "Reference field %s with non-integer size %r" % (self, self.size)
1313
1314     _related_size = property(attrgetter('size'))
1315
1316     _column_size = property(attrgetter('size'))
1317
1318     def convert_to_cache(self, value, record, validate=True):
1319         if isinstance(value, BaseModel):
1320             if ((not validate or value._name in self.get_values(record.env))
1321                     and len(value) <= 1):
1322                 return value.with_env(record.env) or False
1323         elif isinstance(value, basestring):
1324             res_model, res_id = value.split(',')
1325             return record.env[res_model].browse(int(res_id))
1326         elif not value:
1327             return False
1328         raise ValueError("Wrong value for %s: %r" % (self, value))
1329
1330     def convert_to_read(self, value, use_name_get=True):
1331         return "%s,%s" % (value._name, value.id) if value else False
1332
1333     def convert_to_export(self, value, env):
1334         return bool(value) and value.name_get()[0][1]
1335
1336     def convert_to_display_name(self, value):
1337         return ustr(value and value.display_name)
1338
1339
1340 class _Relational(Field):
1341     """ Abstract class for relational fields. """
1342     relational = True
1343     domain = None                       # domain for searching values
1344     context = None                      # context for searching values
1345
1346     def _setup(self, env):
1347         super(_Relational, self)._setup(env)
1348         assert self.comodel_name in env.registry, \
1349             "Field %s with unknown comodel_name %r" % (self, self.comodel_name)
1350
1351     @property
1352     def _related_domain(self):
1353         if callable(self.domain):
1354             # will be called with another model than self's
1355             return lambda recs: self.domain(recs.env[self.model_name])
1356         else:
1357             # maybe not correct if domain is a string...
1358             return self.domain
1359
1360     _related_context = property(attrgetter('context'))
1361
1362     _description_relation = property(attrgetter('comodel_name'))
1363     _description_context = property(attrgetter('context'))
1364
1365     def _description_domain(self, env):
1366         return self.domain(env[self.model_name]) if callable(self.domain) else self.domain
1367
1368     _column_obj = property(attrgetter('comodel_name'))
1369     _column_domain = property(attrgetter('domain'))
1370     _column_context = property(attrgetter('context'))
1371
1372     def null(self, env):
1373         return env[self.comodel_name]
1374
1375     def modified(self, records):
1376         # Invalidate cache for self.inverse_fields, too. Note that recomputation
1377         # of fields that depend on self.inverse_fields is already covered by the
1378         # triggers (see above).
1379         spec = super(_Relational, self).modified(records)
1380         for invf in self.inverse_fields:
1381             spec.append((invf, None))
1382         return spec
1383
1384
1385 class Many2one(_Relational):
1386     """ The value of such a field is a recordset of size 0 (no
1387     record) or 1 (a single record).
1388
1389     :param comodel_name: name of the target model (string)
1390
1391     :param domain: an optional domain to set on candidate values on the
1392         client side (domain or string)
1393
1394     :param context: an optional context to use on the client side when
1395         handling that field (dictionary)
1396
1397     :param ondelete: what to do when the referred record is deleted;
1398         possible values are: ``'set null'``, ``'restrict'``, ``'cascade'``
1399
1400     :param auto_join: whether JOINs are generated upon search through that
1401         field (boolean, by default ``False``)
1402
1403     :param delegate: set it to ``True`` to make fields of the target model
1404         accessible from the current model (corresponds to ``_inherits``)
1405
1406     The attribute `comodel_name` is mandatory except in the case of related
1407     fields or field extensions.
1408     """
1409     type = 'many2one'
1410     ondelete = 'set null'               # what to do when value is deleted
1411     auto_join = False                   # whether joins are generated upon search
1412     delegate = False                    # whether self implements delegation
1413
1414     def __init__(self, comodel_name=None, string=None, **kwargs):
1415         super(Many2one, self).__init__(comodel_name=comodel_name, string=string, **kwargs)
1416
1417     def set_class_name(self, cls, name):
1418         super(Many2one, self).set_class_name(cls, name)
1419         # determine self.delegate
1420         if not self.delegate:
1421             self.delegate = name in cls._inherits.values()
1422
1423     _column_ondelete = property(attrgetter('ondelete'))
1424     _column_auto_join = property(attrgetter('auto_join'))
1425
1426     def _update(self, records, value):
1427         """ Update the cached value of `self` for `records` with `value`. """
1428         records._cache[self] = value
1429
1430     def convert_to_cache(self, value, record, validate=True):
1431         if isinstance(value, (NoneType, int)):
1432             return record.env[self.comodel_name].browse(value)
1433         if isinstance(value, BaseModel):
1434             if value._name == self.comodel_name and len(value) <= 1:
1435                 return value.with_env(record.env)
1436             raise ValueError("Wrong value for %s: %r" % (self, value))
1437         elif isinstance(value, tuple):
1438             return record.env[self.comodel_name].browse(value[0])
1439         elif isinstance(value, dict):
1440             return record.env[self.comodel_name].new(value)
1441         else:
1442             return record.env[self.comodel_name].browse(value)
1443
1444     def convert_to_read(self, value, use_name_get=True):
1445         if use_name_get and value:
1446             # evaluate name_get() as superuser, because the visibility of a
1447             # many2one field value (id and name) depends on the current record's
1448             # access rights, and not the value's access rights.
1449             try:
1450                 return value.sudo().name_get()[0]
1451             except MissingError:
1452                 # Should not happen, unless the foreign key is missing.
1453                 return False
1454         else:
1455             return value.id
1456
1457     def convert_to_write(self, value, target=None, fnames=None):
1458         return value.id
1459
1460     def convert_to_onchange(self, value):
1461         return value.id
1462
1463     def convert_to_export(self, value, env):
1464         return bool(value) and value.name_get()[0][1]
1465
1466     def convert_to_display_name(self, value):
1467         return ustr(value.display_name)
1468
1469
1470 class UnionUpdate(SpecialValue):
1471     """ Placeholder for a value update; when this value is taken from the cache,
1472         it returns ``record[field.name] | value`` and stores it in the cache.
1473     """
1474     def __init__(self, field, record, value):
1475         self.args = (field, record, value)
1476
1477     def get(self):
1478         field, record, value = self.args
1479         # in order to read the current field's value, remove self from cache
1480         del record._cache[field]
1481         # read the current field's value, and update it in cache only
1482         record._cache[field] = new_value = record[field.name] | value
1483         return new_value
1484
1485
1486 class _RelationalMulti(_Relational):
1487     """ Abstract class for relational fields *2many. """
1488
1489     def _update(self, records, value):
1490         """ Update the cached value of `self` for `records` with `value`. """
1491         for record in records:
1492             if self in record._cache:
1493                 record._cache[self] = record[self.name] | value
1494             else:
1495                 record._cache[self] = UnionUpdate(self, record, value)
1496
1497     def convert_to_cache(self, value, record, validate=True):
1498         if isinstance(value, BaseModel):
1499             if value._name == self.comodel_name:
1500                 return value.with_env(record.env)
1501         elif isinstance(value, list):
1502             # value is a list of record ids or commands
1503             if not record.id:
1504                 record = record.browse()        # new record has no value
1505             result = record[self.name]
1506             # modify result with the commands;
1507             # beware to not introduce duplicates in result
1508             for command in value:
1509                 if isinstance(command, (tuple, list)):
1510                     if command[0] == 0:
1511                         result += result.new(command[2])
1512                     elif command[0] == 1:
1513                         result.browse(command[1]).update(command[2])
1514                         result += result.browse(command[1]) - result
1515                     elif command[0] == 2:
1516                         # note: the record will be deleted by write()
1517                         result -= result.browse(command[1])
1518                     elif command[0] == 3:
1519                         result -= result.browse(command[1])
1520                     elif command[0] == 4:
1521                         result += result.browse(command[1]) - result
1522                     elif command[0] == 5:
1523                         result = result.browse()
1524                     elif command[0] == 6:
1525                         result = result.browse(command[2])
1526                 elif isinstance(command, dict):
1527                     result += result.new(command)
1528                 else:
1529                     result += result.browse(command) - result
1530             return result
1531         elif not value:
1532             return self.null(record.env)
1533         raise ValueError("Wrong value for %s: %s" % (self, value))
1534
1535     def convert_to_read(self, value, use_name_get=True):
1536         return value.ids
1537
1538     def convert_to_write(self, value, target=None, fnames=None):
1539         # remove/delete former records
1540         if target is None:
1541             set_ids = []
1542             result = [(6, 0, set_ids)]
1543             add_existing = lambda id: set_ids.append(id)
1544         else:
1545             tag = 2 if self.type == 'one2many' else 3
1546             result = [(tag, record.id) for record in target[self.name] - value]
1547             add_existing = lambda id: result.append((4, id))
1548
1549         if fnames is None:
1550             # take all fields in cache, except the inverses of self
1551             fnames = set(value._fields) - set(MAGIC_COLUMNS)
1552             for invf in self.inverse_fields:
1553                 fnames.discard(invf.name)
1554
1555         # add new and existing records
1556         for record in value:
1557             if not record.id or record._dirty:
1558                 values = dict((k, v) for k, v in record._cache.iteritems() if k in fnames)
1559                 values = record._convert_to_write(values)
1560                 if not record.id:
1561                     result.append((0, 0, values))
1562                 else:
1563                     result.append((1, record.id, values))
1564             else:
1565                 add_existing(record.id)
1566
1567         return result
1568
1569     def convert_to_export(self, value, env):
1570         return bool(value) and ','.join(name for id, name in value.name_get())
1571
1572     def convert_to_display_name(self, value):
1573         raise NotImplementedError()
1574
1575     def _compute_related(self, records):
1576         """ Compute the related field `self` on `records`. """
1577         for record in records:
1578             value = record
1579             # traverse the intermediate fields, and keep at most one record
1580             for name in self.related[:-1]:
1581                 value = value[name][:1]
1582             record[self.name] = value[self.related[-1]]
1583
1584
1585 class One2many(_RelationalMulti):
1586     """ One2many field; the value of such a field is the recordset of all the
1587         records in `comodel_name` such that the field `inverse_name` is equal to
1588         the current record.
1589
1590         :param comodel_name: name of the target model (string)
1591
1592         :param inverse_name: name of the inverse `Many2one` field in
1593             `comodel_name` (string)
1594
1595         :param domain: an optional domain to set on candidate values on the
1596             client side (domain or string)
1597
1598         :param context: an optional context to use on the client side when
1599             handling that field (dictionary)
1600
1601         :param auto_join: whether JOINs are generated upon search through that
1602             field (boolean, by default ``False``)
1603
1604         :param limit: optional limit to use upon read (integer)
1605
1606         The attributes `comodel_name` and `inverse_name` are mandatory except in
1607         the case of related fields or field extensions.
1608     """
1609     type = 'one2many'
1610     inverse_name = None                 # name of the inverse field
1611     auto_join = False                   # whether joins are generated upon search
1612     limit = None                        # optional limit to use upon read
1613     copy = False                        # o2m are not copied by default
1614
1615     def __init__(self, comodel_name=None, inverse_name=None, string=None, **kwargs):
1616         super(One2many, self).__init__(
1617             comodel_name=comodel_name,
1618             inverse_name=inverse_name,
1619             string=string,
1620             **kwargs
1621         )
1622
1623     def _setup_regular(self, env):
1624         super(One2many, self)._setup_regular(env)
1625
1626         if self.inverse_name:
1627             # link self to its inverse field and vice-versa
1628             invf = env[self.comodel_name]._fields[self.inverse_name]
1629             # In some rare cases, a `One2many` field can link to `Int` field
1630             # (res_model/res_id pattern). Only inverse the field if this is
1631             # a `Many2one` field.
1632             if isinstance(invf, Many2one):
1633                 self.inverse_fields.append(invf)
1634                 invf.inverse_fields.append(self)
1635
1636     _description_relation_field = property(attrgetter('inverse_name'))
1637
1638     _column_fields_id = property(attrgetter('inverse_name'))
1639     _column_auto_join = property(attrgetter('auto_join'))
1640     _column_limit = property(attrgetter('limit'))
1641
1642
1643 class Many2many(_RelationalMulti):
1644     """ Many2many field; the value of such a field is the recordset.
1645
1646         :param comodel_name: name of the target model (string)
1647
1648         The attribute `comodel_name` is mandatory except in the case of related
1649         fields or field extensions.
1650
1651         :param relation: optional name of the table that stores the relation in
1652             the database (string)
1653
1654         :param column1: optional name of the column referring to "these" records
1655             in the table `relation` (string)
1656
1657         :param column2: optional name of the column referring to "those" records
1658             in the table `relation` (string)
1659
1660         The attributes `relation`, `column1` and `column2` are optional. If not
1661         given, names are automatically generated from model names, provided
1662         `model_name` and `comodel_name` are different!
1663
1664         :param domain: an optional domain to set on candidate values on the
1665             client side (domain or string)
1666
1667         :param context: an optional context to use on the client side when
1668             handling that field (dictionary)
1669
1670         :param limit: optional limit to use upon read (integer)
1671
1672     """
1673     type = 'many2many'
1674     relation = None                     # name of table
1675     column1 = None                      # column of table referring to model
1676     column2 = None                      # column of table referring to comodel
1677     limit = None                        # optional limit to use upon read
1678
1679     def __init__(self, comodel_name=None, relation=None, column1=None, column2=None,
1680                  string=None, **kwargs):
1681         super(Many2many, self).__init__(
1682             comodel_name=comodel_name,
1683             relation=relation,
1684             column1=column1,
1685             column2=column2,
1686             string=string,
1687             **kwargs
1688         )
1689
1690     def _setup_regular(self, env):
1691         super(Many2many, self)._setup_regular(env)
1692
1693         if self.store and not self.relation:
1694             model = env[self.model_name]
1695             column = model._columns[self.name]
1696             if not isinstance(column, fields.function):
1697                 self.relation, self.column1, self.column2 = column._sql_names(model)
1698
1699         if self.relation:
1700             m2m = env.registry._m2m
1701             # if inverse field has already been setup, it is present in m2m
1702             invf = m2m.get((self.relation, self.column2, self.column1))
1703             if invf:
1704                 self.inverse_fields.append(invf)
1705                 invf.inverse_fields.append(self)
1706             else:
1707                 # add self in m2m, so that its inverse field can find it
1708                 m2m[(self.relation, self.column1, self.column2)] = self
1709
1710     _column_rel = property(attrgetter('relation'))
1711     _column_id1 = property(attrgetter('column1'))
1712     _column_id2 = property(attrgetter('column2'))
1713     _column_limit = property(attrgetter('limit'))
1714
1715
1716 class Id(Field):
1717     """ Special case for field 'id'. """
1718     store = True
1719     #: Can't write this!
1720     readonly = True
1721
1722     def __init__(self, string=None, **kwargs):
1723         super(Id, self).__init__(type='integer', string=string, **kwargs)
1724
1725     def to_column(self):
1726         return fields.integer('ID')
1727
1728     def __get__(self, record, owner):
1729         if record is None:
1730             return self         # the field is accessed through the class owner
1731         if not record:
1732             return False
1733         return record.ensure_one()._ids[0]
1734
1735     def __set__(self, record, value):
1736         raise TypeError("field 'id' cannot be assigned")
1737
1738
1739 # imported here to avoid dependency cycle issues
1740 from openerp import SUPERUSER_ID
1741 from .exceptions import Warning, AccessError, MissingError
1742 from .models import BaseModel, MAGIC_COLUMNS
1743 from .osv import fields