imp] res.config.installer: set already installed modules to readonly, as res.config.installer can't uninstall them.

Also, remove already installed modules from the set of modules to
install, and add a few docstrings to clarify the purpose of
overloading default_get and fields_get, and how _modules_to_install
works

bzr revid: xmo@tinyerp.com-20100123143705-9qyjhfnrlx372nso
This commit is contained in:
Xavier Morel
2010-01-23 15:37:05 +01:00
parent 2bfaec5adf
commit c6eddc3335
+59 -13
View File
@@ -22,6 +22,7 @@
from operator import attrgetter
from osv import osv, fields
from tools.translate import _
import netsvc
import pooler
@@ -121,13 +122,49 @@ class res_config_installer(osv.osv_memory):
_install_if = {}
def _already_installed(self, cr, uid, context=None):
""" For each module (boolean fields in a res.config.installer),
check if it's already installed (neither uninstallable nor uninstalled)
and if it is, check it by default
"""
modules = self.pool.get('ir.module.module')
selectable = [field for field in self._columns
if type(self._columns[field]) is fields.boolean]
return modules.browse(
cr, uid,
modules.search(cr, uid,
[('name','in',selectable),
('state','not in',['uninstallable', 'uninstalled'])],
context=context),
context=context)
def _modules_to_install(self, cr, uid, ids, context=None):
""" selects all modules to install:
* checked boolean fields
* return values of hook methods. Hook methods are of the form
``_if_%(addon_name)s``, and are called if the corresponding
addon is marked for installation. They take the arguments
cr, uid, ids and context, and return an iterable of addon
names
* additionals, additionals are setup through the ``_install_if``
class variable. ``_install_if`` is a dict of {iterable:iterable}
where key and value are iterables of addon names.
If all the addons in the key are selected for installation
(warning: addons added through hooks don't count), then the
addons in the value are added to the set of modules to install
* not already installed
"""
base = set(module_name
for installer in self.read(cr, uid, ids, context=context)
for module_name, to_install in installer.iteritems()
if module_name != 'id'
if type(self._columns[module_name]) is fields.boolean
if to_install)
hooks_results = set()
for module in base:
hook = getattr(self, '_if_%s'%(module), None)
@@ -140,28 +177,37 @@ class res_config_installer(osv.osv_memory):
if base.issuperset(requirements)
for module in consequences)
return base | hooks_results | additionals
return (base | hooks_results | additionals) - set(
map(attrgetter('name'), self._already_installed(cr, uid, context)))
def default_get(self, cr, uid, fields_list, context=None):
modules = self.pool.get('ir.module.module')
''' If an addon is already installed, check it by default
'''
defaults = super(res_config_installer, self).default_get(
cr, uid, fields_list, context=context)
selectable = [field for field in self._columns
if type(self._columns[field]) is fields.boolean]
already_installed = modules.browse(
cr, uid,
modules.search(cr, uid,
[('name','in',selectable),
('state','not in',['uninstallable', 'uninstalled'])],
context=context),
context=context)
return dict(defaults,
**dict.fromkeys(
map(attrgetter('name'), already_installed),
map(attrgetter('name'),
self._already_installed(cr, uid, context=context)),
True))
def fields_get(self, cr, uid, fields=None, context=None, read_access=True):
""" If an addon is already installed, set it to readonly as
res.config.installer doesn't handle uninstallations of already
installed addons
"""
fields = super(res_config_installer, self).fields_get(
cr, uid, fields, context, read_access)
for module in self._already_installed(cr, uid, context=context):
fields[module.name].update(
readonly=True,
help=fields[module.name].get('help', '') +
'\n\nThis module is already installed on your system')
return fields
def execute(self, cr, uid, ids, context=None):
modules = self.pool.get('ir.module.module')
to_install = list(self._modules_to_install(