[cwvreg] cleanup the event manager when reloading modules stable
authorAlain Leufroy <alain.leufroy@logilab.fr>
Wed, 21 May 2014 16:14:17 +0200
branchstable
changeset 9926 93a44cf0d030
parent 9874 f288ab643958
child 9927 4febc1682f44
[cwvreg] cleanup the event manager when reloading modules Closes #3848995 The event manager callbacks are not cleaned during reloading. So the callback defined in the reloaded module appears twice (old and new version). This may cause problem when the old version is called.
__pkginfo__.py
cubicweb.spec
cwvreg.py
debian/control
--- a/__pkginfo__.py	Tue Jul 08 14:02:43 2014 +0200
+++ b/__pkginfo__.py	Wed May 21 16:14:17 2014 +0200
@@ -40,7 +40,7 @@
 ]
 
 __depends__ = {
-    'logilab-common': '>= 0.59.0',
+    'logilab-common': '>= 0.62.0',
     'logilab-mtconverter': '>= 0.8.0',
     'rql': '>= 0.31.2',
     'yams': '>= 0.38.1',
--- a/cubicweb.spec	Tue Jul 08 14:02:43 2014 +0200
+++ b/cubicweb.spec	Wed May 21 16:14:17 2014 +0200
@@ -20,7 +20,7 @@
 BuildArch:      noarch
 
 Requires:       %{python}
-Requires:       %{python}-logilab-common >= 0.59.0
+Requires:       %{python}-logilab-common >= 0.62.0
 Requires:       %{python}-logilab-mtconverter >= 0.8.0
 Requires:       %{python}-rql >= 0.31.2
 Requires:       %{python}-yams >= 0.38.1
--- a/cwvreg.py	Tue Jul 08 14:02:43 2014 +0200
+++ b/cwvreg.py	Wed May 21 16:14:17 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.
@@ -609,11 +609,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
@@ -622,7 +644,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')
 
--- a/debian/control	Tue Jul 08 14:02:43 2014 +0200
+++ b/debian/control	Wed May 21 16:14:17 2014 +0200
@@ -150,7 +150,7 @@
  graphviz,
  gettext,
  python-logilab-mtconverter (>= 0.8.0),
- python-logilab-common (>= 0.59.0),
+ python-logilab-common (>= 0.62.0),
  python-yams (>= 0.38.1),
  python-yams (<< 0.39),
  python-rql (>= 0.31.2),