diff --git a/addons/auth_oauth/ir_configparameter.py b/addons/auth_oauth/ir_configparameter.py
index b0fa17ffa5b9f2e79cfe2b063983474dcbf0e4e3..e421bcb4b399f8f9805fdb0677d4ca0954f516de 100644
--- a/addons/auth_oauth/ir_configparameter.py
+++ b/addons/auth_oauth/ir_configparameter.py
@@ -1,14 +1,12 @@
 # -*- coding: utf-8 -*-
-from openerp import SUPERUSER_ID
-from openerp.osv import osv
+from odoo import models
 
-class ir_configparameter(osv.Model):
+
+class IrConfigParameter(models.Model):
     _inherit = 'ir.config_parameter'
 
-    def init(self, cr, force=False):
-        super(ir_configparameter, self).init(cr, force=force)
+    def init(self, force=False):
+        super(IrConfigParameter, self).init(force=force)
         if force:
-            IMD = self.pool['ir.model.data']
-            oauth_oe = IMD.xmlid_to_object(cr, SUPERUSER_ID, 'auth_oauth.provider_openerp')
-            dbuuid = self.get_param(cr, SUPERUSER_ID, 'database.uuid')
-            oauth_oe.write({'client_id': dbuuid})
+            oauth_oe = self.env.ref('auth_oauth.provider_openerp')
+            oauth_oe.write({'client_id': self.sudo().get_param('database.uuid')})
diff --git a/addons/report_webkit/ir_report.py b/addons/report_webkit/ir_report.py
index 4f5be2949b05f8cb39897400fadef102a680b4cc..347d59352e83889002bb2464283e977c5c4d1762 100644
--- a/addons/report_webkit/ir_report.py
+++ b/addons/report_webkit/ir_report.py
@@ -25,7 +25,7 @@ class ir_actions_report_xml(orm.Model):
             " is printed on a separate HTML but memory and disk usage are wider.")
     }
 
-    def _lookup_report(self, cr, name):
+    def _lookup_report(self, name):
         """
         Look up a report definition.
         """
@@ -41,8 +41,8 @@ class ir_actions_report_xml(orm.Model):
             if not isinstance(new_report, WebKitParser):
                 new_report = None
         else:
-            cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s and report_type=%s", (name, 'webkit'))
-            r = cr.dictfetchone()
+            self.env.cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s and report_type=%s", (name, 'webkit'))
+            r = self.env.cr.dictfetchone()
             if r:
                 if r['parser']:
                     parser = operator.attrgetter(r['parser'])(openerp.addons)
@@ -59,4 +59,4 @@ class ir_actions_report_xml(orm.Model):
         if new_report:
             return new_report
         else:
-            return super(ir_actions_report_xml, self)._lookup_report(cr, name)
+            return super(ir_actions_report_xml, self)._lookup_report(name)
diff --git a/addons/website/models/ir_actions.py b/addons/website/models/ir_actions.py
index febe85488abb4c1d0620c79dac6b49a09e6bafc7..dff702ba867cd2f00008bd43db83c154391626a3 100644
--- a/addons/website/models/ir_actions.py
+++ b/addons/website/models/ir_actions.py
@@ -2,64 +2,59 @@
 
 import urlparse
 
-from openerp.http import request
-from openerp.osv import fields, osv
+from odoo.http import request
+from odoo import api, fields, models
 
 
-class actions_server(osv.Model):
+class actions_server(models.Model):
     """ Add website option in server actions. """
     _name = 'ir.actions.server'
-    _inherit = ['ir.actions.server']
-
-    def _compute_website_url(self, cr, uid, id, website_path, xml_id, context=None):
-        base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url', context=context)
-        link = website_path or xml_id or (id and '%d' % id) or ''
+    _inherit = 'ir.actions.server'
+
+    xml_id = fields.Char(compute=models.Model.get_xml_id, string="External ID",
+                         help="ID of the action if defined in a XML file")
+    website_path = fields.Char()
+    website_url = fields.Char(compute='_get_website_url', help='The full URL to access the server action through the website.')
+    website_published = fields.Boolean(string='Available on the Website', copy=False,
+                                       help='A code server action can be executed from the website, using a dedicated '
+                                            'controller. The address is <base>/website/action/<website_path>. '
+                                            'Set this field as True to allow users to run this action. If it '
+                                            'is set to False the action cannot be run through the website.')
+
+    def _compute_website_url(self, website_path, xml_id):
+        base_url = self.env['ir.config_parameter'].get_param('web.base.url')
+        link = website_path or xml_id or (self.id and '%d' % self.id) or ''
         if base_url and link:
             path = '%s/%s' % ('/website/action', link)
             return '%s' % urlparse.urljoin(base_url, path)
         return ''
 
-    def _get_website_url(self, cr, uid, ids, name, args, context=None):
-        res = dict.fromkeys(ids, False)
-        for action in self.browse(cr, uid, ids, context=context):
+    @api.depends('website_url')
+    def _get_website_url(self):
+        for action in self:
             if action.state == 'code' and action.website_published:
-                res[action.id] = self._compute_website_url(cr, uid, action.id, action.website_path, action.xml_id, context=context)
-        return res
-
-    _columns = {
-        'xml_id': fields.function(
-            osv.osv.get_xml_id, type='char', string="External ID",
-            help="ID of the action if defined in a XML file"),
-        'website_path': fields.char('Website Path'),
-        'website_url': fields.function(
-            _get_website_url, type='char', string='Website URL',
-            help='The full URL to access the server action through the website.'),
-        'website_published': fields.boolean(
-            'Available on the Website', copy=False,
-            help='A code server action can be executed from the website, using a dedicated '
-                 'controller. The address is <base>/website/action/<website_path>. '
-                 'Set this field as True to allow users to run this action. If it '
-                 'is set to False the action cannot be run through the website.'),
-    }
+                action.website_url = self._compute_website_url(action.website_path, action.xml_id)
 
-    def on_change_website_path(self, cr, uid, ids, website_path, xml_id, context=None):
+    @api.onchange('website_path', 'xml_id')
+    def on_change_website_path(self):
         values = {
-            'website_url': self._compute_website_url(cr, uid, ids and ids[0] or None, website_path, xml_id, context=context)
+            'website_url': self._compute_website_url(self.website_path, self.xml_id)
         }
         return {'value': values}
 
-    def _get_eval_context(self, cr, uid, action, context=None):
+    @api.model
+    def _get_eval_context(self, action):
         """ Override to add the request object in eval_context. """
-        eval_context = super(actions_server, self)._get_eval_context(cr, uid, action, context=context)
+        eval_context = super(actions_server, self)._get_eval_context(action)
         if action.state == 'code':
             eval_context['request'] = request
         return eval_context
 
-    def run_action_code_multi(self, cr, uid, action, eval_context=None, context=None):
+    def run_action_code_multi(self, action, eval_context=None):
         """ Override to allow returning response the same way action is already
         returned by the basic server action behavior. Note that response has
         priority over action, avoid using both. """
-        res = super(actions_server, self).run_action_code_multi(cr, uid, action, eval_context, context)
+        res = super(actions_server, self).run_action_code_multi(action, eval_context)
         if 'response' in eval_context:
             return eval_context['response']
         return res
diff --git a/addons/website/views/ir_actions.xml b/addons/website/views/ir_actions.xml
index ac6005103c18ec6e22134709e97a059bc1578cbe..fc6240e21a020c5ba27b23b711b5a37383bf0476 100644
--- a/addons/website/views/ir_actions.xml
+++ b/addons/website/views/ir_actions.xml
@@ -15,7 +15,6 @@
                     <xpath expr="//field[@name='sequence']" position="after">
                         <field name="xml_id" invisible="1"/>
                         <field name="website_path"
-                            on_change="on_change_website_path(website_path, xml_id, context)"
                             attrs="{'invisible': ['|', ('website_published', '!=', True), ('state', '!=', 'code')]}"/>
                         <field name="website_url" readonly="1" widget="url"
                             attrs="{'invisible': ['|', ('website_published', '!=', True), ('state', '!=', 'code')]}"/>
diff --git a/addons/website_theme_install/views/views.xml b/addons/website_theme_install/views/views.xml
index 1b5ec2e39122253b50bef8626970947bc4a8a77a..249b926baf970bc759ebbb29f7d6aa96aa5b7c17 100644
--- a/addons/website_theme_install/views/views.xml
+++ b/addons/website_theme_install/views/views.xml
@@ -62,7 +62,7 @@
         <field name="name">Choose Your Theme Todo Action</field>
         <field name="model_id" ref="model_ir_module_module"/>
         <field name="code">
-self.update_list(cr, uid, context=context)
+self.update_list()
 action = {
     'type': 'ir.actions.act_url',
     'url': '/web?reload#action=website_theme_install.theme_install_kanban_action', # the ?reload option is there to fool the webclient into thinking it is a different location and so to force a reload
diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py
index 5ce474c0187f3b46856ad7813886b3c3f7e2e11d..45af48f64e61ed3e3555474a7d605f00059ef6de 100644
--- a/openerp/addons/base/ir/ir_actions.py
+++ b/openerp/addons/base/ir/ir_actions.py
@@ -1,96 +1,127 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from functools import partial
+import datetime
+import dateutil
 import logging
 import operator
 import os
 import time
-import datetime
-import dateutil
-import pytz
-
-import openerp
-from openerp import SUPERUSER_ID
-from openerp import tools
-from openerp import workflow
-import openerp.api
-from openerp.osv import fields, osv
-from openerp.osv.orm import browse_record
-import openerp.report.interface
-from openerp.report.report_sxw import report_sxw, report_rml
-from openerp.tools import ormcache
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.translate import _
-import openerp.workflow
-from openerp.exceptions import MissingError, UserError
+from functools import partial
+from pytz import timezone
+
+import odoo
+from odoo import api, fields, models, tools, workflow, _
+from odoo.exceptions import MissingError, UserError
+from odoo.report.report_sxw import report_sxw, report_rml
+from odoo.tools.safe_eval import safe_eval as eval
 
 _logger = logging.getLogger(__name__)
 
 
-class actions(osv.osv):
+class Actions(models.Model):
     _name = 'ir.actions.actions'
     _table = 'ir_actions'
     _order = 'name'
-    _columns = {
-        'name': fields.char('Name', required=True),
-        'type': fields.char('Action Type', required=True),
-        'usage': fields.char('Action Usage'),
-        'xml_id': fields.function(osv.osv.get_external_id, type='char', string="External ID"),
-        'help': fields.html('Action description',
-            help='Optional help text for the users with a description of the target view, such as its usage and purpose.',
-            translate=True),
-    }
-    _defaults = {
-        'usage': lambda *a: False,
-    }
-
-    def create(self, cr, uid, vals, context=None):
-        res = super(actions, self).create(cr, uid, vals, context=context)
+
+    name = fields.Char(required=True)
+    type = fields.Char(string='Action Type', required=True)
+    usage = fields.Char(string='Action Usage')
+    xml_id = fields.Char(compute=models.Model.get_external_id, string="External ID")
+    help = fields.Html(string='Action Description',
+                              help='Optional help text for the users with a description of the target view, such as its usage and purpose.',
+                              translate=True)
+
+    @api.model
+    def create(self, vals):
+        res = super(Actions, self).create(vals)
         # ir_values.get_actions() depends on action records
-        self.pool['ir.values'].clear_caches()
+        self.env['ir.values'].clear_caches()
         return res
 
-    def write(self, cr, uid, ids, vals, context=None):
-        res = super(actions, self).write(cr, uid, ids, vals, context=context)
+    @api.multi
+    def write(self, vals):
+        res = super(Actions, self).write(vals)
         # ir_values.get_actions() depends on action records
-        self.pool['ir.values'].clear_caches()
+        self.env['ir.values'].clear_caches()
         return res
 
-    def unlink(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink(self):
         """unlink ir.action.todo which are related to actions which will be deleted.
            NOTE: ondelete cascade will not work on ir.actions.actions so we will need to do it manually."""
-        todo_obj = self.pool.get('ir.actions.todo')
-        if not ids:
-            return True
-        if isinstance(ids, (int, long)):
-            ids = [ids]
-        todo_ids = todo_obj.search(cr, uid, [('action_id', 'in', ids)], context=context)
-        todo_obj.unlink(cr, uid, todo_ids, context=context)
-        res = super(actions, self).unlink(cr, uid, ids, context=context)
+        todo_ids = self.env['ir.actions.todo'].search([('action_id', 'in', self.ids)])
+        todo_ids.unlink()
+        res = super(Actions, self).unlink()
         # ir_values.get_actions() depends on action records
-        self.pool['ir.values'].clear_caches()
+        self.env['ir.values'].clear_caches()
         return res
 
-    def _get_eval_context(self, cr, uid, action=None, context=None):
+    @api.model
+    def _get_eval_context(self, action=None):
         """ evaluation context to pass to safe_eval """
-        user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
         return {
-            'uid': uid,
-            'user': user,
+            'uid': self.env.uid,
+            'user': self.env.user,
             'time': time,
             'datetime': datetime,
             'dateutil': dateutil,
-            # NOTE: only `timezone` function. Do not provide the whole `pytz` module as users
-            #       will have access to `pytz.os` and `pytz.sys` to do nasty things...
-            'timezone': pytz.timezone,
+            'timezone': timezone,
         }
 
-class ir_actions_report_xml(osv.osv):
 
-    def _report_content(self, cursor, user, ids, name, arg, context=None):
+class IrActionsReportXml(models.Model):
+    _name = 'ir.actions.report.xml'
+    _inherit = 'ir.actions.actions'
+    _table = 'ir_act_report_xml'
+    _sequence = 'ir_actions_id_seq'
+    _order = 'name'
+
+    type = fields.Char(string='Action Type', default='ir.actions.report.xml', required=True)
+    name = fields.Char(required=True, translate=True)
+
+    model = fields.Char(required=True)
+    report_type = fields.Selection([('qweb-pdf', 'PDF'),
+                                    ('qweb-html', 'HTML'),
+                                    ('controller', 'Controller'),
+                                    ('pdf', 'RML pdf (deprecated)'),
+                                    ('sxw', 'RML sxw (deprecated)'),
+                                    ('webkit', 'Webkit (deprecated)')], default="pdf", required=True,
+                                   help="HTML will open the report directly in your browser, PDF will use wkhtmltopdf to render the HTML into a PDF file and let you download it, Controller allows you to define the url of a custom controller outputting any kind of report.")
+    report_name = fields.Char(string='Template Name', required=True,
+                              help="For QWeb reports, name of the template used in the rendering. The method 'render_html' of the model 'report.template_name' will be called (if any) to give the html. For RML reports, this is the LocalService name.")
+    groups_id = fields.Many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', string='Groups')
+    ir_values_id = fields.Many2one('ir.values', string='More Menu entry', readonly=True,
+                                   help='More menu entry.', copy=False)
+
+    # options
+    multi = fields.Boolean(string='On Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view.")
+    attachment_use = fields.Boolean(string='Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.')
+    attachment = fields.Char(string='Save as Attachment Prefix',
+                             help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.')
+
+    # Deprecated rml stuff
+    usage = fields.Char(string='Action Usage')
+    header = fields.Boolean(string='Add RML Header', default=True, help="Add or not the corporate RML header")
+    parser = fields.Char(string='Parser Class')
+    auto = fields.Boolean(string='Custom Python Parser', default=True)
+
+    report_xsl = fields.Char(string='XSL Path')
+    report_xml = fields.Char(string='XML Path')
+
+    report_rml = fields.Char(string='Main Report File Path/controller', help="The path to the main report file/controller (depending on Report Type) or empty if the content is in another data field")
+    report_file = fields.Char(related='report_rml', string='Report File', required=False, readonly=False, store=True,
+                              help="The path to the main report file (depending on Report Type) or empty if the content is in another field")
+
+    report_sxw = fields.Char(compute='_compute_report_sxw', string='SXW Path')
+    report_sxw_content_data = fields.Binary(string='SXW Content')
+    report_rml_content_data = fields.Binary(string='RML Content')
+    report_sxw_content = fields.Binary(compute='_compute_report_sxw_content', inverse='_inverse_report_content', string='SXW Content')
+    report_rml_content = fields.Binary(compute='_compute_report_rml_content', inverse='_inverse_report_content', string='RML Content')
+
+    def _report_content(self, name):
         res = {}
-        for report in self.browse(cursor, user, ids, context=context):
+        for report in self:
             data = report[name + '_data']
             if not data and report[name[:-8]]:
                 fp = None
@@ -105,19 +136,25 @@ class ir_actions_report_xml(osv.osv):
             res[report.id] = data
         return res
 
-    def _report_content_inv(self, cursor, user, id, name, value, arg, context=None):
-        self.write(cursor, user, id, {name+'_data': value}, context=context)
+    @api.depends('report_sxw_content')
+    def _compute_report_sxw_content(self):
+        self.report_sxw_content = self._report_content(self.name)
 
-    def _report_sxw(self, cursor, user, ids, name, arg, context=None):
-        res = {}
-        for report in self.browse(cursor, user, ids, context=context):
+    @api.depends('report_rml_content')
+    def _compute_report_rml_content(self):
+        self.report_rml_content = self._report_content(self.name)
+
+    def _inverse_report_content(self, name, value):
+        self.write({name+'_data': value})
+
+    @api.depends('report_sxw')
+    def _compute_report_sxw(self):
+        for report in self:
             if report.report_rml:
-                res[report.id] = report.report_rml.replace('.rml', '.sxw')
-            else:
-                res[report.id] = False
-        return res
+                self.report_sxw = report.report_rml.replace('.rml', '.sxw')
 
-    def _lookup_report(self, cr, name):
+    @api.multi
+    def _lookup_report(self, name):
         """
         Look up a report definition.
         """
@@ -126,156 +163,96 @@ class ir_actions_report_xml(osv.osv):
         # First lookup in the deprecated place, because if the report definition
         # has not been updated, it is more likely the correct definition is there.
         # Only reports with custom parser sepcified in Python are still there.
-        if 'report.' + name in openerp.report.interface.report_int._reports:
-            new_report = openerp.report.interface.report_int._reports['report.' + name]
+        if 'report.' + name in odoo.report.interface.report_int._reports:
+            new_report = odoo.report.interface.report_int._reports['report.' + name]
         else:
-            cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,))
-            r = cr.dictfetchone()
-            if r:
-                if r['report_type'] in ['qweb-pdf', 'qweb-html']:
-                    return r['report_name']
-                elif r['report_rml'] or r['report_rml_content_data']:
-                    if r['parser']:
-                        kwargs = { 'parser': operator.attrgetter(r['parser'])(openerp.addons) }
+            self.env.cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,))
+            report = self.env.cr.dictfetchone()
+            if report:
+                if report['report_type'] in ['qweb-pdf', 'qweb-html']:
+                    return report['report_name']
+                elif report['report_rml'] or report['report_rml_content_data']:
+                    if report['parser']:
+                        kwargs = {'parser': operator.attrgetter(report['parser'])(odoo.addons)}
                     else:
                         kwargs = {}
-                    new_report = report_sxw('report.'+r['report_name'], r['model'],
-                            opj('addons',r['report_rml'] or '/'), header=r['header'], register=False, **kwargs)
-                elif r['report_xsl'] and r['report_xml']:
-                    new_report = report_rml('report.'+r['report_name'], r['model'],
-                            opj('addons',r['report_xml']),
-                            r['report_xsl'] and opj('addons',r['report_xsl']), register=False)
+                    new_report = report_sxw('report.'+report['report_name'], report['model'],
+                                            opj('addons', report['report_rml'] or '/'), header=report['header'], register=False, **kwargs)
+                elif report['report_xsl'] and report['report_xml']:
+                    new_report = report_rml('report.'+report['report_name'], report['model'],
+                                            opj('addons', report['report_xml']),
+                                            report['report_xsl'] and opj('addons', report['report_xsl']), register=False)
                 else:
-                    raise Exception, "Unhandled report type: %s" % r
+                    raise Exception, "Unhandled report type: %s" % report
             else:
                 raise Exception, "Required report does not exist: %s" % name
 
         return new_report
 
-    def create_action(self, cr, uid, ids, context=None):
+    @api.multi
+    def create_action(self):
         """ Create a contextual action for each of the report."""
-        for ir_actions_report_xml in self.browse(cr, uid, ids, context=context):
-            ir_values_id = self.pool['ir.values'].create(cr, SUPERUSER_ID, {
+        for ir_actions_report_xml in self:
+            ir_values_id = self.env['ir.values'].sudo().create({
                 'name': ir_actions_report_xml.name,
                 'model': ir_actions_report_xml.model,
                 'key2': 'client_print_multi',
                 'value': "ir.actions.report.xml,%s" % ir_actions_report_xml.id,
-            }, context)
+            })
             ir_actions_report_xml.write({
-                'ir_values_id': ir_values_id,
+                'ir_values_id': ir_values_id.id,
             })
         return True
 
-    def unlink_action(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink_action(self):
         """ Remove the contextual actions created for the reports."""
-        self.check_access_rights(cr , uid, 'write', raise_exception=True)
-        for ir_actions_report_xml in self.browse(cr, uid, ids, context=context):
+        self.check_access_rights('write', raise_exception=True)
+        for ir_actions_report_xml in self:
             if ir_actions_report_xml.ir_values_id:
                 try:
-                    self.pool['ir.values'].unlink(
-                        cr, SUPERUSER_ID, ir_actions_report_xml.ir_values_id.id, context
-                    )
+                    self.ir_actions_report_xml.ir_values_id.sudo().unlink()
                 except Exception:
                     raise UserError(_('Deletion of the action record failed.'))
         return True
 
-    def render_report(self, cr, uid, res_ids, name, data, context=None):
+    @api.multi
+    def render_report(self, name, data):
         """
         Look up a report definition and render the report for the provided IDs.
         """
-        new_report = self._lookup_report(cr, name)
+        new_report = self._lookup_report(name)
 
         if isinstance(new_report, (str, unicode)):  # Qweb report
             # The only case where a QWeb report is rendered with this method occurs when running
             # yml tests originally written for RML reports.
-            if openerp.tools.config['test_enable'] and not tools.config['test_report_directory']:
+            if tools.config['test_enable'] and not tools.config['test_report_directory']:
                 # Only generate the pdf when a destination folder has been provided.
-                return self.pool['report'].get_html(cr, uid, res_ids, new_report, data=data, context=context), 'html'
+                return self.env['report']._model.get_html(self._cr, self._uid, self.ids, new_report, data=data), 'html'
             else:
-                return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf'
+                return self.env['report']._model.get_pdf(self._cr, self._uid, self.ids, new_report, data=data), 'pdf'
         else:
-            return new_report.create(cr, uid, res_ids, data, context)
+            return new_report.create(self._cr, self._uid, self.ids, data)
 
-    _name = 'ir.actions.report.xml'
-    _inherit = 'ir.actions.actions'
-    _table = 'ir_act_report_xml'
-    _sequence = 'ir_actions_id_seq'
-    _order = 'name'
-    _columns = {
-        'type': fields.char('Action Type', required=True),
-        'name': fields.char('Name', required=True, translate=True),
-
-        'model': fields.char('Model', required=True),
-        'report_type': fields.selection([('qweb-pdf', 'PDF'),
-                    ('qweb-html', 'HTML'),
-                    ('controller', 'Controller'),
-                    ('pdf', 'RML pdf (deprecated)'),
-                    ('sxw', 'RML sxw (deprecated)'),
-                    ('webkit', 'Webkit (deprecated)'),
-                    ], 'Report Type', required=True, help="HTML will open the report directly in your browser, PDF will use wkhtmltopdf to render the HTML into a PDF file and let you download it, Controller allows you to define the url of a custom controller outputting any kind of report."),
-        'report_name': fields.char('Template Name', required=True, help="For QWeb reports, name of the template used in the rendering. The method 'render_html' of the model 'report.template_name' will be called (if any) to give the html. For RML reports, this is the LocalService name."),
-        'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
-        'ir_values_id': fields.many2one('ir.values', 'More Menu entry', readonly=True,
-                                        help='More menu entry.', copy=False),
-
-        # options
-        'multi': fields.boolean('On Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view."),
-        'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.'),
-        'attachment': fields.char('Save as Attachment Prefix', help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'),
-
-
-        # Deprecated rml stuff
-        'usage': fields.char('Action Usage'),
-        'header': fields.boolean('Add RML Header', help="Add or not the corporate RML header"),
-        'parser': fields.char('Parser Class'),
-        'auto': fields.boolean('Custom Python Parser'),
-
-        'report_xsl': fields.char('XSL Path'),
-        'report_xml': fields.char('XML Path'),
-
-        'report_rml': fields.char('Main Report File Path/controller', help="The path to the main report file/controller (depending on Report Type) or empty if the content is in another data field"),
-        'report_file': fields.related('report_rml', type="char", required=False, readonly=False, string='Report File', help="The path to the main report file (depending on Report Type) or empty if the content is in another field", store=True),
-
-        'report_sxw': fields.function(_report_sxw, type='char', string='SXW Path'),
-        'report_sxw_content_data': fields.binary('SXW Content'),
-        'report_rml_content_data': fields.binary('RML Content'),
-        'report_sxw_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='SXW Content',),
-        'report_rml_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='RML Content'),
-    }
-    _defaults = {
-        'type': 'ir.actions.report.xml',
-        'multi': False,
-        'auto': True,
-        'header': True,
-        'report_sxw_content': False,
-        'report_type': 'pdf',
-        'attachment': False,
-    }
-
-
-class ir_actions_act_window(osv.osv):
+
+class IrActionsActWindow(models.Model):
     _name = 'ir.actions.act_window'
     _table = 'ir_act_window'
     _inherit = 'ir.actions.actions'
     _sequence = 'ir_actions_id_seq'
     _order = 'name'
 
-    def _check_model(self, cr, uid, ids, context=None):
-        for action in self.browse(cr, uid, ids, context):
-            if action.res_model not in self.pool:
-                return False
-            if action.src_model and action.src_model not in self.pool:
-                return False
+    @api.constrains('res_model', 'src_model')
+    def _check_model(self):
+        for action in self:
+            if action.res_model not in self.env:
+                raise UserError(_('Invalid model name in the action definition.'))
+            if action.src_model and action.src_model not in self.env:
+                raise UserError(_('Invalid model name in the action definition.'))
         return True
 
-    def _invalid_model_msg(self, cr, uid, ids, context=None):
-        return _('Invalid model name in the action definition.')
-
-    _constraints = [
-        (_check_model, _invalid_model_msg, ['res_model','src_model'])
-    ]
-
-    def _views_get_fnc(self, cr, uid, ids, name, arg, context=None):
+    @api.depends('views')
+    def _views_get_fnc(self):
         """Returns an ordered list of the specific view modes that should be
            enabled when displaying the result of this action, along with the
            ID of the specific view to use for each mode, if any were required.
@@ -290,9 +267,8 @@ class ir_actions_act_window(osv.osv):
                     is the ID of a specific view to use for this mode, or False for
                     the default one.
         """
-        res = {}
-        for act in self.browse(cr, uid, ids):
-            res[act.id] = [(view.view_id.id, view.view_mode) for view in act.view_ids]
+        for act in self:
+            act.views = [(view.view_id.id, view.view_mode) for view in act.view_ids]
             view_ids_modes = [view.view_mode for view in act.view_ids]
             modes = act.view_mode.split(',')
             missing_modes = [mode for mode in modes if mode not in view_ids_modes]
@@ -300,74 +276,55 @@ class ir_actions_act_window(osv.osv):
                 if act.view_id and act.view_id.type in missing_modes:
                     # reorder missing modes to put view_id first if present
                     missing_modes.remove(act.view_id.type)
-                    res[act.id].append((act.view_id.id, act.view_id.type))
-                res[act.id].extend([(False, mode) for mode in missing_modes])
-        return res
+                    act.views.append((act.view_id.id, act.view_id.type))
+                act.views.extend([(False, mode) for mode in missing_modes])
+
+    @api.depends('search_view')
+    def _search_view(self):
+        for act in self:
+            act.search_view = str(self.env[act.res_model].fields_view_get(act.search_view_id and act.search_view_id.id, 'search'))
+
+    name = fields.Char(string='Action Name', required=True, translate=True)
+    type = fields.Char(string='Action Type', default="ir.actions.act_window", required=True)
+    view_id = fields.Many2one('ir.ui.view', string='View Ref.', ondelete='set null')
+    domain = fields.Char(string='Domain Value',
+                         help="Optional domain filtering of the destination data, as a Python expression")
+    context = fields.Char(string='Context Value', default={}, required=True,
+                          help="Context dictionary as Python expression, empty by default (Default: {})")
+    res_id = fields.Integer(string='Record ID', help="Database ID of record to open in form view, when ``view_mode`` is set to 'form' only")
+    res_model = fields.Char(string='Destination Model', required=True,
+                            help="Model name of the object to open in the view window")
+    src_model = fields.Char(string='Source Model',
+                            help="Optional model name of the objects on which this action should be visible")
+    target = fields.Selection([('current', 'Current Window'), ('new', 'New Window'), ('inline', 'Inline Edit'), ('inlineview', 'Inline View')], default="current", string='Target Window')
+    view_mode = fields.Char(required=True, default='tree,form',
+                            help="Comma-separated list of allowed view modes, such as 'form', 'tree', 'calendar', etc. (Default: tree,form)")
+    view_type = fields.Selection([('tree', 'Tree'), ('form', 'Form')], default="form", string='View Type', required=True,
+                                 help="View type: Tree type to use for the tree view, set to 'tree' for a hierarchical tree view, or 'form' for a regular list view")
+    usage = fields.Char(string='Action Usage',
+                        help="Used to filter menu and home actions from the user form.")
+    view_ids = fields.One2many('ir.actions.act_window.view', 'act_window_id', string='Views')
+    views = fields.Binary(compute='_views_get_fnc',
+                          help="This function field computes the ordered list of views that should be enabled " \
+                               "when displaying the result of an action, federating view mode, views and " \
+                               "reference view. The result is returned as an ordered list of pairs (view_id,view_mode).")
+    limit = fields.Integer(default=80, help='Default limit for the list view')
+    auto_refresh = fields.Integer(default=0, help='Add an auto-refresh on the view')
+    groups_id = fields.Many2many('res.groups', 'ir_act_window_group_rel',
+                                 'act_id', 'gid', string='Groups')
+    search_view_id = fields.Many2one('ir.ui.view', string='Search View Ref.')
+    filter = fields.Boolean()
+    auto_search = fields.Boolean(default=True)
+    search_view = fields.Text(compute='_search_view')
+    multi = fields.Boolean(string='Restrict to lists', help="If checked and the action is bound to a model, it will only appear in the More menu on list views")
 
-    def _search_view(self, cr, uid, ids, name, arg, context=None):
-        res = {}
-        for act in self.browse(cr, uid, ids, context=context):
-            field_get = self.pool[act.res_model].fields_view_get(cr, uid,
-                act.search_view_id and act.search_view_id.id or False,
-                'search', context=context)
-            res[act.id] = str(field_get)
-        return res
-
-    _columns = {
-        'name': fields.char('Action Name', required=True, translate=True),
-        'type': fields.char('Action Type', required=True),
-        'view_id': fields.many2one('ir.ui.view', 'View Ref.', ondelete='set null'),
-        'domain': fields.char('Domain Value',
-            help="Optional domain filtering of the destination data, as a Python expression"),
-        'context': fields.char('Context Value', required=True,
-            help="Context dictionary as Python expression, empty by default (Default: {})"),
-        'res_id': fields.integer('Record ID', help="Database ID of record to open in form view, when ``view_mode`` is set to 'form' only"),
-        'res_model': fields.char('Destination Model', required=True,
-            help="Model name of the object to open in the view window"),
-        'src_model': fields.char('Source Model',
-            help="Optional model name of the objects on which this action should be visible"),
-        'target': fields.selection([('current','Current Window'),('new','New Window'),('inline','Inline Edit'),('inlineview','Inline View')], 'Target Window'),
-        'view_mode': fields.char('View Mode', required=True,
-            help="Comma-separated list of allowed view modes, such as 'form', 'tree', 'calendar', etc. (Default: tree,form)"),
-        'view_type': fields.selection((('tree','Tree'),('form','Form')), string='View Type', required=True,
-            help="View type: Tree type to use for the tree view, set to 'tree' for a hierarchical tree view, or 'form' for a regular list view"),
-        'usage': fields.char('Action Usage',
-            help="Used to filter menu and home actions from the user form."),
-        'view_ids': fields.one2many('ir.actions.act_window.view', 'act_window_id', 'Views'),
-        'views': fields.function(_views_get_fnc, type='binary', string='Views',
-               help="This function field computes the ordered list of views that should be enabled " \
-                    "when displaying the result of an action, federating view mode, views and " \
-                    "reference view. The result is returned as an ordered list of pairs (view_id,view_mode)."),
-        'limit': fields.integer('Limit', help='Default limit for the list view'),
-        'auto_refresh': fields.integer('Auto-Refresh',
-            help='Add an auto-refresh on the view'),
-        'groups_id': fields.many2many('res.groups', 'ir_act_window_group_rel',
-            'act_id', 'gid', 'Groups'),
-        'search_view_id': fields.many2one('ir.ui.view', 'Search View Ref.'),
-        'filter': fields.boolean('Filter'),
-        'auto_search':fields.boolean('Auto Search'),
-        'search_view' : fields.function(_search_view, type='text', string='Search View'),
-        'multi': fields.boolean('Restrict to lists', help="If checked and the action is bound to a model, it will only appear in the More menu on list views"),
-    }
-
-    _defaults = {
-        'type': 'ir.actions.act_window',
-        'view_type': 'form',
-        'view_mode': 'tree,form',
-        'context': '{}',
-        'limit': 80,
-        'target': 'current',
-        'auto_refresh': 0,
-        'auto_search':True,
-        'multi': False,
-    }
     def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
         """ call the method get_empty_list_help of the model and set the window action help message
         """
         ids_int = isinstance(ids, (int, long))
         if ids_int:
             ids = [ids]
-        results = super(ir_actions_act_window, self).read(cr, uid, ids, fields=fields, context=context, load=load)
+        results = super(IrActionsActWindow, self).read(cr, uid, ids, fields=fields, context=context, load=load)
 
         if not fields or 'help' in fields:
             for res in results:
@@ -379,7 +336,8 @@ class ir_actions_act_window(osv.osv):
             return results[0]
         return results
 
-    def for_xml_id(self, cr, uid, module, xml_id, context=None):
+    @api.model
+    def for_xml_id(self, module, xml_id):
         """ Returns the act_window object created for the provided xml_id
 
         :param module: the module the act_window originates in
@@ -387,106 +345,93 @@ class ir_actions_act_window(osv.osv):
                        attribute from the XML file)
         :return: A read() view of the ir.actions.act_window
         """
-        dataobj = self.pool.get('ir.model.data')
-        data_id = dataobj._get_id (cr, SUPERUSER_ID, module, xml_id)
-        res_id = dataobj.browse(cr, uid, data_id, context).res_id
-        return self.read(cr, uid, [res_id], [], context)[0]
+        DataObj = self.env['ir.model.data']
+        data_id = DataObj.sudo()._get_id(module, xml_id)
+        res = DataObj.browse(data_id)
+        result = self.env['ir.actions.act_window'].sudo().browse(res.res_id)
+        return result
 
-    @openerp.api.model
+    @api.model
     def create(self, vals):
         self.clear_caches()
-        return super(ir_actions_act_window, self).create(vals)
+        return super(IrActionsActWindow, self).create(vals)
 
-    @openerp.api.multi
+    @api.multi
     def unlink(self):
         self.clear_caches()
-        return super(ir_actions_act_window, self).unlink()
+        return super(IrActionsActWindow, self).unlink()
 
-    @openerp.api.multi
+    @api.multi
     def exists(self):
         ids = self._existing()
         existing = self.filtered(lambda rec: rec.id in ids)
         if len(existing) < len(self):
             # mark missing records in cache with a failed value
             exc = MissingError(_("Record does not exist or has been deleted."))
-            (self - existing)._cache.update(openerp.fields.FailedValue(exc))
+            (self - existing)._cache.update(fields.FailedValue(exc))
         return existing
 
-    @openerp.api.model
-    @ormcache()
+    @api.model
+    @tools.ormcache()
     def _existing(self):
         self._cr.execute("SELECT id FROM %s" % self._table)
         return set(row[0] for row in self._cr.fetchall())
 
-VIEW_TYPES = [
-    ('tree', 'Tree'),
-    ('form', 'Form'),
-    ('graph', 'Graph'),
-    ('pivot', 'Pivot'),
-    ('calendar', 'Calendar'),
-    ('gantt', 'Gantt'),
-    ('kanban', 'Kanban')]
-class ir_actions_act_window_view(osv.osv):
+
+class IrActionsActWindowView(models.Model):
     _name = 'ir.actions.act_window.view'
     _table = 'ir_act_window_view'
     _rec_name = 'view_id'
     _order = 'sequence'
-    _columns = {
-        'sequence': fields.integer('Sequence'),
-        'view_id': fields.many2one('ir.ui.view', 'View'),
-        'view_mode': fields.selection(VIEW_TYPES, string='View Type', required=True),
-        'act_window_id': fields.many2one('ir.actions.act_window', 'Action', ondelete='cascade'),
-        'multi': fields.boolean('On Multiple Doc.',
-            help="If set to true, the action will not be displayed on the right toolbar of a form view."),
-    }
-    _defaults = {
-        'multi': False,
-    }
-    def _auto_init(self, cr, context=None):
-        super(ir_actions_act_window_view, self)._auto_init(cr, context)
-        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'act_window_view_unique_mode_per_action\'')
-        if not cr.fetchone():
-            cr.execute('CREATE UNIQUE INDEX act_window_view_unique_mode_per_action ON ir_act_window_view (act_window_id, view_mode)')
-
-
-class ir_actions_act_window_close(osv.osv):
+
+    sequence = fields.Integer()
+    view_id = fields.Many2one('ir.ui.view', string='View')
+    view_mode = fields.Selection([('tree', 'Tree'),
+                                  ('form', 'Form'),
+                                  ('graph', 'Graph'),
+                                  ('pivot', 'Pivot'),
+                                  ('calendar', 'Calendar'),
+                                  ('gantt', 'Gantt'),
+                                  ('kanban', 'Kanban')], string='View Type', required=True)
+    act_window_id = fields.Many2one('ir.actions.act_window', string='Action', ondelete='cascade')
+    multi = fields.Boolean(string='On Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view.")
+
+    def _auto_init(self):
+        super(IrActionsActWindowView, self)._auto_init()
+        self.env.cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'act_window_view_unique_mode_per_action\'')
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE UNIQUE INDEX act_window_view_unique_mode_per_action ON ir_act_window_view (act_window_id, view_mode)')
+
+
+class IrActionsActWindowclose(models.Model):
     _name = 'ir.actions.act_window_close'
     _inherit = 'ir.actions.actions'
     _table = 'ir_actions'
-    _defaults = {
-        'type': 'ir.actions.act_window_close',
-    }
+
+    type = fields.Char(string='Action Type', default='ir.actions.act_window_close')
 
 
-class ir_actions_act_url(osv.osv):
+class IrActionsActUrl(models.Model):
     _name = 'ir.actions.act_url'
     _table = 'ir_act_url'
     _inherit = 'ir.actions.actions'
     _sequence = 'ir_actions_id_seq'
     _order = 'name'
-    _columns = {
-        'name': fields.char('Action Name', required=True, translate=True),
-        'type': fields.char('Action Type', required=True),
-        'url': fields.text('Action URL',required=True),
-        'target': fields.selection((
-            ('new', 'New Window'),
-            ('self', 'This Window')),
-            'Action Target', required=True
-        )
-    }
-    _defaults = {
-        'type': 'ir.actions.act_url',
-        'target': 'new'
-    }
-
-
-class ir_actions_server(osv.osv):
+
+    name = fields.Char(string='Action Name', required=True, translate=True)
+    type = fields.Char(string='Action Type', default='ir.actions.act_url')
+    url = fields.Text(string='Action URL', required=True)
+    target = fields.Selection([('new', 'New Window'), ('self', 'This Window')],
+                              string='Action Target', default='new', required=True)
+
+
+class IrActionsServer(models.Model):
     """ Server actions model. Server action work on a base model and offer various
     type of actions that can be executed automatically, for example using base
     action rules, of manually, by adding the action in the 'More' contextual
     menu.
 
-    Since OpenERP 8.0 a button 'Create Menu Action' button is available on the
+    Since Odoo 8.0 a button 'Create Menu Action' button is available on the
     action form view. It creates an entry in the More menu of the base model.
     This allows to create server actions and run them in mass mode easily through
     the interface.
@@ -508,13 +453,11 @@ class ir_actions_server(osv.osv):
     _sequence = 'ir_actions_id_seq'
     _order = 'sequence,name'
 
-    def _select_objects(self, cr, uid, context=None):
-        model_pool = self.pool.get('ir.model')
-        ids = model_pool.search(cr, uid, [], limit=None)
-        res = model_pool.read(cr, uid, ids, ['model', 'name'])
-        return [(r['model'], r['name']) for r in res] + [('', '')]
+    def _select_objects(self):
+        records = self.env['ir.model'].search([])
+        return [(record.model, record.name) for record in records] + [('', '')]
 
-    def _get_states(self, cr, uid, context=None):
+    def _get_states(self):
         """ Override me in order to add new states in the server action. Please
         note that the added key length should not be higher than already-existing
         ones. """
@@ -525,133 +468,108 @@ class ir_actions_server(osv.osv):
                 ('object_write', 'Write on a Record'),
                 ('multi', 'Execute several actions')]
 
-    def _get_states_wrapper(self, cr, uid, context=None):
-        return self._get_states(cr, uid, context)
+    @api.model
+    def _get_states_wrapper(self):
+        return self._get_states()
 
-    _columns = {
-        'name': fields.char('Action Name', required=True, translate=True),
-        'condition': fields.char('Condition',
-                                 help="Condition verified before executing the server action. If it "
+    name = fields.Char(string='Action Name', required=True, translate=True)
+    condition = fields.Char(default="True",
+                            help="Condition verified before executing the server action. If it "
                                  "is not verified, the action will not be executed. The condition is "
                                  "a Python expression, like 'object.list_price > 5000'. A void "
                                  "condition is considered as always True. Help about python expression "
-                                 "is given in the help tab."),
-        'state': fields.selection(_get_states_wrapper, 'Action To Do', required=True,
-                                  help="Type of server action. The following values are available:\n"
+                                 "is given in the help tab.")
+    state = fields.Selection(selection='_get_states_wrapper', string='Action To Do', default='code', required=True,
+                             help="Type of server action. The following values are available:\n"
                                   "- 'Execute Python Code': a block of python code that will be executed\n"
                                   "- 'Trigger a Workflow Signal': send a signal to a workflow\n"
                                   "- 'Run a Client Action': choose a client action to launch\n"
                                   "- 'Create or Copy a new Record': create a new record with new values, or copy an existing record in your database\n"
                                   "- 'Write on a Record': update the values of a record\n"
                                   "- 'Execute several actions': define an action that triggers several other server actions\n"
-                                  "- 'Send Email': automatically send an email (available in email_template)"),
-        'usage': fields.char('Action Usage'),
-        'type': fields.char('Action Type', required=True),
-        # Generic
-        'sequence': fields.integer('Sequence',
-                                   help="When dealing with multiple actions, the execution order is "
-                                   "based on the sequence. Low number means high priority."),
-        'model_id': fields.many2one('ir.model', 'Base Model', required=True, ondelete='cascade',
-                                    help="Base model on which the server action runs."),
-        'model_name': fields.related('model_id', 'model', type='char',
-                                     string='Model Name', readonly=True),
-        'menu_ir_values_id': fields.many2one('ir.values', 'More Menu entry', readonly=True,
-                                             help='More menu entry.', copy=False),
-        # Client Action
-        'action_id': fields.many2one('ir.actions.actions', 'Client Action',
-                                     help="Select the client action that has to be executed."),
-        # Python code
-        'code': fields.text('Python Code',
-                            help="Write Python code that the action will execute. Some variables are "
-                            "available for use; help about pyhon expression is given in the help tab."),
-        # Workflow signal
-        'use_relational_model': fields.selection([('base', 'Use the base model of the action'),
-                                                  ('relational', 'Use a relation field on the base model')],
-                                                 string='Target Model', required=True),
-        'wkf_transition_id': fields.many2one('workflow.transition', string='Signal to Trigger',
-                                             help="Select the workflow signal to trigger."),
-        'wkf_model_id': fields.many2one('ir.model', 'Target Model',
-                                        help="The model that will receive the workflow signal. Note that it should have a workflow associated with it."),
-        'wkf_model_name': fields.related('wkf_model_id', 'model', type='char', string='Target Model Name', store=True, readonly=True),
-        'wkf_field_id': fields.many2one('ir.model.fields', string='Relation Field',
-                                        oldname='trigger_obj_id',
-                                        help="The field on the current object that links to the target object record (must be a many2one, or an integer field with the record ID)"),
-        # Multi
-        'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions',
-                                      'server_id', 'action_id',
-                                      string='Child Actions',
-                                      help='Child server actions that will be executed. Note that the last return returned action value will be used as global return value.'),
-        # Create/Copy/Write
-        'use_create': fields.selection([('new', 'Create a new record in the Base Model'),
-                                        ('new_other', 'Create a new record in another model'),
-                                        ('copy_current', 'Copy the current record'),
-                                        ('copy_other', 'Choose and copy a record in the database')],
-                                       string="Creation Policy", required=True,
-                                       help=""),
-        'crud_model_id': fields.many2one('ir.model', 'Target Model',
-                                         oldname='srcmodel_id',
-                                         help="Model for record creation / update. Set this field only to specify a different model than the base model."),
-        'crud_model_name': fields.related('crud_model_id', 'model', type='char',
-                                          string='Create/Write Target Model Name',
-                                          store=True, readonly=True),
-        'ref_object': fields.reference('Reference record', selection=_select_objects, size=128,
-                                       oldname='copy_object'),
-        'link_new_record': fields.boolean('Attach the new record',
-                                          help="Check this if you want to link the newly-created record "
-                                          "to the current record on which the server action runs."),
-        'link_field_id': fields.many2one('ir.model.fields', 'Link using field',
-                                         oldname='record_id',
-                                         help="Provide the field where the record id is stored after the operations."),
-        'use_write': fields.selection([('current', 'Update the current record'),
-                                       ('expression', 'Update a record linked to the current record using python'),
-                                       ('other', 'Choose and Update a record in the database')],
-                                      string='Update Policy', required=True,
-                                      help=""),
-        'write_expression': fields.char('Expression',
-                                        oldname='write_id',
-                                        help="Provide an expression that, applied on the current record, gives the field to update."),
-        'fields_lines': fields.one2many('ir.server.object.lines', 'server_id',
-                                        string='Value Mapping',
-                                        copy=True),
-
-        # Fake fields used to implement the placeholder assistant
-        'model_object_field': fields.many2one('ir.model.fields', string="Field",
-                                              help="Select target field from the related document model.\n"
-                                                   "If it is a relationship field you will be able to select "
-                                                   "a target field at the destination of the relationship."),
-        'sub_object': fields.many2one('ir.model', 'Sub-model', readonly=True,
-                                      help="When a relationship field is selected as first field, "
-                                           "this field shows the document model the relationship goes to."),
-        'sub_model_object_field': fields.many2one('ir.model.fields', 'Sub-field',
-                                                  help="When a relationship field is selected as first field, "
-                                                       "this field lets you select the target field within the "
-                                                       "destination document model (sub-model)."),
-        'copyvalue': fields.char('Placeholder Expression', help="Final placeholder expression, to be copy-pasted in the desired template field."),
-        # Fake fields used to implement the ID finding assistant
-        'id_object': fields.reference('Record', selection=_select_objects, size=128),
-        'id_value': fields.char('Record ID'),
-    }
-
-    _defaults = {
-        'state': 'code',
-        'condition': 'True',
-        'type': 'ir.actions.server',
-        'sequence': 5,
-        'code': """# Available locals:
-#  - time, datetime, dateutil: Python libraries
-#  - env: Odoo Environement
-#  - model: Model of the record on which the action is triggered
-#  - object: Record on which the action is triggered if there is one, otherwise None
-#  - workflow: Workflow engine
-#  - log : log(message), function to log debug information in logging table
-#  - Warning: Warning Exception to use with raise
-# To return an action, assign: action = {...}""",
-        'use_relational_model': 'base',
-        'use_create': 'new',
-        'use_write': 'current',
-    }
-
-    def _check_expression(self, cr, uid, expression, model_id, context):
+                                  "- 'Send Email': automatically send an email (available in email_template)")
+    usage = fields.Char(string='Action Usage')
+    type = fields.Char(string='Action Type', default='ir.actions.server', required=True)
+    # Generic
+    sequence = fields.Integer(default=5,
+                              help="When dealing with multiple actions, the execution order is "
+                                   "based on the sequence. Low number means high priority.")
+    model_id = fields.Many2one('ir.model', string='Base Model', required=True, ondelete='cascade',
+                               help="Base model on which the server action runs.")
+    model_name = fields.Char(related='model_id.model', readonly=True)
+    menu_ir_values_id = fields.Many2one('ir.values', string='More Menu entry', readonly=True,
+                                        help='More menu entry.', copy=False)
+    # Client Action
+    action_id = fields.Many2one('ir.actions.actions', string='Client Action',
+                                help="Select the client action that has to be executed.")
+    # Python code
+    code = fields.Text(string='Python Code',
+                       default="""# Available locals:
+                                  #  - time, datetime, dateutil: Python libraries
+                                  #  - env: Odoo Environement
+                                  #  - model: Model of the record on which the action is triggered
+                                  #  - object: Record on which the action is triggered if there is one, otherwise None
+                                  #  - workflow: Workflow engine
+                                  #  - log : log(message), function to log debug information in logging table
+                                  #  - Warning: Warning Exception to use with raise
+                                  # To return an action, assign: action = {...}""",
+                       help="Write Python code that the action will execute. Some variables are "
+                            "available for use; help about pyhon expression is given in the help tab.")
+    # Workflow signal
+    use_relational_model = fields.Selection([('base', 'Use the base model of the action'),
+                                             ('relational', 'Use a relation field on the base model')],
+                                            string='Target Model', default='base', required=True)
+    wkf_transition_id = fields.Many2one('workflow.transition', string='Signal to Trigger',
+                                        help="Select the workflow signal to trigger.")
+    wkf_model_id = fields.Many2one('ir.model', string='Target Model',
+                                   help="The model that will receive the workflow signal. Note that it should have a workflow associated with it.")
+    wkf_model_name = fields.Char(string='Target Model Name', related='wkf_model_id.model', store=True, readonly=True)
+    wkf_field_id = fields.Many2one('ir.model.fields', string='Relation Field',
+                                   oldname='trigger_obj_id', help="The field on the current object that links to the target object record (must be a many2one, or an integer field with the record ID)")
+    # Multi
+    child_ids = fields.Many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id',
+                                 string='Child Actions', help='Child server actions that will be executed. Note that the last return returned action value will be used as global return value.')
+    # Create/Copy/Write
+    use_create = fields.Selection([('new', 'Create a new record in the Base Model'),
+                                   ('new_other', 'Create a new record in another model'),
+                                   ('copy_current', 'Copy the current record'),
+                                   ('copy_other', 'Choose and copy a record in the database')],
+                                  string="Creation Policy", default='new', required=True)
+    crud_model_id = fields.Many2one('ir.model', string='Target Model',
+                                    oldname='srcmodel_id', help="Model for record creation / update. Set this field only to specify a different model than the base model.")
+    crud_model_name = fields.Char(string='Create/Write Target Model Name', related='crud_model_id.model', store=True, readonly=True)
+    ref_object = fields.Reference(string='Reference record', selection='_select_objects', oldname='copy_object')
+    link_new_record = fields.Boolean(string='Attach the new record',
+                                     help="Check this if you want to link the newly-created record "
+                                          "to the current record on which the server action runs.")
+    link_field_id = fields.Many2one('ir.model.fields', string='Link using field',
+                                    oldname='record_id', help="Provide the field where the record id is stored after the operations.")
+    use_write = fields.Selection([('current', 'Update the current record'),
+                                  ('expression', 'Update a record linked to the current record using python'),
+                                  ('other', 'Choose and Update a record in the database')],
+                                 string='Update Policy', default='current', required=True)
+    write_expression = fields.Char(string='Expression', oldname='write_id',
+                                   help="Provide an expression that, applied on the current record, gives the field to update.")
+    fields_lines = fields.One2many('ir.server.object.lines', 'server_id', string='Value Mapping', copy=True)
+
+    # Fake fields used to implement the placeholder assistant
+    model_object_field = fields.Many2one('ir.model.fields', string="Field",
+                                         help="Select target field from the related document model.\n"
+                                              "If it is a relationship field you will be able to select "
+                                              "a target field at the destination of the relationship.")
+    sub_object = fields.Many2one('ir.model', string='Sub-model', readonly=True,
+                                 help="When a relationship field is selected as first field, "
+                                      "this field shows the document model the relationship goes to.")
+    sub_model_object_field = fields.Many2one('ir.model.fields', string='Sub-field',
+                                             help="When a relationship field is selected as first field, "
+                                                  "this field lets you select the target field within the "
+                                                  "destination document model (sub-model).")
+    copyvalue = fields.Char(string='Placeholder Expression', help="Final placeholder expression, to be copy-pasted in the desired template field.")
+    # Fake fields used to implement the ID finding assistant
+    id_object = fields.Reference(string='Record', selection='_select_objects')
+    id_value = fields.Char(string='Record ID')
+
+    def _check_expression(self, expression, model_id):
         """ Check python expression (condition, write_expression). Each step of
         the path must be a valid many2one field, or an integer field for the last
         step.
@@ -663,7 +581,7 @@ class ir_actions_server(osv.osv):
         if not model_id:
             return (False, None, 'Your expression cannot be validated because the Base Model is not set.')
         # fetch current model
-        current_model_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
+        current_model_name = self.env['ir.model'].browse(model_id).model
         # transform expression into a path that should look like 'object.many2onefield.many2onefield'
         path = expression.split('.')
         initial = path.pop(0)
@@ -672,7 +590,7 @@ class ir_actions_server(osv.osv):
         # analyze path
         while path:
             step = path.pop(0)
-            field = self.pool[current_model_name]._fields.get(step)
+            field = self.env[current_model_name]._fields.get(step)
             if not field:
                 return (False, None, 'Part of the expression (%s) is not recognized as a column in the model %s.' % (step, current_model_name))
             ftype = field.type
@@ -684,42 +602,42 @@ class ir_actions_server(osv.osv):
                 current_model_name = field.comodel_name
         return (True, current_model_name, None)
 
-    def _check_write_expression(self, cr, uid, ids, context=None):
-        for record in self.browse(cr, uid, ids, context=context):
+    @api.constrains('write_expression', 'model_id')
+    def _check_write_expression(self):
+        for record in self:
             if record.write_expression and record.model_id:
-                correct, model_name, message = self._check_expression(cr, uid, record.write_expression, record.model_id.id, context=context)
+                correct, model_name, message = self._check_expression(record.write_expression, record.model_id.id)
                 if not correct:
                     _logger.warning('Invalid expression: %s' % message)
-                    return False
+                    raise ValueError(_('Incorrect Write Record Expression'))
         return True
 
     _constraints = [
-        (_check_write_expression,
-            'Incorrect Write Record Expression',
-            ['write_expression']),
-        (partial(osv.Model._check_m2m_recursion, field_name='child_ids'),
+        (partial(models.Model._check_m2m_recursion, field_name='child_ids'),
             'Recursion found in child server actions',
             ['child_ids']),
     ]
 
-    def on_change_model_id(self, cr, uid, ids, model_id, wkf_model_id, crud_model_id, context=None):
+    @api.onchange('model_id', 'wkf_model_id', 'crud_model_id')
+    def on_change_model_id(self):
         """ When changing the action base model, reset workflow and crud config
         to ease value coherence. """
         values = {
             'use_create': 'new',
             'use_write': 'current',
             'use_relational_model': 'base',
-            'wkf_model_id': model_id,
+            'wkf_model_id': self.model_id.id,
             'wkf_field_id': False,
-            'crud_model_id': model_id,
+            'crud_model_id': self.model_id.id,
         }
 
-        if model_id:
-            values['model_name'] = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
+        if self.model_id:
+            values['model_name'] = self.env['ir.model'].browse(self.model_id.id).model
 
         return {'value': values}
 
-    def on_change_wkf_wonfig(self, cr, uid, ids, use_relational_model, wkf_field_id, wkf_model_id, model_id, context=None):
+    @api.onchange('use_relational_model', 'wkf_field_id', 'wkf_model_id', 'model_id')
+    def on_change_wkf_wonfig(self):
         """ Update workflow type configuration
 
          - update the workflow model (for base (model_id) /relational (field.relation))
@@ -727,32 +645,34 @@ class ir_actions_server(osv.osv):
            the user to choose a new one
         """
         values = {}
-        if use_relational_model == 'relational' and wkf_field_id:
-            field = self.pool['ir.model.fields'].browse(cr, uid, wkf_field_id, context=context)
-            new_wkf_model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', field.relation)], context=context)[0]
-            values['wkf_model_id'] = new_wkf_model_id
+        if self.use_relational_model == 'relational' and self.wkf_field_id:
+            field = self.env['ir.model.fields'].browse(self.wkf_field_id.id)
+            new_wkf_model = self.env['ir.model'].search([('model', '=', field.relation)])
+            values['wkf_model_id'] = new_wkf_model.id
         else:
-            values['wkf_model_id'] = model_id
+            values['wkf_model_id'] = self.model_id.id
         return {'value': values}
 
-    def on_change_wkf_model_id(self, cr, uid, ids, wkf_model_id, context=None):
+    @api.onchange('wkf_model_id')
+    def on_change_wkf_model_id(self):
         """ When changing the workflow model, update its stored name also """
-        wkf_model_name = False
-        if wkf_model_id:
-            wkf_model_name = self.pool.get('ir.model').browse(cr, uid, wkf_model_id, context).model
-        values = {'wkf_transition_id': False, 'wkf_model_name': wkf_model_name}
+        values = {'wkf_transition_id': False}
+        if self.wkf_model_id:
+            values['wkf_model_name'] = self.env['ir.model'].browse(self.wkf_model_id.id).model
         return {'value': values}
 
-    def on_change_crud_config(self, cr, uid, ids, state, use_create, use_write, ref_object, crud_model_id, model_id, context=None):
+    @api.onchange('state', 'use_create', 'use_write', 'ref_object', 'crud_model_id', 'model_id')
+    def on_change_crud_config(self):
         """ Wrapper on CRUD-type (create or write) on_change """
-        if state == 'object_create':
-            return self.on_change_create_config(cr, uid, ids, use_create, ref_object, crud_model_id, model_id, context=context)
-        elif state == 'object_write':
-            return self.on_change_write_config(cr, uid, ids, use_write, ref_object, crud_model_id, model_id, context=context)
+        if self.state == 'object_create':
+            return self.on_change_create_config(self.use_create, self.ref_object, self.crud_model_id.id, self.model_id.id)
+        elif self.state == 'object_write':
+            return self.on_change_write_config(self.use_write, self.ref_object, self.crud_model_id.id, self.model_id.id)
         else:
             return {}
 
-    def on_change_create_config(self, cr, uid, ids, use_create, ref_object, crud_model_id, model_id, context=None):
+    @api.multi
+    def on_change_create_config(self, use_create, ref_object, crud_model_id, model_id):
         """ When changing the object_create type configuration:
 
          - `new` and `copy_current`: crud_model_id is the same as base model
@@ -769,15 +689,16 @@ class ir_actions_server(osv.osv):
         elif use_create == 'copy_current':
             values['crud_model_id'] = model_id
         elif use_create == 'copy_other' and ref_object:
-            ref_model, ref_id = ref_object.split(',')
-            ref_model_id = self.pool['ir.model'].search(cr, uid, [('model', '=', ref_model)], context=context)[0]
-            values['crud_model_id'] = ref_model_id
+            ref_model = str(ref_object).split('(')
+            ref_model = self.env['ir.model'].search([('model', '=', ref_model)])
+            values['crud_model_id'] = ref_model.id
 
         if values.get('crud_model_id') != crud_model_id:
             values['link_field_id'] = False
         return {'value': values}
 
-    def on_change_write_config(self, cr, uid, ids, use_write, ref_object, crud_model_id, model_id, context=None):
+    @api.multi
+    def on_change_write_config(self, use_write, ref_object, crud_model_id, model_id):
         """ When changing the object_write type configuration:
 
          - `current`: crud_model_id is the same as base model
@@ -788,9 +709,9 @@ class ir_actions_server(osv.osv):
         if use_write == 'current':
             values['crud_model_id'] = model_id
         elif use_write == 'other' and ref_object:
-            ref_model, ref_id = ref_object.split(',')
-            ref_model_id = self.pool['ir.model'].search(cr, uid, [('model', '=', ref_model)], context=context)[0]
-            values['crud_model_id'] = ref_model_id
+            ref_model = str(ref_object).split('(')
+            ref_model = self.env['ir.model'].search([('model', '=', ref_model)])
+            values['crud_model_id'] = ref_model.id
         elif use_write == 'expression':
             pass
 
@@ -798,15 +719,16 @@ class ir_actions_server(osv.osv):
             values['link_field_id'] = False
         return {'value': values}
 
-    def on_change_write_expression(self, cr, uid, ids, write_expression, model_id, context=None):
+    @api.onchange('write_expression', 'model_id')
+    def on_change_write_expression(self):
         """ Check the write_expression and update crud_model_id accordingly """
         values = {}
-        if write_expression:
-            valid, model_name, message = self._check_expression(cr, uid, write_expression, model_id, context=context)
+        if self.write_expression:
+            valid, model_name, message = self._check_expression(self.write_expression, self.model_id.id)
         else:
             valid, model_name, message = True, None, False
-            if model_id:
-                model_name = self.pool['ir.model'].browse(cr, uid, model_id, context).model
+            if self.model_id:
+                model_name = self.env['ir.model'].browse(self.model_id.id).model
         if not valid:
             return {
                 'warning': {
@@ -815,17 +737,17 @@ class ir_actions_server(osv.osv):
                 }
             }
         if model_name:
-            ref_model_id = self.pool['ir.model'].search(cr, uid, [('model', '=', model_name)], context=context)[0]
-            values['crud_model_id'] = ref_model_id
+            ref_model = self.env['ir.model'].search([('model', '=', model_name)])
+            values['crud_model_id'] = ref_model.id
             return {'value': values}
         return {'value': {}}
 
-    def on_change_crud_model_id(self, cr, uid, ids, crud_model_id, context=None):
+    @api.onchange('crud_model_id')
+    def on_change_crud_model_id(self):
         """ When changing the CRUD model, update its stored name also """
-        crud_model_name = False
-        if crud_model_id:
-            crud_model_name = self.pool.get('ir.model').browse(cr, uid, crud_model_id, context).model
-        values = {'link_field_id': False, 'crud_model_name': crud_model_name}
+        values = {'link_field_id': False}
+        if self.crud_model_id:
+            values['crud_model_name'] = self.env['ir.model'].browse(self.crud_model_id.id).model
         return {'value': values}
 
     def _build_expression(self, field_name, sub_field_name):
@@ -843,25 +765,25 @@ class ir_actions_server(osv.osv):
                 expression += "." + sub_field_name
         return expression
 
-    def onchange_sub_model_object_value_field(self, cr, uid, ids, model_object_field, sub_model_object_field=False, context=None):
+    @api.onchange('model_object_field', 'sub_model_object_field')
+    def onchange_sub_model_object_value_field(self):
         result = {
             'sub_object': False,
             'copyvalue': False,
             'sub_model_object_field': False,
         }
-        if model_object_field:
-            fields_obj = self.pool.get('ir.model.fields')
-            field_value = fields_obj.browse(cr, uid, model_object_field, context)
+        if self.model_object_field:
+            FieldsObj = self.env['ir.model.fields']
+            field_value = FieldsObj.browse(self.model_object_field.id)
             if field_value.ttype in ['many2one', 'one2many', 'many2many']:
-                res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_value.relation)], context=context)
-                sub_field_value = False
-                if sub_model_object_field:
-                    sub_field_value = fields_obj.browse(cr, uid, sub_model_object_field, context)
+                res_ids = self.env['ir.model'].search([('model', '=', field_value.relation)])
+                if self.sub_model_object_field:
+                    sub_field_value = FieldsObj.browse(self.sub_model_object_field.id)
                 if res_ids:
                     result.update({
-                        'sub_object': res_ids[0],
+                        'sub_object': res_ids.id,
                         'copyvalue': self._build_expression(field_value.name, sub_field_value and sub_field_value.name or False),
-                        'sub_model_object_field': sub_model_object_field or False,
+                        'sub_model_object_field': self.sub_model_object_field,
                     })
             else:
                 result.update({
@@ -869,48 +791,53 @@ class ir_actions_server(osv.osv):
                 })
         return {'value': result}
 
-    def onchange_id_object(self, cr, uid, ids, id_object, context=None):
-        if id_object:
-            ref_model, ref_id = id_object.split(',')
-            return {'value': {'id_value': ref_id}}
+    @api.onchange('id_object')
+    def onchange_id_object(self):
+        if self.id_object:
+            return {'value': {'id_value': self.id_object.id}}
         return {'value': {'id_value': False}}
 
-    def create_action(self, cr, uid, ids, context=None):
+    @api.multi
+    def create_action(self):
         """ Create a contextual action for each of the server actions. """
-        for action in self.browse(cr, uid, ids, context=context):
-            ir_values_id = self.pool.get('ir.values').create(cr, SUPERUSER_ID, {
+        for action in self:
+            ir_values_id = self.env['ir.values'].sudo().create({
                 'name': _('Run %s') % action.name,
                 'model': action.model_id.model,
                 'key2': 'client_action_multi',
                 'value': "ir.actions.server,%s" % action.id,
-            }, context)
+            })
             action.write({
-                'menu_ir_values_id': ir_values_id,
+                'menu_ir_values_id': ir_values_id.id,
             })
         return True
 
-    def unlink_action(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink_action(self):
         """ Remove the contextual actions created for the server actions. """
-        self.check_access_rights(cr , uid, 'write', raise_exception=True)
-        for action in self.browse(cr, uid, ids, context=context):
+        self.check_access_rights('write', raise_exception=True)
+        for action in self:
             if action.menu_ir_values_id:
                 try:
-                    self.pool.get('ir.values').unlink(cr, SUPERUSER_ID, action.menu_ir_values_id.id, context)
+                    action.menu_ir_values_id.sudo().unlink()
                 except Exception:
                     raise UserError(_('Deletion of the action record failed.'))
         return True
 
-    def run_action_client_action(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_client_action(self, action, eval_context=None):
         if not action.action_id:
             raise UserError(_("Please specify an action to launch!"))
-        return self.pool[action.action_id.type].read(cr, uid, [action.action_id.id], context=context)[0]
+        return self.env[action.action_id.type].browse(action.action_id.id)[0]
 
-    def run_action_code_multi(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_code_multi(self, action, eval_context=None):
         eval(action.code.strip(), eval_context, mode="exec", nocopy=True)  # nocopy allows to return 'action'
         if 'action' in eval_context:
             return eval_context['action']
 
-    def run_action_trigger(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_trigger(self, action, eval_context=None):
         """ Trigger a workflow signal, depending on the use_relational_model:
 
          - `base`: base_model_pool.signal_workflow(cr, uid, context.get('active_id'), <TRIGGER_NAME>)
@@ -918,23 +845,25 @@ class ir_actions_server(osv.osv):
            field, then target_model_pool.signal_workflow(cr, uid, target_id, <TRIGGER_NAME>)
         """
         # weird signature and calling -> no self.env, use action param's
-        record = action.env[action.model_id.model].browse(context['active_id'])
+        record = action.env[action.model_id.model].browse(self.env.context['active_id'])
         if action.use_relational_model == 'relational':
             record = getattr(record, action.wkf_field_id.name)
-            if not isinstance(record, openerp.models.BaseModel):
+            if not isinstance(record, models.BaseModel):
                 record = action.env[action.wkf_model_id.model].browse(record)
 
         record.signal_workflow(action.wkf_transition_id.signal)
 
-    def run_action_multi(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_multi(self, action, eval_context=None):
         res = False
         for act in action.child_ids:
-            result = self.run(cr, uid, [act.id], context=context)
+            result = act.run()
             if result:
                 res = result
         return res
 
-    def run_action_object_write(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_object_write(self, action, eval_context=None):
         """ Write server action.
 
          - 1. evaluate the value mapping
@@ -950,22 +879,22 @@ class ir_actions_server(osv.osv):
 
         if action.use_write == 'current':
             model = action.model_id.model
-            ref_id = context.get('active_id')
+            ref_id = self.env.context.get('active_id')
         elif action.use_write == 'other':
             model = action.crud_model_id.model
             ref_id = action.ref_object.id
         elif action.use_write == 'expression':
             model = action.crud_model_id.model
             ref = eval(action.write_expression, eval_context)
-            if isinstance(ref, browse_record):
+            if isinstance(ref, odoo.osv.orm.browse_record):
                 ref_id = getattr(ref, 'id')
             else:
                 ref_id = int(ref)
 
-        obj_pool = self.pool[model]
-        obj_pool.write(cr, uid, [ref_id], res, context=context)
+        self.env[model].browse(ref_id).write(res)
 
-    def run_action_object_create(self, cr, uid, action, eval_context=None, context=None):
+    @api.model
+    def run_action_object_create(self, action, eval_context=None):
         """ Create and Copy server action.
 
          - 1. evaluate the value mapping
@@ -986,20 +915,20 @@ class ir_actions_server(osv.osv):
         elif action.use_create in ['new_other', 'copy_other']:
             model = action.crud_model_id.model
 
-        obj_pool = self.pool[model]
+        ObjPool = self.env[model]
         if action.use_create == 'copy_current':
-            ref_id = context.get('active_id')
-            res_id = obj_pool.copy(cr, uid, ref_id, res, context=context)
+            ref_id = self.env.context.get('active_id')
+            res = ObjPool.browse(ref_id).copy(res)
         elif action.use_create == 'copy_other':
-            ref_id = action.ref_object.id
-            res_id = obj_pool.copy(cr, uid, ref_id, res, context=context)
+            res = action.ref_object.copy(res)
         else:
-            res_id = obj_pool.create(cr, uid, res, context=context)
+            res = ObjPool.create(res)
 
         if action.link_new_record and action.link_field_id:
-            self.pool[action.model_id.model].write(cr, uid, [context.get('active_id')], {action.link_field_id.name: res_id})
+            self.env[action.model_id.model].browse(self.env.context.get('active_id')).write({action.link_field_id.name: res.id})
 
-    def _get_eval_context(self, cr, uid, action=None, context=None):
+    @api.model
+    def _get_eval_context(self, action=None):
         """ Prepare the context used when evaluating python code, like the
         condition or code server actions.
 
@@ -1007,45 +936,43 @@ class ir_actions_server(osv.osv):
         :type action: browse record
         :returns: dict -- evaluation context given to (safe_)eval """
         def log(message, level="info"):
-            val = (uid, 'server', cr.dbname, __name__, level, message, "action", action.id, action.name)
-            cr.execute("""
+            val = ('server', self.env.cr.dbname, __name__, level, message, "action", action.id, action.name)
+            self.env.cr.execute("""
                 INSERT INTO ir_logging(create_date, create_uid, type, dbname, name, level, message, path, line, func)
                 VALUES (NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s, %s)
             """, val)
 
-        eval_context = super(ir_actions_server, self)._get_eval_context(cr, uid, action=action, context=context)
-        obj_pool = self.pool[action.model_id.model]
-        env = openerp.api.Environment(cr, uid, context)
-        model = env[action.model_id.model]
-        obj = None
-        if context.get('active_model') == action.model_id.model and context.get('active_id'):
-            obj = model.browse(context['active_id'])
-        if context.get('onchange_self'):
-            obj = context['onchange_self']
+        eval_context = super(IrActionsServer, self)._get_eval_context(action=action)
+        Model = self.env[action.model_id.model]
+        if self.env.context.get('active_model') == action.model_id.model and self.env.context.get('active_id'):
+            obj = Model.browse(self.env.context['active_id'])
+        if self.env.context.get('onchange_self'):
+            obj = self.env.context['onchange_self']
         eval_context.update({
             # orm
-            'env': env,
-            'model': model,
+            'env': self.env,
+            'model': Model,
             'workflow': workflow,
             # Exceptions
-            'Warning': openerp.exceptions.Warning,
+            'Warning': odoo.exceptions.Warning,
             # record
             # TODO: When porting to master move badly named obj and object to
             # deprecated and define record (active_id) and records (active_ids)
             'object': obj,
             'obj': obj,
             # Deprecated use env or model instead
-            'self': obj_pool,
-            'pool': self.pool,
-            'cr': cr,
-            'context': context,
-            'user': env.user,
+            'self': self.env[action.model_id.model],
+            'pool': self.env,
+            'cr': self.env.cr,
+            'context': self.env.context,
+            'user': self.env.user,
             # helpers
             'log': log,
         })
         return eval_context
 
-    def run(self, cr, uid, ids, context=None):
+    @api.multi
+    def run(self):
         """ Runs the server action. For each server action, the condition is
         checked. Note that a void (``False``) condition is considered as always
         valid. If it is verified, the run_action_<STATE> method is called. This
@@ -1064,65 +991,52 @@ class ir_actions_server(osv.osv):
         :return: an action_id to be executed, or False is finished correctly without
                  return action
         """
-        if context is None:
-            context = {}
-        res = False
-        for action in self.browse(cr, uid, ids, context):
-            eval_context = self._get_eval_context(cr, uid, action, context=context)
+        for action in self:
+            eval_context = self._get_eval_context(action)
             condition = action.condition
             if condition is False:
                 # Void (aka False) conditions are considered as True
                 condition = True
             if hasattr(self, 'run_action_%s_multi' % action.state):
-                run_context = eval_context['context']
                 expr = eval(str(condition), eval_context)
                 if not expr:
                     continue
                 # call the multi method
                 func = getattr(self, 'run_action_%s_multi' % action.state)
-                res = func(cr, uid, action, eval_context=eval_context, context=run_context)
+                res = func(action, eval_context=eval_context)
 
             elif hasattr(self, 'run_action_%s' % action.state):
                 func = getattr(self, 'run_action_%s' % action.state)
-                active_id = context.get('active_id')
-                active_ids = context.get('active_ids', [active_id] if active_id else [])
+                active_id = self.env.context.get('active_id')
+                active_ids = self.env.context.get('active_ids', [active_id] if active_id else [])
                 for active_id in active_ids:
                     # run context dedicated to a particular active_id
-                    run_context = dict(context, active_ids=[active_id], active_id=active_id)
-                    eval_context["context"] = run_context
+                    eval_context["context"] = dict(self.env.context, active_ids=[active_id], active_id=active_id)
                     expr = eval(str(condition), eval_context)
                     if not expr:
                         continue
                     # call the single method related to the action: run_action_<STATE>
-                    res = func(cr, uid, action, eval_context=eval_context, context=run_context)
+                    res = func(action, eval_context=eval_context)
         return res
 
 
-class ir_server_object_lines(osv.osv):
+class IrServerObjectLines(models.Model):
     _name = 'ir.server.object.lines'
     _description = 'Server Action value mapping'
     _sequence = 'ir_actions_id_seq'
 
-    _columns = {
-        'server_id': fields.many2one('ir.actions.server', 'Related Server Action', ondelete='cascade'),
-        'col1': fields.many2one('ir.model.fields', 'Field', required=True),
-        'value': fields.text('Value', required=True, help="Expression containing a value specification. \n"
-                                                          "When Formula type is selected, this field may be a Python expression "
-                                                          " that can use the same values as for the condition field on the server action.\n"
-                                                          "If Value type is selected, the value will be used directly without evaluation."),
-        'type': fields.selection([
-            ('value', 'Value'),
-            ('equation', 'Python expression')
-        ], 'Evaluation Type', required=True, change_default=True),
-    }
-
-    _defaults = {
-        'type': 'value',
-    }
-
-    def eval_value(self, cr, uid, ids, eval_context=None, context=None):
-        res = dict.fromkeys(ids, False)
-        for line in self.browse(cr, uid, ids, context=context):
+    server_id = fields.Many2one('ir.actions.server', string='Related Server Action', ondelete='cascade')
+    col1 = fields.Many2one('ir.model.fields', string='Field', required=True)
+    value = fields.Text(required=True, help="Expression containing a value specification. \n"
+                                            "When Formula type is selected, this field may be a Python expression "
+                                            " that can use the same values as for the condition field on the server action.\n"
+                                            "If Value type is selected, the value will be used directly without evaluation.")
+    type = fields.Selection([('value', 'Value'), ('equation', 'Python expression')], 'Evaluation Type', default='value', required=True, change_default=True)
+
+    @api.multi
+    def eval_value(self, eval_context=None):
+        result = dict.fromkeys(self.ids, False)
+        for line in self:
             expr = line.value
             if line.type == 'equation':
                 expr = eval(line.value, eval_context)
@@ -1131,85 +1045,79 @@ class ir_server_object_lines(osv.osv):
                     expr = int(line.value)
                 except Exception:
                     pass
-            res[line.id] = expr
-        return res
+            result[line.id] = expr
+        return result
 
 
-TODO_STATES = [('open', 'To Do'),
-               ('done', 'Done')]
-TODO_TYPES = [('manual', 'Launch Manually'),('once', 'Launch Manually Once'),
-              ('automatic', 'Launch Automatically')]
-class ir_actions_todo(osv.osv):
+class IrActionsTodo(models.Model):
     """
     Configuration Wizards
     """
     _name = 'ir.actions.todo'
     _description = "Configuration Wizards"
-    _columns={
-        'action_id': fields.many2one(
-            'ir.actions.actions', 'Action', select=True, required=True),
-        'sequence': fields.integer('Sequence'),
-        'state': fields.selection(TODO_STATES, string='Status', required=True),
-        'name': fields.char('Name'),
-        'type': fields.selection(TODO_TYPES, 'Type', required=True,
-            help="""Manual: Launched manually.
-Automatic: Runs whenever the system is reconfigured.
-Launch Manually Once: after having been launched manually, it sets automatically to Done."""),
-        'groups_id': fields.many2many('res.groups', 'res_groups_action_rel', 'uid', 'gid', 'Groups'),
-        'note': fields.text('Text', translate=True),
-    }
-    _defaults={
-        'state': 'open',
-        'sequence': 10,
-        'type': 'manual',
-    }
-    _order="sequence,id"
-
-    def name_get(self, cr, uid, ids, context=None):
-        return [(rec.id, rec.action_id.name) for rec in self.browse(cr, uid, ids, context=context)]
-
-    def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
+    _order = "sequence, id"
+
+    action_id = fields.Many2one('ir.actions.actions', string='Action', select=True, required=True)
+    sequence = fields.Integer(default=10)
+    state = fields.Selection([('open', 'To Do'), ('done', 'Done')], string='Status', default='open', required=True)
+    name = fields.Char()
+    type = fields.Selection([('manual', 'Launch Manually'),
+                             ('once', 'Launch Manually Once'),
+                             ('automatic', 'Launch Automatically')], default='manual', required=True,
+                            help="""Manual: Launched manually.
+                                    Automatic: Runs whenever the system is reconfigured.
+                                    Launch Manually Once: after having been launched manually, it sets automatically to Done.""")
+    groups_id = fields.Many2many('res.groups', 'res_groups_action_rel', 'uid', 'gid', string='Groups')
+    note = fields.Text(string='Text', translate=True)
+
+    @api.multi
+    @api.depends('action_id', 'name')
+    def name_get(self):
+        return [(record.id, record.action_id.name) for record in self]
+
+    @api.model
+    def name_search(self, name, args=None, operator='ilike', limit=100):
         if args is None:
             args = []
         if name:
-            ids = self.search(cr, user, [('action_id', operator, name)] + args, limit=limit)
-            return self.name_get(cr, user, ids, context=context)
-        return super(ir_actions_todo, self).name_search(cr, user, name, args=args, operator=operator, context=context, limit=limit)
-
+            action = self.search([('action_id', operator, name)] + args, limit=limit)
+            return action.name_get()
+        return super(IrActionsTodo, self).name_search(name, args=args, operator=operator, limit=limit)
 
-    def action_launch(self, cr, uid, ids, context=None):
+    @api.multi
+    def action_launch(self, context=None):
         """ Launch Action of Wizard"""
-        wizard_id = ids and ids[0] or False
-        wizard = self.browse(cr, uid, wizard_id, context=context)
+        wizard_id = self.ids and self.ids[0]
+        wizard = self.browse(wizard_id)
         if wizard.type in ('automatic', 'once'):
             wizard.write({'state': 'done'})
 
         # Load action
         act_type = wizard.action_id.type
 
-        res = self.pool[act_type].read(cr, uid, [wizard.action_id.id], [], context=context)[0]
+        result = self.env[act_type].browse(wizard.action_id.id).read()[0]
         if act_type != 'ir.actions.act_window':
-            return res
-        res.setdefault('context','{}')
+            return result
+        result.setdefault('context', '{}')
 
         # Open a specific record when res_id is provided in the context
-        user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
-        ctx = eval(res['context'], {'user': user})
+        ctx = eval(result['context'], {'user': self.env.user})
         if ctx.get('res_id'):
-            res.update({'res_id': ctx.pop('res_id')})
+            result.update({'res_id': ctx.pop('res_id')})
 
         # disable log for automatic wizards
         if wizard.type == 'automatic':
             ctx.update({'disable_log': True})
-        res.update({'context': ctx})
+        result.update({'context': ctx})
 
-        return res
+        return result
 
-    def action_open(self, cr, uid, ids, context=None):
+    @api.multi
+    def action_open(self):
         """ Sets configuration wizard in TODO state"""
-        return self.write(cr, uid, ids, {'state': 'open'}, context=context)
+        return self.write({'state': 'open'})
 
-    def progress(self, cr, uid, context=None):
+    def progress(self):
         """ Returns a dict with 3 keys {todo, done, total}.
 
         These keys all map to integers and provide the number of todos
@@ -1218,9 +1126,8 @@ Launch Manually Once: after having been launched manually, it sets automatically
 
         :rtype: dict
         """
-        user_groups = set(map(
-            lambda x: x.id,
-            self.pool['res.users'].browse(cr, uid, [uid], context=context)[0].groups_id))
+        user_groups = set(map(lambda x: x.id, self.env.user.groups_id))
+
         def groups_match(todo):
             """ Checks if the todo's groups match those of the current user
             """
@@ -1228,17 +1135,8 @@ Launch Manually Once: after having been launched manually, it sets automatically
                    or bool(user_groups.intersection((
                         group.id for group in todo.groups_id)))
 
-        done = filter(
-            groups_match,
-            self.browse(cr, uid,
-                self.search(cr, uid, [('state', '!=', 'open')], context=context),
-                        context=context))
-
-        total = filter(
-            groups_match,
-            self.browse(cr, uid,
-                self.search(cr, uid, [], context=context),
-                        context=context))
+        done = filter(groups_match, self.browse(self.search([('state', '!=', 'open')])))
+        total = filter(groups_match, self.browse(self.search([])))
 
         return {
             'done': len(done),
@@ -1247,46 +1145,35 @@ Launch Manually Once: after having been launched manually, it sets automatically
         }
 
 
-class ir_actions_act_client(osv.osv):
+class IrActionsActClient(models.Model):
     _name = 'ir.actions.client'
     _inherit = 'ir.actions.actions'
     _table = 'ir_act_client'
     _sequence = 'ir_actions_id_seq'
     _order = 'name'
 
-    def _get_params(self, cr, uid, ids, field_name, arg, context):
-        result = {}
+    name = fields.Char(string='Action Name', required=True, translate=True)
+    tag = fields.Char(string='Client action tag', required=True,
+                      help="An arbitrary string, interpreted by the client"
+                           " according to its own needs and wishes. There "
+                           "is no central tag repository across clients.")
+    res_model = fields.Char(string='Destination Model', help="Optional model, mostly used for needactions.")
+    context = fields.Char(string='Context Value', default={}, required=True, help="Context dictionary as Python expression, empty by default (Default: {})")
+    params = fields.Binary(compute='_get_params', inverse='_set_params', string='Supplementary arguments',
+                           help="Arguments sent to the client along with"
+                                "the view tag")
+    params_store = fields.Binary(string='Params storage', readonly=True)
+    type = fields.Char(string='Action Type', default='ir.actions.client')
+
+    @api.depends('params')
+    def _get_params(self):
         # Need to remove bin_size from context, to obtains the binary and not the length.
-        context = dict(context, bin_size_params_store=False)
-        for record in self.browse(cr, uid, ids, context=context):
-            result[record.id] = record.params_store and eval(record.params_store, {'uid': uid}) or False
-        return result
+        self = self.with_context(bin_size_params_store=False)
+        for record in self:
+            record.params = record.params_store and eval(record.params_store, {'uid': self.env.uid})
 
-    def _set_params(self, cr, uid, id, field_name, field_value, arg, context):
-        if isinstance(field_value, dict):
-            self.write(cr, uid, id, {'params_store': repr(field_value)}, context=context)
+    def _set_params(self):
+        if isinstance(self.params, dict):
+            self.write({'params_store': repr(self.params)})
         else:
-            self.write(cr, uid, id, {'params_store': field_value}, context=context)
-
-    _columns = {
-        'name': fields.char('Action Name', required=True, translate=True),
-        'tag': fields.char('Client action tag', required=True,
-                           help="An arbitrary string, interpreted by the client"
-                                " according to its own needs and wishes. There "
-                                "is no central tag repository across clients."),
-        'res_model': fields.char('Destination Model', 
-            help="Optional model, mostly used for needactions."),
-        'context': fields.char('Context Value', required=True,
-            help="Context dictionary as Python expression, empty by default (Default: {})"),
-        'params': fields.function(_get_params, fnct_inv=_set_params,
-                                  type='binary', 
-                                  string="Supplementary arguments",
-                                  help="Arguments sent to the client along with"
-                                       "the view tag"),
-        'params_store': fields.binary("Params storage", readonly=True)
-    }
-    _defaults = {
-        'type': 'ir.actions.client',
-        'context': '{}',
-
-    }
+            self.write({'params_store': self.params})
diff --git a/openerp/addons/base/ir/ir_actions.xml b/openerp/addons/base/ir/ir_actions.xml
index d2dd8ea35bbf10f2fcbcf73656c96657b177ae4b..de43839852f03e78e952d370511d38e7025ae368 100644
--- a/openerp/addons/base/ir/ir_actions.xml
+++ b/openerp/addons/base/ir/ir_actions.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
 
         <!-- ir.actions -->
 
@@ -275,8 +274,7 @@
                         <group>
                             <group>
                                 <field name="type" invisible="1"/>
-                                <field name="model_id"
-                                        on_change="on_change_model_id(model_id, wkf_model_id, crud_model_id)"/>
+                                <field name="model_id"/>
                                 <field name="state"/>
                             </group>
                             <group>
@@ -297,15 +295,12 @@
                                 </p>
                                 <group attrs="{'invisible': [('model_id', '=', False)]}">
                                     <field name="use_relational_model" widget="radio"
-                                            on_change="on_change_wkf_wonfig(use_relational_model, wkf_field_id, wkf_model_id, model_id)"
                                             attrs="{'readonly': [('model_id', '=', False)]}"/>
                                     <field name="wkf_field_id" context="{'key': ''}"
-                                            on_change="on_change_wkf_wonfig(use_relational_model, wkf_field_id, wkf_model_id, model_id)"
                                             attrs="{'required': [('state', '=', 'trigger'), ('use_relational_model', '=', 'relational')],
                                                     'invisible': [('use_relational_model', '=', 'base')]}"
                                             domain="[('model_id', '=', model_id), ('ttype', 'in', ['many2one'])]"/>
-                                    <field name="wkf_model_id" invisible="1"
-                                            on_change="on_change_wkf_model_id(wkf_model_id)"/>
+                                    <field name="wkf_model_id" invisible="1"/>
                                     <field name="wkf_model_name" invisible="1"/>
                                     <field name="wkf_transition_id" attrs="{'required': [('state', '=', 'trigger')]}"
                                             domain="[('wkf_id.osv', '=', wkf_model_name)]"/>
@@ -327,11 +322,9 @@
                                 </p>
                                 <group attrs="{'invisible': [('model_id', '=', False)]}">
                                     <field name="use_create" widget="radio"
-                                            on_change="on_change_crud_config(state, use_create, use_write, ref_object, crud_model_id, model_id)"
                                             attrs="{'invisible': [('state', '!=', 'object_create')]}"/>
 
                                     <field name="use_write" widget="radio"
-                                            on_change="on_change_crud_config(state, use_create, use_write, ref_object, crud_model_id, model_id)"
                                             attrs="{'invisible': [('state', '!=', 'object_write')]}"/>
 
                                     <label for="ref_object" string=" "
@@ -342,12 +335,10 @@
                                             attrs="{'invisible': ['&amp;', 
                                                                     '|', ('state', '!=', 'object_write'), ('use_write', '!=', 'other'),
                                                                     '|', ('state', '!=', 'object_create'), ('use_create', '!=', 'copy_other')]}">
-                                        <field name="ref_object" nolabel="1"
-                                                on_change="on_change_crud_config(state, use_create, use_write, ref_object, crud_model_id, model_id)"/>
+                                        <field name="ref_object" nolabel="1"/>
                                     </div>
 
                                     <field name="crud_model_id"
-                                            on_change="on_change_crud_model_id(crud_model_id)"
                                             attrs="{'invisible': ['|', ('state', '!=', 'object_create'), ('use_create', '!=', 'new_other')]}"/>
                                     <field name="crud_model_name" invisible="1"/>
 
@@ -376,7 +367,6 @@
                                             <li>object.partner_id.currency_id</li>
                                         </ul>
                                         <field name="write_expression"
-                                                on_change="on_change_write_expression(write_expression, model_id)"
                                                 attrs="{'required': [('state', '=', 'object_write'), ('use_write', '=', 'expression')]}"/>
                                     </div>
 
@@ -445,18 +435,16 @@
                                         </p>
                                         <field name="model_object_field"
                                                 attrs="{'invisible': [('model_id', '=', False)]}"
-                                                domain="[('model_id', '=', model_id), ('ttype', '!=', 'one2many'), ('ttype', '!=', 'many2many')]"
-                                                on_change="onchange_sub_model_object_value_field(model_object_field)"/>
+                                                domain="[('model_id', '=', model_id), ('ttype', '!=', 'one2many'), ('ttype', '!=', 'many2many')]"/>
                                         <field name="sub_object" readonly="1" attrs="{'invisible': [('model_id', '=', False)]}"/>
                                         <field name="sub_model_object_field"
                                                 domain="[('model_id', '=', sub_object), ('ttype', '!=', 'one2many'), ('ttype', '!=', 'many2many')]"
                                                 attrs="{'readonly':[('sub_object','=',False)],
                                                         'required':[('sub_object','!=',False)],
-                                                        'invisible': [('model_id', '=', False)]}"
-                                                on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field)"/>
+                                                        'invisible': [('model_id', '=', False)]}"/>
                                         <field name="copyvalue" attrs="{'invisible': [('model_id', '=', False)]}"/>
                                         <h3 colspan="2">Find the ID of a record in the database</h3>
-                                        <field name="id_object" on_change="onchange_id_object(id_object)"/>
+                                        <field name="id_object"/>
                                         <field name="id_value" />
                                     </group>
                                 </group>
@@ -583,5 +571,4 @@ if config.get('type') not in ('ir.actions.act_window_close',):
 </field>
         </record>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_attachment_view.xml b/openerp/addons/base/ir/ir_attachment_view.xml
index f177682f120e49bf6fbe98bdc55c31efbf890027..c9131c611c90c3a36ad634f0b6ab8a892700530f 100644
--- a/openerp/addons/base/ir/ir_attachment_view.xml
+++ b/openerp/addons/base/ir/ir_attachment_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- Attachment -->
         <record id="view_attachment_form" model="ir.ui.view">
             <field name="model">ir.attachment</field>
@@ -104,5 +103,4 @@
         </record>
         <menuitem action="action_attachment" id="menu_action_attachment" parent="base.next_id_9"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_autovacuum.py b/openerp/addons/base/ir/ir_autovacuum.py
index e2a647e456a9a97a9ddcd9493eb432f83770bf29..f964e14b74d8b4b87046ea02e88dac11382737d5 100644
--- a/openerp/addons/base/ir/ir_autovacuum.py
+++ b/openerp/addons/base/ir/ir_autovacuum.py
@@ -3,31 +3,33 @@
 
 import logging
 
-from openerp import models
+from odoo import api, models
 
 _logger = logging.getLogger(__name__)
 
+
 class AutoVacuum(models.TransientModel):
     """ Expose the vacuum method to the cron jobs mechanism. """
     _name = 'ir.autovacuum'
 
-
-    def _gc_transient_models(self, cr, uid, *args, **kwargs):
+    @api.model
+    def _gc_transient_models(self):
         for model in self.pool.itervalues():
             if model.is_transient():
-                model._transient_vacuum(cr, uid, force=True)
+                model._transient_vacuum(self._cr, self._uid, force=True)
 
-    def _gc_user_logs(self, cr, uid, *args, **kwargs):
-        cr.execute("""
+    def _gc_user_logs(self):
+        self.env.cr.execute("""
             DELETE FROM res_users_log log1 WHERE EXISTS (
                 SELECT 1 FROM res_users_log log2
                 WHERE log1.create_uid = log2.create_uid
                 AND log1.create_date < log2.create_date
             )
         """)
-        _logger.info("GC'd %d user log entries", cr.rowcount)
+        _logger.info("GC'd %d user log entries", self.env.cr.rowcount)
 
-    def power_on(self, cr, uid, *args, **kwargs):
-        self._gc_transient_models(cr, uid, *args, **kwargs)
-        self._gc_user_logs(cr, uid, *args, **kwargs)
+    @api.model
+    def power_on(self):
+        self._gc_transient_models()
+        self._gc_user_logs()
         return True
diff --git a/openerp/addons/base/ir/ir_autovacuum.xml b/openerp/addons/base/ir/ir_autovacuum.xml
index 5b89f4e39a1e7679b45c12261fb3b17300e357aa..1e015c89395df393440966e6630a6bcc99b7facb 100644
--- a/openerp/addons/base/ir/ir_autovacuum.xml
+++ b/openerp/addons/base/ir/ir_autovacuum.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <record model="ir.cron" id="autovacuum_job">
             <field name='name'>Auto-vacuum internal data</field>
             <field name='interval_number'>1</field>
@@ -11,6 +10,4 @@
             <field name="function">power_on</field>
             <field name="args">()</field>
         </record>
-
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_config_parameter.py b/openerp/addons/base/ir/ir_config_parameter.py
index f8e48e42181fc659e677872b72b96f4de237add1..f509156b084840382832a9785571613c0fcb6bab 100644
--- a/openerp/addons/base/ir/ir_config_parameter.py
+++ b/openerp/addons/base/ir/ir_config_parameter.py
@@ -7,9 +7,8 @@ Store database-specific configuration parameters
 import uuid
 import datetime
 
-from openerp import SUPERUSER_ID
-from openerp.osv import osv, fields
-from openerp.tools import misc, config, ormcache
+from odoo import api, fields, models
+from odoo.tools import misc, config, ormcache
 
 """
 A dictionary holding some configuration parameters to be initialized when the database is created.
@@ -22,35 +21,34 @@ _default_parameters = {
 }
 
 
-class ir_config_parameter(osv.osv):
+class IrConfigParameter(models.Model):
     """Per-database storage of configuration key-value pairs."""
 
     _name = 'ir.config_parameter'
     _rec_name = 'key'
 
-    _columns = {
-        'key': fields.char('Key', required=True, select=1),
-        'value': fields.text('Value', required=True),
-        'group_ids': fields.many2many('res.groups', 'ir_config_parameter_groups_rel', 'icp_id', 'group_id', string='Groups'),
-    }
+    key = fields.Char(required=True, index=True)
+    value = fields.Text(required=True)
+    group_ids = fields.Many2many('res.groups', 'ir_config_parameter_groups_rel', 'icp_id', 'group_id', string='Groups')
 
     _sql_constraints = [
         ('key_uniq', 'unique (key)', 'Key must be unique.')
     ]
 
-    def init(self, cr, force=False):
+    def init(self, force=False):
         """
         Initializes the parameters listed in _default_parameters.
         It overrides existing parameters if force is ``True``.
         """
         for key, func in _default_parameters.iteritems():
             # force=True skips search and always performs the 'if' body (because ids=False)
-            ids = not force and self.search(cr, SUPERUSER_ID, [('key','=',key)])
-            if not ids:
+            self = not force and self.sudo().search([('key', '=', key)])
+            if not self.ids:
                 value, groups = func()
-                self.set_param(cr, SUPERUSER_ID, key, value, groups=groups)
+                self.sudo().set_param(key, value, groups=groups)
 
-    def get_param(self, cr, uid, key, default=False, context=None):
+    @api.model
+    def get_param(self, key, default=False):
         """Retrieve the value for a given key.
 
         :param string key: The key of the parameter value to retrieve.
@@ -58,10 +56,10 @@ class ir_config_parameter(osv.osv):
         :return: The value of the parameter, or ``default`` if it does not exist.
         :rtype: string
         """
-        result = self._get_param(cr, uid, key)
-        if result is None:
-            return default
-        return result
+        result = self._get_param(key)
+        if result:
+            return result
+        return default
 
     @ormcache('uid', 'key')
     def _get_param(self, cr, uid, key):
@@ -70,7 +68,8 @@ class ir_config_parameter(osv.osv):
             return None
         return params[0]['value']
 
-    def set_param(self, cr, uid, key, value, groups=(), context=None):
+    @api.model
+    def set_param(self, key, value, groups=()):
         """Sets the value of a parameter.
 
         :param string key: The key of the parameter value to set.
@@ -81,35 +80,35 @@ class ir_config_parameter(osv.osv):
         :rtype: string
         """
         self._get_param.clear_cache(self)
-        ids = self.search(cr, uid, [('key','=',key)], context=context)
+        self = self.search([('key', '=', key)])
 
         gids = []
         for group_xml in groups:
-            res_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, group_xml)
+            res_id = self.env['ir.model.data'].xmlid_to_res_id(group_xml)
             if res_id:
                 gids.append((4, res_id))
 
         vals = {'value': value}
         if gids:
             vals.update(group_ids=gids)
-        if ids:
-            param = self.browse(cr, uid, ids[0], context=context)
-            old = param.value
+        if self.ids:
             if value is not False and value is not None:
-                self.write(cr, uid, ids, vals, context=context)
+                self.write(vals)
             else:
-                self.unlink(cr, uid, ids, context=context)
-            return old
+                self.unlink()
+            return self.value
         else:
             vals.update(key=key)
             if value is not False and value is not None:
-                self.create(cr, uid, vals, context=context)
+                self.create(vals)
             return False
 
-    def write(self, cr, uid, ids, vals, context=None):
+    @api.multi
+    def write(self, vals):
         self._get_param.clear_cache(self)
-        return super(ir_config_parameter, self).write(cr, uid, ids, vals, context=context)
+        return super(IrConfigParameter, self).write(vals)
 
-    def unlink(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink(self):
         self._get_param.clear_cache(self)
-        return super(ir_config_parameter, self).unlink(cr, uid, ids, context=context)
\ No newline at end of file
+        return super(IrConfigParameter, self).unlink()
diff --git a/openerp/addons/base/ir/ir_config_parameter_view.xml b/openerp/addons/base/ir/ir_config_parameter_view.xml
index 643fe6b6bf59f6368c963602a5849a4091c10caa..dbe5eae2a91532e8f266b62aa76f36de0720438e 100644
--- a/openerp/addons/base/ir/ir_config_parameter_view.xml
+++ b/openerp/addons/base/ir/ir_config_parameter_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <openerp>
-    <data>
         <record model="ir.ui.view" id="view_ir_config_search">
             <field name="model">ir.config_parameter</field>
             <field name="arch" type="xml">
@@ -36,5 +35,4 @@
         </record>
         <act_window name="System Parameters" res_model="ir.config_parameter" id="ir_config_list_action"/>
         <menuitem id="ir_config_menu" name="System Parameters" parent="menu_ir_property" action="ir_config_list_action"/>
-    </data>
 </openerp>
diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py
index 6f19a2247cf20a1256357a482242d08883961091..b2a2f5b45d1c7e829491fb0852813dc11678ff9f 100644
--- a/openerp/addons/base/ir/ir_cron.py
+++ b/openerp/addons/base/ir/ir_cron.py
@@ -4,22 +4,20 @@ import logging
 import threading
 import time
 import psycopg2
+import pytz
 from datetime import datetime
 from dateutil.relativedelta import relativedelta
-import pytz
 
-import openerp
-from openerp import SUPERUSER_ID, netsvc, api
-from openerp.osv import fields, osv
-from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.translate import _
-from openerp.modules import load_information_from_description_file
-from openerp.exceptions import UserError
+import odoo
+from odoo import api, fields, models, _
+from odoo.exceptions import UserError
+from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
+from odoo.tools.safe_eval import safe_eval as eval
 
 _logger = logging.getLogger(__name__)
 
-BASE_VERSION = load_information_from_description_file('base')['version']
+BASE_VERSION = odoo.modules.load_information_from_description_file('base')['version']
+
 
 def str2tuple(s):
     return eval('tuple(%s)' % (s or ''))
@@ -33,58 +31,49 @@ _intervalTypes = {
     'minutes': lambda interval: relativedelta(minutes=interval),
 }
 
-class ir_cron(osv.osv):
+
+class ir_cron(models.Model):
     """ Model describing cron jobs (also called actions or tasks).
     """
 
     # TODO: perhaps in the future we could consider a flag on ir.cron jobs
     # that would cause database wake-up even if the database has not been
     # loaded yet or was already unloaded (e.g. 'force_db_wakeup' or something)
-    # See also openerp.cron
+    # See also odoo.cron
 
     _name = "ir.cron"
     _order = 'name'
-    _columns = {
-        'name': fields.char('Name', required=True),
-        'user_id': fields.many2one('res.users', 'User', required=True),
-        'active': fields.boolean('Active'),
-        'interval_number': fields.integer('Interval Number',help="Repeat every x."),
-        'interval_type': fields.selection( [('minutes', 'Minutes'),
-            ('hours', 'Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Interval Unit'),
-        'numbercall': fields.integer('Number of Calls', help='How many times the method is called,\na negative number indicates no limit.'),
-        'doall' : fields.boolean('Repeat Missed', help="Specify if missed occurrences should be executed when the server restarts."),
-        'nextcall' : fields.datetime('Next Execution Date', required=True, help="Next planned execution date for this job."),
-        'model': fields.char('Object', help="Model name on which the method to be called is located, e.g. 'res.partner'."),
-        'function': fields.char('Method', help="Name of the method to be called when this job is processed."),
-        'args': fields.text('Arguments', help="Arguments to be passed to the method, e.g. (uid,)."),
-        'priority': fields.integer('Priority', help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
-    }
-
-    _defaults = {
-        'nextcall' : lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
-        'priority' : 5,
-        'user_id' : lambda obj,cr,uid,context: uid,
-        'interval_number' : 1,
-        'interval_type' : 'months',
-        'numbercall' : 1,
-        'active' : 1,
-    }
-
-    def _check_args(self, cr, uid, ids, context=None):
+
+    name = fields.Char(required=True)
+    user_id = fields.Many2one('res.users', string='User', default=lambda self: self.env.user, required=True)
+    active = fields.Boolean(default=True)
+    interval_number = fields.Integer(default=1, help="Repeat every x.")
+    interval_type = fields.Selection([('minutes', 'Minutes'),
+                                      ('hours', 'Hours'),
+                                      ('work_days', 'Work Days'),
+                                      ('days', 'Days'),
+                                      ('weeks', 'Weeks'),
+                                      ('months', 'Months')], string='Interval Unit', default='months')
+    numbercall = fields.Integer(string='Number of Calls', default=1, help='How many times the method is called,\na negative number indicates no limit.')
+    doall = fields.Boolean(string='Repeat Missed', help="Specify if missed occurrences should be executed when the server restarts.")
+    nextcall = fields.Datetime(string='Next Execution Date', required=True, default=lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), help="Next planned execution date for this job.")
+    model = fields.Char(string='Object', help="Model name on which the method to be called is located, e.g. 'res.partner'.")
+    function = fields.Char(string='Method', help="Name of the method to be called when this job is processed.")
+    args = fields.Text(string='Arguments', help="Arguments to be passed to the method, e.g. (uid,).")
+    priority = fields.Integer(default=5, help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
+
+    @api.constrains('args')
+    def _check_args(self):
         try:
-            for this in self.browse(cr, uid, ids, context):
+            for this in self:
                 str2tuple(this.args)
         except Exception:
-            return False
+            raise Exception('Invalid arguments')
         return True
 
-    _constraints = [
-        (_check_args, 'Invalid arguments', ['args']),
-    ]
-
     def method_direct_trigger(self, cr, uid, ids, context=None):
         if context is None:
-            context={}
+            context = {}
         cron_obj = self.browse(cr, uid, ids, context=context)
         for cron in cron_obj:
             self._callback(cr, uid, cron_obj.model, cron_obj.function, cron_obj.args, cron_obj.id)
@@ -117,20 +106,20 @@ class ir_cron(osv.osv):
         """
         try:
             args = str2tuple(args)
-            openerp.modules.registry.RegistryManager.check_registry_signaling(cr.dbname)
-            registry = openerp.registry(cr.dbname)
+            odoo.modules.registry.RegistryManager.check_registry_signaling(cr.dbname)
+            registry = odoo.registry(cr.dbname)
             if model_name in registry:
                 model = registry[model_name]
                 if hasattr(model, method_name):
                     log_depth = (None if _logger.isEnabledFor(logging.DEBUG) else 1)
-                    netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (cr.dbname,uid,'*',model_name,method_name)+tuple(args), depth=log_depth)
+                    odoo.netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (cr.dbname, uid, '*', model_name, method_name)+tuple(args), depth=log_depth)
                     if _logger.isEnabledFor(logging.DEBUG):
                         start_time = time.time()
                     getattr(model, method_name)(cr, uid, *args)
                     if _logger.isEnabledFor(logging.DEBUG):
                         end_time = time.time()
                         _logger.debug('%.3fs (%s, %s)' % (end_time - start_time, model_name, method_name))
-                    openerp.modules.registry.RegistryManager.signal_caches_change(cr.dbname)
+                    odoo.modules.registry.RegistryManager.signal_caches_change(cr.dbname)
                 else:
                     msg = "Method `%s.%s` does not exist." % (model_name, method_name)
                     _logger.warning(msg)
@@ -150,8 +139,8 @@ class ir_cron(osv.osv):
         """
         try:
             with api.Environment.manage():
-                now = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.now())
-                nextcall = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
+                now = odoo.osv.fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.now())
+                nextcall = odoo.osv.fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
                 numbercall = job['numbercall']
 
                 ok = False
@@ -167,8 +156,8 @@ class ir_cron(osv.osv):
                 if not numbercall:
                     addsql = ', active=False'
                 cron_cr.execute("UPDATE ir_cron SET nextcall=%s, numbercall=%s"+addsql+" WHERE id=%s",
-                           (nextcall.astimezone(pytz.UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id']))
-                self.invalidate_cache(job_cr, SUPERUSER_ID)
+                               (nextcall.astimezone(pytz.UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id']))
+                self.invalidate_cache(job_cr, odoo.SUPERUSER_ID)
 
         finally:
             job_cr.commit()
@@ -186,7 +175,7 @@ class ir_cron(osv.osv):
 
         If a job was processed, returns True, otherwise returns False.
         """
-        db = openerp.sql_db.db_connect(db_name)
+        db = odoo.sql_db.db_connect(db_name)
         threading.current_thread().dbname = db_name
         cr = db.cursor()
         jobs = []
@@ -237,7 +226,7 @@ class ir_cron(osv.osv):
                 _logger.debug('Starting job `%s`.', job['name'])
                 job_cr = db.cursor()
                 try:
-                    registry = openerp.registry(db_name)
+                    registry = odoo.registry(db_name)
                     registry[cls._name]._process_job(job_cr, job, lock_cr)
                 except Exception:
                     _logger.exception('Unexpected exception while processing cron job %r', job)
@@ -256,48 +245,49 @@ class ir_cron(osv.osv):
                 # we're exiting due to an exception while acquiring the lock
                 lock_cr.close()
 
-        if hasattr(threading.current_thread(), 'dbname'): # cron job could have removed it as side-effect
+        if hasattr(threading.current_thread(), 'dbname'):  # cron job could have removed it as side-effect
             del threading.current_thread().dbname
 
-    def _try_lock(self, cr, uid, ids, context=None):
+    def _try_lock(self):
         """Try to grab a dummy exclusive write-lock to the rows with the given ids,
            to make sure a following write() or unlink() will not block due
            to a process currently executing those cron tasks"""
         try:
-            cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table,
-                       (tuple(ids),), log_exceptions=False)
+            self.env.cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table,
+                               (tuple(self.ids),), log_exceptions=False)
         except psycopg2.OperationalError:
-            cr.rollback() # early rollback to allow translations to work for the user feedback
+            self.env.cr.rollback()  # early rollback to allow translations to work for the user feedback
             raise UserError(_("Record cannot be modified right now: "
-                                "This cron task is currently being executed and may not be modified "
-                                "Please try again in a few minutes"))
+                              "This cron task is currently being executed and may not be modified "
+                              "Please try again in a few minutes"))
 
-    def create(self, cr, uid, vals, context=None):
-        res = super(ir_cron, self).create(cr, uid, vals, context=context)
-        return res
+    @api.model
+    def create(self, vals):
+        return super(ir_cron, self).create(vals)
 
-    def write(self, cr, uid, ids, vals, context=None):
-        self._try_lock(cr, uid, ids, context)
-        res = super(ir_cron, self).write(cr, uid, ids, vals, context=context)
-        return res
+    @api.multi
+    def write(self, vals):
+        self._try_lock()
+        return super(ir_cron, self).write(vals)
 
-    def unlink(self, cr, uid, ids, context=None):
-        self._try_lock(cr, uid, ids, context)
-        res = super(ir_cron, self).unlink(cr, uid, ids, context=context)
-        return res
+    @api.multi
+    def unlink(self):
+        self._try_lock()
+        return super(ir_cron, self).unlink()
 
-    def try_write(self, cr, uid, ids, values, context=None):
+    @api.multi
+    def try_write(self, values):
         try:
-            with cr.savepoint():
-                cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table,
-                           (tuple(ids),), log_exceptions=False)
+            with self.env.cr.savepoint():
+                self.env.cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table,
+                                   (tuple(self.ids),), log_exceptions=False)
         except psycopg2.OperationalError:
             pass
         else:
-            return super(ir_cron, self).write(cr, uid, ids, values, context=context)
+            return super(ir_cron, self).write(values)
         return False
 
-    def toggle(self, cr, uid, ids, model, domain, context=None):
-        active = bool(self.pool[model].search_count(cr, uid, domain, context=context))
-
-        return self.try_write(cr, uid, ids, {'active': active}, context=context)
+    @api.model
+    def toggle(self, model, domain):
+        active = bool(self.env[model].search_count(domain))
+        return self.try_write({'active': active})
diff --git a/openerp/addons/base/ir/ir_cron_view.xml b/openerp/addons/base/ir/ir_cron_view.xml
index 0fb8719a30831f2959a0dfad99ca2c90afbeb310..572322526969f4e62e099265bc0de6eca18d5c04 100644
--- a/openerp/addons/base/ir/ir_cron_view.xml
+++ b/openerp/addons/base/ir/ir_cron_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- ir.cron -->
         <record id="ir_cron_view" model="ir.ui.view">
             <field name="model">ir.cron</field>
@@ -90,5 +89,4 @@
         </record>
         <menuitem id="menu_ir_cron_act" action="ir_cron_act" parent="base.menu_automation"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_exports.py b/openerp/addons/base/ir/ir_exports.py
index d23ea8d067507ee8890a2bbec4e18b0fb601e349..107acd6c83da8004b2f3a3ece89e4d10f3a0ab84 100644
--- a/openerp/addons/base/ir/ir_exports.py
+++ b/openerp/addons/base/ir/ir_exports.py
@@ -1,24 +1,21 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from openerp.osv import fields,osv
+from odoo import fields, models
 
 
-class ir_exports(osv.osv):
+class IrExports(models.Model):
     _name = "ir.exports"
     _order = 'name'
-    _columns = {
-        'name': fields.char('Export Name'),
-        'resource': fields.char('Resource', select=True),
-        'export_fields': fields.one2many('ir.exports.line', 'export_id',
-                                         'Export ID', copy=True),
-    }
 
+    name = fields.Char(string='Export Name')
+    resource = fields.Char(select=True)
+    export_fields = fields.One2many('ir.exports.line', 'export_id', string='Export ID', copy=True)
 
-class ir_exports_line(osv.osv):
+
+class IrExportsLine(models.Model):
     _name = 'ir.exports.line'
     _order = 'id'
-    _columns = {
-        'name': fields.char('Field Name'),
-        'export_id': fields.many2one('ir.exports', 'Export', select=True, ondelete='cascade'),
-    }
+
+    name = fields.Char(string='Field Name')
+    export_id = fields.Many2one('ir.exports', string='Export', select=True, ondelete='cascade')
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 488dfc502fc20ed8006b08b0f1fdedfff3743e28..92b85b523e8a87c1971245145bad14d8964da29b 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
-import datetime
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
 import functools
 import itertools
 import time
@@ -7,8 +8,8 @@ import time
 import psycopg2
 import pytz
 
-from openerp import models, fields, api, _
-from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, ustr
+from odoo import api, fields, models, _
+from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, ustr
 
 REFERENCING_FIELDS = {None, 'id', '.id'}
 def only_ref_fields(record):
@@ -33,7 +34,7 @@ class ImportWarning(Warning):
 class ConversionNotFound(ValueError): pass
 
 
-class ir_fields_converter(models.AbstractModel):
+class IrFieldsConverter(models.AbstractModel):
     _name = 'ir.fields.converter'
 
     @api.model
@@ -389,8 +390,7 @@ class ir_fields_converter(models.AbstractModel):
 
         subfield, w1 = self._referencing_subfield(record)
 
-        reference = record[subfield]
-        id, _, w2 = self.db_id_for(model, field, subfield, reference)
+        id, _, w2 = self.db_id_for(model, field, subfield, record[subfield])
         return id, w1 + w2
 
     @api.model
@@ -435,8 +435,7 @@ class ir_fields_converter(models.AbstractModel):
             if refs:
                 subfield, w1 = self._referencing_subfield(refs)
                 warnings.extend(w1)
-                reference = record[subfield]
-                id, _, w2 = self.db_id_for(model, field, subfield, reference)
+                id, _, w2 = self.db_id_for(model, field, subfield, record[subfield])
                 warnings.extend(w2)
 
             writable = convert(exclude_ref_fields(record), log)
diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py
index 3f2b5ee13e385781bd011f2b38978b1203102b0d..db33fef071f6db893c6faa0e6af7fbc07d22d874 100644
--- a/openerp/addons/base/ir/ir_filters.py
+++ b/openerp/addons/base/ir/ir_filters.py
@@ -1,33 +1,51 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from openerp import exceptions
-from openerp.osv import osv, fields
-from openerp.tools.translate import _
+from odoo import exceptions
+from odoo import api, fields, models, _
 
-class ir_filters(osv.osv):
+
+class IrFilters(models.Model):
     _name = 'ir.filters'
     _description = 'Filters'
+    _order = 'model_id, name, id desc'
 
-    def _list_all_models(self, cr, uid, context=None):
-        cr.execute("SELECT model, name FROM ir_model ORDER BY name")
-        return cr.fetchall()
-
-    def copy(self, cr, uid, id, default=None, context=None):
-        name = self.read(cr, uid, [id], ['name'])[0]['name']
-        default.update({'name':_('%s (copy)') % name})
-        return super(ir_filters, self).copy(cr, uid, id, default, context)
-
-    def _get_action_domain(self, cr, uid, action_id=None):
+    def _list_all_models(self):
+        self.env.cr.execute("SELECT model, name FROM ir_model ORDER BY name")
+        return self.env.cr.fetchall()
+
+    name = fields.Char(string='Filter Name', translate=True, required=True)
+    user_id = fields.Many2one('res.users', string='User', ondelete='cascade', default=lambda self: self._uid,
+                              help="The user this filter is private to. When left empty the filter is public "
+                                   "and available to all users.")
+    domain = fields.Text(default='[]', required=True)
+    context = fields.Text(default='{}', required=True)
+    sort = fields.Text(default='[]', required=True)
+    model_id = fields.Selection(selection='_list_all_models', string='Model', required=True)
+    is_default = fields.Boolean(string='Default filter')
+    action_id = fields.Many2one('ir.actions.actions', string='Action', ondelete='cascade',
+                                help="The menu action this filter applies to. "
+                                     "When left empty the filter applies to all menus "
+                                     "for this model.")
+    active = fields.Boolean(default=True)
+
+    @api.multi
+    def copy(self, default=None):
+        self.ensure_one()
+        default.update({'name': _('%s (copy)') % self.name})
+        return super(IrFilters, self).copy(default)
+
+    def _get_action_domain(self, action_id=None):
         """Return a domain component for matching filters that are visible in the
            same context (menu/view) as the given action."""
         if action_id:
             # filters specific to this menu + global ones
-            return [('action_id', 'in' , [action_id, False])]
+            return [('action_id', 'in', [action_id, False])]
         # only global ones
         return [('action_id', '=', False)]
 
-    def get_filters(self, cr, uid, model, action_id=None, context=None):
+    @api.model
+    def get_filters(self, model, action_id=None):
         """Obtain the list of filters available for the user on the given model.
 
         :param action_id: optional ID of action to restrict filters to this action
@@ -40,15 +58,12 @@ class ir_filters(osv.osv):
         """
         # available filters: private filters (user_id=uid) and public filters (uid=NULL),
         # and filters for the action (action_id=action_id) or global (action_id=NULL)
-        context = self.pool['res.users'].context_get(cr, uid)
-        action_domain = self._get_action_domain(cr, uid, action_id)
-        filter_ids = self.search(cr, uid, action_domain +
-            [('model_id','=',model),('user_id','in',[uid, False])])
-        my_filters = self.read(cr, uid, filter_ids,
-            ['name', 'is_default', 'domain', 'context', 'user_id', 'sort'], context=context)
+        action_domain = self._get_action_domain(action_id)
+        filter_ids = self.search(action_domain + [('model_id', '=', model), ('user_id', 'in', [self._uid, False])])
+        my_filters = filter_ids.with_context(self.env.user.context_get()).read(['name', 'is_default', 'domain', 'context', 'user_id', 'sort'])
         return my_filters
 
-    def _check_global_default(self, cr, uid, vals, matching_filters, context=None):
+    def _check_global_default(self, vals, matching_filters):
         """ _check_global_default(cursor, UID, dict, list(dict), dict) -> None
 
         Checks if there is a global default for the model_id requested.
@@ -64,96 +79,66 @@ class ir_filters(osv.osv):
         :raises openerp.exceptions.Warning: if there is an existing default and
                                             we're not updating it
         """
-        action_domain = self._get_action_domain(cr, uid, vals.get('action_id'))
-        existing_default = self.search(cr, uid, action_domain + [
+        action_domain = self._get_action_domain(vals.get('action_id'))
+        existing_default = self.search(action_domain + [
             ('model_id', '=', vals['model_id']),
             ('user_id', '=', False),
-            ('is_default', '=', True)], context=context)
+            ('is_default', '=', True)])
 
-        if not existing_default: return
-        if matching_filters and \
-           (matching_filters[0]['id'] == existing_default[0]):
+        if not existing_default:
+            return
+        if matching_filters and (matching_filters[0]['id'] == existing_default.id):
             return
 
-        raise exceptions.Warning(
-            _("There is already a shared filter set as default for %(model)s, delete or change it before setting a new default") % {
-                'model': vals['model_id']
-            })
+        raise exceptions.Warning(_("There is already a shared filter set as default for %(model)s, delete or change it before setting a new default") % {'model': vals.get('model_id')})
 
-    def create_or_replace(self, cr, uid, vals, context=None):
-        lower_name = vals['name'].lower()
+    @api.model
+    def create_or_replace(self, vals):
         action_id = vals.get('action_id')
-        current_filters = self.get_filters(cr, uid, vals['model_id'], action_id)
+        current_filters = self.get_filters(vals['model_id'], action_id)
         matching_filters = [f for f in current_filters
-                                if f['name'].lower() == lower_name
-                                # next line looks for matching user_ids (specific or global), i.e.
-                                # f.user_id is False and vals.user_id is False or missing,
-                                # or f.user_id.id == vals.user_id
-                                if (f['user_id'] and f['user_id'][0]) == vals.get('user_id', False)]
+                            if f['name'].lower() == vals['name'].lower()
+                            # next line looks for matching user_ids (specific or global), i.e.
+                            # f.user_id is False and vals.user_id is False or missing,
+                            # or f.user_id.id == vals.user_id
+                            if (f['user_id'] and f['user_id'][0]) == vals.get('user_id')]
 
         if vals.get('is_default'):
             if vals.get('user_id'):
                 # Setting new default: any other default that belongs to the user
                 # should be turned off
-                action_domain = self._get_action_domain(cr, uid, action_id)
-                act_ids = self.search(cr, uid, action_domain + [
-                        ('model_id', '=', vals['model_id']),
-                        ('user_id', '=', vals['user_id']),
-                        ('is_default', '=', True),
-                    ], context=context)
+                action_domain = self._get_action_domain(action_id)
+                act_ids = self.search(action_domain + [
+                                     ('model_id', '=', vals['model_id']),
+                                     ('user_id', '=', vals['user_id']),
+                                     ('is_default', '=', True),
+                ])
                 if act_ids:
-                    self.write(cr, uid, act_ids, {'is_default': False}, context=context)
+                    act_ids.write({'is_default': False})
             else:
-                self._check_global_default(
-                    cr, uid, vals, matching_filters, context=None)
+                self._check_global_default(vals, matching_filters)
 
         # When a filter exists for the same (name, model, user) triple, we simply
         # replace its definition (considering action_id irrelevant here)
         if matching_filters:
-            self.write(cr, uid, matching_filters[0]['id'], vals, context)
+            self.browse(matching_filters[0]['id']).write(vals)
             return matching_filters[0]['id']
 
-        return self.create(cr, uid, vals, context)
+        return self.create(vals)
 
     _sql_constraints = [
         # Partial constraint, complemented by unique index (see below)
         # Still useful to keep because it provides a proper error message when a violation
-        # occurs, as it shares the same prefix as the unique index. 
+        # occurs, as it shares the same prefix as the unique index.
         ('name_model_uid_unique', 'unique (name, model_id, user_id, action_id)', 'Filter names must be unique'),
     ]
 
-    def _auto_init(self, cr, context=None):
-        result = super(ir_filters, self)._auto_init(cr, context)
+    def _auto_init(self):
+        result = super(IrFilters, self)._auto_init()
         # Use unique index to implement unique constraint on the lowercase name (not possible using a constraint)
-        cr.execute("DROP INDEX IF EXISTS ir_filters_name_model_uid_unique_index") # drop old index w/o action
-        cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_filters_name_model_uid_unique_action_index'")
-        if not cr.fetchone():
-            cr.execute("""CREATE UNIQUE INDEX "ir_filters_name_model_uid_unique_action_index" ON ir_filters
+        self.env.cr.execute("DROP INDEX IF EXISTS ir_filters_name_model_uid_unique_index")  # drop old index w/o action
+        self.env.cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_filters_name_model_uid_unique_action_index'")
+        if not self.env.cr.fetchone():
+            self.env.cr.execute("""CREATE UNIQUE INDEX "ir_filters_name_model_uid_unique_action_index" ON ir_filters
                             (lower(name), model_id, COALESCE(user_id,-1), COALESCE(action_id,-1))""")
         return result
-
-    _columns = {
-        'name': fields.char('Filter Name', translate=True, required=True),
-        'user_id': fields.many2one('res.users', 'User', ondelete='cascade',
-                                   help="The user this filter is private to. When left empty the filter is public "
-                                        "and available to all users."),
-        'domain': fields.text('Domain', required=True),
-        'context': fields.text('Context', required=True),
-        'sort': fields.text('Sort', required=True),
-        'model_id': fields.selection(_list_all_models, 'Model', required=True),
-        'is_default': fields.boolean('Default filter'),
-        'action_id': fields.many2one('ir.actions.actions', 'Action', ondelete='cascade',
-                                     help="The menu action this filter applies to. "
-                                          "When left empty the filter applies to all menus "
-                                          "for this model."),
-        'active': fields.boolean('Active')
-    }
-    _defaults = {
-        'domain': '[]',
-        'context':'{}',
-        'sort': '[]',
-        'user_id': lambda self,cr,uid,context=None: uid,
-        'is_default': False,
-        'active': True
-    }
-    _order = 'model_id, name, id desc'
diff --git a/openerp/addons/base/ir/ir_filters.xml b/openerp/addons/base/ir/ir_filters.xml
index baf372de7b1539d13d973d23096f2a2f6676036b..7acbc54a18f98315c70eee84ce4e46836f345e9e 100644
--- a/openerp/addons/base/ir/ir_filters.xml
+++ b/openerp/addons/base/ir/ir_filters.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
+<odoo>
     <data noupdate="1">
         <!-- Restrict modifications on ir.filters to owner only -->
         <record id="ir_filters_rule" model="ir.rule">
@@ -73,4 +73,4 @@
         <menuitem parent="base.next_id_2" name="User-defined Filters"
             id="menu_ir_filters" action="actions_ir_filters_view" sequence="5"/>
     </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py
index 72e66e24c33be8935020b322ff7295d252917811..2c3dd1b9b13f286a151804ae7152fd99fcc5fe6a 100644
--- a/openerp/addons/base/ir/ir_http.py
+++ b/openerp/addons/base/ir/ir_http.py
@@ -18,18 +18,17 @@ import werkzeug.routing
 import werkzeug.urls
 import werkzeug.utils
 
-import openerp
-import openerp.exceptions
-import openerp.models
-from openerp import http
-from openerp.http import request, STATIC_CACHE
-from openerp.modules.module import get_resource_path, get_module_path
-from openerp.osv import osv, orm
+import odoo
+from odoo import models, tools
+from odoo import http
+from odoo.http import request, STATIC_CACHE
+from odoo.modules.module import get_resource_path, get_module_path
 
 _logger = logging.getLogger(__name__)
 
 UID_PLACEHOLDER = object()
 
+
 class ModelConverter(werkzeug.routing.BaseConverter):
 
     def __init__(self, url_map, model=False):
@@ -45,6 +44,7 @@ class ModelConverter(werkzeug.routing.BaseConverter):
     def to_url(self, value):
         return value.id
 
+
 class ModelsConverter(werkzeug.routing.BaseConverter):
 
     def __init__(self, url_map, model=False):
@@ -59,12 +59,13 @@ class ModelsConverter(werkzeug.routing.BaseConverter):
     def to_url(self, value):
         return ",".join(i.id for i in value)
 
+
 class SignedIntConverter(werkzeug.routing.NumberConverter):
     regex = r'-?\d+'
     num_convert = int
 
 
-class ir_http(osv.AbstractModel):
+class IrHttp(models.AbstractModel):
     _name = 'ir.http'
     _description = "HTTP routing"
 
@@ -84,7 +85,7 @@ class ir_http(osv.AbstractModel):
 
     def _auth_method_public(self):
         if not request.session.uid:
-            dummy, request.uid = self.pool['ir.model.data'].get_object_reference(request.cr, openerp.SUPERUSER_ID, 'base', 'public_user')
+            dummy, request.uid = self.env['ir.model.data'].sudo().get_object_reference(request.cr, 'base', 'public_user')
         else:
             request.uid = request.session.uid
 
@@ -96,22 +97,22 @@ class ir_http(osv.AbstractModel):
                     # what if error in security.check()
                     #   -> res_users.check()
                     #   -> res_users.check_credentials()
-                except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
+                except (odoo.exceptions.AccessDenied, http.SessionExpiredException):
                     # All other exceptions mean undetermined status (e.g. connection pool full),
                     # let them bubble up
                     request.session.logout(keep_db=True)
             if request.uid is None:
                 getattr(self, "_auth_method_%s" % auth_method)()
-        except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException, werkzeug.exceptions.HTTPException):
+        except (odoo.exceptions.AccessDenied, http.SessionExpiredException, werkzeug.exceptions.HTTPException):
             raise
         except Exception:
             _logger.info("Exception during request Authentication.", exc_info=True)
-            raise openerp.exceptions.AccessDenied()
+            raise odoo.exceptions.AccessDenied()
         return auth_method
 
     def _serve_attachment(self):
         domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)]
-        attach = self.pool['ir.attachment'].search_read(request.cr, openerp.SUPERUSER_ID, domain, ['__last_update', 'datas', 'name', 'mimetype', 'checksum'], context=request.context)
+        attach = self.pool['ir.attachment'].search_read(request.cr, odoo.SUPERUSER_ID, domain, ['__last_update', 'datas', 'name', 'mimetype', 'checksum'], context=request.context)
         if attach:
             wdate = attach[0]['__last_update']
             datas = attach[0]['datas'] or ''
@@ -123,7 +124,7 @@ class ir_http(osv.AbstractModel):
                 return werkzeug.utils.redirect(name, 301)
 
             response = werkzeug.wrappers.Response()
-            server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
+            server_format = tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
             try:
                 response.last_modified = datetime.datetime.strptime(wdate, server_format + '.%f')
             except ValueError:
@@ -151,11 +152,11 @@ class ir_http(osv.AbstractModel):
                 return attach
 
         # Don't handle exception but use werkeug debugger if server in --dev mode
-        if openerp.tools.config['dev_mode']:
+        if tools.config['dev_mode']:
             raise
         try:
             return request._handle_exception(exception)
-        except openerp.exceptions.AccessDenied:
+        except odoo.exceptions.AccessDenied:
             return werkzeug.exceptions.Forbidden()
 
     def _dispatch(self):
@@ -190,26 +191,26 @@ class ir_http(osv.AbstractModel):
     def _postprocess_args(self, arguments, rule):
         """ post process arg to set uid on browse records """
         for name, arg in arguments.items():
-            if isinstance(arg, orm.browse_record) and arg._uid is UID_PLACEHOLDER:
+            if isinstance(arg, odoo.osv.orm.browse_record) and arg._uid is UID_PLACEHOLDER:
                 arguments[name] = arg.sudo(request.uid)
                 try:
                     arg.exists()
-                except openerp.models.MissingError:
+                except models.MissingError:
                     return self._handle_exception(werkzeug.exceptions.NotFound())
 
     def routing_map(self):
         if not hasattr(self, '_routing_map'):
             _logger.info("Generating routing map")
             installed = request.registry._init_modules - {'web'}
-            if openerp.tools.config['test_enable']:
-                installed.add(openerp.modules.module.current_test)
-            mods = [''] + openerp.conf.server_wide_modules + sorted(installed)
+            if tools.config['test_enable']:
+                installed.add(odoo.modules.module.current_test)
+            mods = [''] + odoo.conf.server_wide_modules + sorted(installed)
             self._routing_map = http.routing_map(mods, False, converters=self._get_converters())
 
         return self._routing_map
 
     def content_disposition(self, filename):
-        filename = openerp.tools.ustr(filename)
+        filename = tools.ustr(filename)
         escaped = urllib2.quote(filename.encode('utf8'))
         browser = request.httprequest.user_agent.browser
         version = int((request.httprequest.user_agent.version or '0').split('.')[0])
@@ -255,7 +256,7 @@ class ir_http(osv.AbstractModel):
         # check read access
         try:
             last_update = obj['__last_update']
-        except openerp.exceptions.AccessError:
+        except odoo.exceptions.AccessError:
             return (403, [], None)
 
         status, headers, content = None, [], None
diff --git a/openerp/addons/base/ir/ir_logging.py b/openerp/addons/base/ir/ir_logging.py
index b67afa05e7cedbedc654fd6ca399acaee1113839..d6833e27c880601dcd668beadc0dbfc6b87af68d 100644
--- a/openerp/addons/base/ir/ir_logging.py
+++ b/openerp/addons/base/ir/ir_logging.py
@@ -1,27 +1,18 @@
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
-import logging
+from odoo import fields, models
 
-from openerp.osv import osv, fields
-from openerp.tools.translate import _
 
-class ir_logging(osv.Model):
+class IrLogging(models.Model):
     _name = 'ir.logging'
     _order = 'id DESC'
 
-    EXCEPTIONS_TYPE = [
-        ('client', 'Client'),
-        ('server', 'Server')
-    ]
-
-    _columns = {
-        'create_date': fields.datetime('Create Date', readonly=True),
-        'create_uid': fields.integer('Uid', readonly=True),  # Integer not m2o is intentionnal
-        'name': fields.char('Name', required=True),
-        'type': fields.selection(EXCEPTIONS_TYPE, string='Type', required=True, select=True),
-        'dbname': fields.char('Database Name', select=True),
-        'level': fields.char('Level', select=True),
-        'message': fields.text('Message', required=True),
-        'path': fields.char('Path', required=True),
-        'func': fields.char('Function', required=True),
-        'line': fields.char('Line', required=True),
-    }
+    create_date = fields.Datetime(readonly=True)
+    create_uid = fields.Integer(string='Uid', readonly=True)  # Integer not m2o is intentionnal
+    name = fields.Char(required=True)
+    type = fields.Selection([('client', 'Client'), ('server', 'Server')], required=True, select=True)
+    dbname = fields.Char(string='Database Name', select=True)
+    level = fields.Char(select=True)
+    message = fields.Text(required=True)
+    path = fields.Char(required=True)
+    func = fields.Char(string='Function', required=True)
+    line = fields.Char(required=True)
diff --git a/openerp/addons/base/ir/ir_logging_view.xml b/openerp/addons/base/ir/ir_logging_view.xml
index 6ecd6fa437b44563f0eb2bdec1ace83526bdc3ec..2cb00055df98bb349380e94828ae5d0cf49138dd 100644
--- a/openerp/addons/base/ir/ir_logging_view.xml
+++ b/openerp/addons/base/ir/ir_logging_view.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0"?>
-<openerp>
-    <data>
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
         <record model="ir.ui.view" id="ir_logging_form_view">
             <field name="model">ir.logging</field>
             <field name="arch" type="xml">
@@ -62,5 +61,4 @@
             <field name="search_view_id" ref="ir_logging_search_view" />
         </record>
         <menuitem parent="base.next_id_9" id="ir_logging_all_menu" action="ir_logging_all_act" />
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_mail_server.py b/openerp/addons/base/ir/ir_mail_server.py
index b5fb772a8512199b79259c474af4b416b03b14d9..ad4c4326712c1738f435466cd4f097b1f9fae6ae 100644
--- a/openerp/addons/base/ir/ir_mail_server.py
+++ b/openerp/addons/base/ir/ir_mail_server.py
@@ -1,29 +1,26 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from email.mime.text import MIMEText
-from email.mime.base import MIMEBase
-from email.mime.multipart import MIMEMultipart
+from email import Encoders
 from email.charset import Charset
 from email.header import Header
-from email.utils import formatdate, make_msgid, COMMASPACE, getaddresses, formataddr
-from email import Encoders
+from email.mime.base import MIMEBase
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
+from email.utils import COMMASPACE, formataddr, formatdate, getaddresses, make_msgid
 import logging
 import re
 import smtplib
 import threading
 
-from openerp import SUPERUSER_ID
-from openerp.osv import osv, fields
-from openerp.tools.translate import _
-from openerp.tools import html2text
-import openerp.tools as tools
-from openerp.exceptions import UserError
-from openerp.exceptions import except_orm
+from odoo import api, fields, models, tools, _
+from odoo.exceptions import except_orm
+from odoo.exceptions import UserError
+from odoo.tools import html2text
 
 # ustr was originally from tools.misc.
 # it is moved to loglevels until we refactor tools.
-from openerp.loglevels import ustr
+from odoo.loglevels import ustr
 
 _logger = logging.getLogger(__name__)
 _test_logger = logging.getLogger('openerp.tests')
@@ -34,6 +31,7 @@ class MailDeliveryException(except_orm):
     def __init__(self, name, value):
         super(MailDeliveryException, self).__init__(name, value)
 
+
 class WriteToLogger(object):
     """debugging helper: behave as a fd and pipe to logger at the given level"""
     def __init__(self, logger, level=logging.DEBUG):
@@ -58,6 +56,7 @@ def try_coerce_ascii(string_utf8):
         return
     return string_utf8
 
+
 def encode_header(header_text):
     """Returns an appropriate representation of the given header value,
        suitable for direct assignment as a header value in an
@@ -72,7 +71,8 @@ def encode_header(header_text):
                 that will perform the appropriate RFC2047 encoding of
                 non-ASCII values.
     """
-    if not header_text: return ""
+    if not header_text:
+        return ""
     # convert anything to utf-8, suitable for testing ASCIIness, as 7-bit chars are
     # encoded as ASCII in utf-8
     header_text_utf8 = tools.ustr(header_text).encode('utf-8')
@@ -82,7 +82,8 @@ def encode_header(header_text):
     # that will take care of RFC2047-encoding it as
     # 7-bit string.
     return header_text_ascii if header_text_ascii\
-         else Header(header_text_utf8, 'utf-8')
+        else Header(header_text_utf8, 'utf-8')
+
 
 def encode_header_param(param_text):
     """Returns an appropriate RFC2047 encoded representation of the given
@@ -98,25 +99,29 @@ def encode_header_param(param_text):
                 ASCII string containing the RFC2047 encoded text.
     """
     # For details see the encode_header() method that uses the same logic
-    if not param_text: return ""
+    if not param_text:
+        return ""
     param_text_utf8 = tools.ustr(param_text).encode('utf-8')
     param_text_ascii = try_coerce_ascii(param_text_utf8)
     return param_text_ascii if param_text_ascii\
-         else Charset('utf8').header_encode(param_text_utf8)
+        else Charset('utf8').header_encode(param_text_utf8)
 
 # TODO master, remove me, no longer used internaly
 name_with_email_pattern = re.compile(r'("[^<@>]+")\s*<([^ ,<@]+@[^> ,]+)>')
 address_pattern = re.compile(r'([^ ,<@]+@[^> ,]+)')
 
+
 def extract_rfc2822_addresses(text):
     """Returns a list of valid RFC2822 addresses
-       that can be found in ``source``, ignoring 
+       that can be found in ``source``, ignoring
        malformed ones and non-ASCII ones.
     """
-    if not text: return []
+    if not text:
+        return []
     candidates = address_pattern.findall(tools.ustr(text).encode('utf-8'))
     return filter(try_coerce_ascii, candidates)
 
+
 def encode_rfc2822_address_header(header_text):
     """If ``header_text`` contains non-ASCII characters,
        attempts to locate patterns of the form
@@ -134,41 +139,32 @@ def encode_rfc2822_address_header(header_text):
     return COMMASPACE.join(map(encode_addr, addresses))
 
 
-class ir_mail_server(osv.osv):
+class IrMailServer(models.Model):
     """Represents an SMTP server, able to send outgoing emails, with SSL and TLS capabilities."""
     _name = "ir.mail_server"
 
     NO_VALID_RECIPIENT = ("At least one valid recipient address should be "
                           "specified for outgoing emails (To/Cc/Bcc)")
 
-    _columns = {
-        'name': fields.char('Description', required=True, select=True),
-        'smtp_host': fields.char('SMTP Server', required=True, help="Hostname or IP of SMTP server"),
-        'smtp_port': fields.integer('SMTP Port', size=5, required=True, help="SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases."),
-        'smtp_user': fields.char('Username', size=64, help="Optional username for SMTP authentication"),
-        'smtp_pass': fields.char('Password', size=64, help="Optional password for SMTP authentication"),
-        'smtp_encryption': fields.selection([('none','None'),
-                                             ('starttls','TLS (STARTTLS)'),
-                                             ('ssl','SSL/TLS')],
-                                            string='Connection Security', required=True,
-                                            help="Choose the connection encryption scheme:\n"
-                                                 "- None: SMTP sessions are done in cleartext.\n"
-                                                 "- TLS (STARTTLS): TLS encryption is requested at start of SMTP session (Recommended)\n"
-                                                 "- SSL/TLS: SMTP sessions are encrypted with SSL/TLS through a dedicated port (default: 465)"),
-        'smtp_debug': fields.boolean('Debugging', help="If enabled, the full output of SMTP sessions will "
-                                                       "be written to the server log at DEBUG level"
-                                                       "(this is very verbose and may include confidential info!)"),
-        'sequence': fields.integer('Priority', help="When no specific mail server is requested for a mail, the highest priority one "
-                                                    "is used. Default priority is 10 (smaller number = higher priority)"),
-        'active': fields.boolean('Active')
-    }
-
-    _defaults = {
-         'smtp_port': 25,
-         'active': True,
-         'sequence': 10,
-         'smtp_encryption': 'none',
-     }
+    name = fields.Char(string='Description', required=True, index=True)
+    smtp_host = fields.Char(string='SMTP Server', required=True, help="Hostname or IP of SMTP server")
+    smtp_port = fields.Integer(string='SMTP Port', size=5, required=True, default=25, help="SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases.")
+    smtp_user = fields.Char(string='Username', size=64, help="Optional username for SMTP authentication")
+    smtp_pass = fields.Char(string='Password', size=64, help="Optional password for SMTP authentication")
+    smtp_encryption = fields.Selection([('none', 'None'),
+                                        ('starttls', 'TLS (STARTTLS)'),
+                                        ('ssl', 'SSL/TLS')],
+                                       string='Connection Security', required=True, default='none',
+                                       help="Choose the connection encryption scheme:\n"
+                                            "- None: SMTP sessions are done in cleartext.\n"
+                                            "- TLS (STARTTLS): TLS encryption is requested at start of SMTP session (Recommended)\n"
+                                            "- SSL/TLS: SMTP sessions are encrypted with SSL/TLS through a dedicated port (default: 465)")
+    smtp_debug = fields.Boolean(string='Debugging', help="If enabled, the full output of SMTP sessions will "
+                                                         "be written to the server log at DEBUG level"
+                                                         "(this is very verbose and may include confidential info!)")
+    sequence = fields.Integer(string='Priority', default=10, help="When no specific mail server is requested for a mail, the highest priority one "
+                                                                  "is used. Default priority is 10 (smaller number = higher priority)")
+    active = fields.Boolean(default=True)
 
     def __init__(self, *args, **kwargs):
         # Make sure we pipe the smtplib outputs to our own DEBUG logger
@@ -176,13 +172,14 @@ class ir_mail_server(osv.osv):
             logpiper = WriteToLogger(_logger)
             smtplib.stderr = logpiper
             smtplib.stdout = logpiper
-        super(ir_mail_server, self).__init__(*args,**kwargs)
+        super(IrMailServer, self).__init__(*args, **kwargs)
 
-    def name_get(self, cr, uid, ids, context=None):
-        return [(a["id"], "(%s)" % (a['name'])) for a in self.read(cr, uid, ids, ['name'], context=context)]
+    @api.multi
+    def name_get(self):
+        return [(a.id, "(%s)" % (a.name)) for a in self]
 
-    def test_smtp_connection(self, cr, uid, ids, context=None):
-        for smtp_server in self.browse(cr, uid, ids, context=context):
+    def test_smtp_connection(self):
+        for smtp_server in self:
             smtp = False
             try:
                 smtp = self.connect(smtp_server.smtp_host, smtp_server.smtp_port, user=smtp_server.smtp_user,
@@ -192,7 +189,8 @@ class ir_mail_server(osv.osv):
                 raise UserError(_("Connection Test Failed! Here is what we got instead:\n %s") % tools.ustr(e))
             finally:
                 try:
-                    if smtp: smtp.quit()
+                    if smtp:
+                        smtp.quit()
                 except Exception:
                     # ignored, just a consequence of the previous exception
                     pass
@@ -214,7 +212,7 @@ class ir_mail_server(osv.osv):
         if encryption == 'ssl':
             if not 'SMTP_SSL' in smtplib.__all__:
                 raise UserError(_("Your OpenERP Server does not support SMTP-over-SSL. You could use STARTTLS instead."
-                                    "If SSL is needed, an upgrade to Python 2.6 on the server-side should do the trick."))
+                                  "If SSL is needed, an upgrade to Python 2.6 on the server-side should do the trick."))
             connection = smtplib.SMTP_SSL(host, port)
         else:
             connection = smtplib.SMTP(host, port)
@@ -234,13 +232,13 @@ class ir_mail_server(osv.osv):
             # certain hashing schemes, like HMAC.
             # See also bug #597143 and python issue #5285
             user = tools.ustr(user).encode('utf-8')
-            password = tools.ustr(password).encode('utf-8') 
+            password = tools.ustr(password).encode('utf-8')
             connection.login(user, password)
         return connection
 
     def build_email(self, email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
-               attachments=None, message_id=None, references=None, object_id=False, subtype='plain', headers=None,
-               body_alternative=None, subtype_alternative='plain'):
+                    attachments=None, message_id=None, references=None, object_id=False, subtype='plain', headers=None,
+                    body_alternative=None, subtype_alternative='plain'):
         """Constructs an RFC2822 email.message.Message object based on the keyword arguments passed, and returns it.
 
            :param string email_from: sender email address
@@ -277,7 +275,7 @@ class ir_mail_server(osv.osv):
         # Note: we must force all strings to to 8-bit utf-8 when crafting message,
         #       or use encode_header() for headers, which does it automatically.
 
-        headers = headers or {} # need valid dict later
+        headers = headers or {}  # need valid dict later
 
         if not email_cc: email_cc = []
         if not email_bcc: email_bcc = []
@@ -345,7 +343,7 @@ class ir_mail_server(osv.osv):
                 msg.attach(part)
         return msg
 
-    def _get_default_bounce_address(self, cr, uid, context=None):
+    def _get_default_bounce_address(self):
         '''Compute the default bounce address.
 
         The default bounce address is used to set the envelop address if no
@@ -358,17 +356,14 @@ class ir_mail_server(osv.osv):
         If "mail.catchall.domain" is not set, return None.
 
         '''
-        get_param = self.pool['ir.config_parameter'].get_param
-        postmaster = get_param(cr, SUPERUSER_ID, 'mail.bounce.alias',
-                               default='postmaster-odoo',
-                               context=context,)
-        domain = get_param(cr, SUPERUSER_ID, 'mail.catchall.domain', context=context)
+        get_param = self.env['ir.config_parameter'].sudo().get_param
+        postmaster = get_param('mail.bounce.alias', default='postmaster-odoo')
+        domain = get_param('mail.catchall.domain')
         if postmaster and domain:
             return '%s@%s' % (postmaster, domain)
 
-    def send_email(self, cr, uid, message, mail_server_id=None, smtp_server=None, smtp_port=None,
-                   smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False,
-                   context=None):
+    def send_email(self, message, mail_server_id=None, smtp_server=None, smtp_port=None,
+                   smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False):
         """Sends an email directly (no queuing).
 
         No retries are done, the caller should handle MailDeliveryException in order to ensure that
@@ -399,7 +394,7 @@ class ir_mail_server(osv.osv):
         # Path (VERP) to detect no-longer valid email addresses.
         smtp_from = message['Return-Path']
         if not smtp_from:
-            smtp_from = self._get_default_bounce_address(cr, uid, context=context)
+            smtp_from = self._get_default_bounce_address()
         if not smtp_from:
             smtp_from = message['From']
         assert smtp_from, "The Return-Path or From header is required for any outbound email"
@@ -413,15 +408,15 @@ class ir_mail_server(osv.osv):
         email_to = message['To']
         email_cc = message['Cc']
         email_bcc = message['Bcc']
-        
-        smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses,[email_to, email_cc, email_bcc])))
+
+        smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses, [email_to, email_cc, email_bcc])))
         assert smtp_to_list, self.NO_VALID_RECIPIENT
 
         x_forge_to = message['X-Forge-To']
         if x_forge_to:
             # `To:` header forged, e.g. for posting on mail.channels, to avoid confusion
             del message['X-Forge-To']
-            del message['To'] # avoid multiple To: headers!
+            del message['To']  # avoid multiple To: headers!
             message['To'] = x_forge_to
 
         # Do not actually send emails in testing mode!
@@ -432,11 +427,9 @@ class ir_mail_server(osv.osv):
         # Get SMTP Server Details from Mail Server
         mail_server = None
         if mail_server_id:
-            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_id)
+            mail_server = self.sudo().browse(mail_server_id)
         elif not smtp_server:
-            mail_server_ids = self.search(cr, SUPERUSER_ID, [], order='sequence', limit=1)
-            if mail_server_ids:
-                mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])
+            mail_server = self.sudo().search([], order='sequence', limit=1)
 
         if mail_server:
             smtp_server = mail_server.smtp_host
@@ -452,10 +445,10 @@ class ir_mail_server(osv.osv):
             smtp_user = smtp_user or tools.config.get('smtp_user')
             smtp_password = smtp_password or tools.config.get('smtp_password')
             if smtp_encryption is None and tools.config.get('smtp_ssl'):
-                smtp_encryption = 'starttls' # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0
+                smtp_encryption = 'starttls'  # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0
 
         if not smtp_server:
-            raise UserError(_("Missing SMTP Server")+ "\n" + _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."))
+            raise UserError(_("Missing SMTP Server") + "\n" + _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."))
 
         try:
             message_id = message['Message-Id']
@@ -464,7 +457,7 @@ class ir_mail_server(osv.osv):
             if smtp_server.startswith('maildir:/'):
                 from mailbox import Maildir
                 maildir_path = smtp_server[8:]
-                mdir = Maildir(maildir_path, factory=None, create = True)
+                mdir = Maildir(maildir_path, factory=None, create=True)
                 mdir.add(message.as_string(True))
                 return message_id
 
diff --git a/openerp/addons/base/ir/ir_mail_server_view.xml b/openerp/addons/base/ir/ir_mail_server_view.xml
index 81783d7910a30222d908a58820ba86a8d6b2d2dc..35bf5bb117bfa0f6f7d24e0d21d07dca9b88b179 100644
--- a/openerp/addons/base/ir/ir_mail_server_view.xml
+++ b/openerp/addons/base/ir/ir_mail_server_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- ir.mail.server -->
         <record model="ir.ui.view" id="ir_mail_server_form">
             <field name="model">ir.mail_server</field>
@@ -58,5 +57,4 @@
             <field name="search_view_id" ref="view_ir_mail_server_search"/>
         </record>
         <menuitem id="menu_mail_servers" parent="menu_email" action="action_ir_mail_server_list" sequence="15" groups="base.group_no_one"/>
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py
index fd9e9f8ad7c976534d53417eb4eb7f9aa92480e7..a1a9f773fb71f0be0589ee9c08ceee674860ba7a 100644
--- a/openerp/addons/base/ir/ir_model.py
+++ b/openerp/addons/base/ir/ir_model.py
@@ -1,54 +1,30 @@
 # -*- coding: utf-8 -*-
-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
-from collections import defaultdict
 import logging
 import re
 import time
 import types
+from collections import defaultdict
 
-import openerp
-from openerp import SUPERUSER_ID
-from openerp import models, tools, api
-from openerp.modules import init_models
-from openerp.modules.registry import RegistryManager
-from openerp.osv import fields, osv
-from openerp.osv.orm import BaseModel, Model, MAGIC_COLUMNS
-from openerp.exceptions import UserError, AccessError
-from openerp.tools import config
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.translate import _
+import odoo
+from odoo import api, fields, models, SUPERUSER_ID, tools,  _
+from odoo.exceptions import AccessError, UserError
+from odoo.modules import init_models
+from odoo.modules.registry import RegistryManager
+from odoo.osv import osv
+from odoo.osv.orm import BaseModel, MAGIC_COLUMNS
+from odoo.tools import config
+from odoo.tools.safe_eval import safe_eval as eval
 
 _logger = logging.getLogger(__name__)
 
 MODULE_UNINSTALL_FLAG = '_force_unlink'
 
+
 def encode(s):
     """ Return an UTF8-encoded version of ``s``. """
     return s.encode('utf8') if isinstance(s, unicode) else s
 
-def _get_fields_type(self, cr, uid, context=None):
-    # Avoid too many nested `if`s below, as RedHat's Python 2.6
-    # break on it. See bug 939653.
-    return sorted([(k,k) for k,v in fields.__dict__.iteritems()
-                      if type(v) == types.TypeType and \
-                         issubclass(v, fields._column) and \
-                         v != fields._column and \
-                         not v._deprecated and \
-                         not issubclass(v, fields.function)])
-
-def _in_modules(self, cr, uid, ids, field_name, arg, context=None):
-    #pseudo-method used by fields.function in ir.model/ir.model.fields
-    module_pool = self.pool["ir.module.module"]
-    installed_module_ids = module_pool.search(cr, uid, [('state','=','installed')])
-    installed_module_names = module_pool.read(cr, uid, installed_module_ids, ['name'], context=context)
-    installed_modules = set(x['name'] for x in installed_module_names)
-
-    result = {}
-    xml_ids = osv.osv._get_xml_ids(self, cr, uid, ids)
-    for k,v in xml_ids.iteritems():
-        result[k] = ', '.join(sorted(installed_modules & set(xml_id.split('.')[0] for xml_id in v)))
-    return result
 
 #
 # IMPORTANT: this must be the first model declared in the module
@@ -64,135 +40,131 @@ class unknown(models.AbstractModel):
     """
     _name = '_unknown'
 
-class ir_model(osv.osv):
+
+class IrModel(models.Model):
     _name = 'ir.model'
     _description = "Models"
     _order = 'model'
 
-    def _view_ids(self, cr, uid, ids, field_name, arg, context=None):
-        models = self.browse(cr, uid, ids)
-        res = {}
-        for model in models:
-            res[model.id] = self.pool["ir.ui.view"].search(cr, uid, [('model', '=', model.model)])
-        return res
-
-    def _inherited_models(self, cr, uid, ids, field_name, arg, context=None):
-        res = {}
-        for model in self.browse(cr, uid, ids, context=context):
-            res[model.id] = []
-            inherited_models = [model_name for model_name in self.pool[model.model]._inherits]
+    name = fields.Char(string='Model Description', translate=True, required=True)
+    model = fields.Char(default='x_', required=True, index=True)
+    info = fields.Text(string='Information')
+    field_id = fields.One2many('ir.model.fields', 'model_id', string='Fields', required=True, copy=True)
+    inherited_model_ids = fields.Many2many('ir.model', compute='_inherited_models', string="Inherited models",
+                                           help="The list of models that extends the current model.")
+    state = fields.Selection([('manual', 'Custom Object'), ('base', 'Base Object')], string='Type', default='manual', readonly=True)
+    access_ids = fields.One2many('ir.model.access', 'model_id', string='Access')
+    transient = fields.Boolean(string="Transient Model")
+    modules = fields.Char(compute='_in_modules', string='In Apps', help='List of modules in which the object is defined or inherited')
+    view_ids = fields.One2many('ir.ui.view', compute='_view_ids', string='Views')
+
+    @api.depends('inherited_model_ids')
+    def _inherited_models(self):
+        for model in self:
+            inherited_models = [model_name for model_name in self.env[model.model]._inherits]
             if inherited_models:
-                res[model.id] = self.search(cr, uid, [('model', 'in', inherited_models)], context=context)
-        return res
-
-    _columns = {
-        'name': fields.char('Model Description', translate=True, required=True),
-        'model': fields.char('Model', required=True, select=1),
-        'info': fields.text('Information'),
-        'field_id': fields.one2many('ir.model.fields', 'model_id', 'Fields', required=True, copy=True),
-        'inherited_model_ids': fields.function(_inherited_models, type="many2many", obj="ir.model", string="Inherited models",
-            help="The list of models that extends the current model."),
-        'state': fields.selection([('manual','Custom Object'),('base','Base Object')],'Type', readonly=True),
-        'access_ids': fields.one2many('ir.model.access', 'model_id', 'Access'),
-        'transient': fields.boolean(string="Transient Model"),
-        'modules': fields.function(_in_modules, type='char', string='In Apps', help='List of modules in which the object is defined or inherited'),
-        'view_ids': fields.function(_view_ids, type='one2many', obj='ir.ui.view', string='Views'),
-    }
-
-    _defaults = {
-        'model': 'x_',
-        'state': 'manual',
-    }
-
-    def _check_model_name(self, cr, uid, ids, context=None):
-        for model in self.browse(cr, uid, ids, context=context):
-            if model.state=='manual':
+                model.inherited_model_ids = self.search([('model', 'in', inherited_models)])
+
+    @api.depends('modules')
+    def _in_modules(self):
+        #pseudo-method used by fields.function in ir.model/ir.model.fields
+        module = self.env['ir.module.module']
+        installed_module_ids = module.search([('state', '=', 'installed')])
+        installed_module_names = installed_module_ids.read(['name'])
+        installed_modules = set(x['name'] for x in installed_module_names)
+        xml_ids = models.Model._get_xml_ids(self)
+        for key, value in xml_ids.iteritems():
+            self.modules = ', '.join(sorted(installed_modules & set(xml_id.split('.')[0] for xml_id in value)))
+
+    @api.depends('view_ids')
+    def _view_ids(self):
+        for model in self:
+            model.view_ids = self.env['ir.ui.view'].search([('model', '=', model.model)])
+
+    @api.constrains('model')
+    def _check_model_name(self):
+        for model in self:
+            if model.state == 'manual':
                 if not model.model.startswith('x_'):
-                    return False
-            if not re.match('^[a-z_A-Z0-9.]+$',model.model):
-                return False
+                    return self._model_name_msg()
+            if not re.match('^[a-z_A-Z0-9.]+$', model.model):
+                return self._model_name_msg()
         return True
 
-    def _model_name_msg(self, cr, uid, ids, context=None):
+    def _model_name_msg(self):
         return _('The Object name must start with x_ and not contain any special character !')
 
-    _constraints = [
-        (_check_model_name, _model_name_msg, ['model']),
-    ]
     _sql_constraints = [
         ('obj_name_uniq', 'unique (model)', 'Each model must be unique!'),
     ]
 
     # overridden to allow searching both on model name (model field)
     # and model description (name field)
-    def _name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
+    @api.model
+    def _name_search(self, name='', args=None, operator='ilike', limit=100):
         if args is None:
             args = []
-        domain = args + ['|', ('model', operator, name), ('name', operator, name)]
-        return self.name_get(cr, name_get_uid or uid,
-                             super(ir_model, self).search(cr, uid, domain, limit=limit, context=context),
-                             context=context)
-
-    def _drop_table(self, cr, uid, ids, context=None):
-        for model in self.browse(cr, uid, ids, context):
-            model_pool = self.pool[model.model]
-            cr.execute('select relkind from pg_class where relname=%s', (model_pool._table,))
-            result = cr.fetchone()
+        domain = args + ['|', ('model', operator, self.name), ('name', operator, self.name)]
+        return super(IrModel, self).search(domain, limit=limit).name_get()
+
+    def _drop_table(self):
+        for model in self:
+            model_pool = self.env[model.model]
+            self.env.cr.execute('select relkind from pg_class where relname=%s', (model_pool._table,))
+            result = self.env.cr.fetchone()
             if result and result[0] == 'v':
-                cr.execute('DROP view %s' % (model_pool._table,))
+                self.env.cr.execute('DROP view %s' % (model_pool._table,))
             elif result and result[0] == 'r':
-                cr.execute('DROP TABLE %s CASCADE' % (model_pool._table,))
+                self.env.cr.execute('DROP TABLE %s CASCADE' % (model_pool._table,))
         return True
 
-    def unlink(self, cr, user, ids, context=None):
+    @api.multi
+    def unlink(self):
         # Prevent manual deletion of module tables
-        if context is None: context = {}
-        if isinstance(ids, (int, long)):
-            ids = [ids]
-        if not context.get(MODULE_UNINSTALL_FLAG):
-            for model in self.browse(cr, user, ids, context):
+        if not self.env.context.get(MODULE_UNINSTALL_FLAG):
+            for model in self:
                 if model.state != 'manual':
                     raise UserError(_("Model '%s' contains module data and cannot be removed!") % (model.name,))
 
-        self._drop_table(cr, user, ids, context)
-        res = super(ir_model, self).unlink(cr, user, ids, context)
-        if not context.get(MODULE_UNINSTALL_FLAG):
+        self._drop_table()
+        res = super(IrModel, self).unlink()
+        if not self.env.context.get(MODULE_UNINSTALL_FLAG):
             # only reload pool for normal unlink. For module uninstall the
-            # reload is done independently in openerp.modules.loading
-            cr.commit() # must be committed before reloading registry in new cursor
+            # reload is done independently in odoo.modules.loading
+            self.env.cr.commit()  # must be committed before reloading registry in new cursor
             api.Environment.reset()
-            RegistryManager.new(cr.dbname)
-            RegistryManager.signal_registry_change(cr.dbname)
+            RegistryManager.new(self.env.cr.dbname)
+            RegistryManager.signal_registry_change(self.env.cr.dbname)
 
         return res
 
-    def write(self, cr, user, ids, vals, context=None):
-        if context:
-            context = dict(context)
-            context.pop('__last_update', None)
+    @api.multi
+    def write(self, vals):
+        if self.env.context:
+            self.env.context = dict(self.env.context)
+            self.env.context.pop('__last_update', None)
         if 'model' in vals:
             raise UserError(_('Field "Model" cannot be modified on models.'))
         if 'state' in vals:
             raise UserError(_('Field "Type" cannot be modified on models.'))
         if 'transient' in vals:
             raise UserError(_('Field "Transient Model" cannot be modified on models.'))
-        # Filter out operations 4 link from field id, because openerp-web
+        # Filter out operations 4 link from field id, because odoo-web
         # always write (4,id,False) even for non dirty items
         if 'field_id' in vals:
             vals['field_id'] = [op for op in vals['field_id'] if op[0] != 4]
-        return super(ir_model,self).write(cr, user, ids, vals, context)
+        return super(IrModel, self).write(vals)
 
-    def create(self, cr, user, vals, context=None):
-        if  context is None:
-            context = {}
-        res = super(ir_model,self).create(cr, user, vals, context)
-        if vals.get('state','manual')=='manual':
+    @api.model
+    def create(self, vals):
+        res = super(IrModel, self).create(vals)
+        if vals.get('state', 'manual') == 'manual':
             # setup models; this automatically adds model in registry
-            self.pool.setup_models(cr, partial=(not self.pool.ready))
+            self.pool.setup_models(self.env.cr, partial=(not self.pool.ready))
             # update database schema
             model = self.pool[vals['model']]
-            init_models([model], cr, dict(context, update_custom_fields=True))
-            RegistryManager.signal_registry_change(cr.dbname)
+            init_models([model], self.env.cr, dict(self.env.context, update_custom_fields=True))
+            RegistryManager.signal_registry_change(self.env.cr.dbname)
         return res
 
     @api.model
@@ -208,89 +180,99 @@ class ir_model(osv.osv):
 
         CustomModel._build_model(self.pool, self._cr)
 
-class ir_model_fields(osv.osv):
+
+class IrModelFields(osv.osv):
     _name = 'ir.model.fields'
     _description = "Fields"
-    _rec_name = 'field_description'
-
-    _columns = {
-        'name': fields.char('Field Name', required=True, select=1),
-        'complete_name': fields.char('Complete Name', select=1),
-        'model': fields.char('Object Name', required=True, select=1,
-            help="The technical name of the model this field belongs to"),
-        'relation': fields.char('Object Relation',
-            help="For relationship fields, the technical name of the target model"),
-        'relation_field': fields.char('Relation Field',
-            help="For one2many fields, the field on the target model that implement the opposite many2one relationship"),
-        'model_id': fields.many2one('ir.model', 'Model', required=True, select=True, ondelete='cascade',
-            help="The model this field belongs to"),
-        'field_description': fields.char('Field Label', required=True, translate=True),
-        'help': fields.text('Field Help', translate=True),
-        'ttype': fields.selection(_get_fields_type, 'Field Type', required=True),
-        'selection': fields.char('Selection Options', help="List of options for a selection field, "
-            "specified as a Python expression defining a list of (key, label) pairs. "
-            "For example: [('blue','Blue'),('yellow','Yellow')]"),
-        'copy': fields.boolean('Copied', help="Whether the value is copied when duplicating a record."),
-        'related': fields.char('Related Field', help="The corresponding related field, if any. This must be a dot-separated list of field names."),
-        'required': fields.boolean('Required'),
-        'readonly': fields.boolean('Readonly'),
-        'index': fields.boolean('Indexed'),
-        'translate': fields.boolean('Translatable', help="Whether values for this field can be translated (enables the translation mechanism for that field)"),
-        'size': fields.integer('Size'),
-        'state': fields.selection([('manual','Custom Field'),('base','Base Field')],'Type', required=True, readonly=True, select=1),
-        'on_delete': fields.selection([('cascade', 'Cascade'), ('set null', 'Set NULL'), ('restrict', 'Restrict')],
-                                      'On Delete', help='On delete property for many2one fields'),
-        'domain': fields.char('Domain', help="The optional domain to restrict possible values for relationship fields, "
-            "specified as a Python expression defining a list of triplets. "
-            "For example: [('color','=','red')]"),
-        'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'),
-        'selectable': fields.boolean('Selectable'),
-        'modules': fields.function(_in_modules, type='char', string='In Apps', help='List of modules in which the field is defined'),
-        'serialization_field_id': fields.many2one('ir.model.fields', 'Serialization Field', domain = "[('ttype','=','serialized')]",
-                                                  ondelete='cascade', help="If set, this field will be stored in the sparse "
-                                                                           "structure of the serialization field, instead "
-                                                                           "of having its own database column. This cannot be "
-                                                                           "changed after creation."),
-        'relation_table': fields.char("Relation Table", help="Used for custom many2many fields to define a custom relation table name"),
-        'column1': fields.char("Column 1", help="Column referring to the record in the model table"),
-        'column2': fields.char("Column 2", help="Column referring to the record in the comodel table"),
-        'compute': fields.text("Compute", help="Code to compute the value of the field.\n"
-                        "Iterate on the recordset 'self' and assign the field's value:\n\n"
-                        "    for record in self:\n"
-                        "        record['size'] = len(record.name)\n\n"
-                        "Modules time, datetime, dateutil are available."),
-        'depends': fields.char("Dependencies", help="Dependencies of compute method; "
-                        "a list of comma-separated field names, like\n\n"
-                        "    name, partner_id.name"),
-        'store': fields.boolean('Stored', help="Whether the value is stored in the database."),
-    }
-    _rec_name='field_description'
-    _defaults = {
-        'selection': "",
-        'domain': "[]",
-        'name': 'x_',
-        'state': 'manual',
-        'on_delete': 'set null',
-        'field_description': '',
-        'selectable': 1,
-        'store': True,
-    }
     _order = "name"
+    _rec_name = 'field_description'
 
-    def _check_selection(self, cr, uid, selection, context=None):
+    @api.depends('ttype')
+    def _get_fields_type(self):
+        # Avoid too many nested `if`s below, as RedHat's Python 2.6
+        # break on it. See bug 939653.
+        return sorted([(k,k) for k,v in odoo.osv.fields.__dict__.iteritems()
+                      if type(v) == types.TypeType and \
+                         issubclass(v, odoo.osv.fields._column) and \
+                         v != odoo.osv.fields._column and \
+                         not v._deprecated and \
+                         not issubclass(v, odoo.osv.fields.function)])
+
+    name = fields.Char(string='Field Name', default='x_', required=True, index=True)
+    complete_name = fields.Char(index=True)
+    model = fields.Char(string='Object Name', required=True, index=True,
+                        help="The technical name of the model this field belongs to")
+    relation = fields.Char(string='Object Relation',
+                           help="For relationship fields, the technical name of the target model")
+    relation_field = fields.Char(help="For one2many fields, the field on the target model that implement the opposite many2one relationship")
+    model_id = fields.Many2one('ir.model', string='Model', required=True, index=True, ondelete='cascade',
+                               help="The model this field belongs to")
+    field_description = fields.Char(string='Field Label', default='', required=True, translate=True)
+    help = fields.Text(string='Field Help', translate=True)
+    ttype = fields.Selection(selection='_get_fields_type', string='Field Type', required=True)
+    selection = fields.Char(string='Selection Options', default="",
+                            help="List of options for a selection field, "
+                                 "specified as a Python expression defining a list of (key, label) pairs. "
+                                 "For example: [('blue','Blue'),('yellow','Yellow')]")
+    copy = fields.Boolean(string='Copied', help="Whether the value is copied when duplicating a record.")
+    related = fields.Char(string='Related Field', help="The corresponding related field, if any. This must be a dot-separated list of field names.")
+    required = fields.Boolean()
+    readonly = fields.Boolean()
+    index = fields.Boolean(string='Indexed')
+    translate = fields.Boolean(string='Translatable', help="Whether values for this field can be translated (enables the translation mechanism for that field)")
+    size = fields.Integer()
+    state = fields.Selection([('manual', 'Custom Field'), ('base', 'Base Field')], string='Type', default='manual', required=True, readonly=True, index=True)
+    on_delete = fields.Selection([('cascade', 'Cascade'), ('set null', 'Set NULL'), ('restrict', 'Restrict')],
+                                 string='On Delete', default='set null', help='On delete property for many2one fields')
+    domain = fields.Char(default="[]", help="The optional domain to restrict possible values for relationship fields, "
+                                            "specified as a Python expression defining a list of triplets. "
+                                            "For example: [('color','=','red')]")
+    groups = fields.Many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id')
+    selectable = fields.Boolean(default=True)
+    modules = fields.Char(compute='_in_modules', string='In Apps', help='List of modules in which the field is defined')
+    serialization_field_id = fields.Many2one('ir.model.fields', 'Serialization Field', domain="[('ttype','=','serialized')]",
+                                             ondelete='cascade', help="If set, this field will be stored in the sparse "
+                                                                      "structure of the serialization field, instead "
+                                                                      "of having its own database column. This cannot be "
+                                                                      "changed after creation.")
+    relation_table = fields.Char(help="Used for custom many2many fields to define a custom relation table name")
+    column1 = fields.Char(string='Column 1', help="Column referring to the record in the model table")
+    column2 = fields.Char(string="Column 2", help="Column referring to the record in the comodel table")
+    compute = fields.Text(help="Code to compute the value of the field.\n"
+                               "Iterate on the recordset 'self' and assign the field's value:\n\n"
+                               "    for record in self:\n"
+                               "        record['size'] = len(record.name)\n\n"
+                               "Modules time, datetime, dateutil are available.")
+    depends = fields.Char(string='Dependencies', help="Dependencies of compute method; "
+                                                      "a list of comma-separated field names, like\n\n"
+                                                      "    name, partner_id.name")
+    store = fields.Boolean(string='Stored', default=True, help="Whether the value is stored in the database.")
+
+    @api.depends('modules')
+    def _in_modules(self):
+        #pseudo-method used by fields.function in ir.model/ir.model.fields
+        module = self.env['ir.module.module']
+        installed_module_ids = module.search([('state', '=', 'installed')])
+        installed_module_names = installed_module_ids.read(['name'])
+        installed_modules = set(x['name'] for x in installed_module_names)
+        xml_ids = models.Model._get_xml_ids(self)
+        for key, value in xml_ids.iteritems():
+            self.modules = ', '.join(sorted(installed_modules & set(xml_id.split('.')[0] for xml_id in value)))
+
+    def _check_selection(self, selection):
         try:
             selection_list = eval(selection)
         except Exception:
             _logger.info('Invalid selection list definition for fields.selection', exc_info=True)
             raise UserError(_("The Selection Options expression is not a valid Pythonic expression."
-                                "Please provide an expression in the [('key','Label'), ...] format."))
+                              "Please provide an expression in the [('key','Label'), ...] format."))
 
         check = True
         if not (isinstance(selection_list, list) and selection_list):
             check = False
         else:
             for item in selection_list:
-                if not (isinstance(item, (tuple,list)) and len(item) == 2):
+                if not (isinstance(item, (tuple, list)) and len(item) == 2):
                     check = False
                     break
 
@@ -301,9 +283,7 @@ class ir_model_fields(osv.osv):
     def _size_gt_zero_msg(self, cr, user, ids, context=None):
         return _('Size of the field can never be less than 0 !')
 
-    _sql_constraints = [
-        ('size_gt_zero', 'CHECK (size>=0)',_size_gt_zero_msg ),
-    ]
+    _sql_constraints = [('size_gt_zero', 'CHECK (size>=0)', _size_gt_zero_msg)]
 
     def _related_field(self):
         """ Return the ``Field`` instance corresponding to ``self.related``. """
@@ -388,103 +368,97 @@ class ir_model_fields(osv.osv):
                         self.column1 = other.column2
                         self.column2 = other.column1
                         return
-                return {'warning':{
+                return {'warning': {
                     'title': _("Warning"),
                     'message': _("The table %r if used for other, possibly incompatible fields.") % self.relation_table,
                 }}
 
-    def _drop_column(self, cr, uid, ids, context=None):
+    @api.multi
+    def _drop_column(self):
         tables_to_drop = set()
 
-        for field in self.browse(cr, uid, ids, context):
+        for field in self:
             if field.name in MAGIC_COLUMNS:
                 continue
             model = self.pool[field.model]
-            cr.execute('SELECT relkind FROM pg_class WHERE relname=%s', (model._table,))
-            result = cr.fetchone()
-            cr.execute("""SELECT column_name FROM information_schema.columns
-                          WHERE table_name=%s AND column_name=%s""",
-                       (model._table, field.name))
-            column_name = cr.fetchone()
+            self.env.cr.execute('SELECT relkind FROM pg_class WHERE relname=%s', (model._table,))
+            result = self.env.cr.fetchone()
+            self.env.cr.execute("""SELECT column_name FROM information_schema.columns
+                                   WHERE table_name=%s AND column_name=%s""", (model._table, field.name))
+            column_name = self.env.cr.fetchone()
             if column_name and (result and result[0] == 'r'):
-                cr.execute('ALTER table "%s" DROP column "%s" cascade' % (model._table, field.name))
+                self.env.cr.execute('ALTER table "%s" DROP column "%s" cascade' % (model._table, field.name))
             if field.state == 'manual' and field.ttype == 'many2many':
                 rel_name = field.relation_table or model._fields[field.name].relation
                 tables_to_drop.add(rel_name)
-            model._pop_field(cr, uid, field.name, context=context)
+            model._pop_field(self.env.cr, self.env.uid, field.name, context=self.env.context)
 
         if tables_to_drop:
             # drop the relation tables that are not used by other fields
-            cr.execute("""SELECT relation_table FROM ir_model_fields
-                          WHERE relation_table IN %s AND id NOT IN %s""",
-                       (tuple(tables_to_drop), tuple(ids)))
-            tables_to_keep = set(row[0] for row in cr.fetchall())
+            self.env.cr.execute("""SELECT relation_table FROM ir_model_fields
+                                   WHERE relation_table IN %s AND id NOT IN %s""", (tuple(tables_to_drop), tuple(self.ids)))
+            tables_to_keep = set(row[0] for row in self.env.cr.fetchall())
             for rel_name in tables_to_drop - tables_to_keep:
-                cr.execute('DROP TABLE "%s"' % rel_name)
+                self.env.cr.execute('DROP TABLE "%s"' % rel_name)
 
         return True
 
-    def unlink(self, cr, user, ids, context=None):
+    @api.multi
+    def unlink(self):
         # Prevent manual deletion of module columns
-        if context is None: context = {}
-        if isinstance(ids, (int, long)):
-            ids = [ids]
-        if not context.get(MODULE_UNINSTALL_FLAG) and \
-                any(field.state != 'manual' for field in self.browse(cr, user, ids, context)):
+        if not self.env.context.get(MODULE_UNINSTALL_FLAG) and \
+                any(field.state != 'manual' for field in self):
             raise UserError(_("This column contains module data and cannot be removed!"))
 
-        self._drop_column(cr, user, ids, context)
-        res = super(ir_model_fields, self).unlink(cr, user, ids, context)
-        if not context.get(MODULE_UNINSTALL_FLAG):
+        self._drop_column()
+        res = super(IrModelFields, self).unlink()
+        if not self.env.context.get(MODULE_UNINSTALL_FLAG):
             # The field we just deleted might be inherited, and the registry is
             # inconsistent in this case; therefore we reload the registry.
-            cr.commit()
+            self.env.cr.commit()
             api.Environment.reset()
-            RegistryManager.new(cr.dbname)
-            RegistryManager.signal_registry_change(cr.dbname)
+            RegistryManager.new(self.env.cr.dbname)
+            RegistryManager.signal_registry_change(self.env.cr.dbname)
         return res
 
-    def create(self, cr, user, vals, context=None):
+    @api.model
+    def create(self, vals):
         if 'model_id' in vals:
-            model_data = self.pool['ir.model'].browse(cr, user, vals['model_id'])
+            model_data = self.env['ir.model'].browse(vals['model_id'])
             vals['model'] = model_data.model
-        if context is None:
-            context = {}
         if vals.get('ttype', False) == 'selection':
-            if not vals.get('selection',False):
+            if not vals.get('selection', False):
                 raise UserError(_('For selection fields, the Selection Options must be given!'))
-            self._check_selection(cr, user, vals['selection'], context=context)
-        res = super(ir_model_fields,self).create(cr, user, vals, context)
-        if vals.get('state','manual') == 'manual':
+            self._check_selection(vals['selection'])
+        res = super(IrModelFields, self).create(vals)
+        if vals.get('state', 'manual') == 'manual':
             if not vals['name'].startswith('x_'):
                 raise UserError(_("Custom fields must have a name that starts with 'x_' !"))
 
-            if vals.get('relation',False) and not self.pool['ir.model'].search(cr, user, [('model','=',vals['relation'])]):
+            if vals.get('relation', False) and not self.env['ir.model'].search([('model', '=', vals['relation'])]):
                 raise UserError(_("Model %s does not exist!") % vals['relation'])
 
             if vals.get('ttype', False) == 'one2many':
-                if not self.search(cr, user, [('model_id','=',vals['relation']), ('name','=',vals['relation_field']), ('ttype','=','many2one')]):
+                if not self.search([('model_id', '=', vals['relation']), ('name', '=', vals['relation_field']), ('ttype', '=', 'many2one')]):
                     raise UserError(_("Many2one %s on model %s does not exist!") % (vals['relation_field'], vals['relation']))
 
             self.pool.clear_manual_fields()
 
             if vals['model'] in self.pool:
                 # setup models; this re-initializes model in registry
-                self.pool.setup_models(cr, partial=(not self.pool.ready))
+                self.pool.setup_models(self.env.cr, partial=(not self.pool.ready))
                 # update database schema
                 model = self.pool[vals['model']]
-                init_models([model], cr, dict(context, update_custom_fields=True))
-                RegistryManager.signal_registry_change(cr.dbname)
+                init_models([model], self.env.cr, dict(self.env.context, update_custom_fields=True))
+                RegistryManager.signal_registry_change(self.env.cr.dbname)
 
         return res
 
-    def write(self, cr, user, ids, vals, context=None):
-        if context is None:
-            context = {}
-
+    @api.multi
+    def write(self, vals):
         #For the moment renaming a sparse field or changing the storing system is not allowed. This may be done later
         if 'serialization_field_id' in vals or 'name' in vals:
-            for field in self.browse(cr, user, ids, context=context):
+            for field in self:
                 if 'serialization_field_id' in vals and field.serialization_field_id.id != vals['serialization_field_id']:
                     raise UserError(_('Changing the storing system for field "%s" is not allowed.') % field.name)
                 if field.serialization_field_id and (field.name != vals['name']):
@@ -496,16 +470,16 @@ class ir_model_fields(osv.osv):
         # names of the models to patch
         patched_models = set()
 
-        if vals and ids:
+        if vals and self.ids:
             # check selection if given
             if vals.get('selection'):
-                self._check_selection(cr, user, vals['selection'], context=context)
+                self._check_selection(vals['selection'])
 
-            for item in self.browse(cr, user, ids, context=context):
+            for item in self:
                 if item.state != 'manual':
                     raise UserError(_('Properties of base fields cannot be altered in this manner! '
-                                        'Please modify them through Python code, '
-                                        'preferably through a custom addon!'))
+                                      'Please modify them through Python code, '
+                                      'preferably through a custom addon!'))
 
                 if vals.get('model_id', item.model_id.id) != item.model_id.id:
                     raise UserError(_("Changing the model of a field is forbidden!"))
@@ -539,180 +513,174 @@ class ir_model_fields(osv.osv):
             if column_name in vals:
                 del vals[column_name]
 
-        res = super(ir_model_fields,self).write(cr, user, ids, vals, context=context)
+        res = super(IrModelFields, self).write(vals)
 
         self.pool.clear_manual_fields()
 
         if column_rename:
             # rename column in database, and its corresponding index if present
             table, oldname, newname, index = column_rename
-            cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % (table, oldname, newname))
+            self.env.cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % (table, oldname, newname))
             if index:
-                cr.execute('ALTER INDEX "%s_%s_index" RENAME TO "%s_%s_index"' % (table, oldname, table, newname))
+                self.env.cr.execute('ALTER INDEX "%s_%s_index" RENAME TO "%s_%s_index"' % (table, oldname, table, newname))
 
         if column_rename or patched_models:
             # setup models, this will reload all manual fields in registry
-            self.pool.setup_models(cr, partial=(not self.pool.ready))
+            self.pool.setup_models(self.env.cr, partial=(not self.pool.ready))
 
         if patched_models:
             # update the database schema of the models to patch
             models = [self.pool[name] for name in patched_models]
-            init_models(models, cr, dict(context, update_custom_fields=True))
+            init_models(models, self.env.cr, dict(self.env.context, update_custom_fields=True))
 
         if column_rename or patched_models:
-            RegistryManager.signal_registry_change(cr.dbname)
+            RegistryManager.signal_registry_change(self.env.cr.dbname)
 
         return res
 
-class ir_model_constraint(Model):
+
+class IrModelConstraint(models.Model):
     """
-    This model tracks PostgreSQL foreign keys and constraints used by OpenERP
+    This model tracks PostgreSQL foreign keys and constraints used by Odoo
     models.
     """
     _name = 'ir.model.constraint'
-    _columns = {
-        'name': fields.char('Constraint', required=True, select=1,
-            help="PostgreSQL constraint or foreign key name."),
-        'definition': fields.char('Definition', help="PostgreSQL constraint definition"),
-        'model': fields.many2one('ir.model', string='Model',
-            required=True, select=1),
-        'module': fields.many2one('ir.module.module', string='Module',
-            required=True, select=1),
-        'type': fields.char('Constraint Type', required=True, size=1, select=1,
-            help="Type of the constraint: `f` for a foreign key, "
-                "`u` for other constraints."),
-        'date_update': fields.datetime('Update Date'),
-        'date_init': fields.datetime('Initialization Date')
-    }
+
+    name = fields.Char(string='Constraint', required=True, index=True,
+                       help="PostgreSQL constraint or foreign key name.")
+    definition = fields.Char(help="PostgreSQL constraint definition")
+    model = fields.Many2one('ir.model', required=True, index=True)
+    module = fields.Many2one('ir.module.module', required=True, index=True)
+    type = fields.Char(string='Constraint Type', required=True, size=1, index=True,
+                       help="Type of the constraint: `f` for a foreign key, "
+                            "`u` for other constraints.")
+    date_update = fields.Datetime(string='Update Date')
+    date_init = fields.Datetime(string='Initialization Date')
 
     _sql_constraints = [
         ('module_name_uniq', 'unique(name, module)',
             'Constraints with the same name are unique per module.'),
     ]
 
-    def _module_data_uninstall(self, cr, uid, ids, context=None):
+    @api.multi
+    def _module_data_uninstall(self):
         """
         Delete PostgreSQL foreign keys and constraints tracked by this model.
-        """ 
+        """
 
-        if uid != SUPERUSER_ID and not self.pool['ir.model.access'].check_groups(cr, uid, "base.group_system"):
+        if self.env.uid != SUPERUSER_ID and not self.env['ir.model.access'].check_groups("base.group_system"):
             raise AccessError(_('Administrator access is required to uninstall a module'))
 
-        context = dict(context or {})
-
-        ids_set = set(ids)
-        ids.sort()
-        ids.reverse()
-        for data in self.browse(cr, uid, ids, context):
+        ids_set = set(self.ids)
+        self.ids.sort()
+        self.ids.reverse()
+        for data in self:
             model = data.model.model
-            model_obj = self.pool[model]
-            name = openerp.tools.ustr(data.name)
+            model_obj = self.env[model]
+            name = tools.ustr(data.name)
             typ = data.type
 
             # double-check we are really going to delete all the owners of this schema element
-            cr.execute("""SELECT id from ir_model_constraint where name=%s""", (data.name,))
-            external_ids = [x[0] for x in cr.fetchall()]
+            self.env.cr.execute("""SELECT id from ir_model_constraint where name=%s""", (data.name,))
+            external_ids = [x[0] for x in self.env.cr.fetchall()]
             if set(external_ids)-ids_set:
                 # as installed modules have defined this element we must not delete it!
                 continue
 
             if typ == 'f':
                 # test if FK exists on this table (it could be on a related m2m table, in which case we ignore it)
-                cr.execute("""SELECT 1 from pg_constraint cs JOIN pg_class cl ON (cs.conrelid = cl.oid)
+                self.env.cr.execute("""SELECT 1 from pg_constraint cs JOIN pg_class cl ON (cs.conrelid = cl.oid)
                               WHERE cs.contype=%s and cs.conname=%s and cl.relname=%s""", ('f', name, model_obj._table))
-                if cr.fetchone():
-                    cr.execute('ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (model_obj._table, name),)
+                if self.env.cr.fetchone():
+                    self.env.cr.execute('ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (model_obj._table, name),)
                     _logger.info('Dropped FK CONSTRAINT %s@%s', name, model)
 
             if typ == 'u':
                 # test if constraint exists
-                cr.execute("""SELECT 1 from pg_constraint cs JOIN pg_class cl ON (cs.conrelid = cl.oid)
+                self.env.cr.execute("""SELECT 1 from pg_constraint cs JOIN pg_class cl ON (cs.conrelid = cl.oid)
                               WHERE cs.contype=%s and cs.conname=%s and cl.relname=%s""", ('u', name, model_obj._table))
-                if cr.fetchone():
-                    cr.execute('ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (model_obj._table, name),)
+                if self.env.cr.fetchone():
+                    self.env.cr.execute('ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (model_obj._table, name),)
                     _logger.info('Dropped CONSTRAINT %s@%s', name, model)
 
-        self.unlink(cr, uid, ids, context)
+        self.unlink()
+
 
-class ir_model_relation(Model):
+class IrModelRelation(models.Model):
     """
-    This model tracks PostgreSQL tables used to implement OpenERP many2many
+    This model tracks PostgreSQL tables used to implement Odoo many2many
     relations.
     """
     _name = 'ir.model.relation'
-    _columns = {
-        'name': fields.char('Relation Name', required=True, select=1,
-            help="PostgreSQL table name implementing a many2many relation."),
-        'model': fields.many2one('ir.model', string='Model',
-            required=True, select=1),
-        'module': fields.many2one('ir.module.module', string='Module',
-            required=True, select=1),
-        'date_update': fields.datetime('Update Date'),
-        'date_init': fields.datetime('Initialization Date')
-    }
-
-    def _module_data_uninstall(self, cr, uid, ids, context=None):
+
+    name = fields.Char(string='Relation Name', required=True, index=True,
+                       help="PostgreSQL table name implementing a many2many relation.")
+    model = fields.Many2one('ir.model', required=True, index=True)
+    module = fields.Many2one('ir.module.module', required=True, index=True)
+    date_update = fields.Datetime(string='Update Date')
+    date_init = fields.Datetime(string='Initialization Date')
+
+    @api.multi
+    def _module_data_uninstall(self):
         """
         Delete PostgreSQL many2many relations tracked by this model.
         """ 
 
-        if uid != SUPERUSER_ID and not self.pool['ir.model.access'].check_groups(cr, uid, "base.group_system"):
+        if self.env.uid != SUPERUSER_ID and not self.env['ir.model.access'].check_groups("base.group_system"):
             raise AccessError(_('Administrator access is required to uninstall a module'))
 
-        ids_set = set(ids)
+        ids_set = set(self.ids)
         to_drop_table = []
-        ids.sort()
-        ids.reverse()
-        for data in self.browse(cr, uid, ids, context):
-            model = data.model
-            name = openerp.tools.ustr(data.name)
+        self.ids.sort()
+        self.ids.reverse()
+        for data in self:
+            name = tools.ustr(data.name)
 
             # double-check we are really going to delete all the owners of this schema element
-            cr.execute("""SELECT id from ir_model_relation where name = %s""", (data.name,))
-            external_ids = [x[0] for x in cr.fetchall()]
+            self.env.cr.execute("""SELECT id from ir_model_relation where name = %s""", (data.name,))
+            external_ids = [x[0] for x in self.env.cr.fetchall()]
             if set(external_ids)-ids_set:
                 # as installed modules have defined this element we must not delete it!
                 continue
 
-            cr.execute("SELECT 1 FROM information_schema.tables WHERE table_name=%s", (name,))
-            if cr.fetchone() and not name in to_drop_table:
+            self.env.cr.execute("SELECT 1 FROM information_schema.tables WHERE table_name=%s", (name,))
+            if self.env.cr.fetchone() and not name in to_drop_table:
                 to_drop_table.append(name)
 
-        self.unlink(cr, uid, ids, context)
+        self.unlink()
 
         # drop m2m relation tables
         for table in to_drop_table:
-            cr.execute('DROP TABLE %s CASCADE'% table,)
+            self.env.cr.execute('DROP TABLE %s CASCADE' % table,)
             _logger.info('Dropped table %s', table)
 
-        cr.commit()
+        self.env.cr.commit()
+
 
-class ir_model_access(osv.osv):
+class IrModelAccess(models.Model):
     _name = 'ir.model.access'
-    _columns = {
-        'name': fields.char('Name', required=True, select=True),
-        'active': fields.boolean('Active', help='If you uncheck the active field, it will disable the ACL without deleting it (if you delete a native ACL, it will be re-created when you reload the module).'),
-        'model_id': fields.many2one('ir.model', 'Object', required=True, domain=[('transient','=', False)], select=True, ondelete='cascade'),
-        'group_id': fields.many2one('res.groups', 'Group', ondelete='cascade', select=True),
-        'perm_read': fields.boolean('Read Access'),
-        'perm_write': fields.boolean('Write Access'),
-        'perm_create': fields.boolean('Create Access'),
-        'perm_unlink': fields.boolean('Delete Access'),
-    }
-    _defaults = {
-        'active': True,
-    }
-
-    def check_groups(self, cr, uid, group):
-        grouparr  = group.split('.')
+
+    name = fields.Char(required=True, index=True)
+    active = fields.Boolean(default=True, help='If you uncheck the active field, it will disable the ACL without deleting it (if you delete a native ACL, it will be re-created when you reload the module).')
+    model_id = fields.Many2one('ir.model', string='Object', required=True, domain=[('transient', '=', False)], index=True, ondelete='cascade')
+    group_id = fields.Many2one('res.groups', string='Group', ondelete='cascade', index=True)
+    perm_read = fields.Boolean(string='Read Access')
+    perm_write = fields.Boolean(string='Write Access')
+    perm_create = fields.Boolean(string='Create Access')
+    perm_unlink = fields.Boolean(string='Delete Access')
+
+    @api.model
+    def check_groups(self, group):
+        grouparr = group.split('.')
         if not grouparr:
             return False
-        cr.execute("select 1 from res_groups_users_rel where uid=%s and gid IN (select res_id from ir_model_data where module=%s and name=%s)", (uid, grouparr[0], grouparr[1],))
-        return bool(cr.fetchone())
+        self.env.cr.execute("select 1 from res_groups_users_rel where uid=%s and gid IN (select res_id from ir_model_data where module=%s and name=%s)", (self.env.uid, grouparr[0], grouparr[1],))
+        return bool(self.env.cr.fetchone())
 
-    def check_group(self, cr, uid, model, mode, group_ids):
+    @api.model
+    def check_group(self, model, mode, group_ids):
         """ Check if a specific group has the access mode to the specified model"""
-        assert mode in ['read','write','create','unlink'], 'Invalid access mode'
+        assert mode in ['read', 'write', 'create', 'unlink'], 'Invalid access mode'
 
         if isinstance(model, BaseModel):
             assert model._name == 'ir.model', 'Invalid model object'
@@ -723,21 +691,21 @@ class ir_model_access(osv.osv):
         if isinstance(group_ids, (int, long)):
             group_ids = [group_ids]
         for group_id in group_ids:
-            cr.execute("SELECT perm_" + mode + " "
-                   "  FROM ir_model_access a "
-                   "  JOIN ir_model m ON (m.id = a.model_id) "
-                   " WHERE m.model = %s AND a.active IS True "
-                   " AND a.group_id = %s", (model_name, group_id)
-                   )
-            r = cr.fetchone()
+            self.env.cr.execute("SELECT perm_" + mode + " "
+                                "  FROM ir_model_access a "
+                                "  JOIN ir_model m ON (m.id = a.model_id) "
+                                " WHERE m.model = %s AND a.active IS True "
+                                " AND a.group_id = %s", (model_name, group_id)
+                                )
+            r = self.env.cr.fetchone()
             if r is None:
-                cr.execute("SELECT perm_" + mode + " "
-                       "  FROM ir_model_access a "
-                       "  JOIN ir_model m ON (m.id = a.model_id) "
-                       " WHERE m.model = %s AND a.active IS True "
-                       " AND a.group_id IS NULL", (model_name, )
-                       )
-                r = cr.fetchone()
+                self.env.cr.execute("SELECT perm_" + mode + " "
+                                    "  FROM ir_model_access a "
+                                    "  JOIN ir_model m ON (m.id = a.model_id) "
+                                    " WHERE m.model = %s AND a.active IS True "
+                                    " AND a.group_id IS NULL", (model_name, )
+                                    )
+                r = self.env.cr.fetchone()
 
             access = bool(r and r[0])
             if access:
@@ -745,13 +713,14 @@ class ir_model_access(osv.osv):
         # pass no groups -> no access
         return False
 
-    def group_names_with_access(self, cr, model_name, access_mode):
+    @api.model
+    def group_names_with_access(self, model_name, access_mode):
         """Returns the names of visible groups which have been granted ``access_mode`` on
            the model ``model_name``.
            :rtype: list
         """
-        assert access_mode in ['read','write','create','unlink'], 'Invalid access mode: %s' % access_mode
-        cr.execute('''SELECT
+        assert access_mode in ['read', 'write', 'create', 'unlink'], 'Invalid access mode: %s' % access_mode
+        self.env.cr.execute('''SELECT
                         c.name, g.name
                       FROM
                         ir_model_access a
@@ -762,20 +731,21 @@ class ir_model_access(osv.osv):
                         m.model=%s AND
                         a.active IS True AND
                         a.perm_''' + access_mode, (model_name,))
-        return [('%s/%s' % x) if x[0] else x[1] for x in cr.fetchall()]
+        return [('%s/%s' % x) if x[0] else x[1] for x in self.env.cr.fetchall()]
 
     # The context parameter is useful when the method translates error messages.
     # But as the method raises an exception in that case,  the key 'lang' might
     # not be really necessary as a cache key, unless the `ormcache_context`
     # decorator catches the exception (it does not at the moment.)
-    @tools.ormcache_context('uid', 'model', 'mode', 'raise_exception', keys=('lang',))
-    def check(self, cr, uid, model, mode='read', raise_exception=True, context=None):
-        if uid==1:
+    @api.model
+    @tools.ormcache_context('self.env.uid', 'model', 'mode', 'raise_exception', keys=('lang',))
+    def check(self, model, mode='read', raise_exception=True):
+        if self.env.uid == 1:
             # User root have all accesses
             # TODO: exclude xml-rpc requests
             return True
 
-        assert mode in ['read','write','create','unlink'], 'Invalid access mode'
+        assert mode in ['read', 'write', 'create', 'unlink'], 'Invalid access mode'
 
         if isinstance(model, BaseModel):
             assert model._name == 'ir.model', 'Invalid model object'
@@ -784,37 +754,33 @@ class ir_model_access(osv.osv):
             model_name = model
 
         # TransientModel records have no access rights, only an implicit access rule
-        if model_name not in self.pool:
+        if model_name not in self.env:
             _logger.error('Missing model %s' % (model_name, ))
         elif self.pool[model_name].is_transient():
             return True
 
         # We check if a specific rule exists
-        cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
-                   '  FROM ir_model_access a '
-                   '  JOIN ir_model m ON (m.id = a.model_id) '
-                   '  JOIN res_groups_users_rel gu ON (gu.gid = a.group_id) '
-                   ' WHERE m.model = %s '
-                   '   AND gu.uid = %s '
-                   '   AND a.active IS True '
-                   , (model_name, uid,)
-                   )
-        r = cr.fetchone()[0]
+        self.env.cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
+                            '  FROM ir_model_access a '
+                            '  JOIN ir_model m ON (m.id = a.model_id) '
+                            '  JOIN res_groups_users_rel gu ON (gu.gid = a.group_id) '
+                            ' WHERE m.model = %s '
+                            '   AND gu.uid = %s '
+                            '   AND a.active IS True ', (model_name, self.env.uid,))
+        r = self.env.cr.fetchone()[0]
 
         if r is None:
             # there is no specific rule. We check the generic rule
-            cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
-                       '  FROM ir_model_access a '
-                       '  JOIN ir_model m ON (m.id = a.model_id) '
-                       ' WHERE a.group_id IS NULL '
-                       '   AND m.model = %s '
-                       '   AND a.active IS True '
-                       , (model_name,)
-                       )
-            r = cr.fetchone()[0]
+            self.env.cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
+                                '  FROM ir_model_access a '
+                                '  JOIN ir_model m ON (m.id = a.model_id) '
+                                ' WHERE a.group_id IS NULL '
+                                '   AND m.model = %s '
+                                '   AND a.active IS True ', (model_name,))
+            r = self.env.cr.fetchone()[0]
 
         if not r and raise_exception:
-            groups = '\n\t'.join('- %s' % g for g in self.group_names_with_access(cr, model_name, mode))
+            groups = '\n\t'.join('- %s' % g for g in self.group_names_with_access(model_name, mode))
             msg_heads = {
                 # Messages are declared in extenso so they are properly exported in translation terms
                 'read': _("Sorry, you are not allowed to access this document."),
@@ -828,9 +794,9 @@ class ir_model_access(osv.osv):
             else:
                 msg_tail = _("Please contact your system administrator if you think this is an error.") + "\n\n(" + _("Document model") + ": %s)"
                 msg_params = (model_name,)
-            _logger.info('Access Denied by ACLs for operation: %s, uid: %s, model: %s', mode, uid, model_name)
+            _logger.info('Access Denied by ACLs for operation: %s, uid: %s, model: %s', mode, self.env.uid, model_name)
             msg = '%s %s' % (msg_heads[mode], msg_tail)
-            raise openerp.exceptions.AccessError(msg % msg_params)
+            raise odoo.exceptions.AccessError(msg % msg_params)
         return bool(r)
 
     __cache_clearing_methods = []
@@ -855,96 +821,89 @@ class ir_model_access(osv.osv):
     #
     # Check rights on actions
     #
-    def write(self, cr, uid, ids, values, context=None):
-        self.call_cache_clearing_methods(cr)
-        res = super(ir_model_access, self).write(cr, uid, ids, values, context=context)
-        return res
+    @api.multi
+    def write(self, values):
+        self.call_cache_clearing_methods()
+        return super(IrModelAccess, self).write(values)
 
-    def create(self, cr, uid, values, context=None):
-        self.call_cache_clearing_methods(cr)
-        res = super(ir_model_access, self).create(cr, uid, values, context=context)
-        return res
+    @api.model
+    def create(self, values):
+        self.call_cache_clearing_methods()
+        return super(IrModelAccess, self).create(values)
+
+    @api.multi
+    def unlink(self):
+        self.call_cache_clearing_methods()
+        return super(IrModelAccess, self).unlink()
 
-    def unlink(self, cr, uid, ids, context=None):
-        self.call_cache_clearing_methods(cr)
-        res = super(ir_model_access, self).unlink(cr, uid, ids, context=context)
-        return res
 
-class ir_model_data(osv.osv):
+class IrModelData(models.Model):
     """Holds external identifier keys for records in the database.
        This has two main uses:
 
            * allows easy data integration with third-party systems,
              making import/export/sync of data possible, as records
              can be uniquely identified across multiple systems
-           * allows tracking the origin of data installed by OpenERP
+           * allows tracking the origin of data installed by Odoo
              modules themselves, thus making it possible to later
              update them seamlessly.
     """
     _name = 'ir.model.data'
-    _order = 'module,model,name'
+    _order = 'module, model, name'
+
+    name = fields.Char(string='External Identifier', required=True,
+                       help="External Key/Identifier that can be used for "
+                            "data integration with third-party systems")
+    complete_name = fields.Char(compute='_complete_name_get', string='Complete ID')
+    model = fields.Char(string='Model Name', required=True)
+    module = fields.Char(default='', required=True)
+    res_id = fields.Integer(string='Record ID', help="ID of the target record in the database")
+    noupdate = fields.Boolean(string='Non Updatable', default=False)
+    date_update = fields.Datetime(string='Update Date', default=fields.Datetime.now)
+    date_init = fields.Datetime(string='Init Date', default=fields.Datetime.now)
+
+    @api.depends('complete_name')
+    def _complete_name_get(self):
+        for res in self:
+            res.complete_name = (res.module and (res.module + '.') or '') + res.name
 
-    def name_get(self, cr, uid, ids, context=None):
+    def __init__(self, pool, cr):
+        models.Model.__init__(self, pool, cr)
+        # also stored in pool to avoid being discarded along with this osv instance
+        if getattr(pool, 'model_data_reference_ids', None) is None:
+            self.pool.model_data_reference_ids = {}
+        # put loads on the class, in order to share it among all instances
+        type(self).loads = self.pool.model_data_reference_ids
+
+    def _auto_init(self):
+        super(IrModelData, self)._auto_init()
+        self.env.cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_model_data_module_name_uniq_index'")
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE UNIQUE INDEX ir_model_data_module_name_uniq_index ON ir_model_data (module, name)')
+        self.env.cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_model_data_model_res_id_index'")
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE INDEX ir_model_data_model_res_id_index ON ir_model_data (model, res_id)')
+
+    @api.multi
+    def name_get(self):
         bymodel = defaultdict(dict)
         names = {}
 
-        for res in self.browse(cr, uid, ids, context=context):
+        for res in self:
             bymodel[res.model][res.res_id] = res
             names[res.id] = res.complete_name
             #result[res.model][res.res_id] = res.id
 
         for model, id_map in bymodel.iteritems():
             try:
-                ng = dict(self.pool[model].name_get(cr, uid, id_map.keys(), context=context))
+                ng = dict(self.env[model].name_get(id_map.keys()))
             except Exception:
                 pass
             else:
                 for r in id_map.itervalues():
                     names[r.id] = ng.get(r.res_id, r.complete_name)
 
-        return [(i, names[i]) for i in ids]
-
-    def _complete_name_get(self, cr, uid, ids, prop, unknow_none, context=None):
-        result = {}
-        for res in self.browse(cr, uid, ids, context=context):
-            result[res.id] = (res.module and (res.module + '.') or '')+res.name
-        return result
-
-    _columns = {
-        'name': fields.char('External Identifier', required=True,
-                            help="External Key/Identifier that can be used for "
-                                 "data integration with third-party systems"),
-        'complete_name': fields.function(_complete_name_get, type='char', string='Complete ID'),
-        'model': fields.char('Model Name', required=True),
-        'module': fields.char('Module', required=True),
-        'res_id': fields.integer('Record ID', help="ID of the target record in the database"),
-        'noupdate': fields.boolean('Non Updatable'),
-        'date_update': fields.datetime('Update Date'),
-        'date_init': fields.datetime('Init Date')
-    }
-    _defaults = {
-        'date_init': fields.datetime.now,
-        'date_update': fields.datetime.now,
-        'noupdate': False,
-        'module': ''
-    }
-
-    def __init__(self, pool, cr):
-        osv.osv.__init__(self, pool, cr)
-        # also stored in pool to avoid being discarded along with this osv instance
-        if getattr(pool, 'model_data_reference_ids', None) is None:
-            self.pool.model_data_reference_ids = {}
-        # put loads on the class, in order to share it among all instances
-        type(self).loads = self.pool.model_data_reference_ids
-
-    def _auto_init(self, cr, context=None):
-        super(ir_model_data, self)._auto_init(cr, context)
-        cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_model_data_module_name_uniq_index'")
-        if not cr.fetchone():
-            cr.execute('CREATE UNIQUE INDEX ir_model_data_module_name_uniq_index ON ir_model_data (module, name)')
-        cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = 'ir_model_data_model_res_id_index'")
-        if not cr.fetchone():
-            cr.execute('CREATE INDEX ir_model_data_model_res_id_index ON ir_model_data (model, res_id)')
+        return [(i, names[i]) for i in self.ids]
 
     # NEW V8 API
     @tools.ormcache('xmlid')
@@ -953,7 +912,7 @@ class ir_model_data(osv.osv):
         Return (id, res_model, res_id) or raise ValueError if not found
         """
         module, name = xmlid.split('.', 1)
-        ids = self.search(cr, uid, [('module','=',module), ('name','=', name)])
+        ids = self.search(cr, uid, [('module', '=', module), ('name', '=', name)])
         if not ids:
             raise ValueError('External ID not found in the system: %s' % (xmlid))
         # the sql constraints ensure us we have only one result
@@ -961,80 +920,85 @@ class ir_model_data(osv.osv):
         if not res['res_id']:
             raise ValueError('External ID not found in the system: %s' % (xmlid))
         return ids[0], res['model'], res['res_id']
-    
-    def xmlid_to_res_model_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
+
+    @api.model
+    def xmlid_to_res_model_res_id(self, xmlid, raise_if_not_found=False):
         """ Return (res_model, res_id)"""
         try:
-            return self.xmlid_lookup(cr, uid, xmlid)[1:3]
+            return self.xmlid_lookup(xmlid)[1:3]
         except ValueError:
             if raise_if_not_found:
                 raise
             return (False, False)
 
-    def xmlid_to_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
+    @api.model
+    def xmlid_to_res_id(self, xmlid, raise_if_not_found=False):
         """ Returns res_id """
-        return self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)[1]
+        return self.xmlid_to_res_model_res_id(xmlid, raise_if_not_found)[1]
 
-    def xmlid_to_object(self, cr, uid, xmlid, raise_if_not_found=False, context=None):
+    @api.model
+    def xmlid_to_object(self, xmlid, raise_if_not_found=False):
         """ Return a browse_record
         if not found and raise_if_not_found is True return None
-        """ 
-        t = self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)
+        """
+        t = self.xmlid_to_res_model_res_id(xmlid, raise_if_not_found)
         res_model, res_id = t
 
         if res_model and res_id:
-            record = self.pool[res_model].browse(cr, uid, res_id, context=context)
+            record = self.env[res_model].browse(res_id)
             if record.exists():
                 return record
             if raise_if_not_found:
                 raise ValueError('No record found for unique ID %s. It may have been deleted.' % (xmlid))
         return None
 
-    # OLD API
-    def _get_id(self, cr, uid, module, xml_id):
+    @api.model
+    def _get_id(self, module, xml_id):
         """Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found"""
-        return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[0]
+        return self.xmlid_lookup("%s.%s" % (module, xml_id))[0]
 
-    def get_object_reference(self, cr, uid, module, xml_id):
+    @api.model
+    def get_object_reference(self, module, xml_id):
         """Returns (model, res_id) corresponding to a given module and xml_id (cached) or raise ValueError if not found"""
-        return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[1:3]
+        return self.xmlid_lookup("%s.%s" % (module, xml_id))[1:3]
 
-    def check_object_reference(self, cr, uid, module, xml_id, raise_on_access_error=False):
+    @api.model
+    def check_object_reference(self, module, xml_id, raise_on_access_error=False):
         """Returns (model, res_id) corresponding to a given module and xml_id (cached), if and only if the user has the necessary access rights
         to see that object, otherwise raise a ValueError if raise_on_access_error is True or returns a tuple (model found, False)"""
-        model, res_id = self.get_object_reference(cr, uid, module, xml_id)
+        model, res_id = self.get_object_reference(module, xml_id)
         #search on id found in result to check if current user has read access right
-        check_right = self.pool.get(model).search(cr, uid, [('id', '=', res_id)])
-        if check_right:
+        if self.env[model].search([('id', '=', res_id)]):
             return model, res_id
         if raise_on_access_error:
             raise AccessError('Not enough access rights on the external ID: %s.%s' % (module, xml_id))
         return model, False
 
-    def get_object(self, cr, uid, module, xml_id, context=None):
+    @api.model
+    def get_object(self, module, xml_id):
         """ Returns a browsable record for the given module name and xml_id.
             If not found, raise a ValueError or return None, depending
             on the value of `raise_exception`.
         """
-        return self.xmlid_to_object(cr, uid, "%s.%s" % (module, xml_id), raise_if_not_found=True, context=context)
+        return self.xmlid_to_object("%s.%s" % (module, xml_id), raise_if_not_found=True)
 
-    def _update_dummy(self,cr, uid, model, module, xml_id=False, store=True):
+    @api.model
+    def _update_dummy(self, model, module, xml_id=False, store=True):
         if not xml_id:
             return False
-        id = False
         try:
             # One step to check the ID is defined and the record actually exists
-            record = self.get_object(cr, uid, module, xml_id)
+            record = self.get_object(module, xml_id)
             if record:
-                id = record.id
-                self.loads[(module,xml_id)] = (model,id)
+                record_id = record.id
+                self.loads[(module, xml_id)] = (model, self.id)
                 for table, inherit_field in self.pool[model]._inherits.iteritems():
                     parent_id = record[inherit_field].id
                     parent_xid = '%s_%s' % (xml_id, table.replace('.', '_'))
                     self.loads[(module, parent_xid)] = (table, parent_id)
         except Exception:
             pass
-        return id
+        return record_id
 
     def clear_caches(self):
         """ Clears all orm caches on the object's methods
@@ -1044,10 +1008,11 @@ class ir_model_data(osv.osv):
         self.xmlid_lookup.clear_cache(self)
         return self
 
-    def unlink(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink(self):
         """ Regular unlink method, but make sure to clear the caches. """
         self.clear_caches()
-        return super(ir_model_data,self).unlink(cr, uid, ids, context=context)
+        return super(IrModelData, self).unlink()
 
     def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):
         model_obj = self.pool[model]
@@ -1156,12 +1121,14 @@ class ir_model_data(osv.osv):
                 self.loads[(module, xml_id + '_' + table.replace('.', '_'))] = (table, inherit_id)
         return res_id
 
-    def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
-        ir_values_obj = openerp.registry(cr.dbname)['ir.values']
-        ir_values_obj.set(cr, uid, key, key2, name, models, value, replace, isobject, meta)
+    @api.model
+    def ir_set(self, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
+        ir_values = self.env['ir.values']
+        ir_values.set(key, key2, name, models, value, replace, isobject, meta)
         return True
 
-    def _module_data_uninstall(self, cr, uid, modules_to_remove, context=None):
+    @api.model
+    def _module_data_uninstall(self, modules_to_remove):
         """Deletes all the records referenced by the ir.model.data entries
         ``ids`` along with their corresponding database backed (including
         dropping tables, columns, FKs, etc, as long as there is no other
@@ -1172,20 +1139,20 @@ class ir_model_data(osv.osv):
         This step is performed as part of the full uninstallation of a module.
         """ 
 
-        ids = self.search(cr, uid, [('module', 'in', modules_to_remove)])
+        records = self.search([('module', 'in', modules_to_remove)]).ids
 
-        if uid != 1 and not self.pool['ir.model.access'].check_groups(cr, uid, "base.group_system"):
+        if self.env.uid != 1 and not self.env['ir.model.access'].check_groups("base.group_system"):
             raise AccessError(_('Administrator access is required to uninstall a module'))
 
-        context = dict(context or {})
-        context[MODULE_UNINSTALL_FLAG] = True # enable model/field deletion
+        self.env.context = dict(self.env.context or {})
+        self.env.context[MODULE_UNINSTALL_FLAG] = True  # enable model/field deletion
 
-        ids_set = set(ids)
+        ids_set = set(records)
         wkf_todo = []
         to_unlink = []
-        ids.sort()
-        ids.reverse()
-        for data in self.browse(cr, uid, ids, context):
+        records.sort()
+        records.reverse()
+        for data in self:
             model = data.model
             res_id = data.res_id
 
@@ -1197,72 +1164,66 @@ class ir_model_data(osv.osv):
                 # Special treatment for workflow activities: temporarily revert their
                 # incoming transition and trigger an update to force all workflow items
                 # to move out before deleting them
-                cr.execute('select res_type,res_id from wkf_instance where id IN (select inst_id from wkf_workitem where act_id=%s)', (res_id,))
-                wkf_todo.extend(cr.fetchall())
-                cr.execute("update wkf_transition set condition='True', group_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id,res_id))
-                self.invalidate_cache(cr, uid, context=context)
+                self.env.cr.execute('select res_type,res_id from wkf_instance where id IN (select inst_id from wkf_workitem where act_id=%s)', (res_id,))
+                wkf_todo.extend(self.env.cr.fetchall())
+                self.env.cr.execute("update wkf_transition set condition='True', group_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id, res_id))
+                self.invalidate_cache()
 
-        for model,res_id in wkf_todo:
+        for model, res_id in wkf_todo:
             try:
-                openerp.workflow.trg_write(uid, model, res_id, cr)
+                odoo.workflow.trg_write(self.env.uid, model, res_id, self.env.cr)
             except Exception:
                 _logger.info('Unable to force processing of workflow for item %s@%s in order to leave activity to be deleted', res_id, model, exc_info=True)
 
         def unlink_if_refcount(to_unlink):
             for model, res_id in to_unlink:
-                external_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
+                external_ids = self.search([('model', '=', model), ('res_id', '=', res_id)])
                 if set(external_ids)-ids_set:
                     # if other modules have defined this record, we must not delete it
                     continue
                 if model == 'ir.model.fields':
                     # Don't remove the LOG_ACCESS_COLUMNS unless _log_access
                     # has been turned off on the model.
-                    field = self.pool[model].browse(cr, uid, [res_id], context=context)[0]
+                    field = self.env[model].browse(res_id)
                     if not field.exists():
                         _logger.info('Deleting orphan external_ids %s', external_ids)
-                        self.unlink(cr, uid, external_ids)
+                        external_ids.unlink()
                         continue
-                    if field.name in openerp.models.LOG_ACCESS_COLUMNS and self.pool[field.model]._log_access:
+                    if field.name in models.LOG_ACCESS_COLUMNS and self.pool[field.model]._log_access:
                         continue
                     if field.name == 'id':
                         continue
                 _logger.info('Deleting %s@%s', res_id, model)
                 try:
-                    cr.execute('SAVEPOINT record_unlink_save')
-                    self.pool[model].unlink(cr, uid, [res_id], context=context)
+                    self.env.cr.execute('SAVEPOINT record_unlink_save')
+                    self.env[model].browse(res_id).unlink()
                 except Exception:
                     _logger.info('Unable to delete %s@%s', res_id, model, exc_info=True)
-                    cr.execute('ROLLBACK TO SAVEPOINT record_unlink_save')
+                    self.env.cr.execute('ROLLBACK TO SAVEPOINT record_unlink_save')
                 else:
-                    cr.execute('RELEASE SAVEPOINT record_unlink_save')
+                    self.env.cr.execute('RELEASE SAVEPOINT record_unlink_save')
 
         # Remove non-model records first, then model fields, and finish with models
-        unlink_if_refcount((model, res_id) for model, res_id in to_unlink
-                                if model not in ('ir.model','ir.model.fields','ir.model.constraint'))
-        unlink_if_refcount((model, res_id) for model, res_id in to_unlink
-                                if model == 'ir.model.constraint')
+        unlink_if_refcount((model, res_id) for model, res_id in to_unlink if model not in ('ir.model', 'ir.model.fields', 'ir.model.constraint'))
+        unlink_if_refcount((model, res_id) for model, res_id in to_unlink if model == 'ir.model.constraint')
 
-        ir_module_module = self.pool['ir.module.module']
-        ir_model_constraint = self.pool['ir.model.constraint']
-        modules_to_remove_ids = ir_module_module.search(cr, uid, [('name', 'in', modules_to_remove)], context=context)
-        constraint_ids = ir_model_constraint.search(cr, uid, [('module', 'in', modules_to_remove_ids)], context=context)
-        ir_model_constraint._module_data_uninstall(cr, uid, constraint_ids, context)
+        modules_to_remove_ids = self.env['ir.module.module'].search([('name', 'in', modules_to_remove)]).ids
+        constraint_ids = self.env['ir.model.constraint'].search([('module', 'in', modules_to_remove_ids)])
+        constraint_ids._module_data_uninstall()
 
-        unlink_if_refcount((model, res_id) for model, res_id in to_unlink
-                                if model == 'ir.model.fields')
+        unlink_if_refcount((model, res_id) for model, res_id in to_unlink if model == 'ir.model.fields')
 
-        ir_model_relation = self.pool['ir.model.relation']
-        relation_ids = ir_model_relation.search(cr, uid, [('module', 'in', modules_to_remove_ids)])
-        ir_model_relation._module_data_uninstall(cr, uid, relation_ids, context)
+        relation_ids = self.env['ir.model.relation'].search([('module', 'in', modules_to_remove_ids)])
+        relation_ids._module_data_uninstall()
 
-        unlink_if_refcount((model, res_id) for model, res_id in to_unlink
-                                if model == 'ir.model')
+        unlink_if_refcount((model, res_id) for model, res_id in to_unlink if model == 'ir.model')
 
-        cr.commit()
+        self.env.cr.commit()
 
-        self.unlink(cr, uid, ids, context)
+        self.unlink()
 
-    def _process_end(self, cr, uid, modules):
+    @api.model
+    def _process_end(self, modules):
         """ Clear records removed from updated module data.
         This method is called at the end of the module loading process.
         It is meant to removed records that are no longer present in the
@@ -1274,45 +1235,42 @@ class ir_model_data(osv.osv):
             return True
 
         bad_imd_ids = []
-        context = {MODULE_UNINSTALL_FLAG: True}
-        cr.execute("""SELECT id,name,model,res_id,module FROM ir_model_data
+        self.env.cr.execute("""SELECT id, name, model, res_id, module FROM ir_model_data
                       WHERE module IN %s AND res_id IS NOT NULL AND noupdate=%s ORDER BY id DESC
                    """, (tuple(modules), False))
-        for (id, name, model, res_id, module) in cr.fetchall():
+        for (rec_id, name, model, res_id, module) in self.env.cr.fetchall():
             if (module, name) not in self.loads:
                 if model in self.pool:
                     _logger.info('Deleting %s@%s (%s.%s)', res_id, model, module, name)
-                    if self.pool[model].exists(cr, uid, [res_id], context=context):
-                        self.pool[model].unlink(cr, uid, [res_id], context=context)
+                    if self.pool[model].exists(self.env.cr, self.env.uid, [res_id], context=self.env.context):
+                        self.pool[model].unlink(self.env.cr, self.env.uid, [res_id], context=self.env.context)
                     else:
-                        bad_imd_ids.append(id)
+                        bad_imd_ids.append(self.id)
         if bad_imd_ids:
-            self.unlink(cr, uid, bad_imd_ids, context=context)
+            self.browse(bad_imd_ids).with_context({MODULE_UNINSTALL_FLAG: True}).unlink()
         self.loads.clear()
 
-class wizard_model_menu(osv.osv_memory):
+
+class WizardModelMenu(models.TransientModel):
     _name = 'wizard.ir.model.menu.create'
-    _columns = {
-        'menu_id': fields.many2one('ir.ui.menu', 'Parent Menu', required=True),
-        'name': fields.char('Menu Name', required=True),
-    }
 
-    def menu_create(self, cr, uid, ids, context=None):
-        if not context:
-            context = {}
-        model_pool = self.pool.get('ir.model')
-        for menu in self.browse(cr, uid, ids, context):
-            model = model_pool.browse(cr, uid, context.get('model_id'), context=context)
+    menu_id = fields.Many2one('ir.ui.menu', string='Parent Menu', required=True)
+    name = fields.Char(string='Menu Name', required=True)
+
+    @api.multi
+    def menu_create(self):
+        for menu in self:
+            model = self.env['ir.model'].browse(self.env.context.get('model_id'))
             val = {
                 'name': menu.name,
                 'res_model': model.model,
                 'view_type': 'form',
                 'view_mode': 'tree,form'
             }
-            action_id = self.pool.get('ir.actions.act_window').create(cr, uid, val)
-            self.pool.get('ir.ui.menu').create(cr, uid, {
+            action_id = self.env['ir.actions.act_window'].create(val)
+            self.env['ir.ui.menu'].create({
                 'name': menu.name,
                 'parent_id': menu.menu_id.id,
                 'action': 'ir.actions.act_window,%d' % (action_id,)
-            }, context)
-        return {'type':'ir.actions.act_window_close'}
+            })
+        return {'type': 'ir.actions.act_window_close'}
diff --git a/openerp/addons/base/ir/ir_model_report.xml b/openerp/addons/base/ir/ir_model_report.xml
index 9b8027badb0c427299a5564a07f9e6c33a12c8d2..9cd79a16dfd734d6680c39668813c79f8a9075c5 100644
--- a/openerp/addons/base/ir/ir_model_report.xml
+++ b/openerp/addons/base/ir/ir_model_report.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0"?>
-<openerp>
-    <data>
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
 
         <report
             id="report_ir_model_overview"
@@ -10,6 +9,5 @@
             name="base.report_irmodeloverview"
             file="base.report_irmodeloverview"/>
 
-    </data>
-</openerp>
+</odoo>
 
diff --git a/openerp/addons/base/ir/ir_model_view.xml b/openerp/addons/base/ir/ir_model_view.xml
index fcc903c05ddffd5a00da82e958c61e54662d3cd1..000b033c0e83df77eabdc0bead6ef254c7e11137 100644
--- a/openerp/addons/base/ir/ir_model_view.xml
+++ b/openerp/addons/base/ir/ir_model_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
 
         <!-- menu_create from model form -->
         <record id="view_model_menu_create" model="ir.ui.view">
@@ -562,5 +561,4 @@
         </record>
         <menuitem action="ir_access_act" id="menu_ir_access_act" parent="base.menu_security"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_needaction.py b/openerp/addons/base/ir/ir_needaction.py
index 05f07b679ddb06d5136459a28344243c732950b1..765c8bb9da09cff2f0bc1e91dcfe4c5b234762f2 100644
--- a/openerp/addons/base/ir/ir_needaction.py
+++ b/openerp/addons/base/ir/ir_needaction.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from openerp.osv import osv
+from odoo import api, models
 
 
-class ir_needaction_mixin(osv.AbstractModel):
+class IrNeedactionMixin(models.AbstractModel):
     """Mixin class for objects using the need action feature.
 
     Need action feature can be used by models that have to be able to
@@ -28,7 +28,8 @@ class ir_needaction_mixin(osv.AbstractModel):
     # Addons API
     #------------------------------------------------------
 
-    def _needaction_domain_get(self, cr, uid, context=None):
+    @api.model
+    def _needaction_domain_get(self):
         """ Returns the domain to filter records that require an action
             :return: domain or False is no action
         """
@@ -38,10 +39,11 @@ class ir_needaction_mixin(osv.AbstractModel):
     # "Need action" API
     #------------------------------------------------------
 
-    def _needaction_count(self, cr, uid, domain=None, context=None):
+    @api.model
+    def _needaction_count(self, domain=None):
         """ Get the number of actions uid has to perform. """
-        dom = self._needaction_domain_get(cr, uid, context=context)
+        dom = self._needaction_domain_get()
         if not dom:
             return 0
-        res = self.search(cr, uid, (domain or []) + dom, limit=100, order='id DESC', context=context)
+        res = self.search((domain or []) + dom, limit=100, order='id DESC')
         return len(res)
diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py
index e5fd9d955d08b85d6cf53e641328f5405619c557..7f879a7ec372ab09b4134b3fa48d83cd9de69bf4 100644
--- a/openerp/addons/base/ir/ir_qweb.py
+++ b/openerp/addons/base/ir/ir_qweb.py
@@ -4,8 +4,8 @@ import copy
 import cStringIO
 import datetime
 import hashlib
-import json
 import itertools
+import json
 import logging
 import math
 import os
@@ -18,35 +18,35 @@ from urlparse import urlparse
 
 import babel
 import babel.dates
+import psycopg2
 import werkzeug
 from lxml import etree, html
 from PIL import Image
-import psycopg2
 
-import openerp.http
-import openerp.tools
-from openerp.tools.func import lazy_property
-import openerp.tools.lru
-from openerp.exceptions import QWebException
-from openerp.fields import Datetime
-from openerp.http import request
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.osv import osv, orm, fields
-from openerp.tools import html_escape as escape
-from openerp.tools.misc import find_in_path
-from openerp.tools.translate import _
-from openerp.modules.module import get_resource_path
+import odoo.http
+import odoo.tools
+import odoo.tools.lru
+from odoo import api, models, _
+from odoo.exceptions import QWebException
+from odoo.http import request
+from odoo.modules.module import get_resource_path
+from odoo.tools import html_escape as escape
+from odoo.tools.func import lazy_property
+from odoo.tools.misc import find_in_path
+from odoo.tools.safe_eval import safe_eval as eval
 
 _logger = logging.getLogger(__name__)
 
 MAX_CSS_RULES = 4095
 
+
 #--------------------------------------------------------------------
 # QWeb template engine
 #--------------------------------------------------------------------
 class QWebTemplateNotFound(QWebException):
     pass
 
+
 def raise_qweb_exception(etype=None, **kw):
     if etype is None:
         etype = QWebException
@@ -60,12 +60,14 @@ def raise_qweb_exception(etype=None, **kw):
         e.qweb['cause'] = original
         raise
 
+
 def _build_attribute(name, value):
     value = escape(value)
     if isinstance(name, unicode): name = name.encode('utf-8')
     if isinstance(value, unicode): value = value.encode('utf-8')
     return ' %s="%s"' % (name, value)
 
+
 class FileSystemLoader(object):
     def __init__(self, path):
         # TODO: support multiple files #add_file() + add cache
@@ -86,6 +88,7 @@ class FileSystemLoader(object):
                 arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
                 return arch
 
+
 class QWebContext(dict):
     def __init__(self, cr, uid, data, loader=None, context=None):
         self.cr = cr
@@ -114,7 +117,8 @@ class QWebContext(dict):
     def __copy__(self):
         return self.copy()
 
-class QWeb(orm.AbstractModel):
+
+class QWeb(models.AbstractModel):
     """ Base QWeb rendering engine
 
     * to customize ``t-field`` rendering, subclass ``ir.qweb.field`` and
@@ -225,6 +229,7 @@ class QWeb(orm.AbstractModel):
     def eval_bool(self, expr, qwebcontext):
         return int(bool(self.eval(expr, qwebcontext)))
 
+    @api.cr_uid_ids_context
     def render(self, cr, uid, id_or_xml_id, qwebcontext=None, loader=None, context=None):
         """ render(cr, uid, id_or_xml_id, qwebcontext=None, loader=None, context=None)
 
@@ -247,7 +252,7 @@ class QWeb(orm.AbstractModel):
             qwebcontext['__caller__'] = stack[-1]
         stack.append(id_or_xml_id)
         qwebcontext['__stack__'] = stack
-        qwebcontext['xmlid'] = str(stack[0]) # Temporary fix
+        qwebcontext['xmlid'] = str(stack[0])  # Temporary fix
 
         element = self.get_template(id_or_xml_id, qwebcontext)
         element.attrib.pop("name", False)
@@ -259,7 +264,7 @@ class QWeb(orm.AbstractModel):
 
         debugger = element.get('t-debug')
         if debugger is not None:
-            if openerp.tools.config['dev_mode']:
+            if odoo.tools.config['dev_mode']:
                 __import__(debugger).set_trace()  # pdb, ipdb, pudb, ...
             else:
                 _logger.warning("@t-debug in template '%s' is only available in --dev mode" % qwebcontext['__template__'])
@@ -378,7 +383,7 @@ class QWeb(orm.AbstractModel):
         return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner)
 
     def _iterate(self, iterable):
-        if isinstance (iterable, collections.Mapping):
+        if isinstance(iterable, collections.Mapping):
             return iterable.iteritems()
 
         return itertools.izip(*itertools.tee(iterable))
@@ -540,11 +545,12 @@ class QWeb(orm.AbstractModel):
                 return True
         return default
 
+
 #--------------------------------------------------------------------
 # QWeb Fields converters
 #--------------------------------------------------------------------
 
-class FieldConverter(osv.AbstractModel):
+class FieldConverter(models.AbstractModel):
     """ Used to convert a t-field specification into an output HTML field.
 
     :meth:`~.to_html` is the entry point of this conversion from QWeb, it:
@@ -556,9 +562,9 @@ class FieldConverter(osv.AbstractModel):
     """
     _name = 'ir.qweb.field'
 
-    def attributes(self, cr, uid, field_name, record, options,
-                   source_element, g_att, t_att, qweb_context,
-                   context=None):
+    @api.model
+    def attributes(self, field_name, record, options,
+                   source_element, g_att, t_att, qweb_context):
         """ attributes(cr, uid, field_name, record, options, source_element, g_att, t_att, qweb_context, context=None)
 
         Generates the metadata attributes (prefixed by ``data-oe-`` for the
@@ -592,7 +598,8 @@ class FieldConverter(osv.AbstractModel):
             data.append(('data-oe-readonly', 1))
         return data
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         """ value_to_html(cr, uid, value, field, options=None, context=None)
 
         Converts a single value to its HTML version/output
@@ -600,17 +607,18 @@ class FieldConverter(osv.AbstractModel):
         if not value: return ''
         return value
 
-    def record_to_html(self, cr, uid, field_name, record, options=None, context=None):
+    @api.model
+    def record_to_html(self, field_name, record, options=None):
         """ record_to_html(cr, uid, field_name, record, options=None, context=None)
 
         Converts the specified field of the browse_record ``record`` to HTML
         """
         field = record._fields[field_name]
-        return self.value_to_html(
-            cr, uid, record[field_name], field, options=options, context=context)
+        return self.value_to_html(record[field_name], field, options=options)
 
-    def to_html(self, cr, uid, field_name, record, options,
-                source_element, t_att, g_att, qweb_context, context=None):
+    @api.model
+    def to_html(self, field_name, record, options,
+                source_element, t_att, g_att, qweb_context):
         """ to_html(cr, uid, field_name, record, options, source_element, t_att, g_att, qweb_context, context=None)
 
         Converts a ``t-field`` to its HTML output. A ``t-field`` may be
@@ -621,7 +629,7 @@ class FieldConverter(osv.AbstractModel):
         field's own ``_type``.
         """
         try:
-            content = self.record_to_html(cr, uid, field_name, record, options, context=context)
+            content = self.record_to_html(field_name, record, options)
             if options.get('html-escape', True):
                 content = escape(content)
             elif hasattr(content, '__html__'):
@@ -631,22 +639,21 @@ class FieldConverter(osv.AbstractModel):
                             field_name, record._name, exc_info=True)
             content = None
 
-        inherit_branding = context and context.get('inherit_branding')
-        if not inherit_branding and context and context.get('inherit_branding_auto'):
-            inherit_branding = self.pool['ir.model.access'].check(cr, uid, record._name, 'write', False, context=context)
-        translate = context and context.get('edit_translations') and context.get('translatable') and getattr(record._fields[field_name], 'translate', False)
+        inherit_branding = self.env.context and self.env.context.get('inherit_branding')
+        if not inherit_branding and self.env.context and self.env.context.get('inherit_branding_auto'):
+            inherit_branding = self.env['ir.model.access'].check(record._name, 'write', False)
+        translate = self.env.context and self.env.context.get('edit_translations') and self.env.context.get('translatable') and getattr(record._fields[field_name], 'translate', False)
 
         if inherit_branding or translate:
             # add branding attributes
             g_att += ''.join(
                 _build_attribute(name, value)
                 for name, value in self.attributes(
-                    cr, uid, field_name, record, options,
-                    source_element, g_att, t_att, qweb_context,
-                    context=context)
+                    field_name, record, options,
+                    source_element, g_att, t_att, qweb_context)
             )
 
-        return self.render_element(cr, uid, source_element, t_att, g_att,
+        return self.render_element(source_element, t_att, g_att,
                                    qweb_context, content)
 
     def qweb_object(self):
@@ -661,7 +668,8 @@ class FieldConverter(osv.AbstractModel):
         return self.qweb_object().render_element(
             source_element, t_att, g_att, qweb_context, content or '')
 
-    def user_lang(self, cr, uid, context):
+    @api.model
+    def user_lang(self):
         """ user_lang(cr, uid, context)
 
         Fetches the res.lang object corresponding to the language code stored
@@ -670,41 +678,41 @@ class FieldConverter(osv.AbstractModel):
 
         :returns: res.lang browse_record
         """
-        if context is None: context = {}
 
-        lang_code = context.get('lang') or 'en_US'
-        Lang = self.pool['res.lang']
+        lang_code = self.env.context.get('lang') or 'en_US'
+        Lang = self.env['res.lang']
+
+        return Lang.browse(Lang._lang_get(lang_code))
 
-        return Lang.browse(cr, uid, Lang._lang_get(cr, uid, lang_code), context=context)
 
-class IntegerConverter(osv.AbstractModel):
+class IntegerConverter(models.AbstractModel):
     _name = 'ir.qweb.field.integer'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
-        if context is None:
-            context = {}
+    @api.model
+    def value_to_html(self, value, field, options=None):
 
-        lang_code = context.get('lang') or 'en_US'
-        return self.pool['res.lang'].format(cr, uid, [lang_code], '%d', value, grouping=True)
+        lang_code = self.env.context.get('lang') or 'en_US'
+        return self.pool['res.lang'].format(self.env.cr, self.env.uid, [lang_code], '%d', value, grouping=True)
 
-class FloatConverter(osv.AbstractModel):
+
+class FloatConverter(models.AbstractModel):
     _name = 'ir.qweb.field.float'
     _inherit = 'ir.qweb.field'
 
-    def precision(self, cr, uid, field, options=None, context=None):
+    @api.model
+    def precision(self, field, options=None):
         _, precision = field.digits or (None, None)
         return precision
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
-        if context is None:
-            context = {}
-        precision = self.precision(cr, uid, field, options=options, context=context)
+    @api.model
+    def value_to_html(self, value, field, options=None):
+        precision = self.precision(field, options=options)
         fmt = '%f' if precision is None else '%.{precision}f'
 
-        lang_code = context.get('lang') or 'en_US'
+        lang_code = self.env.context.get('lang') or 'en_US'
         lang = self.pool['res.lang']
-        formatted = lang.format(cr, uid, [lang_code], fmt.format(precision=precision), value, grouping=True)
+        formatted = lang.format(self.env.cr, self.env.uid, [lang_code], fmt.format(precision=precision), value, grouping=True)
 
         # %f does not strip trailing zeroes. %g does but its precision causes
         # it to switch to scientific notation starting at a million *and* to
@@ -714,60 +722,66 @@ class FloatConverter(osv.AbstractModel):
             formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)
         return formatted
 
-class DateConverter(osv.AbstractModel):
+
+class DateConverter(models.AbstractModel):
     _name = 'ir.qweb.field.date'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
-        if not value or len(value)<10: return ''
-        lang = self.user_lang(cr, uid, context=context)
+    @api.model
+    def value_to_html(self, value, field, options=None):
+        if not value or len(value) < 10: return ''
+        lang = self.user_lang()
         locale = babel.Locale.parse(lang.code)
 
         if isinstance(value, basestring):
             value = datetime.datetime.strptime(
-                value[:10], openerp.tools.DEFAULT_SERVER_DATE_FORMAT)
+                value[:10], odoo.tools.DEFAULT_SERVER_DATE_FORMAT)
 
         if options and 'format' in options:
             pattern = options['format']
         else:
             strftime_pattern = lang.date_format
-            pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
+            pattern = odoo.tools.posix_to_ldml(strftime_pattern, locale=locale)
 
         return babel.dates.format_date(
             value, format=pattern,
             locale=locale)
 
-class DateTimeConverter(osv.AbstractModel):
+
+class DateTimeConverter(models.AbstractModel):
     _name = 'ir.qweb.field.datetime'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         if not value: return ''
-        lang = self.user_lang(cr, uid, context=context)
+        lang = self.user_lang()
         locale = babel.Locale.parse(lang.code)
 
         if isinstance(value, basestring):
             value = datetime.datetime.strptime(
-                value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT)
-        value = fields.datetime.context_timestamp(
-            cr, uid, timestamp=value, context=context)
+                value, odoo.tools.DEFAULT_SERVER_DATETIME_FORMAT)
+
+        value = odoo.osv.fields.datetime.context_timestamp(self.env.cr, self.env.uid, timestamp=value, context=self.env.context)
 
         if options and 'format' in options:
             pattern = options['format']
         else:
             strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
-            pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
+            pattern = odoo.tools.posix_to_ldml(strftime_pattern, locale=locale)
 
         if options and options.get('hide_seconds'):
             pattern = pattern.replace(":ss", "").replace(":s", "")
 
         return babel.dates.format_datetime(value, format=pattern, locale=locale)
 
-class TextConverter(osv.AbstractModel):
+
+class TextConverter(models.AbstractModel):
     _name = 'ir.qweb.field.text'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         """
         Escapes the value and converts newlines to br. This is bullshit.
         """
@@ -775,36 +789,42 @@ class TextConverter(osv.AbstractModel):
 
         return nl2br(value, options=options)
 
-class SelectionConverter(osv.AbstractModel):
+
+class SelectionConverter(models.AbstractModel):
     _name = 'ir.qweb.field.selection'
     _inherit = 'ir.qweb.field'
 
-    def record_to_html(self, cr, uid, field_name, record, options=None, context=None):
+    @api.model
+    def record_to_html(self, field_name, record, options=None):
         value = record[field_name]
         if not value: return ''
         field = record._fields[field_name]
         selection = dict(field.get_description(record.env)['selection'])
-        return self.value_to_html(
-            cr, uid, selection[value], field, options=options)
+        return self.value_to_html(selection[value], field, options=options)
 
-class ManyToOneConverter(osv.AbstractModel):
+
+class ManyToOneConverter(models.AbstractModel):
     _name = 'ir.qweb.field.many2one'
     _inherit = 'ir.qweb.field'
 
-    def record_to_html(self, cr, uid, field_name, record, options=None, context=None):
+    @api.model
+    def record_to_html(self, field_name, record, options=None):
         [read] = record.read([field_name])
         if not read[field_name]: return ''
         _, value = read[field_name]
         return nl2br(value, options=options)
 
-class HTMLConverter(osv.AbstractModel):
+
+class HTMLConverter(models.AbstractModel):
     _name = 'ir.qweb.field.html'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         return HTMLSafe(value or '')
 
-class ImageConverter(osv.AbstractModel):
+
+class ImageConverter(models.AbstractModel):
     """ ``image`` widget rendering, inserts a data:uri-using image tag in the
     document. May be overridden by e.g. the website module to generate links
     instead.
@@ -816,18 +836,20 @@ class ImageConverter(osv.AbstractModel):
     _name = 'ir.qweb.field.image'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         try:
             image = Image.open(cStringIO.StringIO(value.decode('base64')))
             image.verify()
         except IOError:
             raise ValueError("Non-image binary fields can not be converted to HTML")
-        except: # image.verify() throws "suitable exceptions", I have no idea what they are
+        except:  # image.verify() throws "suitable exceptions", I have no idea what they are
             raise ValueError("Invalid image content")
 
         return HTMLSafe('<img src="data:%s;base64,%s">' % (Image.MIME[image.format], value))
 
-class MonetaryConverter(osv.AbstractModel):
+
+class MonetaryConverter(models.AbstractModel):
     """ ``monetary`` converter, has a mandatory option
     ``display_currency`` only if field is not of type Monetary.
     Otherwise, if we are in presence of a monetary field, the field definition must
@@ -844,16 +866,16 @@ class MonetaryConverter(osv.AbstractModel):
     _name = 'ir.qweb.field.monetary'
     _inherit = 'ir.qweb.field'
 
-    def to_html(self, cr, uid, field_name, record, options,
-                source_element, t_att, g_att, qweb_context, context=None):
+    @api.model
+    def to_html(self, field_name, record, options,
+                source_element, t_att, g_att, qweb_context):
         options['_qweb_context'] = qweb_context
         return super(MonetaryConverter, self).to_html(
-            cr, uid, field_name, record, options,
-            source_element, t_att, g_att, qweb_context, context=context)
+            field_name, record, options,
+            source_element, t_att, g_att, qweb_context)
 
-    def record_to_html(self, cr, uid, field_name, record, options, context=None):
-        if context is None:
-            context = {}
+    @api.model
+    def record_to_html(self, field_name, record, options):
         Currency = self.pool['res.currency']
         cur_field = record._fields[field_name]
         display_currency = False
@@ -862,7 +884,7 @@ class MonetaryConverter(osv.AbstractModel):
             display_currency = record[cur_field.currency_field]
         #otherwise fall back to old method
         if not display_currency:
-            display_currency = self.display_currency(cr, uid, options['display_currency'], options)
+            display_currency = self.display_currency(options['display_currency'], options)
 
         # lang.format mandates a sprintf-style format. These formats are non-
         # minimal (they have a default fixed precision instead), and
@@ -874,14 +896,13 @@ class MonetaryConverter(osv.AbstractModel):
         from_amount = record[field_name]
 
         if options.get('from_currency'):
-            from_currency = self.display_currency(cr, uid, options['from_currency'], options)
-            from_amount = Currency.compute(cr, uid, from_currency.id, display_currency.id, from_amount)
+            from_currency = self.display_currency(options['from_currency'], options)
+            from_amount = Currency.compute(self.env.cr, self.env.uid, from_currency.id, display_currency.id, from_amount)
 
-        lang_code = context.get('lang') or 'en_US'
+        lang_code = self.env.context.get('lang') or 'en_US'
         lang = self.pool['res.lang']
-        formatted_amount = lang.format(cr, uid, [lang_code],
-            fmt, Currency.round(cr, uid, display_currency, from_amount),
-            grouping=True, monetary=True)
+        formatted_amount = lang.format(self.env.cr, self.env.uid, [lang_code],
+                                       fmt, Currency.round(self.env.cr, self.env.uid, display_currency, from_amount), grouping=True, monetary=True)
 
         pre = post = u''
         if display_currency.position == 'before':
@@ -896,9 +917,8 @@ class MonetaryConverter(osv.AbstractModel):
             symbol=display_currency.symbol,
         ))
 
-    def display_currency(self, cr, uid, currency, options):
-        return self.qweb_object().eval_object(
-            currency, options['_qweb_context'])
+    def display_currency(self, currency, options):
+        return self.qweb_object().eval_object(currency, options['_qweb_context'])
 
 TIMEDELTA_UNITS = (
     ('year',   3600 * 24 * 365),
@@ -909,7 +929,9 @@ TIMEDELTA_UNITS = (
     ('minute', 60),
     ('second', 1)
 )
-class DurationConverter(osv.AbstractModel):
+
+
+class DurationConverter(models.AbstractModel):
     """ ``duration`` converter, to display integral or fractional values as
     human-readable time spans (e.g. 1.5 as "1 hour 30 minutes").
 
@@ -924,15 +946,15 @@ class DurationConverter(osv.AbstractModel):
     _name = 'ir.qweb.field.duration'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
+    @api.model
+    def value_to_html(self, value, field, options=None):
         units = dict(TIMEDELTA_UNITS)
         if value < 0:
             raise ValueError(_("Durations can't be negative"))
         if not options or options.get('unit') not in units:
             raise ValueError(_("A unit must be provided to duration widgets"))
 
-        locale = babel.Locale.parse(
-            self.user_lang(cr, uid, context=context).code)
+        locale = babel.Locale.parse(self.user_lang().code)
         factor = units[options['unit']]
 
         sections = []
@@ -947,14 +969,14 @@ class DurationConverter(osv.AbstractModel):
         return ' '.join(sections)
 
 
-class RelativeDatetimeConverter(osv.AbstractModel):
+class RelativeDatetimeConverter(models.AbstractModel):
     _name = 'ir.qweb.field.relative'
     _inherit = 'ir.qweb.field'
 
-    def value_to_html(self, cr, uid, value, field, options=None, context=None):
-        parse_format = openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT
-        locale = babel.Locale.parse(
-            self.user_lang(cr, uid, context=context).code)
+    @api.model
+    def value_to_html(self, value, field, options=None):
+        parse_format = odoo.tools.DEFAULT_SERVER_DATETIME_FORMAT
+        locale = babel.Locale.parse(self.user_lang().code)
 
         if isinstance(value, basestring):
             value = datetime.datetime.strptime(value, parse_format)
@@ -962,17 +984,15 @@ class RelativeDatetimeConverter(osv.AbstractModel):
         # value should be a naive datetime in UTC. So is fields.Datetime.now()
         reference = datetime.datetime.strptime(field.now(), parse_format)
 
-        return babel.dates.format_timedelta(
-            value - reference, add_direction=True, locale=locale)
+        return babel.dates.format_timedelta(value - reference, add_direction=True, locale=locale)
 
-class Contact(orm.AbstractModel):
+
+class Contact(models.AbstractModel):
     _name = 'ir.qweb.field.contact'
     _inherit = 'ir.qweb.field.many2one'
 
-    def record_to_html(self, cr, uid, field_name, record, options=None, context=None):
-        if context is None:
-            context = {}
-
+    @api.model
+    def record_to_html(self, field_name, record, options=None):
         if options is None:
             options = {}
         opf = options.get('fields') or ["name", "address", "phone", "mobile", "fax", "email"]
@@ -998,15 +1018,17 @@ class Contact(orm.AbstractModel):
             'options': options
         }
 
-        html = self.pool["ir.ui.view"].render(cr, uid, "base.contact", val, engine='ir.qweb', context=context).decode('utf8')
+        html = self.env['ir.ui.view']._model.render(self.env.cr, self.env.uid, "base.contact", val, engine='ir.qweb', context=self.env.context).decode('utf8')
 
         return HTMLSafe(html)
 
-class QwebView(orm.AbstractModel):
+
+class QwebView(models.AbstractModel):
     _name = 'ir.qweb.field.qweb'
     _inherit = 'ir.qweb.field.many2one'
 
-    def record_to_html(self, cr, uid, field_name, record, options=None, context=None):
+    @api.model
+    def record_to_html(self, field_name, record, options=None):
         if not getattr(record, field_name):
             return None
 
@@ -1016,13 +1038,14 @@ class QwebView(orm.AbstractModel):
             _logger.warning("%s.%s must be a 'ir.ui.view' model." % (record, field_name))
             return None
 
-        ctx = (context or {}).copy()
+        ctx = (self.env.context or {}).copy()
         ctx['object'] = record
-        html = view.render(ctx, engine='ir.qweb', context=ctx).decode('utf8')
+        html = view._model.render(self.env.cr, self.env.uid, ctx, engine='ir.qweb', context=self.env.ctx).decode('utf8')
 
         return HTMLSafe(html)
 
-class QwebWidget(osv.AbstractModel):
+
+class QwebWidget(models.AbstractModel):
     _name = 'ir.qweb.widget'
 
     def _format(self, inner, options, qwebcontext):
@@ -1031,7 +1054,8 @@ class QwebWidget(osv.AbstractModel):
     def format(self, inner, options, qwebcontext):
         return escape(self._format(inner, options, qwebcontext))
 
-class QwebWidgetMonetary(osv.AbstractModel):
+
+class QwebWidgetMonetary(models.AbstractModel):
     _name = 'ir.qweb.widget.monetary'
     _inherit = 'ir.qweb.widget'
 
@@ -1054,6 +1078,7 @@ class QwebWidgetMonetary(osv.AbstractModel):
             formatted_amount, pre=pre, post=post
         ).format(symbol=display.symbol,)
 
+
 class HTMLSafe(object):
     """ HTMLSafe string wrapper, Werkzeug's escape() has special handling for
     objects with a ``__html__`` methods but AFAIK does not provide any such
@@ -1062,21 +1087,26 @@ class HTMLSafe(object):
     Wrapping a string in HTML will prevent its escaping
     """
     __slots__ = ['string']
+
     def __init__(self, string):
         self.string = string
+
     def __html__(self):
         return self.string
+
     def __str__(self):
         s = self.string
         if isinstance(s, unicode):
             return s.encode('utf-8')
         return s
+
     def __unicode__(self):
         s = self.string
         if isinstance(s, str):
             return s.decode('utf-8')
         return s
 
+
 def nl2br(string, options=None):
     """ Converts newlines to HTML linebreaks in ``string``. Automatically
     escapes content unless options['html-escape'] is set to False, and returns
@@ -1092,15 +1122,20 @@ def nl2br(string, options=None):
         string = escape(string)
     return HTMLSafe(string.replace('\n', '<br>\n'))
 
+
 def get_field_type(field, options):
     """ Gets a t-field's effective type from the field definition and its options """
     return options.get('widget', field.type)
 
+
 class AssetError(Exception):
     pass
+
+
 class AssetNotFound(AssetError):
     pass
 
+
 class AssetsBundle(object):
     rx_css_import = re.compile("(@import[^;{]+;?)", re.M)
     rx_preprocess_imports = re.compile("""(@import\s?['"]([^'"]+)['"](;?))""")
@@ -1242,14 +1277,14 @@ class AssetsBundle(object):
             ('url', '=like', '/web/content/%-%/{0}%.{1}'.format(self.xmlid, type)),  # The wilcards are id, version and pagination number (if any)
             '!', ('url', '=like', '/web/content/%-{}/%'.format(self.version))
         ]
-        attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
-        return ira.unlink(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
+        attachment_ids = ira.search(self.cr, odoo.SUPERUSER_ID, domain, context=self.context)
+        return ira.unlink(self.cr, odoo.SUPERUSER_ID, attachment_ids, context=self.context)
 
     def get_attachments(self, type, inc=None):
         ira = self.registry['ir.attachment']
         domain = [('url', '=like', '/web/content/%%-%s/%s%s.%s' % (self.version, self.xmlid, ('%%' if inc is None else '.%s' % inc), type))]
-        attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, order='name asc', context=self.context)
-        return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
+        attachment_ids = ira.search(self.cr, odoo.SUPERUSER_ID, domain, order='name asc', context=self.context)
+        return ira.browse(self.cr, odoo.SUPERUSER_ID, attachment_ids, context=self.context)
 
     def save_attachment(self, type, content, inc=None):
         ira = self.registry['ir.attachment']
@@ -1264,21 +1299,21 @@ class AssetsBundle(object):
             'public': True,
             'datas': content.encode('utf8').encode('base64'),
         }
-        attachment_id = ira.create(self.cr, openerp.SUPERUSER_ID, values, context=self.context)
+        attachment_id = ira.create(self.cr, odoo.SUPERUSER_ID, values, context=self.context)
 
         url = '/web/content/%s-%s/%s' % (attachment_id, self.version, fname)
         values = {
             'name': url,
             'url': url,
         }
-        ira.write(self.cr, openerp.SUPERUSER_ID, attachment_id, values, context=self.context)
+        ira.write(self.cr, odoo.SUPERUSER_ID, attachment_id, values, context=self.context)
 
         if self.context.get('commit_assetsbundle') is True:
             self.cr.commit()
 
         self.clean_attachments(type)
 
-        return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_id, context=self.context)
+        return ira.browse(self.cr, odoo.SUPERUSER_ID, attachment_id, context=self.context)
 
     def js(self):
         attachments = self.get_attachments('js')
@@ -1412,6 +1447,7 @@ class AssetsBundle(object):
     def compile_css(self, cmd, source):
         """Sanitizes @import rules, remove duplicates @import rules, then compile"""
         imports = []
+
         def sanitize(matchobj):
             ref = matchobj.group(2)
             line = '@import "%s"%s' % (ref, matchobj.group(3))
@@ -1452,6 +1488,7 @@ class AssetsBundle(object):
                 error += '\n    - %s' % (asset.url if asset.url else '<inline sass>')
         return error
 
+
 class WebAsset(object):
     html_url = '%s'
 
@@ -1483,7 +1520,7 @@ class WebAsset(object):
                 fields = ['__last_update', 'datas', 'mimetype']
                 domain = [('type', '=', 'binary'), ('url', '=', self.url)]
                 ira = self.registry['ir.attachment']
-                attach = ira.search_read(self.cr, openerp.SUPERUSER_ID, domain, fields, context=self.context)
+                attach = ira.search_read(self.cr, odoo.SUPERUSER_ID, domain, fields, context=self.context)
                 self._ir_attach = attach[0]
             except Exception:
                 raise AssetNotFound("Could not find %s" % self.name)
@@ -1498,7 +1535,7 @@ class WebAsset(object):
             if self._filename:
                 return datetime.datetime.fromtimestamp(os.path.getmtime(self._filename))
             elif self._ir_attach:
-                server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
+                server_format = odoo.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
                 last_update = self._ir_attach['__last_update']
                 try:
                     return datetime.datetime.strptime(last_update, server_format + '.%f')
@@ -1538,6 +1575,7 @@ class WebAsset(object):
             content = self.content
         return '\n/* %s */\n%s' % (self.name, content)
 
+
 class JavascriptAsset(WebAsset):
     def minify(self):
         return self.with_header(rjsmin(self.content))
@@ -1554,6 +1592,7 @@ class JavascriptAsset(WebAsset):
         else:
             return '<script type="text/javascript" charset="utf-8">%s</script>' % self.with_header()
 
+
 class StylesheetAsset(WebAsset):
     rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U)
     rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://|data:)""", re.U)
@@ -1615,6 +1654,7 @@ class StylesheetAsset(WebAsset):
         else:
             return '<style type="text/css"%s>%s</style>' % (media, self.with_header())
 
+
 class PreprocessedCSS(StylesheetAsset):
     html_url = '%s.css'
     rx_import = None
@@ -1629,6 +1669,7 @@ class PreprocessedCSS(StylesheetAsset):
     def get_command(self):
         raise NotImplementedError
 
+
 class SassStylesheetAsset(PreprocessedCSS):
     rx_indent = re.compile(r'^( +|\t+)', re.M)
     indent = None
@@ -1661,6 +1702,7 @@ class SassStylesheetAsset(PreprocessedCSS):
         return [sass, '--stdin', '-t', 'compressed', '--unix-newlines', '--compass',
                 '-r', 'bootstrap-sass']
 
+
 class LessStylesheetAsset(PreprocessedCSS):
     def get_command(self):
         try:
@@ -1673,6 +1715,7 @@ class LessStylesheetAsset(PreprocessedCSS):
         lesspath = get_resource_path('web', 'static', 'lib', 'bootstrap', 'less')
         return [lessc, '-', '--clean-css', '--no-js', '--no-color', '--include-path=%s' % lesspath]
 
+
 def rjsmin(script):
     """ Minify js with a clever regex.
     Taken from http://opensource.perlig.de/rjsmin
diff --git a/openerp/addons/base/ir/ir_qweb.xml b/openerp/addons/base/ir/ir_qweb.xml
index 71a06764812da760ba80004fdf9e475185b06b25..e4d135119c0ce3dcf1aa24788f2dcfc4dcb9709a 100644
--- a/openerp/addons/base/ir/ir_qweb.xml
+++ b/openerp/addons/base/ir/ir_qweb.xml
@@ -1,5 +1,4 @@
-<openerp>
-<data>
+<odoo>
 <template id="contact">
     <address t-ignore="true" class="mb0" itemscope="itemscope" itemtype="http://schema.org/Organization">
         <div t-if="not (('name' in fields) or (address and 'address' in fields) or (city and 'city' in fields) or (mobile and 'mobile' in fields) or (fax and 'fax' in fields) or (website and 'website' in fields) or (email and 'email' in fields))" class="css_non_editable_mode_hidden">
@@ -36,5 +35,4 @@
         </div>
     </address>
 </template>
- </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_rule.py b/openerp/addons/base/ir/ir_rule.py
index 900462e97ad7063f1c4b1a098ce4acf111b9c3cd..6a475cf8dcf75c6048538404cb8fe6b234275e14 100644
--- a/openerp/addons/base/ir/ir_rule.py
+++ b/openerp/addons/base/ir/ir_rule.py
@@ -2,17 +2,46 @@
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 import time
 
-from openerp import SUPERUSER_ID
-from openerp import tools
-from openerp.osv import fields, osv, expression
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.misc import unquote as unquote
+import odoo
+from odoo import api, fields, models, _
+from odoo import SUPERUSER_ID
+from odoo import tools
+from odoo.osv import expression
+from odoo.tools.safe_eval import safe_eval as eval
+from odoo.tools.misc import unquote as unquote
 
-class ir_rule(osv.osv):
+
+class IrRule(models.Model):
     _name = 'ir.rule'
-    _order = 'name'
+    _order = 'name, model_id DESC'
     _MODES = ['read', 'write', 'create', 'unlink']
 
+    def _get_value(self, cr, uid, ids, field_name, arg, context=None):
+        res = {}
+        for rule in self.browse(cr, uid, ids, context):
+            if not rule.groups:
+                res[rule.id] = True
+            else:
+                res[rule.id] = False
+        return res
+
+    _columns = {'global': odoo.osv.fields.function(_get_value, string='Global', type='boolean', store=True, help="If no group is specified the rule is global and applied to everyone")}
+
+    name = fields.Char(index=True)
+    active = fields.Boolean(default=True, help="If you uncheck the active field, it will disable the record rule without deleting it (if you delete a native record rule, it may be re-created when you reload the module).")
+    model_id = fields.Many2one('ir.model', string='Object', index=True, required=True, ondelete="cascade")
+    groups = fields.Many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id')
+    domain_force = fields.Text(string='Domain')
+    domain = fields.Binary(compute='_domain_force_get', string='Domain')
+    perm_read = fields.Boolean(string='Apply for Read', default=True)
+    perm_write = fields.Boolean(string='Apply for Write', default=True)
+    perm_create = fields.Boolean(string='Apply for Create', default=True)
+    perm_unlink = fields.Boolean(string='Apply for Delete', default=True)
+
+    _sql_constraints = [
+        ('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have at least one checked access right !'),
+    ]
+
     def _eval_context_for_combinations(self):
         """Returns a dictionary to use as evaluation context for
            ir.rule domains, when the goal is to obtain python lists
@@ -21,69 +50,31 @@ class ir_rule(osv.osv):
         return {'user': unquote('user'),
                 'time': unquote('time')}
 
-    def _eval_context(self, cr, uid):
+    @api.model
+    def _eval_context(self):
         """Returns a dictionary to use as evaluation context for
            ir.rule domains."""
-        return {'user': self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid),
-                'time':time}
+        return {'user': self.env.user, 'time': time}
 
-    def _domain_force_get(self, cr, uid, ids, field_name, arg, context=None):
-        res = {}
-        eval_context = self._eval_context(cr, uid)
-        for rule in self.browse(cr, uid, ids, context):
+    @api.depends('domain')
+    def _domain_force_get(self):
+        eval_context = self._eval_context()
+        for rule in self:
             if rule.domain_force:
-                res[rule.id] = expression.normalize_domain(eval(rule.domain_force, eval_context))
-            else:
-                res[rule.id] = []
-        return res
-
-    def _get_value(self, cr, uid, ids, field_name, arg, context=None):
-        res = {}
-        for rule in self.browse(cr, uid, ids, context):
-            if not rule.groups:
-                res[rule.id] = True
+                rule.domain = expression.normalize_domain(eval(rule.domain_force, eval_context))
             else:
-                res[rule.id] = False
-        return res
+                rule.domain = []
 
-    def _check_model_obj(self, cr, uid, ids, context=None):
-        return not any(self.pool[rule.model_id.model].is_transient() for rule in self.browse(cr, uid, ids, context))
+    @api.constrains('model_id')
+    def _check_model_obj(self):
+        if any(self.pool[rule.model_id.model].is_transient() for rule in self):
+            raise UserWarning(_('Rules can not be applied on Transient models.'))
 
-    def _check_model_name(self, cr, uid, ids, context=None):
+    @api.constrains('model_id')
+    def _check_model_name(self):
         # Don't allow rules on rules records (this model).
-        return not any(rule.model_id.model == self._name for rule in self.browse(cr, uid, ids, context))
-
-    _columns = {
-        'name': fields.char('Name', select=1),
-        'active': fields.boolean('Active', help="If you uncheck the active field, it will disable the record rule without deleting it (if you delete a native record rule, it may be re-created when you reload the module)."),
-        'model_id': fields.many2one('ir.model', 'Object',select=1, required=True, ondelete="cascade"),
-        'global': fields.function(_get_value, string='Global', type='boolean', store=True, help="If no group is specified the rule is global and applied to everyone"),
-        'groups': fields.many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id', 'Groups'),
-        'domain_force': fields.text('Domain'),
-        'domain': fields.function(_domain_force_get, string='Domain', type='binary'),
-        'perm_read': fields.boolean('Apply for Read'),
-        'perm_write': fields.boolean('Apply for Write'),
-        'perm_create': fields.boolean('Apply for Create'),
-        'perm_unlink': fields.boolean('Apply for Delete')
-    }
-
-    _order = 'model_id DESC'
-
-    _defaults = {
-        'active': True,
-        'perm_read': True,
-        'perm_write': True,
-        'perm_create': True,
-        'perm_unlink': True,
-        'global': True,
-    }
-    _sql_constraints = [
-        ('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have at least one checked access right !'),
-    ]
-    _constraints = [
-        (_check_model_obj, 'Rules can not be applied on Transient models.', ['model_id']),
-        (_check_model_name, 'Rules can not be applied on the Record Rules model.', ['model_id']),
-    ]
+        if any(rule.model_id.model == self._name for rule in self):
+            raise UserWarning(_('Rules can not be applied on the Record Rules model.'))
 
     @tools.ormcache('uid', 'model_name', 'mode')
     def _compute_domain(self, cr, uid, model_name, mode="read"):
@@ -125,32 +116,37 @@ class ir_rule(osv.osv):
             return domain
         return []
 
-    def clear_cache(self, cr, uid):
+    @api.model
+    def clear_cache(self):
         """ Deprecated, use `clear_caches` instead. """
         self.clear_caches()
 
-    def domain_get(self, cr, uid, model_name, mode='read', context=None):
-        dom = self._compute_domain(cr, uid, model_name, mode)
+    @api.model
+    def domain_get(self, model_name, mode='read'):
+        dom = self._compute_domain(model_name, mode)
         if dom:
             # _where_calc is called as superuser. This means that rules can
             # involve objects on which the real uid has no acces rights.
             # This means also there is no implicit restriction (e.g. an object
             # references another object the user can't see).
-            query = self.pool[model_name]._where_calc(cr, SUPERUSER_ID, dom, active_test=False)
+            query = self.env[model_name].sudo()._where_calc(dom, active_test=False)
             return query.where_clause, query.where_clause_params, query.tables
-        return [], [], ['"' + self.pool[model_name]._table + '"']
+        return [], [], ['"' + self.env[model_name]._table + '"']
 
-    def unlink(self, cr, uid, ids, context=None):
-        res = super(ir_rule, self).unlink(cr, uid, ids, context=context)
+    @api.multi
+    def unlink(self):
+        res = super(IrRule, self).unlink()
         self.clear_caches()
         return res
 
-    def create(self, cr, uid, vals, context=None):
-        res = super(ir_rule, self).create(cr, uid, vals, context=context)
+    @api.model
+    def create(self, vals):
+        res = super(IrRule, self).create(vals)
         self.clear_caches()
         return res
 
-    def write(self, cr, uid, ids, vals, context=None):
-        res = super(ir_rule, self).write(cr, uid, ids, vals, context=context)
+    @api.multi
+    def write(self, vals):
+        res = super(IrRule, self).write(vals)
         self.clear_caches()
         return res
diff --git a/openerp/addons/base/ir/ir_rule_view.xml b/openerp/addons/base/ir/ir_rule_view.xml
index 10267e2cb75c2a1cf983ab747b79ec203de3213a..ca5e20aafac035ee9850b04849092d7a2da3049b 100644
--- a/openerp/addons/base/ir/ir_rule_view.xml
+++ b/openerp/addons/base/ir/ir_rule_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- Rules -->
         <record id="view_rule_form" model="ir.ui.view">
             <field name="model">ir.rule</field>
@@ -95,5 +94,4 @@
         </record>
 
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py
index 2a0f3ab47b7cfe8dfb4bb46bc8d1598a1ec57022..ea139b4cb3a988eea3a9efb6b865c565c3c31720 100644
--- a/openerp/addons/base/ir/ir_sequence.py
+++ b/openerp/addons/base/ir/ir_sequence.py
@@ -1,12 +1,11 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
+from datetime import datetime, timedelta
 import logging
 import pytz
-import time
 
-from datetime import datetime, timedelta
-from openerp import _, api, fields, models
-from openerp.exceptions import UserError
+from odoo import api, fields, models, _
+from odoo.exceptions import UserError
 
 _logger = logging.getLogger(__name__)
 
@@ -21,6 +20,7 @@ def _create_sequence(cr, seq_name, number_increment, number_next):
     sql = "CREATE SEQUENCE %s INCREMENT BY %%s START WITH %%s" % seq_name
     cr.execute(sql, (number_increment, number_next))
 
+
 def _drop_sequence(cr, seq_names):
     """ Drop the PostreSQL sequence if it exists.
 
@@ -34,6 +34,7 @@ def _drop_sequence(cr, seq_names):
     # object depends on it.
     cr.execute("DROP SEQUENCE IF EXISTS %s RESTRICT " % names)
 
+
 def _alter_sequence(cr, seq_name, number_increment=None, number_next=None):
     """ Alter a PostreSQL sequence.
 
@@ -52,10 +53,12 @@ def _alter_sequence(cr, seq_name, number_increment=None, number_next=None):
         statement += " RESTART WITH %d" % (number_next, )
     cr.execute(statement)
 
+
 def _select_nextval(cr, seq_name):
     cr.execute("SELECT nextval('%s')" % seq_name)
     return cr.fetchone()
 
+
 def _update_nogap(self, number_increment):
     number_next = self.number_next
     self.env.cr.execute("SELECT number_next FROM %s WHERE id=%s FOR UPDATE NOWAIT" % (self._table, self.id))
@@ -64,7 +67,7 @@ def _update_nogap(self, number_increment):
     return number_next
 
 
-class ir_sequence(models.Model):
+class IrSequence(models.Model):
     """ Sequence model.
 
     The sequence model allows to define and use so-called sequence objects.
@@ -97,30 +100,29 @@ class ir_sequence(models.Model):
             record.write({'number_next': record.number_next_actual or 0})
 
     name = fields.Char(required=True)
-    code = fields.Char('Sequence Code')
-    implementation = fields.Selection(
-        [('standard', 'Standard'), ('no_gap', 'No gap')],
-        'Implementation', required=True, default='standard',
-        help="Two sequence object implementations are offered: Standard "
-        "and 'No gap'. The later is slower than the former but forbids any"
-        " gap in the sequence (while they are possible in the former).")
+    code = fields.Char(strring='Sequence Code')
+    implementation = fields.Selection([('standard', 'Standard'), ('no_gap', 'No gap')],
+                                      string='Implementation', required=True, default='standard',
+                                      help="Two sequence object implementations are offered: Standard "
+                                           "and 'No gap'. The later is slower than the former but forbids any"
+                                           "gap in the sequence (while they are possible in the former).")
     active = fields.Boolean(default=True)
     prefix = fields.Char(help="Prefix value of the record for the sequence")
     suffix = fields.Char(help="Suffix value of the record for the sequence")
-    number_next = fields.Integer('Next Number', required=True, default=1, help="Next number of this sequence")
+    number_next = fields.Integer(string='Next Number', required=True, default=1, help="Next number of this sequence")
     number_next_actual = fields.Integer(compute='_get_number_next_actual', inverse='_set_number_next_actual',
                                         required=True, string='Next Number', default=1,
                                         help="Next number that will be used. This number can be incremented "
                                         "frequently so the displayed value might already be obsolete")
-    number_increment = fields.Integer('Step', required=True, default=1,
+    number_increment = fields.Integer(string='Step', required=True, default=1,
                                       help="The next number of the sequence will be incremented by this number")
-    padding = fields.Integer('Sequence Size', required=True, default=0,
+    padding = fields.Integer(string='Sequence Size', required=True, default=0,
                              help="Odoo will automatically adds some '0' on the left of the "
-                             "'Next Number' to get the required padding size.")
-    company_id = fields.Many2one('res.company', 'Company',
+                                  "'Next Number' to get the required padding size.")
+    company_id = fields.Many2one('res.company', string='Company',
                                  default=lambda s: s.env['res.company']._company_default_get('ir.sequence'))
-    use_date_range = fields.Boolean('Use subsequences per date_range')
-    date_range_ids = fields.One2many('ir.sequence.date_range', 'sequence_id', 'Subsequences')
+    use_date_range = fields.Boolean(string='Use subsequences per date_range')
+    date_range_ids = fields.One2many('ir.sequence.date_range', 'sequence_id', string='Subsequences')
 
     def init(self, cr):
         return  # Don't do the following index yet.
@@ -141,7 +143,7 @@ class ir_sequence(models.Model):
     def create(self, values):
         """ Create a sequence, in implementation == standard a fast gaps-allowed PostgreSQL sequence is used.
         """
-        seq = super(ir_sequence, self).create(values)
+        seq = super(IrSequence, self).create(values)
         if values.get('implementation', 'standard') == 'standard':
             _create_sequence(self.env.cr, "ir_sequence_%03d" % seq.id, values.get('number_increment', 1), values.get('number_next', 1))
         return seq
@@ -149,7 +151,7 @@ class ir_sequence(models.Model):
     @api.multi
     def unlink(self):
         _drop_sequence(self.env.cr, ["ir_sequence_%03d" % x.id for x in self])
-        return super(ir_sequence, self).unlink()
+        return super(IrSequence, self).unlink()
 
     @api.multi
     def write(self, values):
@@ -178,7 +180,7 @@ class ir_sequence(models.Model):
                     _create_sequence(self.env.cr, "ir_sequence_%03d" % seq.id, i, n)
                     for sub_seq in seq.date_range_ids:
                         _create_sequence(self.env.cr, "ir_sequence_%03d_%03d" % (seq.id, sub_seq.id), i, n)
-        return super(ir_sequence, self).write(values)
+        return super(IrSequence, self).write(values)
 
     def _next_do(self):
         if self.implementation == 'standard':
@@ -308,7 +310,7 @@ class ir_sequence(models.Model):
         return self.get_id(code, 'code')
 
 
-class ir_sequence_date_range(models.Model):
+class IrSequenceDateRange(models.Model):
     _name = 'ir.sequence.date_range'
     _rec_name = "sequence_id"
 
@@ -321,8 +323,7 @@ class ir_sequence_date_range(models.Model):
             else:
                 # get number from postgres sequence. Cannot use currval, because that might give an error when
                 # not having used nextval before.
-                query = "SELECT last_value, increment_by, is_called FROM ir_sequence_%03d_%03d" % (element.sequence_id.id, element.id)
-                self.env.cr.execute(query)
+                self.env.cr.execute("SELECT last_value, increment_by, is_called FROM ir_sequence_%03d_%03d" % (element.sequence_id.id, element.id))
                 (last_value, increment_by, is_called) = self.env.cr.fetchone()
                 if is_called:
                     element.number_next_actual = last_value + increment_by
@@ -333,14 +334,14 @@ class ir_sequence_date_range(models.Model):
         for record in self:
             record.write({'number_next': record.number_next_actual or 0})
 
-    date_from = fields.Date('From', required=True)
-    date_to = fields.Date('To', required=True)
-    sequence_id = fields.Many2one("ir.sequence", 'Main Sequence', required=True, ondelete='cascade')
-    number_next = fields.Integer('Next Number', required=True, default=1, help="Next number of this sequence")
+    date_from = fields.Date(string='From', required=True)
+    date_to = fields.Date(string='To', required=True)
+    sequence_id = fields.Many2one("ir.sequence", string='Main Sequence', required=True, ondelete='cascade')
+    number_next = fields.Integer(string='Next Number', required=True, default=1, help="Next number of this sequence")
     number_next_actual = fields.Integer(compute='_get_number_next_actual', inverse='_set_number_next_actual',
                                         required=True, string='Next Number', default=1,
                                         help="Next number that will be used. This number can be incremented "
-                                        "frequently so the displayed value might already be obsolete")
+                                             "frequently so the displayed value might already be obsolete")
 
     def _next(self):
         if self.sequence_id.implementation == 'standard':
@@ -358,7 +359,7 @@ class ir_sequence_date_range(models.Model):
     def create(self, values):
         """ Create a sequence, in implementation == standard a fast gaps-allowed PostgreSQL sequence is used.
         """
-        seq = super(ir_sequence_date_range, self).create(values)
+        seq = super(IrSequenceDateRange, self).create(values)
         main_seq = seq.sequence_id
         if main_seq.implementation == 'standard':
             _create_sequence(self.env.cr, "ir_sequence_%03d_%03d" % (main_seq.id, seq.id), main_seq.number_increment, values.get('number_next_actual', 1))
@@ -367,11 +368,11 @@ class ir_sequence_date_range(models.Model):
     @api.multi
     def unlink(self):
         _drop_sequence(self.env.cr, ["ir_sequence_%03d_%03d" % (x.sequence_id.id, x.id) for x in self])
-        return super(ir_sequence_date_range, self).unlink()
+        return super(IrSequenceDateRange, self).unlink()
 
     @api.multi
     def write(self, values):
         if values.get('number_next'):
             seq_to_alter = self.filtered(lambda seq: seq.sequence_id.implementation == 'standard')
             seq_to_alter._alter_sequence(number_next=values.get('number_next'))
-        return super(ir_sequence_date_range, self).write(values)
+        return super(IrSequenceDateRange, self).write(values)
diff --git a/openerp/addons/base/ir/ir_sequence_view.xml b/openerp/addons/base/ir/ir_sequence_view.xml
index 05b3df249aa41945cdf6a8cc9b197c4eed74d4b2..9bfaf30850c27712b03bcd84cb6adbe45a349c39 100644
--- a/openerp/addons/base/ir/ir_sequence_view.xml
+++ b/openerp/addons/base/ir/ir_sequence_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- Sequences -->
         <record id="sequence_view" model="ir.ui.view">
             <field name="model">ir.sequence</field>
@@ -105,5 +104,4 @@
         </record>
         <menuitem action="ir_sequence_form" id="menu_ir_sequence_form" parent="next_id_5"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py
index 31500322f2eb3e6c98809be247e4d3764a537d39..0a9c29fdb21c6af7e6f69a378b909c1a8a3a7307 100644
--- a/openerp/addons/base/ir/ir_translation.py
+++ b/openerp/addons/base/ir/ir_translation.py
@@ -1,15 +1,13 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
+import logging
 from collections import defaultdict
 from difflib import get_close_matches
-import logging
 
-from openerp import api, tools, SUPERUSER_ID
-import openerp.modules
-from openerp.osv import fields, osv
-from openerp.tools.translate import _
-from openerp.exceptions import AccessError, UserError, ValidationError
+import odoo
+from odoo import api, fields, models, tools, _
+from odoo.exceptions import AccessError, UserError, ValidationError
 
 _logger = logging.getLogger(__name__)
 
@@ -25,7 +23,8 @@ TRANSLATION_TYPE = [
     ('sql_constraint', 'SQL Constraint')
 ]
 
-class ir_translation_import_cursor(object):
+
+class IrTranslationImportCursor(object):
     """Temporary cursor for optimizing mass insert into ir.translation
 
     Open it (attached to a sql cursor), feed it with translation data and
@@ -168,28 +167,48 @@ class ir_translation_import_cursor(object):
         cr.execute("DROP TABLE %s" % self._table_name)
         return True
 
-class ir_translation(osv.osv):
+
+class IrTranslation(models.Model):
     _name = "ir.translation"
     _log_access = False
 
-    def _get_language(self, cr, uid, context):
-        lang_model = self.pool.get('res.lang')
-        lang_ids = lang_model.search(cr, uid, [('translatable', '=', True)], context=context)
-        lang_data = lang_model.read(cr, uid, lang_ids, ['code', 'name'], context=context)
-        return [(d['code'], d['name']) for d in lang_data]
-
-    def _get_src(self, cr, uid, ids, name, arg, context=None):
+    @api.model
+    def _get_language(self):
+        lang_model = self.env['res.lang']
+        lang = lang_model.search([('translatable', '=', True)])
+        return [(data.code, data.name) for data in lang]
+
+    name = fields.Char(string='Translated field', required=True)
+    res_id = fields.Integer(string='Record ID', index=True)
+    lang = fields.Selection(selection='_get_language', string='Language')
+    type = fields.Selection(TRANSLATION_TYPE, string='Type', index=True)
+    src = fields.Text(string='Internal Source')  # stored in database, kept for backward compatibility
+    source = fields.Text(compute='_get_src', inverse='_set_src', search='_search_src', string='Source term')
+    value = fields.Text(string='Translation Value')
+    module = fields.Char(index=True, help="Module this term belongs to")
+
+    state = fields.Selection([('to_translate', 'To Translate'),
+                              ('inprogress', 'Translation in Progress'),
+                              ('translated', 'Translated')],
+                             string="Status", default='to_translate',
+                             help="Automatically set to let administators find new terms that might need to be translated")
+
+    # aka gettext extracted-comments - we use them to flag openerp-web translation
+    # cfr: http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/PO-Files.html
+    comments = fields.Text(string='Translation comments', index=True)
+
+    _sql_constraints = [('lang_fkey_res_lang', 'FOREIGN KEY(lang) REFERENCES res_lang(code)',
+                        'Language code of translation item must be among known languages')]
+
+    @api.depends('source')
+    def _get_src(self):
         ''' Get source name for the translation. If object type is model then
         return the value store in db. Otherwise return value store in src field
         '''
-        if context is None:
-            context = {}
-        res = dict.fromkeys(ids, False)
-        for record in self.browse(cr, uid, ids, context=context):
-            res[record.id] = record.src
+        for record in self:
             if record.type == 'model':
                 model_name, field_name = record.name.split(',')
-                model = self.pool.get(model_name)
+                model = self.env[model_name]
                 if model is None:
                     continue
                 field = model._fields.get(field_name)
@@ -197,74 +216,41 @@ class ir_translation(osv.osv):
                     continue
                 if not callable(field.translate):
                     # Pass context without lang, need to read real stored field, not translation
-                    context_no_lang = dict(context, lang=None)
-                    result = model.read(cr, uid, [record.res_id], [field_name], context=context_no_lang)
-                    res[record.id] = result[0][field_name] if result else False
-        return res
+                    context_no_lang = dict(self.env.context, lang=None)
+                    result = model.with_context(context_no_lang).browse(record.res_id).read([field_name])
+                    record.source = result[0][field_name] if result else False
 
-    def _set_src(self, cr, uid, id, name, value, args, context=None):
+    def _set_src(self):
         ''' When changing source term of a translation, change its value in db for
         the associated object, and the src field
         '''
-        if context is None:
-            context = {}
-        record = self.browse(cr, uid, id, context=context)
-        if record.type == 'model':
-            model_name, field_name = record.name.split(',')
-            model = self.pool.get(model_name)
+        if self.type == 'model':
+            model_name, field_name = self.name.split(',')
+            model = self.env[model_name]
             field = model._fields[field_name]
             if not callable(field.translate):
                 # Make a context without language information, because we want
                 # to write on the value stored in db and not on the one
                 # associated with the current language. Also not removing lang
                 # from context trigger an error when lang is different.
-                context_wo_lang = context.copy()
+                context_wo_lang = self.env.context.copy()
                 context_wo_lang.pop('lang', None)
-                model.write(cr, uid, [record.res_id], {field_name: value}, context=context_wo_lang)
-        return self.write(cr, uid, id, {'src': value}, context=context)
+                model.with_context(context_wo_lang).browse(self.res_id).write({field_name: self.source})
+        return self.write({'src': self.source})
 
-    def _search_src(self, cr, uid, obj, name, args, context):
+    @api.model
+    def _search_src(self, operator, operand):
         ''' the source term is stored on 'src' field '''
         res = []
-        for field, operator, value in args:
+        for field, operator, value in operand:
             res.append(('src', operator, value))
         return res
 
-    _columns = {
-        'name': fields.char('Translated field', required=True),
-        'res_id': fields.integer('Record ID', select=True),
-        'lang': fields.selection(_get_language, string='Language'),
-        'type': fields.selection(TRANSLATION_TYPE, string='Type', select=True),
-        'src': fields.text('Internal Source'),  # stored in database, kept for backward compatibility
-        'source': fields.function(_get_src, fnct_inv=_set_src, fnct_search=_search_src,
-            type='text', string='Source term'),
-        'value': fields.text('Translation Value'),
-        'module': fields.char('Module', help="Module this term belongs to", select=True),
-
-        'state': fields.selection(
-            [('to_translate','To Translate'),
-             ('inprogress','Translation in Progress'),
-             ('translated','Translated')],
-            string="Status",
-            help="Automatically set to let administators find new terms that might need to be translated"),
-
-        # aka gettext extracted-comments - we use them to flag openerp-web translation
-        # cfr: http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/PO-Files.html
-        'comments': fields.text('Translation comments', select=True),
-    }
-
-    _defaults = {
-        'state': 'to_translate',
-    }
-
-    _sql_constraints = [ ('lang_fkey_res_lang', 'FOREIGN KEY(lang) REFERENCES res_lang(code)',
-        'Language code of translation item must be among known languages' ), ]
-
-    def _auto_init(self, cr, context=None):
-        super(ir_translation, self)._auto_init(cr, context)
-
-        cr.execute("SELECT indexname FROM pg_indexes WHERE indexname LIKE 'ir_translation_%'")
-        indexes = [row[0] for row in cr.fetchall()]
+    def _auto_init(self):
+        super(IrTranslation, self)._auto_init()
+
+        self.env.cr.execute("SELECT indexname FROM pg_indexes WHERE indexname LIKE 'ir_translation_%'")
+        indexes = [row[0] for row in self.env.cr.fetchall()]
 
         # Removed because there is a size limit on btree indexed values (problem with column src):
         # cr.execute('CREATE INDEX ir_translation_ltns ON ir_translation (name, lang, type, src)')
@@ -273,65 +259,65 @@ class ir_translation(osv.osv):
         # Removed because hash indexes are not compatible with postgres streaming replication:
         # cr.execute('CREATE INDEX ir_translation_src_hash_idx ON ir_translation USING hash (src)')
         if set(indexes) & set(['ir_translation_ltns', 'ir_translation_lts', 'ir_translation_src_hash_idx']):
-            cr.execute('DROP INDEX IF EXISTS ir_translation_ltns, ir_translation_lts, ir_translation_src_hash_idx')
-            cr.commit()
+            self.env.cr.execute('DROP INDEX IF EXISTS ir_translation_ltns, ir_translation_lts, ir_translation_src_hash_idx')
+            self.env.cr.commit()
 
         # Add separate md5 index on src (no size limit on values, and good performance).
         if 'ir_translation_src_md5' not in indexes:
-            cr.execute('CREATE INDEX ir_translation_src_md5 ON ir_translation (md5(src))')
-            cr.commit()
+            self.env.cr.execute('CREATE INDEX ir_translation_src_md5 ON ir_translation (md5(src))')
+            self.env.cr.commit()
 
         if 'ir_translation_ltn' not in indexes:
-            cr.execute('CREATE INDEX ir_translation_ltn ON ir_translation (name, lang, type)')
-            cr.commit()
+            self.env.cr.execute('CREATE INDEX ir_translation_ltn ON ir_translation (name, lang, type)')
+            self.env.cr.commit()
 
-    def _check_selection_field_value(self, cr, uid, field, value, context=None):
+    @api.model
+    def _check_selection_field_value(self, field, value):
         if field == 'lang':
             return
-        return super(ir_translation, self)._check_selection_field_value(cr, uid, field, value, context=context)
-
-    def _get_ids(self, cr, uid, name, tt, lang, ids):
-        translations = dict.fromkeys(ids, False)
-        if ids:
-            cr.execute('select res_id,value '
-                    'from ir_translation '
-                    'where lang=%s '
-                        'and type=%s '
-                        'and name=%s '
-                        'and res_id IN %s',
-                    (lang,tt,name,tuple(ids)))
-            for res_id, value in cr.fetchall():
-                translations[res_id] = value
-        return translations
-
-    def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
+        return super(IrTranslation, self)._check_selection_field_value(field, value)
+
+    @api.model
+    def _get_ids(self, name, tt, lang, in_ids):
+        if in_ids:
+            self.env.cr.execute('select res_id,value '
+                                'from ir_translation '
+                                'where lang=%s '
+                                'and type=%s '
+                                'and name=%s '
+                                'and res_id IN %s',
+                                (lang, tt, name, tuple(in_ids)))
+            for res_id, value in self.env.cr.fetchall():
+                self.res_id = value
+
+    @api.model
+    def _set_ids(self, name, tt, lang, rec_ids, value, src=None):
         self.clear_caches()
-        cr.execute('update ir_translation '
-                  'set value=%s '
-                  '  , src=%s '
-                  '  , state=%s '
-                'where lang=%s '
-                    'and type=%s '
-                    'and name=%s '
-                    'and res_id IN %s '
-                'returning res_id',
-                (value,src,'translated',lang,tt,name,tuple(ids),))
-
-        existing_ids = [x[0] for x in cr.fetchall()]
-
-        for id in list(set(ids) - set(existing_ids)):
-            self.create(cr, uid, {
-                'lang':lang,
-                'type':tt,
-                'name':name,
-                'res_id':id,
-                'value':value,
-                'src':src,
-                'state':'translated'
-                })
-        return len(ids)
+        self.env.cr.execute('update ir_translation '
+                            'set value=%s '
+                            '  , src=%s '
+                            '  , state=%s '
+                            'where lang=%s '
+                            'and type=%s '
+                            'and name=%s '
+                            'and res_id IN %s '
+                            'returning res_id',
+                            (value, src, 'translated', lang, tt, name, tuple(rec_ids),))
+
+        existing_ids = [x[0] for x in self.env.cr.fetchall()]
+
+        for id in list(set(rec_ids) - set(existing_ids)):
+            self.create({'lang': lang,
+                         'type': tt,
+                         'name': name,
+                         'res_id': id,
+                         'value': value,
+                         'src': src,
+                         'state': 'translated'}).id
+        return len(rec_ids)
 
-    def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
+    @api.model
+    def _get_source_query(self, name, types, lang, source, res_id):
         if source:
             # Note: the extra test on md5(src) is a hint for postgres to use the
             # index ir_translation_src_md5
@@ -356,21 +342,22 @@ class ir_translation(osv.osv):
                         AND name=%s"""
 
             params = (lang or '', types, tools.ustr(name))
-        
+
         return (query, params)
 
     @tools.ormcache('name', 'types', 'lang', 'source', 'res_id')
-    def __get_source(self, cr, uid, name, types, lang, source, res_id):
+    def __get_source(self, name, types, lang, source, res_id):
         # res_id is a tuple or None, otherwise ormcache cannot cache it!
-        query, params = self._get_source_query(cr, uid, name, types, lang, source, res_id)
-        cr.execute(query, params)
-        res = cr.fetchone()
+        query, params = self._get_source_query(name, types, lang, source, res_id)
+        self.env.cr.execute(query, params)
+        res = self.env.cr.fetchone()
         trad = res and res[0] or u''
         if source and not trad:
             return tools.ustr(source)
         return trad
 
-    def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
+    @api.model
+    def _get_source(self, name, types, lang, source=None, res_id=None):
         """
         Returns the translation for the given combination of name, type, language
         and source. All values passed to this method should be unicode (not byte strings),
@@ -396,7 +383,7 @@ class ir_translation(osv.osv):
                 res_id = (res_id,)
             else:
                 res_id = tuple(res_id)
-        return self.__get_source(cr, uid, name, types, lang, source, res_id)
+        return self.__get_source(name, types, lang, source, res_id)
 
     @api.model
     def _get_terms_query(self, field, records):
@@ -550,7 +537,7 @@ class ir_translation(osv.osv):
 
     @api.model
     def create(self, vals):
-        record = super(ir_translation, self.sudo()).create(vals).with_env(self.env)
+        record = super(IrTranslation, self.sudo()).create(vals).with_env(self.env)
         record.check('create')
         self.clear_caches()
         return record
@@ -562,7 +549,7 @@ class ir_translation(osv.osv):
         elif vals.get('src') or not vals.get('value', True):
             vals.setdefault('state', 'to_translate')
         self.check('write')
-        result = super(ir_translation, self.sudo()).write(vals)
+        result = super(IrTranslation, self.sudo()).write(vals)
         self.check('write')
         self.clear_caches()
         return result
@@ -571,7 +558,7 @@ class ir_translation(osv.osv):
     def unlink(self):
         self.check('unlink')
         self.clear_caches()
-        return super(ir_translation, self.sudo()).unlink()
+        return super(IrTranslation, self.sudo()).unlink()
 
     @api.model
     def insert_missing(self, field, records):
@@ -675,17 +662,17 @@ class ir_translation(osv.osv):
     def _get_import_cursor(self, cr, uid, context=None):
         """ Return a cursor-like object for fast inserting translations
         """
-        return ir_translation_import_cursor(cr, uid, self, context=context)
+        return IrTranslationImportCursor(cr, uid, self, context=context)
 
     def load_module_terms(self, cr, modules, langs, context=None):
         context_template = dict(context or {}) # local copy
         # make sure the given languages are active
         lang_obj = self.pool['res.lang']
         for lang in langs:
-            lang_obj.load_lang(cr, SUPERUSER_ID, lang)
+            lang_obj.load_lang(cr, odoo.SUPERUSER_ID, lang)
         # load i18n files
         for module_name in modules:
-            modpath = openerp.modules.get_module_path(module_name)
+            modpath = odoo.modules.get_module_path(module_name)
             if not modpath:
                 continue
             for lang in langs:
@@ -697,28 +684,28 @@ class ir_translation(osv.osv):
 
                 # Step 1: for sub-languages, load base language first (e.g. es_CL.po is loaded over es.po)
                 if base_lang_code:
-                    base_trans_file = openerp.modules.get_module_resource(module_name, 'i18n', base_lang_code + '.po')
+                    base_trans_file = odoo.modules.get_module_resource(module_name, 'i18n', base_lang_code + '.po')
                     if base_trans_file:
                         _logger.info('module %s: loading base translation file %s for language %s', module_name, base_lang_code, lang)
                         tools.trans_load(cr, base_trans_file, lang, verbose=False, module_name=module_name, context=context)
-                        context['overwrite'] = True # make sure the requested translation will override the base terms later
+                        context['overwrite'] = True  # make sure the requested translation will override the base terms later
 
                     # i18n_extra folder is for additional translations handle manually (eg: for l10n_be)
-                    base_trans_extra_file = openerp.modules.get_module_resource(module_name, 'i18n_extra', base_lang_code + '.po')
+                    base_trans_extra_file = odoo.modules.get_module_resource(module_name, 'i18n_extra', base_lang_code + '.po')
                     if base_trans_extra_file:
                         _logger.info('module %s: loading extra base translation file %s for language %s', module_name, base_lang_code, lang)
                         tools.trans_load(cr, base_trans_extra_file, lang, verbose=False, module_name=module_name, context=context)
-                        context['overwrite'] = True # make sure the requested translation will override the base terms later
+                        context['overwrite'] = True  # make sure the requested translation will override the base terms later
 
                 # Step 2: then load the main translation file, possibly overriding the terms coming from the base language
-                trans_file = openerp.modules.get_module_resource(module_name, 'i18n', lang_code + '.po')
+                trans_file = odoo.modules.get_module_resource(module_name, 'i18n', lang_code + '.po')
                 if trans_file:
                     _logger.info('module %s: loading translation file (%s) for language %s', module_name, lang_code, lang)
                     tools.trans_load(cr, trans_file, lang, verbose=False, module_name=module_name, context=context)
                 elif lang_code != 'en_US':
                     _logger.info('module %s: no translation for language %s', module_name, lang_code)
 
-                trans_extra_file = openerp.modules.get_module_resource(module_name, 'i18n_extra', lang_code + '.po')
+                trans_extra_file = odoo.modules.get_module_resource(module_name, 'i18n_extra', lang_code + '.po')
                 if trans_extra_file:
                     _logger.info('module %s: loading extra translation file (%s) for language %s', module_name, lang_code, lang)
                     tools.trans_load(cr, trans_extra_file, lang, verbose=False, module_name=module_name, context=context)
diff --git a/openerp/addons/base/ir/ir_translation_view.xml b/openerp/addons/base/ir/ir_translation_view.xml
index f7dea59873e70cdfde4d1d94c12ac77557bdb0b6..bca195ca52909909e59579a895e170daec0620e1 100644
--- a/openerp/addons/base/ir/ir_translation_view.xml
+++ b/openerp/addons/base/ir/ir_translation_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- Translations -->
         <record id="view_translation_search" model="ir.ui.view">
             <field name="model">ir.translation</field>
@@ -86,5 +85,4 @@
 
         <menuitem action="action_translation" id="menu_action_translation" parent="base.menu_translation_app" />
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_ui_menu.py b/openerp/addons/base/ir/ir_ui_menu.py
index 89a95f33a6d8b5eeabac5ea79ab1160b2c8b6677..61509c8145e2e16eb9e43faad58e3136afd4bc40 100644
--- a/openerp/addons/base/ir/ir_ui_menu.py
+++ b/openerp/addons/base/ir/ir_ui_menu.py
@@ -4,25 +4,78 @@
 import base64
 import operator
 import re
-import threading
 
-import openerp
-from openerp.osv import fields, osv
-from openerp import api, tools
-from openerp.http import request
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.translate import _
+import odoo
+from odoo import api, fields, models, tools, _
+from odoo.exceptions import ValidationError
+from odoo.http import request
+from odoo.tools.safe_eval import safe_eval as eval
 
 MENU_ITEM_SEPARATOR = "/"
 
 
-class ir_ui_menu(osv.osv):
+class IrUiMenu(models.Model):
     _name = 'ir.ui.menu'
+    _order = "sequence,id"
+    _parent_store = True
 
     def __init__(self, *args, **kwargs):
-        super(ir_ui_menu, self).__init__(*args, **kwargs)
+        super(IrUiMenu, self).__init__(*args, **kwargs)
         self.pool['ir.model.access'].register_cache_clearing_method(self._name, 'clear_caches')
 
+    name = fields.Char(string='Menu', required=True, translate=True)
+    sequence = fields.Integer(default=10)
+    child_id = fields.One2many('ir.ui.menu', 'parent_id', string='Child IDs')
+    parent_id = fields.Many2one('ir.ui.menu', string='Parent Menu', index=True, ondelete="restrict")
+    parent_left = fields.Integer(index=True)
+    parent_right = fields.Integer(index=True)
+    groups_id = fields.Many2many('res.groups', 'ir_ui_menu_group_rel',
+                                 'menu_id', 'gid', string='Groups',
+                                 help="If you have groups, the visibility of this menu will be based on these groups. "\
+                                      "If this field is empty, Odoo will compute visibility based on the related object's read access.")
+    complete_name = fields.Char(compute='_get_full_name', string='Full Path')
+    web_icon = fields.Char(string='Web Icon File')
+    action = fields.Reference(selection=[('ir.actions.report.xml', 'ir.actions.report.xml'),
+                                         ('ir.actions.act_window', 'ir.actions.act_window'),
+                                         ('ir.actions.act_url', 'ir.actions.act_url'),
+                                         ('ir.actions.server', 'ir.actions.server'),
+                                         ('ir.actions.client', 'ir.actions.client')])
+
+    web_icon_data = fields.Binary(string='Web Icon Image', compute="_compute_web_icon", store=True, attachment=True)
+
+    @api.depends('web_icon')
+    def _compute_web_icon(self):
+        for menu in self:
+            menu.web_icon_data = self.read_image(menu.web_icon)
+
+    def read_image(self, path):
+        if not path:
+            return False
+        path_info = path.split(',')
+        icon_path = odoo.modules.get_module_resource(path_info[0], path_info[1])
+        icon_image = False
+        if icon_path:
+            try:
+                icon_file = tools.file_open(icon_path, 'rb')
+                icon_image = base64.encodestring(icon_file.read())
+            finally:
+                icon_file.close()
+        return icon_image
+
+    @api.depends('complete_name')
+    def _get_full_name(self):
+        for element in self:
+            element.complete_name = self._get_one_full_name(element)
+
+    def _get_one_full_name(self, elmt, level=6):
+        if level <= 0:
+            return '...'
+        if elmt.parent_id:
+            parent_path = self._get_one_full_name(elmt.parent_id, level-1) + MENU_ITEM_SEPARATOR
+        else:
+            parent_path = ''
+        return parent_path + elmt.name
+
     @api.model
     @tools.ormcache('frozenset(self.env.user.groups_id.ids)', 'debug')
     def _visible_menu_ids(self, debug=False):
@@ -75,7 +128,7 @@ class ir_ui_menu(osv.osv):
         if context is None:
             context = {}
 
-        ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0,
+        ids = super(IrUiMenu, self).search(cr, uid, args, offset=0,
             limit=None, order=order, context=context, count=False)
 
         if not ids:
@@ -98,99 +151,69 @@ class ir_ui_menu(osv.osv):
             return len(result)
         return result
 
-    def name_get(self, cr, uid, ids, context=None):
+    @api.multi
+    def name_get(self):
         res = []
-        for id in ids:
-            elmt = self.browse(cr, uid, id, context=context)
-            res.append((id, self._get_one_full_name(elmt)))
+        for element in self:
+            res.append((element.id, self._get_one_full_name(element)))
         return res
 
-    def _get_full_name(self, cr, uid, ids, name=None, args=None, context=None):
-        if context is None:
-            context = {}
-        res = {}
-        for elmt in self.browse(cr, uid, ids, context=context):
-            res[elmt.id] = self._get_one_full_name(elmt)
-        return res
-
-    def _get_one_full_name(self, elmt, level=6):
-        if level<=0:
-            return '...'
-        if elmt.parent_id:
-            parent_path = self._get_one_full_name(elmt.parent_id, level-1) + MENU_ITEM_SEPARATOR
-        else:
-            parent_path = ''
-        return parent_path + elmt.name
-
-    def create(self, cr, uid, values, context=None):
+    @api.model
+    def create(self, values):
         self.clear_caches()
-        return super(ir_ui_menu, self).create(cr, uid, values, context=context)
+        return super(IrUiMenu, self).create(values)
 
-    def write(self, cr, uid, ids, values, context=None):
+    @api.multi
+    def write(self, values):
         self.clear_caches()
-        return super(ir_ui_menu, self).write(cr, uid, ids, values, context=context)
+        return super(IrUiMenu, self).write(values)
 
-    def unlink(self, cr, uid, ids, context=None):
+    @api.multi
+    def unlink(self):
         # Detach children and promote them to top-level, because it would be unwise to
         # cascade-delete submenus blindly. We also can't use ondelete=set null because
         # that is not supported when _parent_store is used (would silently corrupt it).
         # TODO: ideally we should move them under a generic "Orphans" menu somewhere?
-        if isinstance(ids, (int, long)):
-            ids = [ids]
-        local_context = dict(context or {})
+        local_context = dict(self.env.context or {})
         local_context['ir.ui.menu.full_list'] = True
-        direct_children_ids = self.search(cr, uid, [('parent_id', 'in', ids)], context=local_context)
-        if direct_children_ids:
-            self.write(cr, uid, direct_children_ids, {'parent_id': False})
+        direct_children = self.with_context(local_context).search([('parent_id', 'in', self.ids)])
+        if direct_children:
+            direct_children.write({'parent_id': False})
 
-        result = super(ir_ui_menu, self).unlink(cr, uid, ids, context=context)
+        result = super(IrUiMenu, self).unlink()
         self.clear_caches()
         return result
 
-    def copy(self, cr, uid, id, default=None, context=None):
-        res = super(ir_ui_menu, self).copy(cr, uid, id, default=default, context=context)
-        datas=self.read(cr,uid,[res],['name'])[0]
-        rex=re.compile('\([0-9]+\)')
-        concat=rex.findall(datas['name'])
+    @api.multi
+    def copy(self, default=None):
+        res = super(IrUiMenu, self).copy(default=default)
+        rex = re.compile('\([0-9]+\)')
+        concat = rex.findall(res.name)
         if concat:
-            next_num=int(concat[0])+1
-            datas['name']=rex.sub(('(%d)'%next_num),datas['name'])
+            next_num = int(concat[0])+1
+            res.name = rex.sub(('(%d)' % next_num), res.name)
         else:
-            datas['name'] += '(1)'
-        self.write(cr,uid,[res],{'name':datas['name']})
+            res.name += '(1)'
+        res.write({'name': res.name})
         return res
 
-    def read_image(self, path):
-        if not path:
-            return False
-        path_info = path.split(',')
-        icon_path = openerp.modules.get_module_resource(path_info[0],path_info[1])
-        icon_image = False
-        if icon_path:
-            try:
-                icon_file = tools.file_open(icon_path,'rb')
-                icon_image = base64.encodestring(icon_file.read())
-            finally:
-                icon_file.close()
-        return icon_image
-
-    def get_needaction_data(self, cr, uid, ids, context=None):
+    @api.multi
+    def get_needaction_data(self):
         """ Return for each menu entry of ids :
             - if it uses the needaction mechanism (needaction_enabled)
             - the needaction counter of the related action, taking into account
               the action domain
         """
-        if context is None:
-            context = {}
         res = {}
         menu_ids = set()
-        for menu in self.browse(cr, uid, ids, context=context):
+        for menu in self:
             menu_ids.add(menu.id)
             ctx = None
             if menu.action and menu.action.type in ('ir.actions.act_window', 'ir.actions.client') and menu.action.context:
                 try:
                     # use magical UnquoteEvalContext to ignore undefined client-side variables such as `active_id`
-                    eval_ctx = tools.UnquoteEvalContext(**context)
+                    ctxt = dict(self.env.context or {})
+                    eval_ctx = tools.UnquoteEvalContext(**ctxt)
                     ctx = eval(menu.action.context, locals_dict=eval_ctx, nocopy=True) or None
                 except Exception:
                     # if the eval still fails for some reason, we'll simply skip this menu
@@ -199,43 +222,44 @@ class ir_ui_menu(osv.osv):
             if menu_ref:
                 if not isinstance(menu_ref, list):
                     menu_ref = [menu_ref]
-                model_data_obj = self.pool.get('ir.model.data')
+                model_data_obj = self.env['ir.model.data']
                 for menu_data in menu_ref:
                     try:
-                        model, id = model_data_obj.get_object_reference(cr, uid, menu_data.split('.')[0], menu_data.split('.')[1])
+                        model, model_id = model_data_obj.get_object_reference(menu_data.split('.')[0], menu_data.split('.')[1])
                         if (model == 'ir.ui.menu'):
-                            menu_ids.add(id)
+                            menu_ids.add(model_id)
                     except Exception:
                         pass
 
         menu_ids = list(menu_ids)
 
-        for menu in self.browse(cr, uid, menu_ids, context=context):
+        for menu in self:
             res[menu.id] = {
                 'needaction_enabled': False,
                 'needaction_counter': False,
             }
             if menu.action and menu.action.type in ('ir.actions.act_window', 'ir.actions.client') and menu.action.res_model:
                 if menu.action.res_model in self.pool:
-                    obj = self.pool[menu.action.res_model]
+                    obj = self.env[menu.action.res_model]
                     if obj._needaction:
                         if menu.action.type == 'ir.actions.act_window':
-                            eval_context = self.pool['ir.actions.act_window']._get_eval_context(cr, uid, context=context)
+                            eval_context = self.env['ir.actions.act_window']._get_eval_context()
                             dom = menu.action.domain and eval(menu.action.domain, eval_context) or []
                         else:
-                            dom = eval(menu.action.params_store or '{}', {'uid': uid}).get('domain')
+                            dom = eval(menu.action.params_store or '{}', {'uid': self.env.uid}).get('domain')
                         res[menu.id]['needaction_enabled'] = obj._needaction
-                        res[menu.id]['needaction_counter'] = obj._needaction_count(cr, uid, dom, context=context)
+                        res[menu.id]['needaction_counter'] = obj._needaction_count(dom)
         return res
 
-    def get_user_roots(self, cr, uid, context=None):
+    @api.model
+    @api.returns('self')
+    def get_user_roots(self):
         """ Return all root menu ids visible for the user.
 
         :return: the root menu ids
         :rtype: list(int)
         """
-        menu_domain = [('parent_id', '=', False)]
-        return self.search(cr, uid, menu_domain, context=context)
+        return self.search([('parent_id', '=', False)])
 
     @api.cr_uid_context
     @tools.ormcache_context('uid', keys=('lang',))
@@ -300,41 +324,3 @@ class ir_ui_menu(osv.osv):
                 key=operator.itemgetter('sequence'))
 
         return menu_root
-
-    _columns = {
-        'name': fields.char('Menu', required=True, translate=True),
-        'sequence': fields.integer('Sequence'),
-        'child_id': fields.one2many('ir.ui.menu', 'parent_id', 'Child IDs'),
-        'parent_id': fields.many2one('ir.ui.menu', 'Parent Menu', select=True, ondelete="restrict"),
-        'parent_left': fields.integer('Parent Left', select=True),
-        'parent_right': fields.integer('Parent Right', select=True),
-        'groups_id': fields.many2many('res.groups', 'ir_ui_menu_group_rel',
-            'menu_id', 'gid', 'Groups', help="If you have groups, the visibility of this menu will be based on these groups. "\
-                "If this field is empty, Odoo will compute visibility based on the related object's read access."),
-        'complete_name': fields.function(_get_full_name, string='Full Path', type='char'),
-        'web_icon': fields.char('Web Icon File'),
-        'action': fields.reference('Action', selection=[
-                ('ir.actions.report.xml', 'ir.actions.report.xml'),
-                ('ir.actions.act_window', 'ir.actions.act_window'),
-                ('ir.actions.act_url', 'ir.actions.act_url'),
-                ('ir.actions.server', 'ir.actions.server'),
-                ('ir.actions.client', 'ir.actions.client'),
-        ]),
-    }
-
-    web_icon_data = openerp.fields.Binary('Web Icon Image',
-        compute="_compute_web_icon", store=True, attachment=True)
-
-    @api.depends('web_icon')
-    def _compute_web_icon(self):
-        for menu in self:
-            menu.web_icon_data = self.read_image(menu.web_icon)
-
-    _constraints = [
-        (osv.osv._check_recursion, 'Error ! You can not create recursive Menu.', ['parent_id'])
-    ]
-    _defaults = {
-        'sequence': 10,
-    }
-    _order = "sequence,id"
-    _parent_store = True
diff --git a/openerp/addons/base/ir/ir_ui_menu_view.xml b/openerp/addons/base/ir/ir_ui_menu_view.xml
index 26794bc732b3ec33fe92cc30dd299c53b1a46d84..aa85487dfbae5ffdac50a92bac497e8f3cebaddc 100644
--- a/openerp/addons/base/ir/ir_ui_menu_view.xml
+++ b/openerp/addons/base/ir/ir_ui_menu_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         
         <record id="edit_menu_access" model="ir.ui.view">
             <field name="model">ir.ui.menu</field>
@@ -70,5 +69,4 @@
         </record>
         <menuitem action="grant_menu_access" id="menu_grant_menu_access" parent="base.next_id_2" sequence="1"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py
index a5895ee5b27fa6ee6b4afed2501e74113231274d..59841882cd5ad8b6b5073ccb2602e49b2eb00e47 100644
--- a/openerp/addons/base/ir/ir_ui_view.py
+++ b/openerp/addons/base/ir/ir_ui_view.py
@@ -3,37 +3,37 @@
 import collections
 import copy
 import datetime
-from dateutil.relativedelta import relativedelta
 import fnmatch
 import logging
 import os
 import re
 import time
+from dateutil.relativedelta import relativedelta
 from operator import itemgetter
 
 import json
 import werkzeug
-import HTMLParser
 from lxml import etree
 
-import openerp
-from openerp import tools, api
-from openerp.exceptions import ValidationError
-from openerp.http import request
-from openerp.modules.module import get_resource_path, get_resource_from_path
-from openerp.osv import fields, osv, orm
-from openerp.tools import config, graph, SKIPPED_ELEMENT_TYPES, SKIPPED_ELEMENTS
-from openerp.tools.convert import _fix_multiple_roots
-from openerp.tools.parse_version import parse_version
-from openerp.tools.safe_eval import safe_eval as eval
-from openerp.tools.view_validation import valid_view
-from openerp.tools import misc
-from openerp.tools.translate import TRANSLATED_ATTRS, encode, xml_translate, _
+import odoo
+from odoo import api, fields, models, tools, _
+from odoo.exceptions import ValidationError
+from odoo.http import request
+from odoo.modules.module import get_resource_from_path, get_resource_path
+from odoo.osv import orm, osv
+from odoo.tools import config, graph, SKIPPED_ELEMENT_TYPES
+from odoo.tools import misc
+from odoo.tools.convert import _fix_multiple_roots
+from odoo.tools.parse_version import parse_version
+from odoo.tools.safe_eval import safe_eval as eval
+from odoo.tools.view_validation import valid_view
+from odoo.tools.translate import encode, TRANSLATED_ATTRS, xml_translate
 
 _logger = logging.getLogger(__name__)
 
 MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath', 'data-oe-source-id']
 
+
 def keep_query(*keep_params, **additional_params):
     """
     Generate a query string keeping the current request querystring's parameters specified
@@ -56,32 +56,32 @@ def keep_query(*keep_params, **additional_params):
                 params[param] = request.httprequest.args.getlist(param)
     return werkzeug.urls.url_encode(params)
 
-class view_custom(osv.osv):
+
+class ViewCustom(models.Model):
     _name = 'ir.ui.view.custom'
     _order = 'create_date desc'  # search(limit=1) should return the last customization
-    _columns = {
-        'ref_id': fields.many2one('ir.ui.view', 'Original View', select=True, required=True, ondelete='cascade'),
-        'user_id': fields.many2one('res.users', 'User', select=True, required=True, ondelete='cascade'),
-        'arch': fields.text('View Architecture', required=True),
-    }
-
-    def name_get(self, cr, uid, ids, context=None):
-        return [(rec.id, rec.user_id.name) for rec in self.browse(cr, uid, ids, context=context)]
-
-    def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
-        if args is None:
-            args = []
+
+    ref_id = fields.Many2one('ir.ui.view', string='Original View', index=True, required=True, ondelete='cascade')
+    user_id = fields.Many2one('res.users', string='User', index=True, required=True, ondelete='cascade')
+    arch = fields.Text(string='View Architecture', required=True)
+
+    @api.depends('user_id')
+    def name_get(self):
+        return [(rec.id, rec.user_id.name) for rec in self]
+
+    @api.model
+    def name_search(self, name, args=None, operator='ilike', limit=100):
         if name:
-            ids = self.search(cr, user, [('user_id', operator, name)] + args, limit=limit)
-            return self.name_get(cr, user, ids, context=context)
-        return super(view_custom, self).name_search(cr, user, name, args=args, operator=operator, context=context, limit=limit)
+            self = self.search([('user_id', operator, name)] + args, limit=limit)
+            return self.name_get()
+        return super(ViewCustom, self).name_search(name, args=args, operator=operator, limit=limit)
 
+    def _auto_init(self):
+        super(ViewCustom, self)._auto_init()
+        self.env.cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_custom_user_id_ref_id\'')
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE INDEX ir_ui_view_custom_user_id_ref_id ON ir_ui_view_custom (user_id, ref_id)')
 
-    def _auto_init(self, cr, context=None):
-        super(view_custom, self)._auto_init(cr, context)
-        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_custom_user_id_ref_id\'')
-        if not cr.fetchone():
-            cr.execute('CREATE INDEX ir_ui_view_custom_user_id_ref_id ON ir_ui_view_custom (user_id, ref_id)')
 
 def _hasclass(context, *cls):
     """ Checks if the context node has all the classes passed as arguments
@@ -90,6 +90,7 @@ def _hasclass(context, *cls):
 
     return node_classes.issuperset(cls)
 
+
 def get_view_arch_from_file(filename, xmlid):
 
     doc = etree.parse(filename)
@@ -98,7 +99,7 @@ def get_view_arch_from_file(filename, xmlid):
         if n.tag in ('template', 'record'):
             node = n
             break
-    if node is None:  
+    if node is None:
         # fallback search on template with implicit module name
         for n in doc.xpath('//*[@id="%s"]' % (xmlid.split('.')[1])):
             if n.tag in ('template', 'record'):
@@ -129,13 +130,18 @@ xpath_utils['hasclass'] = _hasclass
 TRANSLATED_ATTRS_RE = re.compile(r"@(%s)\b" % "|".join(TRANSLATED_ATTRS))
 
 
-class view(osv.osv):
+class View(models.Model):
     _name = 'ir.ui.view'
+    _order = "priority,name"
+
+    # Holds the RNG schema
+    _relaxng_validator = None
 
-    def _get_model_data(self, cr, uid, ids, fname, args, context=None):
-        result = dict.fromkeys(ids, False)
-        IMD = self.pool['ir.model.data']
-        data_ids = IMD.search_read(cr, uid, [('res_id', 'in', ids), ('model', '=', 'ir.ui.view')], ['res_id'], context=context)
+    @api.depends('model_data_id')
+    def _get_model_data(self):
+        result = dict.fromkeys(self.ids, False)
+        IMD = self.env['ir.model.data']
+        data_ids = IMD.search_read([('res_id', 'in', self.ids), ('model', '=', 'ir.ui.view')], ['res_id'])
         result.update(map(itemgetter('res_id', 'id'), data_ids))
         return result
 
@@ -148,113 +154,98 @@ class view(osv.osv):
             return m.group('prefix') + str(self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, xmlid))
         return re.sub('(?P<prefix>[^%])%\((?P<xmlid>.*?)\)[ds]', replacer, arch_fs)
 
-    def _arch_get(self, cr, uid, ids, name, arg, context=None):
-        result = {}
-        for view in self.browse(cr, uid, ids, context=context):
+    @api.depends('arch')
+    def _arch_get(self):
+        for view in self:
             arch_fs = None
             if config['dev_mode'] and view.arch_fs and view.xml_id:
                 # It is safe to split on / herebelow because arch_fs is explicitely stored with '/'
                 fullpath = get_resource_path(*view.arch_fs.split('/'))
                 arch_fs = get_view_arch_from_file(fullpath, view.xml_id)
                 # replace %(xml_id)s, %(xml_id)d, %%(xml_id)s, %%(xml_id)d by the res_id
-                arch_fs = arch_fs and self._resolve_external_ids(cr, uid, view, arch_fs)
-            result[view.id] = arch_fs or view.arch_db
-        return result
+                arch_fs = arch_fs and self._resolve_external_ids(view, arch_fs)
+            view.arch = arch_fs or view.arch_db
 
-    def _arch_set(self, cr, uid, ids, field_name, field_value, args, context=None):
-        if not isinstance(ids, list):
-            ids = [ids]
-        if field_value:
-            for view in self.browse(cr, uid, ids, context=context):
-                data = dict(arch_db=field_value)
+    def _arch_set(self):
+        if self.arch:
+            for view in self:
+                data = dict(arch_db=self.arch)
                 key = 'install_mode_data'
-                if context and key in context:
-                    imd = context[key]
+                if self.env.context and key in self.env.context:
+                    imd = self.env.context[key]
                     if self._model._name == imd['model'] and (not view.xml_id or view.xml_id == imd['xml_id']):
                         # we store the relative path to the resource instead of the absolute path, if found
                         # (it will be missing e.g. when importing data-only modules using base_import_module)
                         path_info = get_resource_from_path(imd['xml_file'])
                         if path_info:
                             data['arch_fs'] = '/'.join(path_info[0:2])
-                self.write(cr, uid, ids, data, context=context)
+                self.write(data)
 
         return True
 
-    @api.multi
-    def _arch_base_get(self, name, arg):
+    @api.depends('arch_base')
+    def _arch_base_get(self):
         """ Return the field 'arch' without translation. """
-        return self.with_context(lang=None)._arch_get(name, arg)
+        return self.with_context(lang=None)._arch_get()
 
-    @api.multi
-    def _arch_base_set(self, name, value, arg):
+    def _arch_base_set(self):
         """ Assign the field 'arch' without translation. """
-        return self.with_context(lang=None)._arch_set(name, value, arg)
-
-    _columns = {
-        'name': fields.char('View Name', required=True),
-        'model': fields.char('Object', select=True),
-        'key': fields.char(string='Key'),
-        'priority': fields.integer('Sequence', required=True),
-        'type': fields.selection([
-            ('tree','Tree'),
-            ('form','Form'),
-            ('graph', 'Graph'),
-            ('pivot', 'Pivot'),
-            ('calendar', 'Calendar'),
-            ('diagram','Diagram'),
-            ('gantt', 'Gantt'),
-            ('kanban', 'Kanban'),
-            ('sales_team_dashboard', 'Sales Team Dashboard'),
-            ('search','Search'),
-            ('qweb', 'QWeb')], string='View Type'),
-        'arch': fields.function(_arch_get, fnct_inv=_arch_set, string='View Architecture', type="text", nodrop=True),
-        'arch_base': fields.function(_arch_base_get, fnct_inv=_arch_base_set, string='View Architecture', type="text"),
-        'arch_db': fields.text('Arch Blob', translate=xml_translate, oldname='arch'),
-        'arch_fs': fields.char('Arch Filename'),
-        'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='restrict', select=True),
-        'inherit_children_ids': fields.one2many('ir.ui.view', 'inherit_id', 'Views which inherit from this one'),
-        'field_parent': fields.char('Child Field'),
-        'model_data_id': fields.function(_get_model_data, type='many2one', relation='ir.model.data', string="Model Data", store=True),
-        'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
-                                  help="ID of the view defined in xml file"),
-        'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
-            string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only."),
-        'model_ids': fields.one2many('ir.model.data', 'res_id', domain=[('model','=','ir.ui.view')], auto_join=True),
-        'create_date': fields.datetime('Create Date', readonly=True),
-        'write_date': fields.datetime('Last Modification Date', readonly=True),
-
-        'mode': fields.selection(
-            [('primary', "Base view"), ('extension', "Extension View")],
-            string="View inheritance mode", required=True,
-            help="""Only applies if this view inherits from an other one (inherit_id is not False/Null).
+        return self.with_context(lang=None)._arch_set()
+
+    name = fields.Char(string='View Name', required=True)
+    model = fields.Char(string='Object', index=True)
+    key = fields.Char()
+    priority = fields.Integer(string='Sequence', default=16, required=True)
+    type = fields.Selection([('tree', 'Tree'),
+                             ('form', 'Form'),
+                             ('graph', 'Graph'),
+                             ('pivot', 'Pivot'),
+                             ('calendar', 'Calendar'),
+                             ('diagram', 'Diagram'),
+                             ('gantt', 'Gantt'),
+                             ('kanban', 'Kanban'),
+                             ('sales_team_dashboard', 'Sales Team Dashboard'),
+                             ('search', 'Search'),
+                             ('qweb', 'QWeb')], string='View Type')
+    arch = fields.Text(compute='_arch_get', inverse='_arch_set', string='View Architecture', nodrop=True)
+    arch_base = fields.Text(compute='_arch_base_get', inverse='_arch_base_set', string='View Architecture')
+    arch_db = fields.Text(string='Arch Blob', translate=xml_translate, oldname='arch')
+    arch_fs = fields.Char(string='Arch Filename')
+    inherit_id = fields.Many2one('ir.ui.view', string='Inherited View', ondelete='restrict', index=True)
+    inherit_children_ids = fields.One2many('ir.ui.view', 'inherit_id', string='Views which inherit from this one')
+    field_parent = fields.Char(string='Child Field')
+    model_data_id = fields.Many2one('ir.model.data', compute='_get_model_data', string="Model Data", store=True)
+    # xml_id = fields.Char(compute=model.Model.get_xml_id, string="External ID",
+    #                      help="ID of the view defined in xml file")
+    _columns = {'xml_id': odoo.osv.fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
+                                                   help="ID of the view defined in xml file")}
+    groups_id = fields.Many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
+                                 string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only.")
+    model_ids = fields.One2many('ir.model.data', 'res_id', domain=[('model', '=', 'ir.ui.view')], auto_join=True)
+    create_date = fields.Datetime(readonly=True)
+    write_date = fields.Datetime(string='Last Modification Date', readonly=True)
+
+    mode = fields.Selection([('primary', "Base view"), ('extension', "Extension View")],
+                            string="View inheritance mode", default='primary', required=True,
+                            help="""Only applies if this view inherits from an other one (inherit_id is not False/Null).
 
 * if extension (default), if this view is requested the closest primary view
-  is looked up (via inherit_id), then all views inheriting from it with this
-  view's model are applied
+is looked up (via inherit_id), then all views inheriting from it with this
+view's model are applied
 * if primary, the closest primary view is fully resolved (even if it uses a
-  different model than this one), then this view's inheritance specs
-  (<xpath/>) are applied, and the result is used as if it were this view's
-  actual arch.
-"""),
-        'active': fields.boolean("Active",
-            help="""If this view is inherited,
+different model than this one), then this view's inheritance specs
+(<xpath/>) are applied, and the result is used as if it were this view's
+actual arch.
+""")
+    active = fields.Boolean(default=True,
+                            help="""If this view is inherited,
 * if True, the view always extends its parent
 * if False, the view currently does not extend its parent but can be enabled
-             """),
-    }
-    _defaults = {
-        'mode': 'primary',
-        'active': True,
-        'priority': 16,
-    }
-    _order = "priority,name"
-
-    # Holds the RNG schema
-    _relaxng_validator = None
+         """)
 
     def _relaxng(self):
         if not self._relaxng_validator:
-            frng = tools.file_open(os.path.join('base','rng','view.rng'))
+            frng = tools.file_open(os.path.join('base', 'rng', 'view.rng'))
             try:
                 relaxng_doc = etree.parse(frng)
                 self._relaxng_validator = etree.RelaxNG(relaxng_doc)
@@ -280,22 +271,20 @@ class view(osv.osv):
                         self.raise_view_error(view._cr, view._uid, message, view.id)
         return True
 
-    def _check_xml(self, cr, uid, ids, context=None):
-        if context is None:
-            context = {}
-        context = dict(context, check_view_ids=ids)
+    @api.constrains('arch', 'arch_base')
+    def _check_xml(self):
 
         # Sanity checks: the view should not break anything upon rendering!
         # Any exception raised below will cause a transaction rollback.
-        for view in self.browse(cr, uid, ids, context):
+        for view in self:
             view_arch = etree.fromstring(encode(view.arch))
             self._valid_inheritance(view, view_arch)
-            view_def = self.read_combined(cr, uid, view.id, ['arch'], context=context)
+            view_def = self.read_combined(view.id, ['arch'])
             view_arch_utf8 = view_def['arch']
             if view.type != 'qweb':
                 view_doc = etree.fromstring(view_arch_utf8)
                 # verify that all fields used are valid, etc.
-                self.postprocess_and_fields(cr, uid, view.model, view_doc, view.id, context=context)
+                self.postprocess_and_fields(view.model, view_doc, view.id)
                 # RNG-based validation is not possible anymore with 7.0 forms
                 view_docs = [view_doc]
                 if view_docs[0].tag == 'data':
@@ -307,9 +296,9 @@ class view(osv.osv):
                     if parse_version(version) < parse_version('7.0') and validator and not validator.validate(view_arch):
                         for error in validator.error_log:
                             _logger.error(tools.ustr(error))
-                        return False
+                        raise ValidationError(_('Invalid view definition'))
                     if not valid_view(view_arch):
-                        return False
+                        raise ValidationError(_('Invalid view definition'))
         return True
 
     _sql_constraints = [
@@ -318,26 +307,24 @@ class view(osv.osv):
          "Invalid inheritance mode: if the mode is 'extension', the view must"
          " extend an other view"),
     ]
-    _constraints = [
-        (_check_xml, 'Invalid view definition', ['arch', 'arch_base']),
-    ]
 
-    def _auto_init(self, cr, context=None):
-        super(view, self)._auto_init(cr, context)
-        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_model_type_inherit_id\'')
-        if not cr.fetchone():
-            cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, inherit_id)')
+    def _auto_init(self):
+        super(View, self)._auto_init()
+        self.env.cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_model_type_inherit_id\'')
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, inherit_id)')
 
-    def _compute_defaults(self, cr, uid, values, context=None):
+    def _compute_defaults(self, values):
         if 'inherit_id' in values:
             values.setdefault(
                 'mode', 'extension' if values['inherit_id'] else 'primary')
         return values
 
-    def create(self, cr, uid, values, context=None):
+    @api.model
+    def create(self, values):
         if not values.get('type'):
             if values.get('inherit_id'):
-                values['type'] = self.browse(cr, uid, values['inherit_id'], context).type
+                values['type'] = self.browse(values['inherit_id']).type
             else:
                 values['type'] = etree.fromstring(values['arch']).tag
 
@@ -345,43 +332,35 @@ class view(osv.osv):
             values['name'] = "%s %s" % (values.get('model'), values['type'])
 
         self.clear_caches()
-        return super(view, self).create(
-            cr, uid,
-            self._compute_defaults(cr, uid, values, context=context),
-            context=context)
-
-    def write(self, cr, uid, ids, vals, context=None):
-        if not isinstance(ids, (list, tuple)):
-            ids = [ids]
-        if context is None:
-            context = {}
+        return super(View, self).create(self._compute_defaults(values))
 
+    @api.multi
+    def write(self, vals):
         # If view is modified we remove the arch_fs information thus activating the arch_db
         # version. An `init` of the view will restore the arch_fs for the --dev mode
-        if 'arch' in vals and 'install_mode_data' not in context:
+        if 'arch' in vals and 'install_mode_data' not in self.env.context:
             vals['arch_fs'] = False
 
         # drop the corresponding view customizations (used for dashboards for example), otherwise
         # not all users would see the updated views
-        custom_view_ids = self.pool.get('ir.ui.view.custom').search(cr, uid, [('ref_id', 'in', ids)])
-        if custom_view_ids:
-            self.pool.get('ir.ui.view.custom').unlink(cr, uid, custom_view_ids)
+        custom_view = self.env['ir.ui.view.custom'].search([('ref_id', 'in', self.ids)])
+        if custom_view:
+            custom_view.unlink()
 
         self.clear_caches()
-        ret = super(view, self).write(
-            cr, uid, ids,
-            self._compute_defaults(cr, uid, vals, context=context),
-            context)
-        return ret
+        res = super(View, self).write(self._compute_defaults(vals))
+        return res
 
-    def toggle(self, cr, uid, ids, context=None):
+    @api.multi
+    def toggle(self):
         """ Switches between enabled and disabled statuses
         """
-        for view in self.browse(cr, uid, ids, context=dict(context or {}, active_test=False)):
+        for view in self:
             view.write({'active': not view.active})
 
     # default view selection
-    def default_view(self, cr, uid, model, view_type, context=None):
+    @api.model
+    def default_view(self, model, view_type):
         """ Fetches the default view for the provided (model, view_type) pair:
          primary view with the lowest priority.
 
@@ -390,20 +369,16 @@ class view(osv.osv):
         :return: id of the default view of False if none found
         :rtype: int
         """
-        domain = [
-            ['model', '=', model],
-            ['type', '=', view_type],
-            ['mode', '=', 'primary'],
-        ]
-        ids = self.search(cr, uid, domain, limit=1, context=context)
-        if not ids:
+        rec = self.search([('model', '=', model), ('type', '=', view_type), ('mode', '=', 'primary')], limit=1)
+        if not rec:
             return False
-        return ids[0]
+        return rec.id
 
     #------------------------------------------------------
     # Inheritance mecanism
     #------------------------------------------------------
-    def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None):
+    @api.model
+    def get_inheriting_views_arch(self, view_id, model):
         """Retrieves the architecture of views that inherit from the given view, from the sets of
            views that should currently be used in the system. During the module upgrade phase it
            may happen that a view is present in the database but the fields it relies on are not
@@ -416,11 +391,8 @@ class view(osv.osv):
            :rtype: list of tuples
            :return: [(view_arch,view_id), ...]
         """
-        if not context:
-            context = {}
 
-        user = self.pool['res.users'].browse(cr, 1, uid, context=context)
-        user_groups = frozenset(user.groups_id or ())
+        user_groups = frozenset(self.env.user.groups_id or ())
 
         conditions = [
             ['inherit_id', '=', view_id],
@@ -428,22 +400,23 @@ class view(osv.osv):
             ['mode', '=', 'extension'],
             ['active', '=', True],
         ]
-        if self.pool._init and not context.get('load_all_views'):
+        if self.pool._init and not self.env.context.get('load_all_views'):
             # Module init currently in progress, only consider views from
             # modules whose code is already loaded
             conditions.extend([
                 '|',
                 ['model_ids.module', 'in', tuple(self.pool._init_modules)],
-                ['id', 'in', context.get('check_view_ids') or (0,)],
+                ['id', 'in', self.env.context.get('check_view_ids') or (0,)],
             ])
-        view_ids = self.search(cr, uid, conditions, context=context)
+        view_ids = self.search(conditions)
 
         return [(view.arch, view.id)
-                for view in self.browse(cr, 1, view_ids, context)
+                for view in view_ids
                 if not (view.groups_id and user_groups.isdisjoint(view.groups_id))]
 
-    def raise_view_error(self, cr, uid, message, view_id, context=None):
-        view = self.browse(cr, uid, view_id, context)
+    @api.model
+    def raise_view_error(self, message, view_id):
+        view = self.browse(view_id)
         not_avail = _('n/a')
         message = ("%(msg)s\n\n" +
                    _("Error context:\nView `%(view_name)s`") + 
@@ -489,7 +462,7 @@ class view(osv.osv):
             if isinstance(node, SKIPPED_ELEMENT_TYPES):
                 continue
             if all(node.get(attr) == spec.get(attr) for attr in spec.attrib
-                   if attr not in ('position','version')):
+                   if attr not in ('position', 'version')):
                 # Version spec should match parent's root element's version
                 if spec.get('version') and spec.get('version') != arch.get('version'):
                     return None
@@ -509,7 +482,8 @@ class view(osv.osv):
 
         return specs_tree
 
-    def apply_inheritance_specs(self, cr, uid, source, specs_tree, inherit_id, context=None):
+    @api.model
+    def apply_inheritance_specs(self, source, specs_tree, inherit_id):
         """ Apply an inheriting view (a descendant of the base view)
 
         Apply to a source architecture all the spec nodes (i.e. nodes
@@ -574,7 +548,7 @@ class view(osv.osv):
                         elif pos == 'before':
                             node.addprevious(child)
                         else:
-                            self.raise_view_error(cr, uid, _("Invalid position attribute: '%s'") % pos, inherit_id, context=context)
+                            self.raise_view_error(_("Invalid position attribute: '%s'") % pos, inherit_id)
             else:
                 attrs = ''.join([
                     ' %s="%s"' % (attr, spec.get(attr))
@@ -582,11 +556,12 @@ class view(osv.osv):
                     if attr != 'position'
                 ])
                 tag = "<%s%s>" % (spec.tag, attrs)
-                self.raise_view_error(cr, uid, _("Element '%s' cannot be located in parent view") % tag, inherit_id, context=context)
+                self.raise_view_error(_("Element '%s' cannot be located in parent view") % tag, inherit_id)
 
         return source
 
-    def apply_view_inheritance(self, cr, uid, source, source_id, model, root_id=None, context=None):
+    @api.model
+    def apply_view_inheritance(self, source, source_id, model, root_id=None):
         """ Apply all the (directly and indirectly) inheriting views.
 
         :param source: a parent architecture to modify (with parent modifications already applied)
@@ -596,19 +571,19 @@ class view(osv.osv):
             views with that specific model will be applied.
         :return: a modified source where all the modifying architecture are applied
         """
-        if context is None: context = {}
         if root_id is None:
             root_id = source_id
-        sql_inherit = self.get_inheriting_views_arch(cr, uid, source_id, model, context=context)
+        sql_inherit = self.get_inheriting_views_arch(source_id, model)
         for (specs, view_id) in sql_inherit:
             specs_tree = etree.fromstring(specs.encode('utf-8'))
-            if context.get('inherit_branding'):
+            if self.env.context.get('inherit_branding'):
                 self.inherit_branding(specs_tree, view_id, root_id)
-            source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
-            source = self.apply_view_inheritance(cr, uid, source, view_id, model, root_id=root_id, context=context)
+            source = self.apply_inheritance_specs(source, specs_tree, view_id)
+            source = self.apply_view_inheritance(source, view_id, model, root_id=root_id)
         return source
 
-    def read_combined(self, cr, uid, view_id, fields=None, context=None):
+    @api.model
+    def read_combined(self, view_id, fields=None):
         """
         Utility function to get a view combined with its inherited views.
 
@@ -618,55 +593,51 @@ class view(osv.osv):
           .. note:: ``arch`` is always added to the fields list even if not
                     requested (similar to ``id``)
         """
-        if context is None: context = {}
-        context = context.copy()
+        ctx = self.env.context.copy()
 
         # if view_id is not a root view, climb back to the top.
-        base = v = self.browse(cr, uid, view_id, context=context)
-        check_view_ids = context.setdefault('check_view_ids', [])
+        base = v = self.browse(view_id)
+        check_view_ids = ctx.setdefault('check_view_ids', [])
         while v.mode != 'primary':
             # Add inherited views to the list of loading forced views
             # Otherwise, inherited views could not find elements created in their direct parents if that parent is defined in the same module
             check_view_ids.append(v.id)
             v = v.inherit_id
-        root_id = v.id
+        root = v
 
         # arch and model fields are always returned
         if fields:
             fields = list({'arch', 'model'}.union(fields))
 
         # read the view arch
-        [view] = self.read(cr, uid, [root_id], fields=fields, context=context)
+        [view] = root.read(fields=fields)
         view_arch = etree.fromstring(view['arch'].encode('utf-8'))
         if not v.inherit_id:
             arch_tree = view_arch
         else:
-            parent_view = self.read_combined(
-                cr, uid, v.inherit_id.id, fields=fields, context=context)
+            parent_view = self.read_combined(v.inherit_id.id, fields=fields)
             arch_tree = etree.fromstring(parent_view['arch'])
-            arch_tree = self.apply_inheritance_specs(
-                cr, uid, arch_tree, view_arch, parent_view['id'], context=context)
+            arch_tree = self.apply_inheritance_specs(arch_tree, view_arch, parent_view['id'])
 
-        if context.get('inherit_branding'):
+        if self.env.context.get('inherit_branding'):
             arch_tree.attrib.update({
                 'data-oe-model': 'ir.ui.view',
-                'data-oe-id': str(root_id),
+                'data-oe-id': str(root.id),
                 'data-oe-field': 'arch',
             })
 
         # and apply inheritance
-        arch = self.apply_view_inheritance(
-            cr, uid, arch_tree, root_id, base.model, context=context)
+        arch = self.apply_view_inheritance(arch_tree, root.id, base.model)
 
         return dict(view, arch=etree.tostring(arch, encoding='utf-8'))
 
     #------------------------------------------------------
     # Postprocessing: translation, groups and modifiers
     #------------------------------------------------------
-    # TODO: 
-    # - remove group processing from ir_qweb
+    # TODO: remove group processing from ir_qweb
     #------------------------------------------------------
-    def postprocess(self, cr, user, model, node, view_id, in_tree_view, model_fields, context=None):
+    @api.model
+    def postprocess(self, model, node, view_id, in_tree_view, model_fields):
         """Return the description of the fields in the node.
 
         In a normal call to this method, node is a complete view architecture
@@ -678,17 +649,14 @@ class view(osv.osv):
         of those information in the architecture.
 
         """
-        if context is None:
-            context = {}
         result = False
         fields = {}
         children = True
 
         modifiers = {}
-        Model = self.pool.get(model)
+        Model = self.env[model]
         if Model is None:
-            self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model),
-                                  view_id, context)
+            self.raise_view_error(_('Model not found: %(model)s') % dict(model=model), view_id)
 
         def encode(s):
             if isinstance(s, unicode):
@@ -707,20 +675,18 @@ class view(osv.osv):
             """
             if node.tag == 'field' and node.get('name') in Model._fields:
                 field = Model._fields[node.get('name')]
-                if field.groups and not self.user_has_groups(
-                        cr, user, groups=field.groups, context=context):
+                if field.groups and not self.user_has_groups(groups=field.groups):
                     node.getparent().remove(node)
                     fields.pop(node.get('name'), None)
                     # no point processing view-level ``groups`` anymore, return
                     return False
             if node.get('groups'):
-                can_see = self.user_has_groups(
-                    cr, user, groups=node.get('groups'), context=context)
+                can_see = self.user_has_groups(groups=node.get('groups'))
                 if not can_see:
                     node.set('invisible', '1')
                     modifiers['invisible'] = True
                     if 'attrs' in node.attrib:
-                        del(node.attrib['attrs']) #avoid making field visible later
+                        del(node.attrib['attrs'])  # avoid making field visible later
                 del(node.attrib['groups'])
             return True
 
@@ -734,9 +700,9 @@ class view(osv.osv):
                         xml += etree.tostring(f, encoding="utf-8")
                 xml += "</form>"
                 new_xml = etree.fromstring(encode(xml))
-                ctx = context.copy()
+                ctx = self.env.context.copy()
                 ctx['base_model_name'] = model
-                xarch, xfields = self.postprocess_and_fields(cr, user, node.get('object'), new_xml, view_id, ctx)
+                xarch, xfields = self.with_context(ctx).postprocess_and_fields(node.get('object'), new_xml, view_id)
                 views['form'] = {
                     'arch': xarch,
                     'fields': xfields
@@ -752,9 +718,9 @@ class view(osv.osv):
                     for f in node:
                         if f.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
                             node.remove(f)
-                            ctx = context.copy()
+                            ctx = self.env.context.copy()
                             ctx['base_model_name'] = model
-                            xarch, xfields = self.postprocess_and_fields(cr, user, field.comodel_name, f, view_id, ctx)
+                            xarch, xfields = self.with_context(ctx).postprocess_and_fields(field.comodel_name, f, view_id)
                             views[str(f.tag)] = {
                                 'arch': xarch,
                                 'fields': xfields
@@ -762,8 +728,8 @@ class view(osv.osv):
                     attrs = {'views': views}
                     Relation = self.pool.get(field.comodel_name)
                     if Relation and field.type in ('many2one', 'many2many'):
-                        node.set('can_create', 'true' if Relation.check_access_rights(cr, user, 'create', raise_exception=False) else 'false')
-                        node.set('can_write', 'true' if Relation.check_access_rights(cr, user, 'write', raise_exception=False) else 'false')
+                        node.set('can_create', 'true' if Relation.check_access_rights(self._cr, self._uid, 'create', raise_exception=False) else 'false')
+                        node.set('can_write', 'true' if Relation.check_access_rights(self._cr, self._uid, 'write', raise_exception=False) else 'false')
                 fields[node.get('name')] = attrs
 
                 field = model_fields.get(node.get('name'))
@@ -771,7 +737,7 @@ class view(osv.osv):
                     orm.transfer_field_to_modifiers(field, modifiers)
 
         elif node.tag in ('form', 'tree'):
-            result = Model.view_header_get(cr, user, False, node.tag, context=context)
+            result = Model.view_header_get(False, node.tag)
             if result:
                 node.set('string', result)
             in_tree_view = node.tag == 'tree'
@@ -787,16 +753,16 @@ class view(osv.osv):
 
         # The view architeture overrides the python model.
         # Get the attrs before they are (possibly) deleted by check_group below
-        orm.transfer_node_to_modifiers(node, modifiers, context, in_tree_view)
+        orm.transfer_node_to_modifiers(node, modifiers, self.env.context, in_tree_view)
 
         for f in node:
-            if children or (node.tag == 'field' and f.tag in ('filter','separator')):
-                fields.update(self.postprocess(cr, user, model, f, view_id, in_tree_view, model_fields, context))
+            if children or (node.tag == 'field' and f.tag in ('filter', 'separator')):
+                fields.update(self.postprocess(model, f, view_id, in_tree_view, model_fields))
 
         orm.transfer_modifiers_to_node(modifiers, node)
         return fields
 
-    def add_on_change(self, cr, user, model_name, arch):
+    def add_on_change(self, model_name, arch):
         """ Add attribute on_change="1" on fields that are dependencies of
             computed fields on the same view.
         """
@@ -809,16 +775,16 @@ class view(osv.osv):
                 if field:
                     field_nodes[field].append(node)
                     if field.relational:
-                        model = self.pool.get(field.comodel_name)
+                        model = self.env[field.comodel_name]
             for child in node:
                 collect(child, model)
 
-        collect(arch, self.pool[model_name])
+        collect(arch, self.env[model_name])
 
         for field, nodes in field_nodes.iteritems():
             # if field should trigger an onchange, add on_change="1" on the
             # nodes referring to field
-            model = self.pool[field.model_name]
+            model = self.env[field.model_name]
             if model._has_onchange(field, field_nodes):
                 for node in nodes:
                     if not node.get('on_change'):
@@ -826,19 +792,18 @@ class view(osv.osv):
 
         return arch
 
-    def _disable_workflow_buttons(self, cr, user, model, node):
+    def _disable_workflow_buttons(self, model, node):
         """ Set the buttons in node to readonly if the user can't activate them. """
-        if model is None or user == 1:
+        if model is None or self.env.user.id == 1:
             # admin user can always activate workflow buttons
             return node
 
         # TODO handle the case of more than one workflow for a model or multiple
         # transitions with different groups and same signal
-        usersobj = self.pool.get('res.users')
         buttons = (n for n in node.getiterator('button') if n.get('type') != 'object')
         for button in buttons:
-            user_groups = usersobj.read(cr, user, [user], ['groups_id'])[0]['groups_id']
-            cr.execute("""SELECT DISTINCT t.group_id
+            user_groups = self.env.user.groups_id
+            self.env.cr.execute("""SELECT DISTINCT t.group_id
                         FROM wkf
                   INNER JOIN wkf_activity a ON a.wkf_id = wkf.id
                   INNER JOIN wkf_transition t ON (t.act_to = a.id)
@@ -846,12 +811,13 @@ class view(osv.osv):
                          AND t.signal = %s
                          AND t.group_id is NOT NULL
                    """, (model, button.get('name')))
-            group_ids = [x[0] for x in cr.fetchall() if x[0]]
+            group_ids = [x[0] for x in self.env.cr.fetchall() if x[0]]
             can_click = not group_ids or bool(set(user_groups).intersection(group_ids))
             button.set('readonly', str(int(not can_click)))
         return node
 
-    def postprocess_and_fields(self, cr, user, model, node, view_id, context=None):
+    @api.model
+    def postprocess_and_fields(self, model, node, view_id):
         """ Return an architecture and a description of all the fields.
 
         The field description combines the result of fields_get() and
@@ -863,33 +829,33 @@ class view(osv.osv):
 
         """
         fields = {}
-        Model = self.pool.get(model)
+        Model = self.env[model]
         if Model is None:
-            self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model), view_id, context)
+            self.raise_view_error(_('Model not found: %(model)s') % dict(model=model), view_id)
 
         if node.tag == 'diagram':
             if node.getchildren()[0].tag == 'node':
-                node_model = self.pool[node.getchildren()[0].get('object')]
-                node_fields = node_model.fields_get(cr, user, None, context=context)
+                node_model = self.env[node.getchildren()[0].get('object')]
+                node_fields = node_model.fields_get(None)
                 fields.update(node_fields)
                 if not node.get("create") and \
-                   not node_model.check_access_rights(cr, user, 'create', raise_exception=False) or \
-                   not context.get("create", True):
+                   not node_model.check_access_rights('create', raise_exception=False) or \
+                   not self.env.context.get("create", True):
                     node.set("create", 'false')
             if node.getchildren()[1].tag == 'arrow':
-                arrow_fields = self.pool[node.getchildren()[1].get('object')].fields_get(cr, user, None, context=context)
+                arrow_fields = self.env[node.getchildren()[1].get('object')].fields_get(None)
                 fields.update(arrow_fields)
         else:
-            fields = Model.fields_get(cr, user, None, context=context)
+            fields = Model.fields_get(None)
 
-        node = self.add_on_change(cr, user, model, node)
-        fields_def = self.postprocess(cr, user, model, node, view_id, False, fields, context=context)
-        node = self._disable_workflow_buttons(cr, user, model, node)
+        node = self.add_on_change(model, node)
+        fields_def = self.postprocess(model, node, view_id, False, fields)
+        node = self._disable_workflow_buttons(model, node)
         if node.tag in ('kanban', 'tree', 'form', 'gantt'):
             for action, operation in (('create', 'create'), ('delete', 'unlink'), ('edit', 'write')):
                 if not node.get(action) and \
-                   not Model.check_access_rights(cr, user, operation, raise_exception=False) or \
-                   not context.get(action, True):
+                   not Model.check_access_rights(operation, raise_exception=False) or \
+                   not self.env.context.get(action, True):
                     node.set(action, 'false')
         if node.tag in ('kanban',):
             group_by_name = node.get('default_group_by')
@@ -899,8 +865,8 @@ class view(osv.osv):
                     group_by_model = Model.pool[group_by_field.comodel_name]
                     for action, operation in (('group_create', 'create'), ('group_delete', 'unlink'), ('group_edit', 'write')):
                         if not node.get(action) and \
-                           not group_by_model.check_access_rights(cr, user, operation, raise_exception=False) or \
-                           not context.get(action, True):
+                           not group_by_model.check_access_rights(operation, raise_exception=False) or \
+                           not self.env.context.get(action, True):
                             node.set(action, 'false')
 
         arch = etree.tostring(node, encoding="utf-8").replace('\t', '')
@@ -913,7 +879,7 @@ class view(osv.osv):
             else:
                 message = _("Field `%(field_name)s` does not exist") % \
                                 dict(field_name=field)
-                self.raise_view_error(cr, user, message, view_id, context)
+                self.raise_view_error(message, view_id)
         return arch, fields
 
     #------------------------------------------------------
@@ -948,7 +914,7 @@ class view(osv.osv):
     def clear_cache(self):
         """ Deprecated, use `clear_caches` instead. """
         if not config['dev_mode']:
-	    self.clear_caches()
+            self.clear_caches()
 
     def _contains_branded(self, node):
         return node.tag == 't'\
@@ -1024,12 +990,10 @@ class view(osv.osv):
         # Deprecated: templates are translated once read from database
         return arch
 
-    @openerp.tools.ormcache('uid', 'id')
-    def get_view_xmlid(self, cr, uid, id):
-        imd = self.pool['ir.model.data']
-        domain = [('model', '=', 'ir.ui.view'), ('res_id', '=', id)]
-        xmlid = imd.search_read(cr, uid, domain, ['module', 'name'])[0]
-        return '%s.%s' % (xmlid['module'], xmlid['name'])
+    @odoo.tools.ormcache('self.env.uid', 'self.id')
+    def get_view_xmlid(self):
+        xmlid = self.env['ir.model.data'].search([('model', '=', 'ir.ui.view'), ('res_id', '=', id)])
+        return '%s.%s' % (xmlid.module, xmlid.name)
 
     @api.cr_uid_ids_context
     def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None):
@@ -1078,60 +1042,60 @@ class view(osv.osv):
         """ Open a view for editing the translations of field 'arch_db'. """
         return self.env['ir.translation'].translate_fields('ir.ui.view', self.id, 'arch_db')
 
-    def graph_get(self, cr, uid, id, model, node_obj, conn_obj, src_node, des_node, label, scale, context=None):
-        nodes=[]
-        nodes_name=[]
-        transitions=[]
-        start=[]
-        tres={}
-        labels={}
-        no_ancester=[]
+    @api.model
+    def graph_get(self, model, node_obj, conn_obj, src_node, des_node, label, scale):
+        nodes = []
+        nodes_name = []
+        transitions = []
+        start = []
+        tres = {}
+        labels = {}
+        no_ancester = []
         blank_nodes = []
 
-        _Model_Obj = self.pool[model]
-        _Node_Obj = self.pool[node_obj]
-        _Arrow_Obj = self.pool[conn_obj]
-
-        for model_key,model_value in _Model_Obj._columns.items():
-                if model_value._type=='one2many':
-                    if model_value._obj==node_obj:
-                        _Node_Field=model_key
-                        _Model_Field=model_value._fields_id
-                    for node_key,node_value in _Node_Obj._columns.items():
-                        if node_value._type=='one2many':
-                             if node_value._obj==conn_obj:
+        _Model_Obj = self.env[model]
+        _Node_Obj = self.env[node_obj]
+
+        for model_key, model_value in _Model_Obj._columns.items():
+                if model_value._type == 'one2many':
+                    if model_value._obj == node_obj:
+                        _Node_Field = model_key
+                        _Model_Field = model_value._fields_id
+                    for node_key, node_value in _Node_Obj._columns.items():
+                        if node_value._type == 'one2many':
+                            if node_value._obj == conn_obj:
                                  # _Source_Field = "Incoming Arrows" (connected via des_node)
-                                 if node_value._fields_id == des_node:
-                                    _Source_Field=node_key
+                                if node_value._fields_id == des_node:
+                                    _Source_Field = node_key
                                  # _Destination_Field = "Outgoing Arrows" (connected via src_node)
-                                 if node_value._fields_id == src_node:
-                                    _Destination_Field=node_key
+                                if node_value._fields_id == src_node:
+                                    _Destination_Field = node_key
 
-        datas = _Model_Obj.read(cr, uid, id, [],context)
-        for a in _Node_Obj.read(cr,uid,datas[_Node_Field],[]):
+        datas = _Model_Obj.read()
+        for a in _Node_Obj.read(datas[_Node_Field]):
             if a[_Source_Field] or a[_Destination_Field]:
-                nodes_name.append((a['id'],a['name'] if 'name' in a else a.get('x_name')))
+                nodes_name.append((a['id'], a['name'] if 'name' in a else a.get('x_name')))
                 nodes.append(a['id'])
             else:
-                blank_nodes.append({'id': a['id'],'name':a['name'] if 'name' in a else a.get('x_name')})
+                blank_nodes.append({'id': a['id'], 'name': a['name'] if 'name' in a else a.get('x_name')})
 
             if a.has_key('flow_start') and a['flow_start']:
                 start.append(a['id'])
             else:
                 if not a[_Source_Field]:
                     no_ancester.append(a['id'])
-            for t in _Arrow_Obj.read(cr,uid, a[_Destination_Field],[]):
+            for t in self.env[conn_obj].read(a[_Destination_Field]):
                 transitions.append((a['id'], t[des_node][0]))
-                tres[str(t['id'])] = (a['id'],t[des_node][0])
+                tres[str(t['id'])] = (a['id'], t[des_node][0])
                 label_string = ""
                 if label:
                     for lbl in eval(label):
-                        if t.has_key(tools.ustr(lbl)) and tools.ustr(t[lbl])=='False':
+                        if t.has_key(tools.ustr(lbl)) and tools.ustr(t[lbl]) == 'False':
                             label_string += ' '
                         else:
                             label_string = label_string + " " + tools.ustr(t[lbl])
-                labels[str(t['id'])] = (a['id'],label_string)
-        g  = graph(nodes, transitions, no_ancester)
+                labels[str(t['id'])] = (a['id'], label_string)
+        g = graph(nodes, transitions, no_ancester)
         g.process(start)
         g.scale(*scale)
         result = g.result_get()
@@ -1141,15 +1105,16 @@ class view(osv.osv):
             results[str(node[0])]['name'] = node[1]
         return {'nodes': results,
                 'transitions': tres,
-                'label' : labels,
+                'label': labels,
                 'blank_nodes': blank_nodes,
-                'node_parent_field': _Model_Field,}
+                'node_parent_field': _Model_Field}
 
-    def _validate_custom_views(self, cr, uid, model):
+    @api.model
+    def _validate_custom_views(self, model):
         """Validate architecture of custom views (= without xml id) for a given model.
             This method is called at the end of registry update.
         """
-        cr.execute("""SELECT max(v.id)
+        self.env.cr.execute("""SELECT max(v.id)
                         FROM ir_ui_view v
                    LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
                        WHERE md.module IS NULL
@@ -1158,11 +1123,11 @@ class view(osv.osv):
                     GROUP BY coalesce(v.inherit_id, v.id)
                    """, (model,))
 
-        ids = map(itemgetter(0), cr.fetchall())
-        context = dict(load_all_views=True)
-        return self._check_xml(cr, uid, ids, context=context)
+        rec = self.browse(map(itemgetter(0), self.env.cr.fetchall()))
+        return rec.with_context({'load_all_views': True})._check_xml()
 
-    def _validate_module_views(self, cr, uid, module):
+    @api.model
+    def _validate_module_views(self, module):
         """Validate architecture of all the views of a given module"""
         assert not self.pool._init or module in self.pool._init_modules
         xmlid_filter = ''
@@ -1175,7 +1140,7 @@ class view(osv.osv):
                 # no views for this module, nothing to validate
                 return
             params += (names,)
-        cr.execute("""SELECT max(v.id)
+        self.env.cr.execute("""SELECT max(v.id)
                         FROM ir_ui_view v
                    LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
                        WHERE md.module = %s
@@ -1183,6 +1148,6 @@ class view(osv.osv):
                     GROUP BY coalesce(v.inherit_id, v.id)
                    """.format(xmlid_filter), params)
 
-        for vid, in cr.fetchall():
-            if not self._check_xml(cr, uid, [vid]):
-                self.raise_view_error(cr, uid, "Can't validate view", vid)
+        for vid, in self.env.cr.fetchall():
+            if not self._check_xml():
+                self.raise_view_error("Can't validate view", vid)
diff --git a/openerp/addons/base/ir/ir_ui_view_view.xml b/openerp/addons/base/ir/ir_ui_view_view.xml
index 5aa6f5c6a99e3571097d7a8bfc82eaefdb9b934f..ae78ecac56694d9ff52106a1849887ac6bcffb84 100644
--- a/openerp/addons/base/ir/ir_ui_view_view.xml
+++ b/openerp/addons/base/ir/ir_ui_view_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- View -->
         <record id="view_view_form" model="ir.ui.view">
             <field name="model">ir.ui.view</field>
@@ -136,5 +135,4 @@
         </record>
         <menuitem id="menu_action_ui_view_custom" action="action_ui_view_custom" parent="base.next_id_2" sequence="3"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/ir_values.py b/openerp/addons/base/ir/ir_values.py
index 6186fb1bd451b6876957b29b77f7a52e43ebcd82..84f3990c1820303f347845823ef29de8eadeaebf 100644
--- a/openerp/addons/base/ir/ir_values.py
+++ b/openerp/addons/base/ir/ir_values.py
@@ -1,11 +1,9 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from openerp import tools
-from openerp.osv import osv, fields
-from openerp.exceptions import AccessError, MissingError
-from openerp.tools.translate import _
-from openerp.tools import pickle
+from odoo import api, fields, models, tools, _
+from odoo.exceptions import AccessError, MissingError
+from odoo.tools import pickle
 
 EXCLUDED_FIELDS = set((
     'report_sxw_content', 'report_rml_content', 'report_sxw', 'report_rml',
@@ -21,7 +19,7 @@ ACTION_SLOTS = [
                ]
 
 
-class ir_values(osv.osv):
+class IrValues(models.Model):
     """Holds internal model-specific action bindings and user-defined default
        field values. definitions. This is a legacy internal model, mixing
        two different concepts, and will likely be updated or replaced in a
@@ -70,124 +68,112 @@ class ir_values(osv.osv):
        users, and set by their UI clients calling :meth:`~.set_default`.
        These default values are then automatically used by the
        ORM every time a new record is about to be created, i.e. when
-       :meth:`~openerp.osv.osv.osv.default_get`
-       or :meth:`~openerp.osv.osv.osv.create` are called.
+       :meth:`~odoo.osv.osv.osv.default_get`
+       or :meth:`~odoo.osv.osv.osv.create` are called.
 
        .. rubric:: Usage: action bindings
 
        Business applications will usually bind their actions during
-       installation, and OpenERP UI clients will apply them as defined,
+       installation, and Odoo UI clients will apply them as defined,
        based on the list of actions included in the result of
-       :meth:`~openerp.osv.osv.osv.fields_view_get`,
+       :meth:`~odoo.osv.osv.osv.fields_view_get`,
        or directly returned by explicit calls to :meth:`~.get_actions`.
     """
     _name = 'ir.values'
 
-    def _value_unpickle(self, cursor, user, ids, name, arg, context=None):
-        res = {}
-        for record in self.browse(cursor, user, ids, context=context):
-            value = record[name[:-9]]
+    name = fields.Char(required=True)
+    model = fields.Char(string='Model Name', select=True, required=True,
+                        help="Model to which this entry applies")
+
+      # TODO: model_id and action_id should be read-write function fields
+    model_id = fields.Many2one('ir.model', string='Model (change only)',
+                               help="Model to which this entry applies - "
+                                    "helper field for setting a model, will "
+                                    "automatically set the correct model name")
+    action_id = fields.Many2one('ir.actions.actions', string='Action (change only)',
+                                help="Action bound to this entry - "
+                                     "helper field for binding an action, will "
+                                     "automatically set the correct reference")
+
+    value = fields.Text(help="Default value (pickled) or reference to an action")
+    value_unpickle = fields.Text(compute='_value_unpickle', inverse='_value_pickle',
+                                 string='Default value or action reference')
+    key = fields.Selection([('action', 'Action'), ('default', 'Default')],
+                           string='Type', index=True, required=True, default='action',
+                           help="- Action: an action attached to one slot of the given model\n"
+                                "- Default: a default value for a model field")
+    key2 = fields.Char(string='Qualifier', index=True, default='tree_but_open',
+                       help="For actions, one of the possible action slots: \n"
+                            "  - client_action_multi\n"
+                            "  - client_print_multi\n"
+                            "  - client_action_relate\n"
+                            "  - tree_but_open\n"
+                            "For defaults, an optional condition")
+    res_id = fields.Integer(string='Record ID', index=True,
+                            help="Database identifier of the record to which this applies. "
+                                 "0 = for all records")
+    user_id = fields.Many2one('res.users', string='User', ondelete='cascade', index=True,
+                              help="If set, action binding only applies for this user.")
+    company_id = fields.Many2one('res.company', string='Company', ondelete='cascade', index=True,
+                                 help="If set, action binding only applies for this company")
+
+    @api.depends('value_unpickle')
+    def _value_unpickle(self):
+        for record in self:
+            value = record.value
             if record.key == 'default' and value:
                 # default values are pickled on the fly
                 try:
                     value = str(pickle.loads(value))
                 except Exception:
                     pass
-            res[record.id] = value
-        return res
+            record.value_unpickle = value
 
-    def _value_pickle(self, cursor, user, id, name, value, arg, context=None):
-        if context is None:
-            context = {}
-        ctx = context.copy()
+    def _value_pickle(self):
+        ctx = self.env.context.copy()
         if self.CONCURRENCY_CHECK_FIELD in ctx:
             del ctx[self.CONCURRENCY_CHECK_FIELD]
-        record = self.browse(cursor, user, id, context=context)
-        if record.key == 'default':
+        if self.key == 'default':
             # default values are pickled on the fly
-            value = pickle.dumps(value)
-        self.write(cursor, user, id, {name[:-9]: value}, context=ctx)
-
-    def onchange_object_id(self, cr, uid, ids, object_id, context=None):
-        if not object_id: return {}
-        act = self.pool.get('ir.model').browse(cr, uid, object_id, context=context)
-        return {
-                'value': {'model': act.model}
-        }
-
-    def onchange_action_id(self, cr, uid, ids, action_id, context=None):
-        if not action_id: return {}
-        act = self.pool.get('ir.actions.actions').browse(cr, uid, action_id, context=context)
-        return {
-                'value': {'value_unpickle': act.type+','+str(act.id)}
-        }
-
-    _columns = {
-        'name': fields.char('Name', required=True),
-        'model': fields.char('Model Name', select=True, required=True,
-                             help="Model to which this entry applies"),
-
-        # TODO: model_id and action_id should be read-write function fields
-        'model_id': fields.many2one('ir.model', 'Model (change only)', size=128,
-                                    help="Model to which this entry applies - "
-                                         "helper field for setting a model, will "
-                                         "automatically set the correct model name"),
-        'action_id': fields.many2one('ir.actions.actions', 'Action (change only)',
-                                     help="Action bound to this entry - "
-                                         "helper field for binding an action, will "
-                                         "automatically set the correct reference"),
-
-        'value': fields.text('Value', help="Default value (pickled) or reference to an action"),
-        'value_unpickle': fields.function(_value_unpickle, fnct_inv=_value_pickle,
-                                          type='text',
-                                          string='Default value or action reference'),
-        'key': fields.selection([('action','Action'),('default','Default')],
-                                'Type', select=True, required=True,
-                                help="- Action: an action attached to one slot of the given model\n"
-                                     "- Default: a default value for a model field"),
-        'key2' : fields.char('Qualifier', select=True,
-                             help="For actions, one of the possible action slots: \n"
-                                  "  - client_action_multi\n"
-                                  "  - client_print_multi\n"
-                                  "  - client_action_relate\n"
-                                  "  - tree_but_open\n"
-                                  "For defaults, an optional condition"
-                             ,),
-        'res_id': fields.integer('Record ID', select=True,
-                                 help="Database identifier of the record to which this applies. "
-                                      "0 = for all records"),
-        'user_id': fields.many2one('res.users', 'User', ondelete='cascade', select=True,
-                                   help="If set, action binding only applies for this user."),
-        'company_id': fields.many2one('res.company', 'Company', ondelete='cascade', select=True,
-                                      help="If set, action binding only applies for this company")
-    }
-    _defaults = {
-        'key': 'action',
-        'key2': 'tree_but_open',
-    }
-
-    def _auto_init(self, cr, context=None):
-        super(ir_values, self)._auto_init(cr, context)
-        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_values_key_model_key2_res_id_user_id_idx\'')
-        if not cr.fetchone():
-            cr.execute('CREATE INDEX ir_values_key_model_key2_res_id_user_id_idx ON ir_values (key, model, key2, res_id, user_id)')
-
-    def create(self, cr, uid, vals, context=None):
-        res = super(ir_values, self).create(cr, uid, vals, context=context)
+            value = pickle.dumps(self.value)
+        self.write({value: value})
+
+    @api.onchange('model_id')
+    def onchange_object_id(self):
+        if not self.model_id:
+            return {}
+        return {'value': {'model': self.env['ir.model'].browse(self.model_id).model}}
+
+    @api.onchange('action_id')
+    def onchange_action_id(self):
+        if not self.action_id:
+            return {}
+        act = self.env['ir.actions.actions'].browse(self.action_id)
+        return {'value': {'value_unpickle': act.type + ',' + str(act.id)}}
+
+    def _auto_init(self):
+        super(IrValues, self)._auto_init()
+        self.env.cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_values_key_model_key2_res_id_user_id_idx\'')
+        if not self.env.cr.fetchone():
+            self.env.cr.execute('CREATE INDEX ir_values_key_model_key2_res_id_user_id_idx ON ir_values (key, model, key2, res_id, user_id)')
+
+    @api.model
+    def create(self, vals):
         self.clear_caches()
-        return res
+        return super(IrValues, self).create(vals)
 
-    def write(self, cr, uid, ids, vals, context=None):
-        res = super(ir_values, self).write(cr, uid, ids, vals, context=context)
+    @api.multi
+    def write(self, vals):
         self.clear_caches()
-        return res
+        return super(IrValues, self).write(vals)
 
-    def unlink(self, cr, uid, ids, context=None):
-        res = super(ir_values, self).unlink(cr, uid, ids, context=context)
+    @api.multi
+    def unlink(self):
         self.clear_caches()
-        return res
+        return super(IrValues, self).unlink()
 
-    def set_default(self, cr, uid, model, field_name, value, for_all_users=True, company_id=False, condition=False):
+    @api.model
+    def set_default(self, model, field_name, value, for_all_users=True, company_id=False, condition=False):
         """Defines a default value for the given model and field_name. Any previous
            default for the same scope (model, field_name, value, for_all_users, company_id, condition)
            will be replaced and lost in the process.
@@ -225,8 +211,7 @@ class ir_values(osv.osv):
             value = value.encode('utf8')
         if company_id is True:
             # should be company-specific, need to get company id
-            user = self.pool.get('res.users').browse(cr, uid, uid)
-            company_id = user.company_id.id
+            company_id = self.env.user.company_id.id
 
         # remove existing defaults for the same scope
         search_criteria = [
@@ -234,22 +219,23 @@ class ir_values(osv.osv):
             ('key2', '=', condition and condition[:200]),
             ('model', '=', model),
             ('name', '=', field_name),
-            ('user_id', '=', False if for_all_users else uid),
-            ('company_id','=', company_id)
-            ]
-        self.unlink(cr, uid, self.search(cr, uid, search_criteria))
+            ('user_id', '=', False if for_all_users else self._uid),
+            ('company_id', '=', company_id)
+        ]
+        self.search(search_criteria).unlink()
 
-        return self.create(cr, uid, {
+        return self.create({
             'name': field_name,
             'value': pickle.dumps(value),
             'model': model,
             'key': 'default',
             'key2': condition and condition[:200],
-            'user_id': False if for_all_users else uid,
+            'user_id': False if for_all_users else self._uid,
             'company_id': company_id,
         })
 
-    def get_default(self, cr, uid, model, field_name, for_all_users=True, company_id=False, condition=False):
+    @api.model
+    def get_default(self, model, field_name, for_all_users=True, company_id=False, condition=False):
         """ Return the default value defined for model, field_name, users, company and condition.
             Return ``None`` if no such default exists.
         """
@@ -258,13 +244,14 @@ class ir_values(osv.osv):
             ('key2', '=', condition and condition[:200]),
             ('model', '=', model),
             ('name', '=', field_name),
-            ('user_id', '=', False if for_all_users else uid),
-            ('company_id','=', company_id)
-            ]
-        defaults = self.browse(cr, uid, self.search(cr, uid, search_criteria))
-        return pickle.loads(defaults[0].value.encode('utf-8')) if defaults else None
-
-    def get_defaults(self, cr, uid, model, condition=False):
+            ('user_id', '=', False if for_all_users else self._uid),
+            ('company_id', '=', company_id)
+        ]
+        defaults = self.search(search_criteria)
+        return pickle.loads(defaults.value.encode('utf-8')) if defaults else None
+
+    @api.model
+    def get_defaults(self, model, condition=False):
         """Returns any default values that are defined for the current model and user,
            (and match ``condition``, if specified), previously registered via
            :meth:`~.set_default`.
@@ -303,31 +290,33 @@ class ir_values(osv.osv):
                           )
                       %s
                    ORDER BY v.user_id, u.company_id"""
-        params = ('default', model, uid, uid)
+        params = ('default', model, self._uid, self._uid)
         if condition:
             query %= 'AND v.key2 = %s'
             params += (condition[:200],)
         else:
             query %= 'AND v.key2 is NULL'
-        cr.execute(query, params)
+        self.env.cr.execute(query, params)
 
         # keep only the highest priority default for each field
         defaults = {}
-        for row in cr.dictfetchall():
+        for row in self.env.cr.dictfetchall():
             defaults.setdefault(row['name'],
-                (row['id'], row['name'], pickle.loads(row['value'].encode('utf-8'))))
+                               (row['id'], row['name'], pickle.loads(row['value'].encode('utf-8'))))
         return defaults.values()
 
     # use ormcache: this is called a lot by BaseModel.default_get()!
-    @tools.ormcache('uid', 'model', 'condition')
-    def get_defaults_dict(self, cr, uid, model, condition=False):
+    @api.model
+    @tools.ormcache('self.env.uid', 'model', 'condition')
+    def get_defaults_dict(self, model, condition=False):
         """ Returns a dictionary mapping field names with their corresponding
             default value. This method simply improves the returned value of
             :meth:`~.get_defaults`.
         """
-        return dict((f, v) for i, f, v in self.get_defaults(cr, uid, model, condition))
+        return dict((f, v) for i, f, v in self.get_defaults(model, condition))
 
-    def set_action(self, cr, uid, name, action_slot, model, action, res_id=False):
+    @api.model
+    def set_action(self, name, action_slot, model, action, res_id=False):
         """Binds an the given action to the given model's action slot - for later
            retrieval via :meth:`~.get_actions`. Any existing binding of the same action
            to the same slot is first removed, allowing an update of the action's name.
@@ -355,22 +344,23 @@ class ir_values(osv.osv):
             ('key', '=', 'action'),
             ('key2', '=', action_slot),
             ('model', '=', model),
-            ('res_id', '=', res_id or 0), # int field -> NULL == 0
+            ('res_id', '=', res_id or 0),  # int field -> NULL == 0
             ('value', '=', action),
-            ]
-        self.unlink(cr, uid, self.search(cr, uid, search_criteria))
+        ]
+        self.search(search_criteria).unlink()
 
-        return self.create(cr, uid, {
+        return self.create({
             'key': 'action',
             'key2': action_slot,
             'model': model,
             'res_id': res_id,
             'name': name,
             'value': action,
-        })
+        }).id
 
-    @tools.ormcache_context('uid', 'action_slot', 'model', 'res_id', keys=('lang',))
-    def get_actions(self, cr, uid, action_slot, model, res_id=False, context=None):
+    @api.model
+    @tools.ormcache_context('self.env.uid', 'action_slot', 'model', 'res_id', keys=('lang',))
+    def get_actions(self, action_slot, model, res_id=False):
         """Retrieves the list of actions bound to the given model's action slot.
            See the class description for more details about the various action
            slots: :class:`~.ir_values`.
@@ -398,21 +388,20 @@ class ir_values(osv.osv):
                              OR v.res_id IS NULL
                              OR v.res_id = 0)
                    ORDER BY v.id"""
-        cr.execute(query, ('action', action_slot, model, res_id or None))
+        self.env.cr.execute(query, ('action', action_slot, model, res_id or None))
 
         # map values to their corresponding action record
         actions = []
-        for id, name, value in cr.fetchall():
+        for id, name, value in self.env.cr.fetchall():
             if not value:
                 continue                # skip if undefined
             action_model, action_id = value.split(',')
             if action_model not in self.pool:
                 continue                # unknown model? skip it!
-            action = self.pool[action_model].browse(cr, uid, int(action_id), context)
+            action = self.env[action_model].browse(int(action_id))
             actions.append((id, name, action))
 
         # process values and their action
-        user = self.pool['res.users'].browse(cr, uid, uid, context)
         results = {}
         for id, name, action in actions:
             fields = [field for field in action._fields if field not in EXCLUDED_FIELDS]
@@ -423,7 +412,7 @@ class ir_values(osv.osv):
                     for field in fields
                 }
                 if action._name in ('ir.actions.report.xml', 'ir.actions.act_window'):
-                    if action.groups_id and not action.groups_id & user.groups_id:
+                    if action.groups_id and not action.groups_id & self.env.user.groups_id:
                         if name == 'Menuitem':
                             raise AccessError(_('You do not have the permission to perform this operation!!!'))
                         continue
@@ -454,7 +443,8 @@ class ir_values(osv.osv):
         return results
 
     # Backards-compatibility adapter layer to retrofit into split API
-    def set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False):
+    @api.model
+    def set(self, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False):
         """Deprecated legacy method to set default values and bind actions to models' action slots.
            Now dispatches to the newer API methods according to the value of ``key``: :meth:`~.set_default`
            (``key=='default'``) or :meth:`~.set_action` (``key == 'action'``).
@@ -463,16 +453,17 @@ class ir_values(osv.osv):
         """
         assert key in ['default', 'action'], "ir.values entry keys must be in ['default','action']"
         if key == 'default':
-            def do_set(model,res_id):
-                return self.set_default(cr, uid, model, field_name=name, value=value,
+            def do_set(model, res_id):
+                return self.set_default(model, field_name=name, value=value,
                                         for_all_users=(not preserve_user), company_id=company,
                                         condition=key2)
         elif key == 'action':
-            def do_set(model,res_id):
-                return self.set_action(cr, uid, name, action_slot=key2, model=model, action=value, res_id=res_id)
+            def do_set(model, res_id):
+                return self.set_action(name, action_slot=key2, model=model, action=value, res_id=res_id)
         return self._map_legacy_model_list(models, do_set)
 
-    def get(self, cr, uid, key, key2, models, meta=False, context=None, res_id_req=False, without_user=True, key2_req=True):
+    @api.model
+    def get(self, key, key2, models, meta=False, res_id_req=False, without_user=True, key2_req=True):
         """Deprecated legacy method to get the list of default values or actions bound to models' action slots.
            Now dispatches to the newer API methods according to the value of ``key``: :meth:`~.get_defaults`
            (``key=='default'``) or :meth:`~.get_actions` (``key == 'action'``)
@@ -482,9 +473,9 @@ class ir_values(osv.osv):
         """
         assert key in ['default', 'action'], "ir.values entry keys must be in ['default','action']"
         if key == 'default':
-            def do_get(model,res_id):
-                return self.get_defaults(cr, uid, model, condition=key2)
+            def do_get(model, res_id):
+                return self.get_defaults(model, condition=key2)
         elif key == 'action':
-            def do_get(model,res_id):
-                return self.get_actions(cr, uid, action_slot=key2, model=model, res_id=res_id, context=context)
+            def do_get(model, res_id):
+                return self.get_actions(action_slot=key2, model=model, res_id=res_id)
         return self._map_legacy_model_list(models, do_get, merge_results=True)
diff --git a/openerp/addons/base/ir/ir_values_view.xml b/openerp/addons/base/ir/ir_values_view.xml
index 1464b077962fce3e4aa7886c36707bb675fea3fe..c196280c2fa2938803e59d56ccfd2ac567bba2f0 100644
--- a/openerp/addons/base/ir/ir_values_view.xml
+++ b/openerp/addons/base/ir/ir_values_view.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
+<odoo>
         <!-- Values -->
         <record id="values_view_form_action" model="ir.ui.view">
             <field name="name">ir.values.form.action</field>
@@ -10,13 +9,13 @@
                     <group>
                         <group>
                             <field name="name"/>
-                            <field name="model_id" on_change="onchange_object_id(model_id)"/>
+                            <field name="model_id"/>
                             <field name="model"/>
                             <field name="res_id"/>
                             <field name="key2"/>
                         </group>
                         <group>
-                            <field name="action_id" on_change="onchange_action_id(action_id)"/>
+                            <field name="action_id"/>
                             <field name="value_unpickle" colspan="4" string="Action Reference"/>
                         </group>
                     </group>
@@ -33,7 +32,7 @@
                         <group>
                             <field name="name"/>
                             <field name="model"/>
-                            <field name="model_id" on_change="onchange_object_id(model_id)"/>
+                            <field name="model_id"/>
                         </group>
                         <group>
                             <field name="key2" string="Condition"/>
@@ -123,5 +122,4 @@
         </record>
         <menuitem action="act_values_form_defaults" id="menu_values_form_defaults" parent="next_id_6"/>
 
-    </data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/ir/report_ir_model.xml b/openerp/addons/base/ir/report_ir_model.xml
index 86803944fcc244a1e9dbf0ac91508c7e8fba7f8e..284767a3247a4dda8f706014c755b28296e51247 100644
--- a/openerp/addons/base/ir/report_ir_model.xml
+++ b/openerp/addons/base/ir/report_ir_model.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<openerp>
-<data>
+<odoo>
 <template id="report_irmodeloverview">
     <t t-call="report.html_container">
         <t t-foreach="docs" t-as="o">
@@ -93,5 +92,4 @@
         </t>
     </t>
 </template>
-</data>
-</openerp>
+</odoo>
diff --git a/openerp/addons/base/module/wizard/base_module_immediate_install.xml b/openerp/addons/base/module/wizard/base_module_immediate_install.xml
index 02b75a1e4c33d73eceef3f3c6e32d58705a4702e..8a43727a40289b46a3ea416c59f52f33e2462675 100644
--- a/openerp/addons/base/module/wizard/base_module_immediate_install.xml
+++ b/openerp/addons/base/module/wizard/base_module_immediate_install.xml
@@ -7,7 +7,7 @@
             <field name="type">ir.actions.server</field>
             <field name="model_id" ref="model_ir_module_module" />
             <field name="state">code</field>
-            <field name="code">self.button_immediate_install(cr, uid, context.get('active_ids', []), context=context)</field>
+            <field name="code">self._model.button_immediate_install(self._cr, self._uid, self.env.context.get('active_ids', []), context=self.env.context)</field>
         </record>
 
         <record model="ir.values" id="action_module_immediate_install">
diff --git a/openerp/addons/base/tests/test_qweb.py b/openerp/addons/base/tests/test_qweb.py
index 82bc0ade76d3abd3d9b2c07428acc63c37b7fdc6..2740cbeefb571ac70a11527b577f382f4423af26 100644
--- a/openerp/addons/base/tests/test_qweb.py
+++ b/openerp/addons/base/tests/test_qweb.py
@@ -128,7 +128,7 @@ class TestQWeb(common.TransactionCase):
             ctx.update(params)
             result = doc.find('result[@id="{}"]'.format(template)).text
             self.assertEqual(
-                qweb.render(template, qwebcontext=ctx).strip(),
+                qweb._model.render(self.cr, self.uid, template, qwebcontext=ctx).strip(),
                 (result or u'').strip().encode('utf-8'),
                 template
             )