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