def _validate(self, ids):
        pool = Pool()
        if (Transaction().user == 0
                and Transaction().context.get('user')):
            with Transaction().set_user(Transaction().context.get('user')):
                return self._validate(ids)

        for field in self._constraints:
            if not getattr(self, field[0])(ids):
                self.raise_user_error(field[1])

        if not 'res.user' in pool.object_name_list() \
                or Transaction().user == 0:
            ctx_pref = {
            }
        else:
            user_obj = pool.get('res.user')
            ctx_pref = user_obj.get_preferences(context_only=True)

        def is_pyson(test):
            if isinstance(test, PYSON):
                return True
            if isinstance(test, (list, tuple)):
                for i in test:
                    if isinstance(i, PYSON):
                        return True
                    if isinstance(i, (list, tuple)):
                        if is_pyson(i):
                            return True
            return False

        with Transaction().set_context(ctx_pref):
            records = self.browse(ids)
            for field_name, field in self._columns.iteritems():
                if isinstance(field, fields.Function) and \
                        not field.setter:
                    continue
                # validate domain
                if (field._type in
                        ('many2one', 'many2many', 'one2many', 'one2one')
                    and field.domain):
                    if field._type in ('many2one', 'one2many'):
                        relation_obj = pool.get(field.model_name)
                    else:
                        relation_obj = field.get_target()
                    if is_pyson(field.domain):
                        pyson_domain = PYSONEncoder().encode(field.domain)
                        for record in records:
                            env = EvalEnvironment(record, self)
                            env.update(Transaction().context)
                            env['current_date'] = datetime.datetime.today()
                            env['time'] = time
                            env['context'] = Transaction().context
                            env['active_id'] = record.id
                            domain = PYSONDecoder(env).decode(pyson_domain)
                            relation_ids = []
                            if record[field_name]:
                                if field._type in ('many2one',):
                                    relation_ids.append(record[field_name].id)
                                else:
                                    relation_ids.extend(
                                            [x.id for x in record[field_name]])
                            if relation_ids and not relation_obj.search([
                                        'AND',
                                        [('id', 'in', relation_ids)],
                                        domain,
                                        ]):
                                self.raise_user_error(
                                        'domain_validation_record',
                                        error_args=self._get_error_args(
                                            field_name))
                    else:
                        relation_ids = []
                        for record in records:
                            if record[field_name]:
                                if field._type in ('many2one',):
                                    relation_ids.append(record[field_name].id)
                                else:
                                    relation_ids.extend(
                                            [x.id for x in record[field_name]])
                        if relation_ids:
                            find_ids = relation_obj.search([
                                'AND',
                                [('id', 'in', relation_ids)],
                                field.domain,
                                ])
                            if not set(relation_ids) == set(find_ids):
                                self.raise_user_error(
                                        'domain_validation_record',
                                        error_args=self._get_error_args(
                                            field_name))
                # validate states required
                if field.states and 'required' in field.states:
                    if is_pyson(field.states['required']):
                        pyson_required = PYSONEncoder().encode(
                                field.states['required'])
                        for record in records:
                            env = EvalEnvironment(record, self)
                            env.update(Transaction().context)
                            env['current_date'] = datetime.datetime.today()
                            env['time'] = time
                            env['context'] = Transaction().context
                            env['active_id'] = record.id
                            required = PYSONDecoder(env).decode(pyson_required)
                            if required and record[field_name] is None:
                                self.raise_user_error(
                                        'required_validation_record',
                                        error_args=self._get_error_args(
                                            field_name))
                    else:
                        if field.states['required']:
                            for record in records:
                                if not record[field_name]:
                                    self.raise_user_error(
                                            'required_validation_record',
                                            error_args=self._get_error_args(
                                                field_name))
                # validate required
                if field.required:
                    for record in records:
                        if (isinstance(record[field_name], (BrowseRecordNull,
                                        type(None), type(False)))
                                and not record[field_name]):
                            self.raise_user_error(
                                'required_validation_record',
                                error_args=self._get_error_args(field_name))
                # validate size
                if hasattr(field, 'size') and field.size:
                    for record in records:
                        if len(record[field_name] or '') > field.size:
                            self.raise_user_error(
                                'size_validation_record',
                                error_args=self._get_error_args(field_name))

                def digits_test(value, digits, field_name):
                    def raise_user_error():
                        self.raise_user_error('digits_validation_record',
                            error_args=self._get_error_args(field_name))
                    if value is None:
                        return
                    if isinstance(value, Decimal):
                        if (value.quantize(Decimal(str(10.0 ** -digits[1])))
                                != value):
                            raise_user_error()
                    elif CONFIG.options['db_type'] != 'mysql':
                        if not (round(value, digits[1]) == float(value)):
                            raise_user_error()
                # validate digits
                if hasattr(field, 'digits') and field.digits:
                    if is_pyson(field.digits):
                        pyson_digits = PYSONEncoder().encode(field.digits)
                        for record in records:
                            env = EvalEnvironment(record, self)
                            env.update(Transaction().context)
                            env['current_date'] = datetime.datetime.today()
                            env['time'] = time
                            env['context'] = Transaction().context
                            env['active_id'] = record.id
                            digits = PYSONDecoder(env).decode(pyson_digits)
                            digits_test(record[field_name], digits, field_name)
                    else:
                        for record in records:
                            digits_test(record[field_name], field.digits,
                                field_name)
 def __export_row(self, record, fields_names):
     pool = Pool()
     lines = []
     data = ['' for x in range(len(fields_names))]
     done = []
     for fpos in range(len(fields_names)):
         fields_tree = fields_names[fpos]
         if not fields_tree:
             continue
         value = record
         i = 0
         while i < len(fields_tree):
             if not isinstance(value, BrowseRecord):
                 break
             field_name = fields_tree[i]
             model_obj = pool.get(value._model_name)
             if field_name in model_obj._columns:
                 field = model_obj._columns[field_name]
             elif field_name in model_obj._inherit_fields:
                 field = model_obj._inherit_fields[field_name][2]
             else:
                 raise Exception('Field %s not available on object "%s"'
                     % (field_name, model_obj._name))
             if field.states and 'invisible' in field.states:
                 pyson_invisible = PYSONEncoder().encode(
                         field.states['invisible'])
                 env = EvalEnvironment(value, model_obj)
                 env.update(Transaction().context)
                 env['current_date'] = datetime.datetime.today()
                 env['time'] = time
                 env['context'] = Transaction().context
                 env['active_id'] = value.id
                 invisible = PYSONDecoder(env).decode(pyson_invisible)
                 if invisible:
                     value = ''
                     break
             value = value[field_name]
             if isinstance(value, (BrowseRecordList, list)):
                 first = True
                 child_fields_names = [(x[:i + 1] == fields_tree[:i + 1] and
                     x[i + 1:]) or [] for x in fields_names]
                 if child_fields_names in done:
                     break
                 done.append(child_fields_names)
                 for child_record in value:
                     child_lines = self.__export_row(child_record,
                             child_fields_names)
                     if first:
                         for child_fpos in xrange(len(fields_names)):
                             if child_lines and child_lines[0][child_fpos]:
                                 data[child_fpos] = \
                                         child_lines[0][child_fpos]
                         lines += child_lines[1:]
                         first = False
                     else:
                         lines += child_lines
                 break
             i += 1
         if i == len(fields_tree):
             if value is None:
                 value = ''
             data[fpos] = value
     return [data] + lines