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