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