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