Merge commit 'origin/master' into mdv-gpl3-py26
[odoo/odoo.git] / bin / osv / orm.py
index ec61d9a..6ecb829 100644 (file)
@@ -88,10 +88,10 @@ class browse_null(object):
         self.id = False
 
     def __getitem__(self, name):
-        return False
+        return None
 
     def __getattr__(self, name):
-        return False  # XXX: return self ?
+        return None  # XXX: return self ?
 
     def __int__(self):
         return False
@@ -155,7 +155,7 @@ class browse_record(object):
                 col = self._table._columns[name]
             elif name in self._table._inherit_fields:
                 col = self._table._inherit_fields[name][2]
-            elif hasattr(self._table, name):
+            elif hasattr(self._table, str(name)):
                 if isinstance(getattr(self._table, name), (types.MethodType, types.LambdaType, types.FunctionType)):
                     return lambda *args, **argv: getattr(self._table, name)(self._cr, self._uid, [self._id], *args, **argv)
                 else:
@@ -163,7 +163,7 @@ class browse_record(object):
             else:
                 logger = netsvc.Logger()
                 logger.notifyChannel('orm', netsvc.LOG_ERROR, "Programming error: field '%s' does not exist in object '%s' !" % (name, self._table._name))
-                return False
+                return None
 
             # if the field is a classic one or a many2one, we'll fetch all classic and many2one fields
             if col._classic_write:
@@ -189,6 +189,9 @@ class browse_record(object):
                                 d[n].set_value(self._cr, self._uid, d[n], self, f)
 
 
+           if not datas:
+                   # Where did those ids come from? Perhaps old entries in ir_model_data?
+                   raise except_orm('NoDataError', 'Field %s in %s%s'%(name,self._table_name,str(ids)))
             # create browse records for 'remote' objects
             for data in datas:
                 for n, f in ffields:
@@ -209,6 +212,12 @@ class browse_record(object):
                     elif f._type in ('one2many', 'many2many') and len(data[n]):
                         data[n] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool.get(f._obj), self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in data[n]], self._context)
                 self._data[data['id']].update(data)
+       if not name in self._data[self._id]:
+               #how did this happen?
+               logger = netsvc.Logger()
+               logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Ffields: %s, datas: %s"%(str(fffields),str(datas)))
+               logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Data: %s, Table: %s"%(str(self._data[self._id]),str(self._table)))
+               raise AttributeError(_('Unknown attribute %s in %s ') % (str(name),self._table_name))
         return self._data[self._id][name]
 
     def __getattr__(self, name):
@@ -514,8 +523,10 @@ class orm_template(object):
                                 module, xml_id = current_module, line[i]
                             ir_model_data_obj = self.pool.get('ir.model.data')
                             id = ir_model_data_obj._get_id(cr, uid, module, xml_id)
-                            res_id = ir_model_data_obj.read(cr, uid, [id],
-                                    ['res_id'])[0]['res_id']
+                           res_res_id = ir_model_data_obj.read(cr, uid, [id],
+                                    ['res_id'])
+                           if res_res_id:
+                                   res_id = res_res_id[0]['res_id']
                     row[field[0][:-3]] = res_id or False
                     continue
                 if (len(field) == len(prefix)+1) and \
@@ -1012,7 +1023,7 @@ class orm_template(object):
                         if attr != 'position'
                     ])
                     tag = "<%s%s>" % (node2.localName, attrs)
-                    raise AttributeError(_("Couldn't find tag '%s' in parent view !") % tag)
+                    raise AttributeError(_("Couldn't find tag '%s' in parent view !\n%s") % (tag,src))
             return doc_src.toxml(encoding="utf-8").replace('\t', '')
 
         result = {'type': view_type, 'model': self._name}
@@ -1064,8 +1075,8 @@ class orm_template(object):
             # otherwise, build some kind of default view
             if view_type == 'form':
                 res = self.fields_get(cr, user, context=context)
-                xml = '''<?xml version="1.0" encoding="utf-8"?>''' \
-                '''<form string="%s">''' % (self._description,)
+                xml = '<?xml version="1.0" encoding="utf-8"?> ' \
+                     '<form string="%s">' % (self._description,)
                 for x in res:
                     if res[x]['type'] not in ('one2many', 'many2many'):
                         xml += '<field name="%s"/>' % (x,)
@@ -1076,19 +1087,25 @@ class orm_template(object):
                 _rec_name = self._rec_name
                 if _rec_name not in self._columns:
                     _rec_name = self._columns.keys()[0]
-                xml = '''<?xml version="1.0" encoding="utf-8"?>''' \
-                '''<tree string="%s"><field name="%s"/></tree>''' \
-                % (self._description, self._rec_name)
+                xml = '<?xml version="1.0" encoding="utf-8"?>' \
+                       '<tree string="%s"><field name="%s"/></tree>' \
+                       % (self._description, self._rec_name)
             elif view_type == 'calendar':
                 xml = self.__get_default_calendar_view()
             else:
-                xml = ''
+                xml = '<?xml version="1.0"?>'  # what happens here, graph case?
             result['arch'] = xml
             result['name'] = 'default'
             result['field_parent'] = False
             result['view_id'] = 0
 
