[Erp5-report] r39879 nicolas.dumazet - in /erp5/trunk/products/ERP5Type: dynamic/ tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Thu Nov 4 08:03:17 CET 2010


Author: nicolas.dumazet
Date: Thu Nov  4 08:03:16 2010
New Revision: 39879

URL: http://svn.erp5.org?rev=39879&view=rev
Log:
add support for interfaces on Portal Type classes.

You can now add and remove interfaces to Portal Types on the fly.

Modified:
    erp5/trunk/products/ERP5Type/dynamic/lazy_class.py
    erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py
    erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py

Modified: erp5/trunk/products/ERP5Type/dynamic/lazy_class.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/dynamic/lazy_class.py?rev=39879&r1=39878&r2=39879&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] Thu Nov  4 08:03:16 2010
@@ -1,9 +1,12 @@
 # -*- coding: utf-8 -*-
 
 import sys
+
 from Products.ERP5Type.Globals import InitializeClass
 from Products.ERP5Type.Base import Base as ERP5Base
 from ExtensionClass import ExtensionClass, pmc_init_of
+
+from zope.interface import classImplements
 from ZODB.broken import Broken, PersistentBroken
 from zLOG import LOG, WARNING, BLATHER
 
@@ -120,22 +123,28 @@ class PortalTypeMetaClass(ExtensionClass
 
     portal_type = klass.__name__
     try:
-      baseclasses, attributes = generatePortalTypeClass(portal_type)
+      class_definition = generatePortalTypeClass(portal_type)
     except AttributeError:
       LOG("ERP5Type.Dynamic", WARNING,
           "Could not access Portal Type Object for type %r"
           % portal_type, error=sys.exc_info())
-      baseclasses = (ERP5BaseBroken, )
-      attributes = {}
+      base_list = (ERP5BaseBroken, )
+      attribute_dict = {}
+      interface_list = []
+    else:
+      base_list, interface_list, attribute_dict = class_definition
+
 
     # save the old bases to be able to restore a ghost state later
     klass.__ghostbase__ = klass.__bases__
-    klass.__bases__ = baseclasses
+    klass.__bases__ = base_list
 
-    for key, value in attributes.iteritems():
+    for key, value in attribute_dict.iteritems():
       setattr(klass, key, value)
 
     klass.resetAcquisitionAndSecurity()
+    for interface in interface_list:
+      classImplements(klass, interface)
 
 def generateLazyPortalTypeClass(portal_type_name):
   return PortalTypeMetaClass(portal_type_name, (GhostPortalType,), {})

Modified: erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py?rev=39879&r1=39878&r2=39879&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] Thu Nov  4 08:03:16 2010
@@ -29,7 +29,6 @@
 
 import sys
 import inspect
-
 from types import ModuleType
 
 from dynamic_module import registerDynamicModule
@@ -39,6 +38,8 @@ from Products.ERP5Type.Globals import In
 from Products.ERP5Type.Utils import setDefaultClassProperties
 from Products.ERP5Type import document_class_registry, mixin_class_registry
 from Products.ERP5Type import PropertySheet as FilesystemPropertySheet
+
+from zope.interface import classImplements
 from zLOG import LOG, ERROR, INFO
 
 def _importClass(classpath):
@@ -175,11 +176,19 @@ def generatePortalTypeClass(portal_type_
 
   baseclasses = [klass] + accessor_holder_list + mixin_class_list
 
+  interface_class_list = []
+  if interface_list:
+    from Products.ERP5Type import interfaces
+    interface_class_list = [getattr(interfaces, name)
+                            for name in interface_list]
+
   #LOG("ERP5Type.dynamic", INFO,
   #    "Portal type %s loaded with bases %s" \
   #        % (portal_type_name, repr(baseclasses)))
 
-  return tuple(baseclasses), dict(portal_type=portal_type_name)
+  return (tuple(baseclasses),
+         interface_class_list,
+         dict(portal_type=portal_type_name))
 
 from lazy_class import generateLazyPortalTypeClass
 def initializeDynamicModules():

Modified: erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py?rev=39879&r1=39878&r2=39879&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py [utf8] Thu Nov  4 08:03:16 2010
@@ -35,6 +35,8 @@ from Products.ERP5Type.dynamic.portal_ty
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
 from Products.ERP5Type.tests.backportUnittest import expectedFailure, skip
 
+from zope.interface import Interface, implementedBy
+
 class TestPortalTypeClass(ERP5TypeTestCase):
   def getBusinessTemplateList(self):
     return 'erp5_base',
@@ -205,6 +207,40 @@ class TestPortalTypeClass(ERP5TypeTestCa
     self.assertEquals(accessor(), 'foobar')
     self.assertEquals(temp.__class__.__module__, 'erp5.temp_portal_type')
 
+  def testInterfaces(self):
+    types_tool = self.portal.portal_types
+
+    # a new interface
+    class IForTest(Interface):
+      pass
+    from Products.ERP5Type import interfaces
+    interfaces.IForTest = IForTest
+
+
+    # one new type
+    dummy_type = types_tool.newContent('InterfaceTestType',
+                                       'Base Type')
+    # implementing IForTest
+    dummy_type.edit(type_class='Person',
+                    type_interface_list=['IForTest',],)
+    transaction.commit()
+
+    from erp5.portal_type import InterfaceTestType
+
+    # it's necessary to load the class
+    # to have a correct list of interfaces
+    implemented_by = list(implementedBy(InterfaceTestType))
+    self.failIf(IForTest in implemented_by)
+    InterfaceTestType.loadClass()
+
+    implemented_by = list(implementedBy(InterfaceTestType))
+    self.assertTrue(IForTest in implemented_by,
+                    'IForTest not in %s' % implemented_by)
+
+    InterfaceTestType.restoreGhostState()
+    implemented_by = list(implementedBy(InterfaceTestType))
+    self.failIf(IForTest in implemented_by)
+
 class TestZodbPropertySheet(ERP5TypeTestCase):
   """
   XXX: WORK IN PROGRESS




More information about the Erp5-report mailing list