diff options
| author | Raphael Collet <rco@openerp.com> | 2014-07-06 16:44:26 +0200 |
|---|---|---|
| committer | Antony Lesuisse <al@openerp.com> | 2014-07-06 17:05:41 +0200 |
| commit | cbe2dbb672a6c55d86f2e515f9d1cdfee426ef80 (patch) | |
| tree | d6ff62b719fce32392397783c961b734b1e4c50e /openerp/addons/base/module/module.py | |
| parent | d78192c489d3be66cd6487b39f5ce7ba4733a187 (diff) | |
[MERGE] new v8 api by rco
A squashed merge is required as the conversion of the apiculture branch from
bzr to git was not correctly done. The git history contains irrelevant blobs
and commits. This branch brings a lot of changes and fixes, too many to list
exhaustively.
- New orm api, objects are now used instead of ids
- Environements to encapsulates cr uid context while maintaining backward compatibility
- Field compute attribute is a new object oriented way to define function fields
- Shared browse record cache
- New onchange protocol
- Optional copy flag on fields
- Documentation update
- Dead code cleanup
- Lots of fixes
Diffstat (limited to 'openerp/addons/base/module/module.py')
| -rw-r--r-- | openerp/addons/base/module/module.py | 103 |
1 files changed, 61 insertions, 42 deletions
diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index d0cb6b18f7b..89f3e9d006e 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -48,7 +48,8 @@ from openerp.modules.db import create_categories from openerp.modules import get_module_resource from openerp.tools.parse_version import parse_version from openerp.tools.translate import _ -from openerp.osv import fields, osv, orm +from openerp.osv import osv, orm, fields +from openerp import api, fields as fields2 _logger = logging.getLogger(__name__) @@ -374,34 +375,41 @@ class module(osv.osv): msg = _('Unable to process module "%s" because an external dependency is not met: %s') raise orm.except_orm(_('Error'), msg % (module_name, e.args[0])) - def state_update(self, cr, uid, ids, newstate, states_to_update, context=None, level=100): + @api.multi + def state_update(self, newstate, states_to_update, level=100): if level < 1: raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !')) + + # whether some modules are installed with demo data demo = False - for module in self.browse(cr, uid, ids, context=context): - mdemo = False + + for module in self: + # determine dependency modules to update/others + update_mods, ready_mods = self.browse(), self.browse() for dep in module.dependencies_id: if dep.state == 'unknown': raise orm.except_orm(_('Error'), _("You try to install module '%s' that depends on module '%s'.\nBut the latter module is not available in your system.") % (module.name, dep.name,)) - ids2 = self.search(cr, uid, [('name', '=', dep.name)]) - if dep.state != newstate: - mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level - 1) or mdemo + if dep.depend_id.state == newstate: + ready_mods += dep.depend_id else: - od = self.browse(cr, uid, ids2)[0] - mdemo = od.demo or mdemo + update_mods += dep.depend_id + # update dependency modules that require it, and determine demo for module + update_demo = update_mods.state_update(newstate, states_to_update, level=level-1) + module_demo = module.demo or update_demo or any(mod.demo for mod in ready_mods) + demo = demo or module_demo + + # check dependencies and update module itself self.check_external_dependencies(module.name, newstate) - if not module.dependencies_id: - mdemo = module.demo if module.state in states_to_update: - self.write(cr, uid, [module.id], {'state': newstate, 'demo': mdemo}) - demo = demo or mdemo + module.write({'state': newstate, 'demo': module_demo}) + return demo def button_install(self, cr, uid, ids, context=None): # Mark the given modules to be installed. - self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context) + self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context=context) # Mark (recursively) the newly satisfied modules to also be installed @@ -524,7 +532,7 @@ class module(osv.osv): def button_upgrade(self, cr, uid, ids, context=None): depobj = self.pool.get('ir.module.module.dependency') - todo = self.browse(cr, uid, ids, context=context) + todo = list(self.browse(cr, uid, ids, context=context)) self.update_list(cr, uid) i = 0 @@ -598,7 +606,7 @@ class module(osv.osv): for key in values: old = getattr(mod, key) updated = isinstance(values[key], basestring) and tools.ustr(values[key]) or values[key] - if not old == updated: + if (old or updated) and updated != old: updated_values[key] = values[key] if terp.get('installable', True) and mod.state == 'uninstallable': updated_values['state'] = 'uninstalled' @@ -726,6 +734,7 @@ class module(osv.osv): cr.execute('INSERT INTO ir_module_module_dependency (module_id, name) values (%s, %s)', (mod_browse.id, dep)) for dep in (existing - needed): cr.execute('DELETE FROM ir_module_module_dependency WHERE module_id = %s and name = %s', (mod_browse.id, dep)) + self.invalidate_cache(cr, uid, ['dependencies_id'], [mod_browse.id]) def _update_category(self, cr, uid, mod_browse, category='Uncategorized'): current_category = mod_browse.category_id @@ -754,37 +763,47 @@ class module(osv.osv): if not mod.description: _logger.warning('module %s: description is empty !', mod.name) -class module_dependency(osv.osv): + +DEP_STATES = [ + ('uninstallable', 'Uninstallable'), + ('uninstalled', 'Not Installed'), + ('installed', 'Installed'), + ('to upgrade', 'To be upgraded'), + ('to remove', 'To be removed'), + ('to install', 'To be installed'), + ('unknown', 'Unknown'), +] + +class module_dependency(osv.Model): _name = "ir.module.module.dependency" _description = "Module dependency" - def _state(self, cr, uid, ids, name, args, context=None): - result = {} - mod_obj = self.pool.get('ir.module.module') - for md in self.browse(cr, uid, ids): - ids = mod_obj.search(cr, uid, [('name', '=', md.name)]) - if ids: - result[md.id] = mod_obj.read(cr, uid, [ids[0]], ['state'])[0]['state'] - else: - result[md.id] = 'unknown' - return result + # the dependency name + name = fields2.Char(index=True) - _columns = { - # The dependency name - 'name': fields.char('Name', select=True), + # the module that depends on it + module_id = fields2.Many2one('ir.module.module', 'Module', ondelete='cascade') - # The module that depends on it - 'module_id': fields.many2one('ir.module.module', 'Module', select=True, ondelete='cascade'), + # the module corresponding to the dependency, and its status + depend_id = fields2.Many2one('ir.module.module', 'Dependency', compute='_compute_depend') + state = fields2.Selection(DEP_STATES, string='Status', compute='_compute_state') + + @api.multi + @api.depends('name') + def _compute_depend(self): + # retrieve all modules corresponding to the dependency names + names = list(set(dep.name for dep in self)) + mods = self.env['ir.module.module'].search([('name', 'in', names)]) + + # index modules by name, and assign dependencies + name_mod = dict((mod.name, mod) for mod in mods) + for dep in self: + dep.depend_id = name_mod.get(dep.name) + + @api.one + @api.depends('depend_id.state') + def _compute_state(self): + self.state = self.depend_id.state or 'unknown' - 'state': fields.function(_state, type='selection', selection=[ - ('uninstallable', 'Uninstallable'), - ('uninstalled', 'Not Installed'), - ('installed', 'Installed'), - ('to upgrade', 'To be upgraded'), - ('to remove', 'To be removed'), - ('to install', 'To be installed'), - ('unknown', 'Unknown'), - ], string='Status', readonly=True, select=True), - } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
