cwvreg.py
branchstable
changeset 9947 6343d91f5200
parent 9771 2656ac7fa9a8
parent 9926 93a44cf0d030
child 9980 91fbd3111828
--- a/cwvreg.py	Tue Sep 02 12:22:18 2014 +0200
+++ b/cwvreg.py	Wed Sep 17 13:43:31 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -598,11 +598,33 @@
         if self.is_reload_needed(path):
             self.reload(path)
 
+    def _cleanup_sys_modules(self, path):
+        """Remove submodules of `directories` from `sys.modules` and cleanup
+        CW_EVENT_MANAGER accordingly.
+
+        We take care to properly remove obsolete registry callbacks.
+
+        """
+        caches = {}
+        callbackdata = CW_EVENT_MANAGER.callbacks.values()
+        for callbacklist in callbackdata:
+            for callback in callbacklist:
+                func = callback[0]
+                # for non-function callable, we do nothing interesting
+                module = getattr(func, '__module__', None)
+                caches[id(callback)] = module
+        deleted_modules = set(cleanup_sys_modules(path))
+        for callbacklist in callbackdata:
+            for callback in callbacklist[:]:
+                module = caches[id(callback)]
+                if module and module in deleted_modules:
+                    callbacklist.remove(callback)
+
     def reload(self, path, force_reload=True):
         """modification detected, reset and reload the vreg"""
         CW_EVENT_MANAGER.emit('before-registry-reload')
         if force_reload:
-            cleanup_sys_modules(path)
+            self._cleanup_sys_modules(path)
             cubes = self.config.cubes()
             # if the fs code use some cubes not yet registered into the instance
             # we should cleanup sys.modules for those as well to avoid potential
@@ -611,7 +633,7 @@
             for cube in cfg.expand_cubes(cubes, with_recommends=True):
                 if not cube in cubes:
                     cpath = cfg.build_appobjects_cube_path([cfg.cube_dir(cube)])
-                    cleanup_sys_modules(cpath)
+                    self._cleanup_sys_modules(cpath)
         self.register_objects(path)
         CW_EVENT_MANAGER.emit('after-registry-reload')