diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py index 690f05c6ac74d595f510d379435920d1935dd1a3..fd2a1b615f68c4a33d8cce9e918135e704577ea9 100644 --- a/product/ERP5/ERP5Site.py +++ b/product/ERP5/ERP5Site.py @@ -348,7 +348,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): except AttributeError: reset_portal_type = False - synchronizeDynamicModules(self, force=reset_portal_type) + synchronizeDynamicModules(self, force=True) return self def manage_beforeDelete(self, item, container): diff --git a/product/ERP5Type/Tool/ComponentTool.py b/product/ERP5Type/Tool/ComponentTool.py index 6f1c0cd0e830207605bb332915cc0ae959626691..97ef9603bb8ab25224cebc18477b7e14795f6333 100644 --- a/product/ERP5Type/Tool/ComponentTool.py +++ b/product/ERP5Type/Tool/ComponentTool.py @@ -44,9 +44,9 @@ from zLOG import LOG, INFO, WARNING last_sync = -1 class ComponentTool(BaseTool): """ - This tool provides methods to load the the different types of - components of the ERP5 framework: Document classes, interfaces, - mixin classes, fields, accessors, etc. + This tool provides methods to load the the different types of components of + the ERP5 framework: Document classes, interfaces, mixin classes, fields, + accessors, etc. """ id = "portal_components" meta_type = "ERP5 Component Tool" @@ -55,22 +55,6 @@ class ComponentTool(BaseTool): security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) - def _resetModule(self, module): - for name, klass in module.__dict__.items(): - if not (name[0] != '_' and isinstance(klass, ModuleType)): - continue - - full_module_name = "%s.%s" % (module.__name__, name) - - LOG("ERP5Type.Tool.ComponentTool", INFO, "Resetting " + full_module_name) - - if name.endswith('_version'): - self._resetModule(getattr(module, name)) - - # The module must be deleted first - del sys.modules[full_module_name] - delattr(module, name) - security.declareProtected(Permissions.ResetDynamicClasses, 'reset') def reset(self, force=True, reset_portal_type=True): """ @@ -103,16 +87,15 @@ class ComponentTool(BaseTool): with Base.aq_method_lock: for content_type in allowed_content_type_list: - module_name = content_type.split(' ')[0].lower() + package_name = content_type.split(' ')[0].lower() try: - module = getattr(erp5.component, module_name) + package = getattr(erp5.component, package_name) # XXX-arnau: not everything is defined yet... except AttributeError: pass else: - module._resetRegistry() - self._resetModule(module) + package.reset() if reset_portal_type: type_tool.resetDynamicDocumentsOnceAtTransactionBoundary() diff --git a/product/ERP5Type/dynamic/component_package.py b/product/ERP5Type/dynamic/component_package.py index ddee651e2955d3d02163cedef452e95a854732d6..b8fadafd87364db6c4766bde5509a07bb1eb2581 100644 --- a/product/ERP5Type/dynamic/component_package.py +++ b/product/ERP5Type/dynamic/component_package.py @@ -35,7 +35,7 @@ import threading from Products.ERP5.ERP5Site import getSite from types import ModuleType -from zLOG import LOG, INFO +from zLOG import LOG, INFO, BLATHER class ComponentVersionPackage(ModuleType): """ @@ -123,9 +123,6 @@ class ComponentDynamicPackage(ModuleType): return self.__registry_dict - def _resetRegistry(self): - self.__registry_dict.clear() - def find_module(self, fullname, path=None): # Ignore imports with a path which are filesystem-only and any # absolute imports which does not start with this package prefix, @@ -264,3 +261,32 @@ class ComponentDynamicPackage(ModuleType): setattr(self, component_name, new_module) return new_module + + def reset(self, sub_package=None): + """ + Reset the content of the current package and its version package as well + recursively. This method must be called within a lock to avoid side + effects + """ + if sub_package is None: + # Clear the Component registry + self.__registry_dict.clear() + package = self + else: + package = sub_package + + for name, module in package.__dict__.items(): + if name[0] == '_' or not isinstance(module, ModuleType): + continue + + # Reset the content of the version package before resetting it + elif isinstance(module, ComponentVersionPackage): + self.reset(sub_package=module) + + module_name = "%s.%s" % (package.__name__, name) + LOG("ERP5Type.Tool.ComponentTool", BLATHER, "Resetting " + module_name) + + # The module must be deleted first from sys.modules to avoid imports in + # the meantime + del sys.modules[module_name] + delattr(package, name) diff --git a/product/ERP5Type/mixin/component.py b/product/ERP5Type/mixin/component.py index c7894a53d0d037b732b7eec14c5e784d13cd2f09..bd3afa2e3921095e79a0474b730883aea5a3239f 100644 --- a/product/ERP5Type/mixin/component.py +++ b/product/ERP5Type/mixin/component.py @@ -150,7 +150,7 @@ class ComponentMixin(PropertyRecordableMixin, Base): _message_reference_not_set = "Reference must be set" _message_invalid_reference = "Reference cannot end with '_version' or "\ - "start with '_' or be equal to find_module or load_module" + "start with '_' or be equal to find_module, load_module or reset" _message_version_not_set = "Version must be set" _message_invalid_version = "Version cannot start with '_'" @@ -177,7 +177,7 @@ class ComponentMixin(PropertyRecordableMixin, Base): elif (reference.endswith('_version') or reference[0] == '_' or - reference in ('find_module', 'load_module')): + reference in ('find_module', 'load_module', 'reset')): error_list.append( ConsistencyMessage(self, object_relative_url,