Commit a7c4a527 authored by Nicolas Dumazet's avatar Nicolas Dumazet

add support for interfaces on Portal Type classes.

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


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39879 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent fa803092
# -*- 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,), {})
......@@ -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 InitializeClass
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_name):
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():
......
......@@ -35,6 +35,8 @@ from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModule
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(ERP5TypeTestCase):
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment