[MERGE] OPW 16988 function fields with multi does not work on osv_memory
authorJean-Christophe VASSORT <jcv@openerp.com>
Wed, 7 Mar 2012 12:30:14 +0000 (13:30 +0100)
committerJean-Christophe VASSORT <jcv@openerp.com>
Wed, 7 Mar 2012 12:30:14 +0000 (13:30 +0100)
bzr revid: jcv@openerp.com-20120307123014-wymjy2c4v1nz0xfh

1  2 
bin/osv/orm.py

diff --combined bin/osv/orm.py
@@@ -723,10 -723,7 +723,10 @@@ class orm_template(object)
              if mode=='.id':
                  id = int(id)
                  obj_model = self.pool.get(model_name)
 -                ids = obj_model.search(cr, uid, [('id', '=', int(id))])
 +                dom = [('id', '=', id)]
 +                if obj_model._columns.get('active'):
 +                    dom.append(('active', 'in', ['True','False']))
 +                ids = obj_model.search(cr, uid, dom, context=context)
                  if not len(ids):
                      raise Exception(_("Database ID doesn't exist: %s : %s") %(model_name, id))
              elif mode=='id':
                  else:
                      module, xml_id = current_module, id
                  record_id = ir_model_data_obj._get_id(cr, uid, module, xml_id)
 -                ir_model_data = ir_model_data_obj.read(cr, uid, [record_id], ['res_id'])
 +                ir_model_data = ir_model_data_obj.read(cr, uid, [record_id], ['res_id'], context=context)
                  if not ir_model_data:
                      raise ValueError('No references to %s.%s' % (module, xml_id))
                  id = ir_model_data[0]['res_id']
              else:
                  obj_model = self.pool.get(model_name)
 -                ids = obj_model.name_search(cr, uid, id, operator='=')
 +                ids = obj_model.name_search(cr, uid, id, operator='=', context=context)
                  if not ids:
                      raise ValueError('No record found for %s' % (id,))
                  id = ids[0][0]
              done = {}
              for i in range(len(fields)):
                  res = False
 -                if not line[i]:
 -                    continue
                  if i >= len(line):
                      raise Exception(_('Please check that all your lines have %d columns.') % (len(fields),))
  
                          continue
                      done[field[len(prefix)]] = True
                      relation_obj = self.pool.get(fields_def[field[len(prefix)]]['relation'])
 -                    newfd = relation_obj.fields_get( cr, uid, context=context )
 +                    newfd = relation_obj.fields_get(cr, uid, context=context)
                      pos = position
                      res = []
                      first = 0
                          mode = False
                      else:
                          mode = field[len(prefix)+1]
 -                    res = _get_id(relation, line[i], current_module, mode)
 +                    res = line[i] and _get_id(relation, line[i], current_module, mode) or False
  
                  elif fields_def[field[len(prefix)]]['type']=='many2many':
                      relation = fields_def[field[len(prefix)]]['relation']
  
                      # TODO: improve this by using csv.csv_reader
                      res = []
 -                    for db_id in line[i].split(config.get('csv_internal_sep')):
 -                        res.append( _get_id(relation, db_id, current_module, mode) )
 +                    if line[i]:
 +                        for db_id in line[i].split(config.get('csv_internal_sep')):
 +                            res.append( _get_id(relation, db_id, current_module, mode) )
                      res = [(6,0,res)]
  
                  elif fields_def[field[len(prefix)]]['type'] == 'integer':
      def copy(self, cr, uid, id, default=None, context=None):
          raise NotImplementedError(_('The copy method is not implemented on this object !'))
  
 -    def exists(self, cr, uid, id, context=None):
 +    def exists(self, cr, uid, ids, context=None):
          raise NotImplementedError(_('The exists method is not implemented on this object !'))
  
      def read_string(self, cr, uid, id, langs, fields=None, context=None):
@@@ -1960,13 -1958,30 +1960,30 @@@ class orm_memory(orm_template)
                  result.append(r)
                  if id in self.datas:
                      self.datas[id]['internal.date_access'] = time.time()
+                     
+             # all non inherited fields for which the attribute whose name is in load is False
              fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields_to_read)
+             todo = {}
              for f in fields_post:
