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