@@ -98,16 +98,49 @@ def module_installed(cr, module):
9898 return modules_installed (cr , module )
9999
100100
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 ):
102126 """
103127 Uninstall and remove all records owned by a module.
104128
105129 :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)
106133 """
134+ result = set ()
107135 cr .execute ("SELECT id FROM ir_module_module WHERE name=%s" , (module ,))
108136 (mod_id ,) = cr .fetchone () or [None ]
109137 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 ))
111144
112145 # delete constraints only owned by this module
113146 cr .execute (
@@ -219,14 +252,18 @@ def uninstall_module(cr, module):
219252 if table_exists (cr , "ir_translation" ):
220253 cr .execute ("DELETE FROM ir_translation WHERE module=%s" , [module ])
221254 cr .execute ("UPDATE ir_module_module SET state='uninstalled' WHERE name=%s" , (module ,))
255+ return result | {module }
222256
223257
224- def uninstall_theme (cr , theme , base_theme = None ):
258+ def uninstall_theme (cr , theme , base_theme = None , with_dependencies = False ):
225259 """
226260 Uninstall a theme module and remove it from websites.
227261
228262 :param str theme: name of the theme module to uninstall
229263 :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)
230267
231268 .. warning::
232269
@@ -238,7 +275,7 @@ def uninstall_theme(cr, theme, base_theme=None):
238275 cr .execute ("SELECT id FROM ir_module_module WHERE name=%s AND state in %s" , [theme , INSTALLED_MODULE_STATES ])
239276 (theme_id ,) = cr .fetchone () or [None ]
240277 if not theme_id :
241- return
278+ return None
242279
243280 env_ = env (cr )
244281 IrModuleModule = env_ ["ir.module.module" ]
@@ -253,17 +290,20 @@ def uninstall_theme(cr, theme, base_theme=None):
253290 for website in websites :
254291 IrModuleModule ._theme_remove (website )
255292 flush (env_ ["base" ])
256- uninstall_module (cr , theme )
293+ return uninstall_module (cr , theme , with_dependencies = with_dependencies )
257294
258295
259- def remove_module (cr , module ):
296+ def remove_module (cr , module , with_dependencies = False ):
260297 """
261298 Completely remove a module.
262299
263300 This operation is equivalent to uninstall and removal of *all* references to
264301 the module - no trace of it is left in the database.
265302
266303 :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)
267307
268308 .. warning::
269309 Since this function removes *all* data associated to the module. Ensure to
@@ -273,15 +313,17 @@ def remove_module(cr, module):
273313 # module need to be currently installed and running as deletions
274314 # are made using orm.
275315
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 ,))
279320 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
282324
283325
284- def remove_theme (cr , theme , base_theme = None ):
326+ def remove_theme (cr , theme , base_theme = None , with_dependencies = False ):
285327 """
286328 Uninstall a theme module.
287329
@@ -290,12 +332,14 @@ def remove_theme(cr, theme, base_theme=None):
290332
291333 See :func:`remove_module` and :func:`uninstall_theme`.
292334 """
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 ,))
296339 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
299343
300344
301345def _update_view_key (cr , old , new ):
0 commit comments