From 5d48a7a62c2bfaef43dcca3bfdadafd455fa1164 Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine <arnaud.fontaine@nexedi.com> Date: Wed, 18 Jan 2012 17:00:34 +0900 Subject: [PATCH] Avoid creating a temporary file when loading the source code of a Component. --- product/ERP5Type/Core/DocumentComponent.py | 46 +++++--------------- product/ERP5Type/dynamic/component_class.py | 48 ++++++--------------- 2 files changed, 23 insertions(+), 71 deletions(-) diff --git a/product/ERP5Type/Core/DocumentComponent.py b/product/ERP5Type/Core/DocumentComponent.py index d4e27b841e..f1c82c3de2 100644 --- a/product/ERP5Type/Core/DocumentComponent.py +++ b/product/ERP5Type/Core/DocumentComponent.py @@ -28,9 +28,6 @@ # ############################################################################## -import imp -import os - from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions from Products.ERP5Type.Base import Base @@ -58,36 +55,13 @@ class DocumentComponent(Base): 'Reference', 'TextDocument') - - # XXX-arnau: per-component reset, global for now - # def reset(self): - # import erp5 - # - # try: - # component_namespace_name, module_name = self.getId().split('.')[1:] - # component_namespace = getattr(erp5, component_namespace_name) - # except (ValueError, AttributeError): - # LOG("ERP5Type.Core.DocumentComponent", DEBUG, - # "Invalid namespace %s..." % self.getId()) - # else: - # if module_name in component_namespace.__dict__: - # LOG("ERP5Type.Core.DocumentComponent", INFO, "Reset %s..." % self.getId()) - # getattr(component_namespace, module_name).restoreGhostState() - - def load(self): - # XXX-arnau: There should be a load_source() taking a string rather than - # creating a temporary file - from App.config import getConfiguration - instance_home = getConfiguration().instancehome - path = '%s/Component' % instance_home - if not os.path.isdir(path): - os.mkdir(path) - - component_path = '%s/%s.py' % (path, self.getId()) - with open(component_path, 'w') as component_file: - component_file.write(self.getTextContent()) - - try: - return imp.load_source(self.getReference(), component_path) - finally: - os.remove(component_path) + def load(self, namespace_dict={}): + """ + Load the source code into the given dict. Using exec() rather than + imp.load_source() as the latter would required creating an intermediary + file. Also, for traceback readability sake, the destination module + __dict__ is given rather than creating an empty dict and returning + it. By default namespace_dict is an empty dict to allow checking the + source code before validate. + """ + exec self.getTextContent() in namespace_dict diff --git a/product/ERP5Type/dynamic/component_class.py b/product/ERP5Type/dynamic/component_class.py index 3b9c581e94..f60353bee5 100644 --- a/product/ERP5Type/dynamic/component_class.py +++ b/product/ERP5Type/dynamic/component_class.py @@ -26,55 +26,33 @@ # ############################################################################## +from types import ModuleType from zLOG import LOG, INFO -class ComponentProxyClass(object): - """ - XXX-arnau: should maybe use Ghost class? - """ - def __init__(self, component, module): - self._component = component - self._module = module - - self.__isghost__ = False - - # XXX-arnau: metaclass! - self.__class__.__name__ = component.getReference() - self.__class__.__module__ = component.getId().rsplit('.', 1)[0] - description = component.getDescription() - if description: - self.__doc__ = description - - def restoreGhostState(self): - self.__isghost__ = True - - def __getattr__(self, name): - if self.__isghost__: - self._module = self._component.load() - self.__isghost__ = False - LOG("ERP5Type.dynamic", INFO, "Reloaded %s" % self._component.getId()) - - return getattr(self._module, name) - def generateComponentClassWrapper(namespace): def generateComponentClass(component_name): from Products.ERP5.ERP5Site import getSite site = getSite() - component_name = '%s.%s' % (namespace, component_name) + component_id = '%s.%s' % (namespace, component_name) try: - component = getattr(site.portal_components, component_name) + component = getattr(site.portal_components, component_id) except AttributeError: LOG("ERP5Type.dynamic", INFO, - "Could not find %s, perhaps it has not been migrated yet?" % component_name) + "Could not find %s, perhaps it has not been migrated yet?" % \ + component_id) raise else: if component.getValidationState() == 'validated': - klass = ComponentProxyClass(component, component.load()) - LOG("ERP5Type.dynamic", INFO, "Loaded successfully %s" % component_name) - return klass + new_module = ModuleType(component_name, + component.getDescription()) + + new_module.__module__ = component_id + component.load(new_module.__dict__) + LOG("ERP5Type.dynamic", INFO, "Loaded successfully %s" % component_id) + return new_module else: - raise AttributeError("Component %s not validated" % component_name) + raise AttributeError("Component %s not validated" % component_id) return generateComponentClass -- 2.30.9