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