@@ -98,16 +98,49 @@ def module_installed(cr, module):
98
98
return modules_installed (cr , module )
99
99
100
100
101
- def uninstall_module (cr , module ):
101
+ def module_dependencies (cr , module ):
102
+ """Get dependencies of given module.
103
+
104
+ :param str module: name of the module
105
+ :return: list names of the dependencies
106
+ :rtype: list(str)
107
+ """
108
+ found = []
109
+ while True :
110
+ cr .execute (
111
+ """
112
+ SELECT ARRAY_AGG(DISTINCT m.name ORDER BY m.name)
113
+ FROM ir_module_module m
114
+ INNER JOIN ir_module_module_dependency d ON d.module_id = m.id
115
+ WHERE d.name = ANY(%s)
116
+ """ ,
117
+ (found + [module ],),
118
+ )
119
+ new = cr .fetchone ()[0 ]
120
+ if new == found :
121
+ return found
122
+ found = new
123
+
124
+
125
+ def uninstall_module (cr , module , with_dependencies = False ):
102
126
"""
103
127
Uninstall and remove all records owned by a module.
104
128
105
129
:param str module: name of the module to uninstall
130
+ :param bool with_dependencies: whether to also remove dependencies of the module
131
+ :return: set of uninstalled module names
132
+ :rtype: set(str)
106
133
"""
134
+ result = set ()
107
135
cr .execute ("SELECT id FROM ir_module_module WHERE name=%s" , (module ,))
108
136
(mod_id ,) = cr .fetchone () or [None ]
109
137
if not mod_id :
110
- return
138
+ return result
139
+
140
+ if with_dependencies :
141
+ dependencies = module_dependencies (cr , module )
142
+ for dep in dependencies :
143
+ result .union (uninstall_module (cr , dep , with_dependencies = with_dependencies ))
111
144
112
145
# delete constraints only owned by this module
113
146
cr .execute (
@@ -219,14 +252,18 @@ def uninstall_module(cr, module):
219
252
if table_exists (cr , "ir_translation" ):
220
253
cr .execute ("DELETE FROM ir_translation WHERE module=%s" , [module ])
221
254
cr .execute ("UPDATE ir_module_module SET state='uninstalled' WHERE name=%s" , (module ,))
255
+ return result | {module }
222
256
223
257
224
- def uninstall_theme (cr , theme , base_theme = None ):
258
+ def uninstall_theme (cr , theme , base_theme = None , with_dependencies = False ):
225
259
"""
226
260
Uninstall a theme module and remove it from websites.
227
261
228
262
:param str theme: name of the theme module to uninstall
229
263
:param str or None base_theme: if not `None`, unload first this base theme
264
+ :param bool with_dependencies: whether to also remove dependencies of the theme
265
+ :return: set of uninstalled module names
266
+ :rtype: set(str)
230
267
231
268
.. warning::
232
269
@@ -238,7 +275,7 @@ def uninstall_theme(cr, theme, base_theme=None):
238
275
cr .execute ("SELECT id FROM ir_module_module WHERE name=%s AND state in %s" , [theme , INSTALLED_MODULE_STATES ])
239
276
(theme_id ,) = cr .fetchone () or [None ]
240
277
if not theme_id :
241
- return
278
+ return None
242
279
243
280
env_ = env (cr )
244
281
IrModuleModule = env_ ["ir.module.module" ]
@@ -253,17 +290,20 @@ def uninstall_theme(cr, theme, base_theme=None):
253
290
for website in websites :
254
291
IrModuleModule ._theme_remove (website )
255
292
flush (env_ ["base" ])
256
- uninstall_module (cr , theme )
293
+ return uninstall_module (cr , theme , with_dependencies = with_dependencies )
257
294
258
295
259
- def remove_module (cr , module ):
296
+ def remove_module (cr , module , with_dependencies = False ):
260
297
"""
261
298
Completely remove a module.
262
299
263
300
This operation is equivalent to uninstall and removal of *all* references to
264
301
the module - no trace of it is left in the database.
265
302
266
303
:param str module: name of the module to remove
304
+ :param bool with_dependencies: whether to also remove dependencies of the module
305
+ :return: set of uninstalled module names
306
+ :rtype: set(str)
267
307
268
308
.. warning::
269
309
Since this function removes *all* data associated to the module. Ensure to
@@ -273,15 +313,17 @@ def remove_module(cr, module):
273
313
# module need to be currently installed and running as deletions
274
314
# are made using orm.
275
315
276
- uninstall_module (cr , module )
277
- cr .execute ("DELETE FROM ir_module_module_dependency WHERE name=%s" , (module ,))
278
- cr .execute ("DELETE FROM ir_module_module WHERE name=%s RETURNING id" , (module ,))
316
+ result = uninstall_module (cr , module , with_dependencies = with_dependencies )
317
+ names = list (result )
318
+ cr .execute ("DELETE FROM ir_module_module_dependency WHERE name = ANY(%s)" , (names ,))
319
+ cr .execute ("DELETE FROM ir_module_module WHERE name = ANY(%s) RETURNING id" , (names ,))
279
320
if cr .rowcount :
280
- [mod_id ] = cr .fetchone ()
281
- cr .execute ("DELETE FROM ir_model_data WHERE model='ir.module.module' AND res_id=%s" , [mod_id ])
321
+ ids = [id_ for (id_ ,) in cr .fetchall ()]
322
+ cr .execute ("DELETE FROM ir_model_data WHERE model='ir.module.module' AND res_id = ANY(%s)" , (ids ,))
323
+ return result
282
324
283
325
284
- def remove_theme (cr , theme , base_theme = None ):
326
+ def remove_theme (cr , theme , base_theme = None , with_dependencies = False ):
285
327
"""
286
328
Uninstall a theme module.
287
329
@@ -290,12 +332,14 @@ def remove_theme(cr, theme, base_theme=None):
290
332
291
333
See :func:`remove_module` and :func:`uninstall_theme`.
292
334
"""
293
- uninstall_theme (cr , theme , base_theme = base_theme )
294
- cr .execute ("DELETE FROM ir_module_module_dependency WHERE name=%s" , (theme ,))
295
- cr .execute ("DELETE FROM ir_module_module WHERE name=%s RETURNING id" , (theme ,))
335
+ result = uninstall_theme (cr , theme , base_theme = base_theme , with_dependencies = with_dependencies )
336
+ themes = list (result )
337
+ cr .execute ("DELETE FROM ir_module_module_dependency WHERE name = ANY(%s)" , (themes ,))
338
+ cr .execute ("DELETE FROM ir_module_module WHERE name = ANY(%s) RETURNING id" , (themes ,))
296
339
if cr .rowcount :
297
- [mod_id ] = cr .fetchone ()
298
- cr .execute ("DELETE FROM ir_model_data WHERE model='ir.module.module' AND res_id=%s" , [mod_id ])
340
+ ids = [id_ for (id_ ,) in cr .fetchall ()]
341
+ cr .execute ("DELETE FROM ir_model_data WHERE model='ir.module.module' AND res_id = ANY(%s)" , (ids ,))
342
+ return result
299
343
300
344
301
345
def _update_view_key (cr , old , new ):
0 commit comments