607 def reload_if_needed(self): |
607 def reload_if_needed(self): |
608 path = self.config.appobjects_path() |
608 path = self.config.appobjects_path() |
609 if self.is_reload_needed(path): |
609 if self.is_reload_needed(path): |
610 self.reload(path) |
610 self.reload(path) |
611 |
611 |
|
612 def _cleanup_sys_modules(self, path): |
|
613 """Remove submodules of `directories` from `sys.modules` and cleanup |
|
614 CW_EVENT_MANAGER accordingly. |
|
615 |
|
616 We take care to properly remove obsolete registry callbacks. |
|
617 |
|
618 """ |
|
619 caches = {} |
|
620 callbackdata = CW_EVENT_MANAGER.callbacks.values() |
|
621 for callbacklist in callbackdata: |
|
622 for callback in callbacklist: |
|
623 func = callback[0] |
|
624 # for non-function callable, we do nothing interesting |
|
625 module = getattr(func, '__module__', None) |
|
626 caches[id(callback)] = module |
|
627 deleted_modules = set(cleanup_sys_modules(path)) |
|
628 for callbacklist in callbackdata: |
|
629 for callback in callbacklist[:]: |
|
630 module = caches[id(callback)] |
|
631 if module and module in deleted_modules: |
|
632 callbacklist.remove(callback) |
|
633 |
612 def reload(self, path, force_reload=True): |
634 def reload(self, path, force_reload=True): |
613 """modification detected, reset and reload the vreg""" |
635 """modification detected, reset and reload the vreg""" |
614 CW_EVENT_MANAGER.emit('before-registry-reload') |
636 CW_EVENT_MANAGER.emit('before-registry-reload') |
615 if force_reload: |
637 if force_reload: |
616 cleanup_sys_modules(path) |
638 self._cleanup_sys_modules(path) |
617 cubes = self.config.cubes() |
639 cubes = self.config.cubes() |
618 # if the fs code use some cubes not yet registered into the instance |
640 # if the fs code use some cubes not yet registered into the instance |
619 # we should cleanup sys.modules for those as well to avoid potential |
641 # we should cleanup sys.modules for those as well to avoid potential |
620 # bad class reference pb after reloading |
642 # bad class reference pb after reloading |
621 cfg = self.config |
643 cfg = self.config |
622 for cube in cfg.expand_cubes(cubes, with_recommends=True): |
644 for cube in cfg.expand_cubes(cubes, with_recommends=True): |
623 if not cube in cubes: |
645 if not cube in cubes: |
624 cpath = cfg.build_appobjects_cube_path([cfg.cube_dir(cube)]) |
646 cpath = cfg.build_appobjects_cube_path([cfg.cube_dir(cube)]) |
625 cleanup_sys_modules(cpath) |
647 self._cleanup_sys_modules(cpath) |
626 self.register_objects(path) |
648 self.register_objects(path) |
627 CW_EVENT_MANAGER.emit('after-registry-reload') |
649 CW_EVENT_MANAGER.emit('after-registry-reload') |
628 |
650 |
629 def _set_schema(self, schema): |
651 def _set_schema(self, schema): |
630 """set instance'schema""" |
652 """set instance'schema""" |