[Erp5-report] r39754 nicolas.dumazet - /erp5/trunk/products/ERP5Type/dynamic/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Nov 2 08:08:59 CET 2010
Author: nicolas.dumazet
Date: Tue Nov 2 08:08:58 2010
New Revision: 39754
URL: http://svn.erp5.org?rev=39754&view=rev
Log:
move ghostify/unghostify-cation and ghost creation to portal type metaclass
Makes the code more efficient, and much more readable.
Modified:
erp5/trunk/products/ERP5Type/dynamic/lazy_class.py
erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py
Modified: erp5/trunk/products/ERP5Type/dynamic/lazy_class.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/dynamic/lazy_class.py?rev=39754&r1=39753&r2=39754&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] Tue Nov 2 08:08:58 2010
@@ -7,12 +7,50 @@ from ExtensionClass import ExtensionClas
from ZODB.broken import Broken, PersistentBroken
from zLOG import LOG, ERROR, BLATHER
+from portal_type_class import generatePortalTypeClass
+
# PersistentBroken can't be reused directly
# because its « layout differs from 'GhostPortalType' »
ERP5BaseBroken = type('ERP5BaseBroken', (Broken, ERP5Base), dict(x
for x in PersistentBroken.__dict__.iteritems()
if x[0] not in ('__dict__', '__module__', '__weakref__')))
+class GhostPortalType(ERP5Base): #SimpleItem
+ """
+ Ghost state for a portal type that is not loaded.
+
+ One instance of this class exists per portal type class on the system.
+ When an object of this portal type is loaded (a new object is created,
+ or an attribute of an existing object is accessed) this class will
+ change the bases of the portal type class so that it points to the
+ correct Document+Mixin+interfaces+AccessorHolder classes.
+ """
+ def __init__(self, *args, **kw):
+ self.__class__.loadClass()
+ getattr(self, '__init__')(*args, **kw)
+
+ def __getattribute__(self, attr):
+ """
+ This is only called once to load the class.
+ Because __bases__ is changed, the behavior of this object
+ will change after the first call.
+ """
+ # Class must be loaded if '__of__' is requested because otherwise,
+ # next call to __getattribute__ would lose any acquisition wrapper.
+ if attr in ('__class__',
+ '__getnewargs__',
+ '__getstate__',
+ '__dict__',
+ '__module__',
+ '__name__',
+ '__repr__',
+ '__str__') or attr[:3] in ('_p_', '_v_'):
+ return super(GhostPortalType, self).__getattribute__(attr)
+ #LOG("ERP5Type.Dynamic", BLATHER,
+ # "loading attribute %s.%s..." % (name, attr))
+ self.__class__.loadClass()
+ return getattr(self, attr)
+
class PortalTypeMetaClass(ExtensionClass):
"""
Meta class that will be used by portal type classes
@@ -54,71 +92,44 @@ class PortalTypeMetaClass(ExtensionClass
pmc_init_of(subcls)
InitializeClass(subcls)
-def generateLazyPortalTypeClass(portal_type_name,
- portal_type_class_loader):
- def load(self, attr):
- # self might be a subclass of a portal type class
- # we need to find the right parent class to change
- for klass in self.__class__.__mro__:
- # XXX hardcoded, this doesnt look too good
- if klass.__module__ == "erp5.portal_type":
- break
- else:
- raise AttributeError("Could not find a portal type class in class hierarchy")
-
- portal_type = klass.__name__
- try:
- baseclasses, attributes = portal_type_class_loader(portal_type)
- except AttributeError:
- LOG("ERP5Type.Dynamic", ERROR,
- "Could not access Portal Type Object for type %r"
- % portal_type, error=sys.exc_info())
- baseclasses = (ERP5BaseBroken, )
- attributes = {}
-
- # save the old bases to be able to restore a ghost state later
- klass.__ghostbase__ = klass.__bases__
- klass.__bases__ = baseclasses
-
- for key, value in attributes.iteritems():
- setattr(klass, key, value)
-
- klass.resetAcquisitionAndSecurity()
-
- return getattr(self, attr)
-
- class GhostPortalType(ERP5Base): #SimpleItem
- """
- Ghost state for a portal type that is not loaded.
+ def restoreGhostState(cls):
+ ghostbase = getattr(cls, '__ghostbase__', None)
+ if ghostbase is not None:
+ for attr in cls.__dict__.keys():
+ if attr not in ('__module__', '__doc__',):
+ delattr(cls, attr)
+ cls.__bases__ = ghostbase
+ cls.resetAcquisitionAndSecurity()
+
+ def loadClass(cls):
+ # cls might be a subclass of a portal type class
+ # we need to find the right class to change
+ for klass in cls.__mro__:
+ # XXX hardcoded, this doesnt look too good
+ if klass.__module__ == "erp5.portal_type":
+ break
+ else:
+ raise AttributeError("Could not find a portal type class in"
+ " class hierarchy")
+
+ portal_type = klass.__name__
+ try:
+ baseclasses, attributes = generatePortalTypeClass(portal_type)
+ except AttributeError:
+ LOG("ERP5Type.Dynamic", ERROR,
+ "Could not access Portal Type Object for type %r"
+ % portal_type, error=sys.exc_info())
+ baseclasses = (ERP5BaseBroken, )
+ attributes = {}
+
+ # save the old bases to be able to restore a ghost state later
+ klass.__ghostbase__ = klass.__bases__
+ klass.__bases__ = baseclasses
- One instance of this class exists per portal type class on the system.
- When an object of this portal type is loaded (a new object is created,
- or an attribute of an existing object is accessed) this class will
- change the bases of the portal type class so that it points to the
- correct Document+Mixin+interfaces+AccessorHolder classes.
- """
- def __init__(self, *args, **kw):
- load(self, '__init__')(*args, **kw)
+ for key, value in attributes.iteritems():
+ setattr(klass, key, value)
- def __getattribute__(self, attr):
- """
- This is only called once to load the class.
- Because __bases__ is changed, the behavior of this object
- will change after the first call.
- """
- # Class must be loaded if '__of__' is requested because otherwise,
- # next call to __getattribute__ would lose any acquisition wrapper.
- if attr in ('__class__',
- '__getnewargs__',
- '__getstate__',
- '__dict__',
- '__module__',
- '__name__',
- '__repr__',
- '__str__') or attr[:3] in ('_p_', '_v_'):
- return super(GhostPortalType, self).__getattribute__(attr)
- #LOG("ERP5Type.Dynamic", BLATHER,
- # "loading attribute %s.%s..." % (name, attr))
- return load(self, attr)
+ klass.resetAcquisitionAndSecurity()
- return PortalTypeMetaClass(portal_type_name, (GhostPortalType,), dict())
+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=39754&r1=39753&r2=39754&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] Tue Nov 2 08:08:58 2010
@@ -33,7 +33,6 @@ import inspect
from types import ModuleType
from dynamic_module import registerDynamicModule
-from lazy_class import generateLazyPortalTypeClass
from Products.ERP5Type.Base import _aq_reset
from Products.ERP5Type.Globals import InitializeClass
@@ -182,6 +181,7 @@ def generatePortalTypeClass(portal_type_
return tuple(baseclasses), dict(portal_type=portal_type_name)
+from lazy_class import generateLazyPortalTypeClass
def initializeDynamicModules():
"""
Create erp5 module and its submodules
@@ -201,13 +201,6 @@ def initializeDynamicModules():
XXX: there should be only one accessor_holder once the code is
stable and all the Property Sheets have been migrated
"""
- def loadPortalTypeClass(portal_type_name):
- """
- Returns a lazily-loaded "portal-type as a class"
- """
- return generateLazyPortalTypeClass(portal_type_name,
- generatePortalTypeClass)
-
erp5 = ModuleType("erp5")
sys.modules["erp5"] = erp5
erp5.document = ModuleType("erp5.document")
@@ -219,7 +212,7 @@ def initializeDynamicModules():
sys.modules["erp5.filesystem_accessor_holder"] = erp5.filesystem_accessor_holder
portal_type_container = registerDynamicModule('erp5.portal_type',
- loadPortalTypeClass)
+ generateLazyPortalTypeClass)
erp5.portal_type = portal_type_container
@@ -302,13 +295,7 @@ def synchronizeDynamicModules(context, f
for class_name, klass in inspect.getmembers(erp5.portal_type,
inspect.isclass):
- ghostbase = getattr(klass, '__ghostbase__', None)
- if ghostbase is not None:
- for attr in klass.__dict__.keys():
- if attr != '__module__':
- delattr(klass, attr)
- klass.__bases__ = ghostbase
- klass.resetAcquisitionAndSecurity()
+ klass.restoreGhostState()
# Clear accessor holders of ZODB Property Sheets
_clearAccessorHolderModule(erp5.zodb_accessor_holder)
More information about the Erp5-report
mailing list