forked from OCA/server-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hooks.py
132 lines (103 loc) · 3.83 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- 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 openerp.sql_db import Cursor
from openerp.modules import module
from openerp.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)