diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index ab9231b129c..592a8b5f426 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -97,7 +97,7 @@ # 'test/test_ir_cron.yml', # <-- These tests perform a roolback. ], 'installable': True, - 'active': True, + 'auto_install': True, 'certificate': '0076807797149', "css": [ 'static/src/css/modules.css' ], } diff --git a/openerp/addons/base/base.sql b/openerp/addons/base/base.sql index 31872b46730..409ce81b285 100644 --- a/openerp/addons/base/base.sql +++ b/openerp/addons/base/base.sql @@ -302,6 +302,7 @@ CREATE TABLE ir_module_module ( web boolean DEFAULT FALSE, license character varying(32), sequence integer DEFAULT 100, + auto_install boolean default False, primary key(id) ); ALTER TABLE ir_module_module add constraint name_uniq unique (name); diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 34ed48378e6..75936146574 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -192,6 +192,10 @@ class module(osv.osv): 'sequence': fields.integer('Sequence'), 'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies', readonly=True), + 'auto_install': fields.boolean('Automatic Installation', + help='An auto-installable module is automatically installed by the ' + 'system when all its dependencies are satisfied. ' + 'If the module has no dependency, it is always installed.'), 'state': fields.selection([ ('uninstallable','Not Installable'), ('uninstalled','Not Installed'), @@ -318,20 +322,27 @@ class module(osv.osv): return demo def button_install(self, cr, uid, ids, context=None): - model_obj = self.pool.get('ir.model.data') + + # Mark the given modules to be installed. self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context) - categ = model_obj.get_object(cr, uid, 'base', 'module_category_hidden_links', context=context) - todo = [] - for mod in categ.module_ids: - if mod.state=='uninstalled': - ok = True - for dep in mod.dependencies_id: - ok = ok and (dep.state in ('to install','installed')) - if ok: - todo.append(mod.id) - if todo: - self.button_install(cr, uid, todo, context=context) + # Mark (recursively) the newly satisfied modules to also be installed: + + # Select all auto-installable (but not yet installed) modules. + domain = [('state', '=', 'uninstalled'), ('auto_install', '=', True),] + uninstalled_ids = self.search(cr, uid, domain, context=context) + uninstalled_modules = self.browse(cr, uid, uninstalled_ids, context=context) + + # Keep those with all their dependencies satisfied. + def all_depencies_satisfied(m): + return all(x.state in ('to install', 'installed', 'to upgrade') for x in m.dependencies_id) + to_install_modules = filter(all_depencies_satisfied, uninstalled_modules) + to_install_ids = map(lambda m: m.id, to_install_modules) + + # Mark them to be installed. + if to_install_ids: + self.button_install(cr, uid, to_install_ids, context=context) + return dict(ACTION_DICT, name=_('Install')) def button_immediate_install(self, cr, uid, ids, context=None): @@ -439,6 +450,7 @@ class module(osv.osv): 'complexity': terp.get('complexity', ''), 'sequence': terp.get('sequence', 100), 'application': terp.get('application', False), + 'auto_install': terp.get('auto_install', False), } # update the list of available packages diff --git a/openerp/addons/base/module/module_data.xml b/openerp/addons/base/module/module_data.xml index 5cf66064a9e..ec5f8aa42af 100644 --- a/openerp/addons/base/module/module_data.xml +++ b/openerp/addons/base/module/module_data.xml @@ -7,13 +7,6 @@ - - - Links - 0 - - - Localization diff --git a/openerp/modules/db.py b/openerp/modules/db.py index a670a29deed..c8ac6d821f2 100644 --- a/openerp/modules/db.py +++ b/openerp/modules/db.py @@ -66,7 +66,7 @@ def initialize(cr): category_id = create_categories(cr, categories) if info['installable']: - if info['active']: + if info['auto_install'] and not info['depends']: state = 'to install' else: state = 'uninstalled' @@ -75,11 +75,12 @@ def initialize(cr): cr.execute('INSERT INTO ir_module_module \ (author, website, name, shortdesc, description, \ - category_id, state, certificate, web, license, complexity, application, icon, sequence) \ - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING id', ( + category_id, auto_install, state, certificate, web, license, complexity, application, icon, sequence) \ + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING id', ( info['author'], info['website'], i, info['name'], - info['description'], category_id, state, info['certificate'], + info['description'], category_id, + info['auto_install'], state, info['certificate'], info['web'], info['license'], info['complexity'], info['application'], info['icon'], diff --git a/openerp/modules/module.py b/openerp/modules/module.py index b82597d656d..2d8ce0abd27 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -48,6 +48,8 @@ import logging import openerp.modules.db import openerp.modules.graph +_logger = logging.getLogger(__name__) + _ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base) ad_paths = [] @@ -317,9 +319,9 @@ def load_information_from_description_file(module): if os.path.isfile(terp_file) or zipfile.is_zipfile(mod_path+'.zip'): # default values for descriptor info = { - 'active': False, 'application': False, 'author': '', + 'auto_install': False, 'category': 'Uncategorized', 'certificate': None, 'complexity': 'normal', @@ -327,6 +329,7 @@ def load_information_from_description_file(module): 'description': '', 'icon': get_module_icon(module), 'installable': True, + 'auto_install': False, 'license': 'AGPL-3', 'name': False, 'post_load': None, @@ -342,6 +345,10 @@ def load_information_from_description_file(module): with tools.file_open(terp_file) as terp_f: info.update(eval(terp_f.read())) + if 'active' in info: + # 'active' has been renamed 'auto_install' + info['auto_install'] = info['active'] + return info #TODO: refactor the logger in this file to follow the logging guidelines diff --git a/openerp/tests/addons/test_exceptions/__openerp__.py b/openerp/tests/addons/test_exceptions/__openerp__.py index bac853e301a..183f8877577 100644 --- a/openerp/tests/addons/test_exceptions/__openerp__.py +++ b/openerp/tests/addons/test_exceptions/__openerp__.py @@ -10,6 +10,6 @@ 'depends': ['base'], 'data': ['view.xml'], 'installable': True, - 'active': False, + 'auto_install': False, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tests/addons/test_limits/__openerp__.py b/openerp/tests/addons/test_limits/__openerp__.py index 333f1fe4372..05b70919a2a 100644 --- a/openerp/tests/addons/test_limits/__openerp__.py +++ b/openerp/tests/addons/test_limits/__openerp__.py @@ -10,6 +10,6 @@ 'depends': ['base'], 'data': [], 'installable': True, - 'active': False, + 'auto_install': False, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: