e103ee14515f5a395fbc87b2ffe97f20a79c0f13
[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         if isinstance(value, dict):
907             # special case, when an integer field is used as inverse for a one2many
908             return value.get('id', False)
909         return int(value or 0)
910
911     def convert_to_read(self, value, use_name_get=True):
912         # Integer values greater than 2^31-1 are not supported in pure XMLRPC,
913         # so we have to pass them as floats :-(
914         if value and value > xmlrpclib.MAXINT:
915             return float(value)
916         return value
917
918     def _update(self, records, value):
919         # special case, when an integer field is used as inverse for a one2many
920         records._cache[self] = value.id or 0
921
922
923 class Float(Field):
924     """ The precision digits are given by the attribute
925
926     :param digits: a pair (total, decimal), or a function taking a database
927                    cursor and returning a pair (total, decimal)
928     """
929     type = 'float'
930     _digits = None              # digits argument passed to class initializer
931     digits = None               # digits as computed by setup()
932
933     def __init__(self, string=None, digits=None, **kwargs):
934         super(Float, self).__init__(string=string, _digits=digits, **kwargs)
935
936     def _setup_regular(self, env):
937         super(Float, self)._setup_regular(env)
938         self.digits = self._digits(env.cr) if callable(self._digits) else self._digits
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