[Erp5-report] r39835 jm - in /erp5/trunk/products: ERP5/Document/ ERP5/tests/ ERP5Type/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Nov 3 14:24:11 CET 2010
Author: jm
Date: Wed Nov 3 14:24:07 2010
New Revision: 39835
URL: http://svn.erp5.org?rev=39835&view=rev
Log:
When uninstalling document item, restore document class from product if any
This fixes TestBusinessTemplate.test_168_DocumentUninstallIsEffective
Modified:
erp5/trunk/products/ERP5/Document/BusinessTemplate.py
erp5/trunk/products/ERP5/tests/testBusinessTemplate.py
erp5/trunk/products/ERP5Type/InitGenerator.py
erp5/trunk/products/ERP5Type/Utils.py
Modified: erp5/trunk/products/ERP5/Document/BusinessTemplate.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/BusinessTemplate.py?rev=39835&r1=39834&r2=39835&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/BusinessTemplate.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/BusinessTemplate.py [utf8] Wed Nov 3 14:24:07 2010
@@ -3380,6 +3380,21 @@ class DocumentTemplateItem(BaseTemplateI
{path : ['Removed', self.__class__.__name__[:-12]]})
return modified_object_list
+ def _resetDynamicModules(self):
+ # before any import, flush all ZODB caches to force a DB reload
+ # otherwise we could have objects trying to get commited while
+ # holding reference to a class that is no longer the same one as
+ # the class in its import location and pickle doesn't tolerate it.
+ # First we do a savepoint to dump dirty objects to temporary
+ # storage, so that all references to them can be freed.
+ transaction.savepoint(optimistic=True)
+ # Then we need to flush from all caches, not only the one from this
+ # connection
+ portal = self.getPortalObject()
+ portal._p_jar.db().cacheMinimize()
+ synchronizeDynamicModules(portal, force=True)
+ gc.collect()
+
def install(self, context, trashbin, **kw):
update_dict = kw.get('object_to_update')
force = kw.get('force')
@@ -3393,7 +3408,6 @@ class DocumentTemplateItem(BaseTemplateI
continue
text = self._objects[id]
path, name = posixpath.split(id)
- # This raises an exception if the file already exists.
try:
self.local_file_writer_name(name, text, create=0)
except IOError, error:
@@ -3405,19 +3419,7 @@ class DocumentTemplateItem(BaseTemplateI
if self.local_file_importer_name is None:
continue
if need_reset:
- # before any import, flush all ZODB caches to force a DB reload
- # otherwise we could have objects trying to get commited while
- # holding reference to a class that is no longer the same one as
- # the class in its import location and pickle doesn't tolerate it.
- # First we do a savepoint to dump dirty objects to temporary
- # storage, so that all references to them can be freed.
- transaction.savepoint(optimistic=True)
- # Then we need to flush from all caches, not only the one from this
- # connection
- portal = self.getPortalObject()
- portal._p_jar.db().cacheMinimize()
- synchronizeDynamicModules(portal, force=True)
- gc.collect()
+ self._resetDynamicModules()
need_reset = False
self.local_file_importer_name(name)
else:
@@ -3435,8 +3437,11 @@ class DocumentTemplateItem(BaseTemplateI
object_keys = [object_path]
else:
object_keys = self._archive.keys()
- for key in object_keys:
- self.local_file_remover_name(key)
+ if object_keys:
+ if isinstance(self, DocumentTemplateItem):
+ self._resetDynamicModules()
+ for key in object_keys:
+ self.local_file_remover_name(key)
BaseTemplateItem.uninstall(self, context, **kw)
def export(self, context, bta, **kw):
Modified: erp5/trunk/products/ERP5/tests/testBusinessTemplate.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/tests/testBusinessTemplate.py?rev=39835&r1=39834&r2=39835&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/tests/testBusinessTemplate.py [utf8] (original)
+++ erp5/trunk/products/ERP5/tests/testBusinessTemplate.py [utf8] Wed Nov 3 14:24:07 2010
@@ -6712,7 +6712,6 @@ class TestBusinessTemplate(ERP5TypeTestC
# check the previously existing instance now behaves as the overriden class
self.assertTrue(getattr(portal.another_file, 'isClassOverriden', False))
- @expectedFailure
def test_168_DocumentUninstallIsEffective(self):
portal = self.portal
# Test_167 above needs to have been run
@@ -6720,11 +6719,8 @@ class TestBusinessTemplate(ERP5TypeTestC
'isClassOverriden',
False):
self.test_167_InstanceAndRelatedClassDefinedInSameBT()
- self.uninstallBusinessTemplate('test_data')
- transaction.commit()
- self.tic()
+ self.uninstallBusinessTemplate('test_bt')
# check both File instances no longer behave like being overriden
- self.assertFalse(getattr(portal.some_file, 'isClassOverriden', False))
self.assertFalse(getattr(portal.another_file, 'isClassOverriden', False))
def test_getBusinessTemplateUrl(self):
Modified: erp5/trunk/products/ERP5Type/InitGenerator.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/InitGenerator.py?rev=39835&r1=39834&r2=39835&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/InitGenerator.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/InitGenerator.py [utf8] Wed Nov 3 14:24:07 2010
@@ -30,46 +30,39 @@
import os, re, string, sys
+from Products.ERP5Type import document_class_registry
from Products.ERP5Type.Globals import package_home, InitializeClass
from zLOG import LOG
-global product_document_registry
-product_document_registry = []
-global product_interactor_registry
+product_document_registry = {}
product_interactor_registry = []
-global interactor_class_id_registry
interactor_class_id_registry = {}
def getProductDocumentPathList():
- result = product_document_registry
- result.sort()
- return result
+ return sorted((k, os.path.dirname(sys.modules[v.rsplit('.', 1)[0]].__file__))
+ for k,v in product_document_registry.iteritems())
-def InitializeDocument(document_class, document_path=None):
- global product_document_registry
+def InitializeDocument(class_id, class_path):
# Register class in ERP5Type.Document
- product_document_registry.append(((document_class, document_path)))
+ product_document_registry[class_id] = class_path
def getProductInteractorPathList():
- result = product_interactor_registry
- result.sort()
- return result
+ return sorted(product_interactor_registry)
def InitializeInteractor(interactor_class, interactor_path=None):
- global product_interactor_registry
# Register class in ERP5Type.Interactor
product_interactor_registry.append(((interactor_class, interactor_path)))
def initializeProductDocumentRegistry():
from Utils import importLocalDocument
- for (class_id, document_path) in product_document_registry:
- importLocalDocument(class_id, path=document_path)
+ for (class_id, class_path) in product_document_registry.iteritems():
+ importLocalDocument(class_id, class_path=class_path)
#from Testing import ZopeTestCase
#ZopeTestCase._print('Added product document to ERP5Type repository: %s (%s) \n' % (class_id, document_path))
#LOG('Added product document to ERP5Type repository: %s (%s)' % (class_id, document_path), 0, '')
#print 'Added product document to ERP5Type repository: %s (%s)' % (class_id, document_path)
-
+
def initializeProductInteractorRegistry():
from Utils import importLocalInteractor
for (class_id, interactor_path) in product_interactor_registry:
@@ -77,10 +70,8 @@ def initializeProductInteractorRegistry(
importLocalInteractor(class_id, path=interactor_path)
def registerInteractorClass(class_id, klass):
- global interactor_class_id_registry
interactor_class_id_registry[class_id] = klass
def installInteractorClassRegistry():
- global interactor_class_id_registry
- for class_id, klass in interactor_class_id_registry.items():
+ for klass in interactor_class_id_registry.itervalues():
klass().install()
Modified: erp5/trunk/products/ERP5Type/Utils.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Utils.py?rev=39835&r1=39834&r2=39835&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Utils.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Utils.py [utf8] Wed Nov 3 14:24:07 2010
@@ -87,7 +87,7 @@ def simple_decorator(decorator):
return new_decorator
from Products.ERP5Type import Permissions
-
+from Products.ERP5Type import document_class_registry
from Products.ERP5Type.Accessor.Constant import PropertyGetter as \
PropertyConstantGetter
from Products.ERP5Type.Accessor.Constant import Getter as ConstantGetter
@@ -470,7 +470,6 @@ def updateGlobals(this_module, global_ho
for module_id in module_id_list:
import_method(module_id, path=path, is_erp5_type=is_erp5_type)
- from Products.ERP5Type import document_class_registry
module_name = this_module.__name__
# Return core document_class list (for ERP5Type only)
# this was introduced to permit overriding ERP5Type Document classes
@@ -478,14 +477,12 @@ def updateGlobals(this_module, global_ho
path, core_module_id_list = getModuleIdList(product_path, 'Core')
for document in core_module_id_list:
module_path = '.'.join((module_name, 'Core', document, document))
- document_class_registry[document] = module_path
- InitializeDocument(document, document_path=path)
+ InitializeDocument(document, module_path)
# Return document_class list
path, module_id_list = getModuleIdList(product_path, 'Document')
for document in module_id_list:
module_path = '.'.join((module_name, 'Document', document, document))
- document_class_registry[document] = module_path
- InitializeDocument(document, document_path=path)
+ InitializeDocument(document, module_path)
# Return interactor_class list
path, interactor_id_list = getModuleIdList(product_path, 'Interactor')
@@ -803,6 +800,14 @@ def removeLocalDocument(class_id):
f = os.path.join(path, "%s.%s" % (class_id, ext))
if os.path.exists(f):
os.remove(f)
+ if document_class_registry.pop(class_id, None):
+ # restore original class (from product) if any
+ from Products.ERP5Type.InitGenerator import product_document_registry
+ product_path = product_document_registry.get(class_id)
+ if product_path:
+ importLocalDocument(class_id, class_path=product_path)
+ else:
+ pass # XXX Do we need to clean up ?
def readLocalDocument(class_id):
instance_home = getConfiguration().instancehome
@@ -826,22 +831,14 @@ def writeLocalDocument(class_id, text, c
if create:
if os.path.exists(path):
raise IOError, 'the file %s is already present' % path
+ # check there is no syntax error (that's the most we can do at this time)
+ compile(text, path, 'exec')
f = open(path, 'w')
try:
f.write(text)
finally:
f.close()
- module_path = "erp5.document"
- classpath = "%s.%s" % (module_path, class_id)
- module = imp.load_source(classpath, path)
- import erp5.document
- setattr(erp5.document, class_id, getattr(module, class_id))
-
- # and register correctly the new document
- from Products.ERP5Type import document_class_registry
- document_class_registry[class_id] = classpath
-
def setDefaultClassProperties(property_holder):
"""Initialize default properties for ERP5Type Documents.
"""
@@ -917,17 +914,16 @@ class PersistentMigrationMixin(object):
from Globals import Persistent, PersistentMapping
-def importLocalDocument(class_id, path=None):
+def importLocalDocument(class_id, path=None, class_path=None):
"""Imports a document class and registers it in ERP5Type Document
repository ( Products.ERP5Type.Document )
"""
import Products.ERP5Type.Document
import Permissions
- from Products.ERP5Type import document_class_registry
- if path and 'products' in path.lower(): # XXX
- classpath = document_class_registry[class_id]
- module_path = classpath.rsplit('.', 1)[0]
+ if class_path:
+ assert path is None
+ module_path = class_path.rsplit('.', 1)[0]
module = __import__(module_path, {}, {}, (module_path,))
else:
# local document in INSTANCE_HOME/Document/
@@ -937,11 +933,11 @@ def importLocalDocument(class_id, path=N
path = os.path.join(instance_home, "Document")
path = os.path.join(path, "%s.py" % class_id)
module_path = "erp5.document"
- classpath = "%s.%s" % (module_path, class_id)
- module = imp.load_source(classpath, path)
+ class_path = "%s.%s" % (module_path, class_id)
+ module = imp.load_source(class_path, path)
import erp5.document
setattr(erp5.document, class_id, getattr(module, class_id))
- document_class_registry[class_id] = classpath
+ document_class_registry[class_id] = class_path
### Migration
module_name = "Products.ERP5Type.Document.%s" % class_id
@@ -986,7 +982,6 @@ def importLocalDocument(class_id, path=N
# XXX really?
return klass, tuple()
-
def initializeLocalRegistry(directory_name, import_local_method):
"""
Initialize local directory.
@@ -1049,7 +1044,6 @@ def initializeProduct( context,
"""
module_name = this_module.__name__
- from Products.ERP5Type import document_class_registry
# Content classes are exceptions and should be registered here.
# other products were all already registered in updateGlobals()
# because getModuleIdList works fine for Document/ and Core/
More information about the Erp5-report
mailing list