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