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