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