-                 res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result)
-                 for record in result:
-                     record[f] = res2[record['id']]
-             if isinstance(ids_orig, (int, long)):
-                 return result[0]
+                 todo.setdefault(self._columns[f]._multi, [])
+                 todo[self._columns[f]._multi].append(f)
+             for key, val in todo.items():
+                 if key:
+                     res2 = self._columns[val[0]].get_memory(cr, self, ids, val, user, context=context, values=result)
+                     for pos in val:
+                         for record in result:
+                             if isinstance(res2[record['id']], str): res2[record['id']] = eval(res2[record['id']]) #TOCHECK : why got string instend of dict in python2.6
+                             multi_fields = res2.get(record['id'],{})
+                             if multi_fields:
+                                 record[pos] = multi_fields.get(pos,[])
+                 else:
+                     for f in val:
+                         res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result)
+                         for record in result:
+                             if res2:
+                                 record[f] = res2[record['id']]
+                             else:
+                                 record[f] = []
          return result
  
      def write(self, cr, user, ids, vals, context=None):
              return self.datas.keys()
  
          res = []
 -        counter = 0
 +        counter = 1
          #Find the value of dict
          f = False
          if result:
              for id, data in self.datas.items():
 -                counter = counter + 1
                  data['id'] = id
 -                if limit and (counter > int(limit)):
 +                if limit and (counter > int(limit) + int(offset)):
                      break
                  f = True
                  for arg in result:
                          val = eval('data[arg[0]]'+arg[1] +' arg[2]', locals())
                      elif arg[1] in ['ilike']:
                          val = (str(data[arg[0]]).find(str(arg[2]))!=-1)
 -
                      f = f and val
 -
                  if f:
 -                    res.append(id)
 +                    if counter > offset:
 +                        res.append(id)
 +                    counter += 1
          if count:
              return len(res)
          return res or []
          # nothing to check in memory...
          pass
  
 -    def exists(self, cr, uid, id, context=None):
 -        return id in self.datas
 +    def exists(self, cr, uid, ids, context=None):
 +        if isinstance(ids, (int,long)):
 +            ids = [ids]
 +        return all(( id in self.datas for id in ids ))
  
  class orm(orm_template):
      _sql_constraints = []
              groupby_def = self._columns.get(groupby) or (self._inherit_fields.get(groupby) and self._inherit_fields.get(groupby)[2])
              assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True"
  
 -        fget = self.fields_get(cr, uid, fields)
 +        fget = self.fields_get(cr, uid, fields, context=context)
          float_int_fields = filter(lambda x: fget[x]['type'] in ('float', 'integer'), fields)
          flist = ''
          group_count = group_by = groupby
          if groupby:
              if fget.get(groupby):
 -                if fget[groupby]['type'] in ('date', 'datetime'):
 -                    flist = "to_char(%s,'yyyy-mm') as %s " % (qualified_groupby_field, groupby)
 -                    groupby = "to_char(%s,'yyyy-mm')" % (qualified_groupby_field)
 -                    qualified_groupby_field = groupby
 +                groupby_type = fget[groupby]['type']
 +                if groupby_type in ('date', 'datetime'):    
 +                    qualified_groupby_field = "to_char(%s,'yyyy-mm')" % qualified_groupby_field
 +                    flist = "%s as %s " % (qualified_groupby_field, groupby)
 +                elif groupby_type == 'boolean':
 +                     qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field
 +                     flist = "%s as %s " % (qualified_groupby_field, groupby)
                  else:
                      flist = qualified_groupby_field
              else:
              f = self._columns[store_field]
              if hasattr(f, 'digits_change'):
                  f.digits_change(cr)
 +            def not_this_field(stored_func):
 +                x, y, z, e, f, l = stored_func
 +                return x != self._name or y != store_field
 +            self.pool._store_function[self._name] = filter(not_this_field, self.pool._store_function.get(self._name, []))
              if not isinstance(f, fields.function):
                  continue
              if not f.store:
                  continue
 -            if self._columns[store_field].store is True:
 +            sm = f.store
 +            if sm is True:
                  sm = {self._name: (lambda self, cr, uid, ids, c={}: ids, None, 10, None)}
 -            else:
 -                sm = self._columns[store_field].store
              for object, aa in sm.items():
                  if len(aa) == 4:
                      (fnct, fields2, order, length) = aa
                      raise except_orm('Error',
                          ('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority, time length)}.' % (store_field, self._name)))
                  self.pool._store_function.setdefault(object, [])
 -                ok = True
 -                for x, y, z, e, f, l in self.pool._store_function[object]:
 -                    if (x==self._name) and (y==store_field) and (e==fields2):
 -                        if f == order:
 -                            ok = False
 -                if ok:
 -                    self.pool._store_function[object].append( (self._name, store_field, fnct, fields2, order, length))
 -                    self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
 +                self.pool._store_function[object].append((self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length))
 +                self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
  
          for (key, _, msg) in self._sql_constraints:
              self.pool._sql_error[self._table+'_'+key] = msg
          domain = domain[:]
          # if the object has a field named 'active', filter out all inactive
          # records unless they were explicitely asked for
 -        if 'active' in self._columns and (active_test and context.get('active_test', True)):
 +        if 'active' in (self._columns.keys() + self._inherit_fields.keys()) and (active_test and context.get('active_test', True)):
              if domain:
                  active_in_args = False
                  for a in domain: