You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.8 KiB
132 lines
3.8 KiB
# -*- coding: utf-8 -*-
|
|
# Copyright 2017 Therp BV <http://therp.nl>
|
|
# Copyright 2017 LasLabs Inc.
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
|
|
|
import inspect
|
|
from werkzeug.local import Local
|
|
from odoo.sql_db import Cursor
|
|
from odoo.modules import module
|
|
from odoo.modules.graph import Graph
|
|
|
|
original = module.load_information_from_description_file
|
|
local = Local()
|
|
local.rdepends_to_process = {}
|
|
|
|
|
|
def load_information_from_description_file(module, mod_path=None):
|
|
result = original(module, mod_path=mod_path)
|
|
|
|
# add the keys you want to react on here
|
|
if result.get('depends_if_installed'):
|
|
cr = _get_cr()
|
|
if cr:
|
|
_handle_depends_if_installed(cr, result)
|
|
if result.get('rdepends_if_installed'):
|
|
cr = _get_cr()
|
|
if cr:
|
|
_handle_rdepends_if_installed(cr, result, module)
|
|
|
|
# Apply depends specified in other modules as rdepends
|
|
extra_depends = local.rdepends_to_process.get(module)
|
|
if extra_depends:
|
|
result['depends'] += extra_depends
|
|
|
|
return result
|
|
|
|
|
|
def _handle_depends_if_installed(cr, manifest):
|
|
if not manifest.get('depends_if_installed'):
|
|
return
|
|
|
|
added_depends = manifest.pop('depends_if_installed')
|
|
added_depends = _installed_modules(cr, added_depends)
|
|
|
|
depends = manifest.setdefault('depends', [])
|
|
depends.extend(added_depends)
|
|
|
|
|
|
def _handle_rdepends_if_installed(cr, manifest, current_module):
|
|
graph = _get_graph()
|
|
if not graph:
|
|
return
|
|
|
|
rdepends = manifest.pop('rdepends_if_installed')
|
|
rdepends = _installed_modules(cr, rdepends)
|
|
|
|
for rdepend in rdepends:
|
|
to_process = local.rdepends_to_process.get(rdepend, set([]))
|
|
local.rdepends_to_process[rdepend] = to_process | set([current_module])
|
|
# If rdepend already in graph, reload it so new depend is applied
|
|
if graph.get(rdepend):
|
|
del graph[rdepend]
|
|
graph.add_module(cr, rdepend)
|
|
|
|
|
|
def _installed_modules(cr, modules):
|
|
if not modules:
|
|
return []
|
|
|
|
cr.execute(
|
|
'SELECT name FROM ir_module_module '
|
|
'WHERE state IN %s AND name IN %s',
|
|
(
|
|
tuple(['installed', 'to install', 'to upgrade']),
|
|
tuple(modules),
|
|
),
|
|
)
|
|
return [module for module, in cr.fetchall()]
|
|
|
|
|
|
def _get_cr():
|
|
cr = None
|
|
for frame, filename, lineno, funcname, line, index in inspect.stack():
|
|
# walk up the stack until we've found a cursor
|
|
if 'cr' in frame.f_locals and isinstance(frame.f_locals['cr'], Cursor):
|
|
cr = frame.f_locals['cr']
|
|
break
|
|
return cr
|
|
|
|
|
|
def _get_graph():
|
|
graph = None
|
|
for frame, filename, lineno, funcname, line, index in inspect.stack():
|
|
# walk up the stack until we've found a graph
|
|
if 'graph' in frame.f_locals and isinstance(
|
|
frame.f_locals['graph'], Graph
|
|
):
|
|
graph = frame.f_locals['graph']
|
|
break
|
|
return graph
|
|
|
|
|
|
def post_load_hook():
|
|
cr = _get_cr()
|
|
if not cr:
|
|
return
|
|
|
|
# do nothing if we're not installed
|
|
installed = _installed_modules(cr, ['base_manifest_extension'])
|
|
if not installed:
|
|
return
|
|
|
|
module.load_information_from_description_file =\
|
|
load_information_from_description_file
|
|
|
|
# here stuff can become tricky: On the python level, modules
|
|
# are not loaded in dependency order. This means that there might
|
|
# be modules loaded depending on us before we could patch the function
|
|
# above. So we reload the module graph for all modules coming after us
|
|
|
|
graph = _get_graph()
|
|
if not graph:
|
|
return
|
|
|
|
this = graph['base_manifest_extension']
|
|
to_reload = []
|
|
for node in graph.itervalues():
|
|
if node.depth > this.depth:
|
|
to_reload.append(node.name)
|
|
for module_name in to_reload:
|
|
del graph[module_name]
|
|
graph.add_modules(cr, to_reload)
|