[Erp5-report] r14005 - in /erp5/trunk/products/ERP5Type: ./ tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Fri Apr 6 15:08:02 CEST 2007


Author: yo
Date: Fri Apr  6 15:08:00 2007
New Revision: 14005

URL: http://svn.erp5.org?rev=14005&view=rev
Log:
Define isTempDocument to specify if an object is a temporary object or persistent object, rather than using a hack. Remove hasattr in TempDocumentConstructor. Write a test for _aq_dynamic with a temporary object. Remove an unused test. Make it safe to call _aq_dynamic with a temporary object.

Modified:
    erp5/trunk/products/ERP5Type/Base.py
    erp5/trunk/products/ERP5Type/Utils.py
    erp5/trunk/products/ERP5Type/tests/testERP5Type.py

Modified: erp5/trunk/products/ERP5Type/Base.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Base.py?rev=14005&r1=14004&r2=14005&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Base.py (original)
+++ erp5/trunk/products/ERP5Type/Base.py Fri Apr  6 15:08:00 2007
@@ -407,6 +407,7 @@
   isPredicate = 0     #
   isTemplate = 0      #
   isDocument = 0      #
+  isTempDocument = 0  # If set to 0, instances are temporary.
 
   # Dynamic method acquisition system (code generation)
   aq_method_generated = {}
@@ -490,6 +491,13 @@
 
     # Proceed with property generation
     klass = self.__class__
+    if self.isTempObject():
+      # If self is a temporary object, generate methods for the base
+      # document class rather than for the temporary document class.
+      # Otherwise, instances of the base document class would fail
+      # in calling such methods, because they are not instances of
+      # the temporary document class.
+      klass = klass.__bases__[0]
     generated = 0 # Prevent infinite loops
 
     # Generate class methods
@@ -2114,13 +2122,9 @@
 
   security.declarePublic('isTempObject')
   def isTempObject(self):
-    """
-      Tells if an object is temporary or not
-
-      Implementation is based on the fact that reindexObject method is overloaded
-      for all TempObjects with the same dummy method
-    """
-    return self.reindexObject.im_func is self._temp_reindexObject.im_func
+    """Return true if self is an instance of a temporary document class.
+    """
+    return getattr(self.__class__, 'isTempDocument', 0)
 
   # Workflow Related Method
   security.declarePublic('getWorkflowStateItemList')
@@ -2916,6 +2920,7 @@
     we shoud used TempBase
   """
   isIndexable = 0
+  isTempDocument = 1
 
   # Declarative security
   security = ClassSecurityInfo()

Modified: erp5/trunk/products/ERP5Type/Utils.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Utils.py?rev=14005&r1=14004&r2=14005&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Utils.py (original)
+++ erp5/trunk/products/ERP5Type/Utils.py Fri Apr  6 15:08:00 2007
@@ -350,6 +350,7 @@
     def __init__(self, klass):
       # Create a new class to set permissions specific to temporary objects.
       class TempDocument(klass):
+        isTempDocument = 1
         pass
 
       # Replace some attributes.
@@ -369,7 +370,8 @@
       o = self.klass(id)
       if kw:
         o.__of__(folder)._edit(force_update=1, **kw)
-      if hasattr(folder, 'isTempObject') and folder.isTempObject(): 
+      isTempObject = getattr(folder, 'isTempObject', None)
+      if isTempObject is not None and isTempObject():
         folder._setObject(id, o)# Temp Object in Temp Object should use containment
         return id               # return id to be compatible with CMF constructInstance
       else:                     # Temp Object in Persistent Object should use acquisition

Modified: erp5/trunk/products/ERP5Type/tests/testERP5Type.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/testERP5Type.py?rev=14005&r1=14004&r2=14005&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/testERP5Type.py (original)
+++ erp5/trunk/products/ERP5Type/tests/testERP5Type.py Fri Apr  6 15:08:00 2007
@@ -209,19 +209,8 @@
       self.failUnless(business_template.getTitle()==test_string)
     
     # Test Dynamic Code Generation
-    def test_01_AqDynamic(self):
-      portal = self.getPortal()
-      #module = portal.person
-      from Products.ERP5Type.Base import initializeClassDynamicProperties
-      from Products.ERP5Type.Base import initializePortalTypeDynamicProperties
-      from Products.ERP5Type.Base import Base
-      from Products.ERP5Type import Document
-      initializeClassDynamicProperties(portal, Base)
-      # Base class should now have a state method
-      # self.failUnless(hasattr(Base, 'getFirstName'))
-      # This test is now useless since methods are portal type based
-    
-    def test_02_AqDynamic(self):
+    def test_02_AqDynamic(self, quiet=quiet, run=run_all_test):
+      if not run: return
       portal = self.getPortal()
       module = self.getPersonModule()
       person = module.newContent(id='1', portal_type='Person')
@@ -1273,6 +1262,72 @@
                                              checked_permission="View"), 
              [doo.getTitle(), bar.getTitle(), ])
 
+    def test_25_AqDynamicWithTempObject(self, quiet=quiet, run=run_all_test):
+      """Check if _aq_dynamic works correctly, regardless of whether
+      it is first called for a temporary object or a persistent object.
+
+      This test is based on the fact that a portal type is shared between
+      a temporary document and a persistent document, and if a class for
+      the temporary document is used for generating new methods, calling
+      such methods from a persistent object may fail, because such a
+      persistent object is not an instance of the temporary document class.
+      """
+      if not run: return
+      portal = self.getPortal()
+
+      # Clear out all generated methods.
+      _aq_reset()
+
+      # Create a new temporary person object.
+      from Products.ERP5Type.Document import newTempPerson
+      o = newTempPerson(portal, 'temp_person_1')
+      self.failUnless(o.isTempObject())
+
+      # This should generate a workflow method.
+      self.assertEquals(o.getValidationState(), 'draft')
+      o.validate()
+      self.assertEquals(o.getValidationState(), 'validated')
+
+      # Create a new persistent person object.
+      person_module = portal.person_module
+      person_id = 'person_1'
+      if person_id in person_module.objectIds():
+        person_module.manage_delObjects([person_id])
+      o = person_module.newContent(id=person_id, portal_type='Person')
+      self.failIf(o.isTempObject())
+
+      # This should call methods generated above for the temporary object.
+      self.assertEquals(o.getValidationState(), 'draft')
+      o.validate()
+      self.assertEquals(o.getValidationState(), 'validated')
+
+      # Paranoia: test the reverse snenario as well, although this
+      # should succeed anyway.
+
+      # Create a new persistent person object.
+      person_id = 'person_2'
+      if person_id in person_module.objectIds():
+        person_module.manage_delObjects([person_id])
+      o = person_module.newContent(id=person_id, portal_type='Person')
+      self.failIf(o.isTempObject())
+
+      # Clear out all generated methods.
+      _aq_reset()
+
+      # This should generate workflow methods.
+      self.assertEquals(o.getValidationState(), 'draft')
+      o.validate()
+      self.assertEquals(o.getValidationState(), 'validated')
+
+      # Create a new temporary person object.
+      o = newTempPerson(portal, 'temp_person_2')
+      self.failUnless(o.isTempObject())
+
+      # This should call methods generated for the persistent object.
+      self.assertEquals(o.getValidationState(), 'draft')
+      o.validate()
+      self.assertEquals(o.getValidationState(), 'validated')
+
 if __name__ == '__main__':
   framework()
 else:




More information about the Erp5-report mailing list