-        doc = dom.minidom.parseString(encode(result['arch']))
+       try:
+               doc = dom.minidom.parseString(encode(result['arch']))
+       except Exception, ex:
+               logger = netsvc.Logger()
+               logger.notifyChannel('init', netsvc.LOG_DEBUG, 'Wrong arch in %s (%s):\n %s' % (result['name'], view_type, result['arch'] ))
+               raise except_orm('Error',
+                        ('Invalid xml in view %s(%d) of %s: %s' % (result['name'], result['view_id'], self._name, str(ex))))
         xarch, xfields = self.__view_look_dom_arch(cr, user, doc, view_id, context=context)
         result['arch'] = xarch
         result['fields'] = xfields
@@ -2284,49 +2301,61 @@ class orm(orm_template):
             if self.pool._init:
                 self.pool._init_parent[self._name]=True
             else:
-                if vals[self._parent_name]:
-                    cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (vals[self._parent_name],))
-                else:
-                    cr.execute('SELECT parent_left,parent_right FROM '+self._table+' WHERE id IS NULL')
-                res = cr.fetchone()
-                if res:
-                    pleft,pright = res
-                else:
-                    cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
-                    pleft,pright = cr.fetchone()
-                cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%s',ids))+')', ids)
-                dest = pleft + 1
-                for cleft,cright,cid in cr.fetchall():
-                    if cleft > pleft:
-                        treeshift  = pleft - cleft + 1
-                        leftbound  = pleft+1
-                        rightbound = cleft-1
-                        cwidth     = cright-cleft+1
-                        leftrange = cright
-                        rightrange  = pleft
+                for id in ids:
+                    if vals[self._parent_name]:
+                        cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (vals[self._parent_name],))
+                        pleft_old = pright_old = None
+                        result_p = cr.fetchall()
+                        for (pleft,pright,pid) in result_p:
+                            if pid == id:
+                                break
+                            pleft_old = pleft
+                            pright_old = pright
+                        if not pleft_old:
+                            cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (vals[self._parent_name],))
+                            pleft_old,pright_old = cr.fetchone()
+                        res = (pleft_old, pright_old)
                     else:
-                        treeshift  = pleft - cright
-                        leftbound  = cright + 1
-                        rightbound = pleft
-                        cwidth     = cleft-cright-1
-                        leftrange  = pleft+1
-                        rightrange = cleft
-                    cr.execute('UPDATE '+self._table+'''
-                        SET
-                            parent_left = CASE
-                                WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
-                                WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
-                                ELSE parent_left
-                            END,
-                            parent_right = CASE
-                                WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
-                                WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
-                                ELSE parent_right
-                            END
-                        WHERE
-                            parent_left<%s OR parent_right>%s;
-                    ''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
-                        cwidth,cleft,cright,treeshift,leftrange,rightrange))
+                        cr.execute('SELECT parent_left,parent_right FROM '+self._table+' WHERE id IS NULL')
+                        res = cr.fetchone()
+                    if res:
+                        pleft,pright = res
+                    else:
+                        cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
+                        pleft,pright = cr.fetchone()
+                    cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%s',ids))+')', ids)
+                    dest = pleft + 1
+                    for cleft,cright,cid in cr.fetchall():
+                        if cleft > pleft:
+                            treeshift  = pleft - cleft + 1
+                            leftbound  = pleft+1
+                            rightbound = cleft-1
+                            cwidth     = cright-cleft+1
+                            leftrange = cright
+                            rightrange  = pleft
+                        else:
+                            treeshift  = pleft - cright
+                            leftbound  = cright + 1
+                            rightbound = pleft
+                            cwidth     = cleft-cright-1
+                            leftrange  = pleft+1
+                            rightrange = cleft
+                        cr.execute('UPDATE '+self._table+'''
+                            SET
+                                parent_left = CASE
+                                    WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
+                                    WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
+                                    ELSE parent_left
+                                END,
+                                parent_right = CASE
+                                    WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
+                                    WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
+                                    ELSE parent_right
+                                END
+                            WHERE
+                                parent_left<%s OR parent_right>%s;
+                        ''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
+                            cwidth,cleft,cright,treeshift,leftrange,rightrange))
 
         result = self._store_get_values(cr, user, ids, vals.keys(), context)
         for order, object, ids, fields in result:
@@ -2444,8 +2473,17 @@ class orm(orm_template):
             else:
                 parent = vals.get(self._parent_name, False)
                 if parent:
-                    cr.execute('select parent_left from '+self._table+' where id=%s', (parent,))
-                    pleft = cr.fetchone()[0]
+                    cr.execute('select parent_right from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (parent,))
+                    pleft_old = None
+                    result_p = cr.fetchall()
+                    for (pleft,) in result_p:
+                        if not pleft:
+                            break
+                        pleft_old = pleft
+                    if not pleft_old:
+                        cr.execute('select parent_left from '+self._table+' where id=%s', (parent,))
+                        pleft_old = cr.fetchone()[0]
+                    pleft = pleft_old
                 else:
                     cr.execute('select max(parent_right) from '+self._table)
                     pleft = cr.fetchone()[0] or 0