[ADD] module install/uninstall hooks.
Since 4ec71c74d1
, migration scripts
are not executed at module install anymore.
As this behavior was missused as "init" scripts (see [1]), this
commit re-add this possiblity via hooks.
There are 3 hooks that can be declared in the manifest file:
- pre_init_hook: called before module installation
- post_init_hook: called after module installation
- uninstall_hook: called before module uninstallation
Like the "post_load" manifest option, the values for these hooks
must be a string containing the name of a method available at the
module root.
The signatures of these functions are:
- (cr) for pre_init_hook
- (cr, registry) for post_init_hook and uninstall_hook
[1] https://bugs.launchpad.net/openobject-server/+bug/1314680
This commit is contained in:
parent
bd51bf1e35
commit
4105b5f028
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||||
# Copyright (C) 2010-2011 OpenERP s.a. (<http://openerp.com>).
|
# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -149,7 +149,14 @@ class Graph(dict):
|
||||||
level += 1
|
level += 1
|
||||||
|
|
||||||
|
|
||||||
class Singleton(object):
|
class Node(object):
|
||||||
|
""" One module in the modules dependency graph.
|
||||||
|
|
||||||
|
Node acts as a per-module singleton. A node is constructed via
|
||||||
|
Graph.add_module() or Graph.add_modules(). Some of its fields are from
|
||||||
|
ir_module_module (setted by Graph.update_from_db()).
|
||||||
|
|
||||||
|
"""
|
||||||
def __new__(cls, name, graph, info):
|
def __new__(cls, name, graph, info):
|
||||||
if name in graph:
|
if name in graph:
|
||||||
inst = graph[name]
|
inst = graph[name]
|
||||||
|
@ -160,22 +167,13 @@ class Singleton(object):
|
||||||
graph[name] = inst
|
graph[name] = inst
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
|
|
||||||
class Node(Singleton):
|
|
||||||
""" One module in the modules dependency graph.
|
|
||||||
|
|
||||||
Node acts as a per-module singleton. A node is constructed via
|
|
||||||
Graph.add_module() or Graph.add_modules(). Some of its fields are from
|
|
||||||
ir_module_module (setted by Graph.update_from_db()).
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, graph, info):
|
def __init__(self, name, graph, info):
|
||||||
self.graph = graph
|
self.graph = graph
|
||||||
if not hasattr(self, 'children'):
|
if not hasattr(self, 'children'):
|
||||||
self.children = []
|
self.children = []
|
||||||
if not hasattr(self, 'depth'):
|
if not hasattr(self, 'depth'):
|
||||||
self.depth = 0
|
self.depth = 0
|
||||||
|
self.info = info or {}
|
||||||
|
|
||||||
def add_child(self, name, info):
|
def add_child(self, name, info):
|
||||||
node = Node(name, self.graph, info)
|
node = Node(name, self.graph, info)
|
||||||
|
@ -189,7 +187,7 @@ class Node(Singleton):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
super(Singleton, self).__setattr__(name, value)
|
super(Node, self).__setattr__(name, value)
|
||||||
if name in ('init', 'update', 'demo'):
|
if name in ('init', 'update', 'demo'):
|
||||||
tools.config[name][self.name] = 1
|
tools.config[name][self.name] = 1
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
|
|
|
@ -148,6 +148,13 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
||||||
migrations.migrate_module(package, 'pre')
|
migrations.migrate_module(package, 'pre')
|
||||||
load_openerp_module(package.name)
|
load_openerp_module(package.name)
|
||||||
|
|
||||||
|
new_install = package.installed_version is None
|
||||||
|
if new_install:
|
||||||
|
py_module = sys.modules['openerp.addons.%s' % (module_name,)]
|
||||||
|
pre_init = package.info.get('pre_init_hook')
|
||||||
|
if pre_init:
|
||||||
|
getattr(py_module, pre_init)(cr)
|
||||||
|
|
||||||
models = registry.load(cr, package)
|
models = registry.load(cr, package)
|
||||||
|
|
||||||
loaded_modules.append(package.name)
|
loaded_modules.append(package.name)
|
||||||
|
@ -181,6 +188,11 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
||||||
|
|
||||||
migrations.migrate_module(package, 'post')
|
migrations.migrate_module(package, 'post')
|
||||||
|
|
||||||
|
if new_install:
|
||||||
|
post_init = package.info.get('post_init_hook')
|
||||||
|
if post_init:
|
||||||
|
getattr(py_module, post_init)(cr, registry)
|
||||||
|
|
||||||
registry._init_modules.add(package.name)
|
registry._init_modules.add(package.name)
|
||||||
# validate all the views at a whole
|
# validate all the views at a whole
|
||||||
registry['ir.ui.view']._validate_module_views(cr, SUPERUSER_ID, module_name)
|
registry['ir.ui.view']._validate_module_views(cr, SUPERUSER_ID, module_name)
|
||||||
|
@ -401,10 +413,17 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||||
if update_module:
|
if update_module:
|
||||||
# Remove records referenced from ir_model_data for modules to be
|
# Remove records referenced from ir_model_data for modules to be
|
||||||
# removed (and removed the references from ir_model_data).
|
# removed (and removed the references from ir_model_data).
|
||||||
cr.execute("SELECT id FROM ir_module_module WHERE state=%s", ('to remove',))
|
cr.execute("SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove',))
|
||||||
mod_ids_to_remove = [x[0] for x in cr.fetchall()]
|
modules_to_remove = dict(cr.fetchall())
|
||||||
if mod_ids_to_remove:
|
if modules_to_remove:
|
||||||
registry['ir.module.module'].module_uninstall(cr, SUPERUSER_ID, mod_ids_to_remove)
|
pkgs = reversed([p for p in graph if p.name in modules_to_remove])
|
||||||
|
for pkg in pkgs:
|
||||||
|
uninstall_hook = pkg.info.get('uninstall_hook')
|
||||||
|
if uninstall_hook:
|
||||||
|
py_module = sys.modules['openerp.addons.%s' % (pkg.name,)]
|
||||||
|
getattr(py_module, uninstall_hook)(cr, registry)
|
||||||
|
|
||||||
|
registry['ir.module.module'].module_uninstall(cr, SUPERUSER_ID, modules_to_remove.values())
|
||||||
# Recursive reload, should only happen once, because there should be no
|
# Recursive reload, should only happen once, because there should be no
|
||||||
# modules to remove next time
|
# modules to remove next time
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
Loading…
Reference in New Issue