[Erp5-report] r39751 nicolas.dumazet - /erp5/trunk/products/ERP5Type/dynamic/lazy_class.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Nov 2 06:28:17 CET 2010
Author: nicolas.dumazet
Date: Tue Nov 2 06:28:10 2010
New Revision: 39751
URL: http://svn.erp5.org?rev=39751&view=rev
Log:
Nicer way to set re-initialize classes after changing their bases.
1) Do not use gc.get_referrers as this is highly inefficient.
(the returned list contains a lot of objects, some of them
are persistent objects, some of them are not classes, etc, etc...
But worse, "dead" objects with a zero reference count can be returned
by this function, and this function would "ressucitate" them.
gc.get_referrers for application code is usually a bad idea)
2) Use instead a Python metaclass to track who's been subclassing
a portal type class, and after a change on the portal type class,
we just call the efficient PortalTypeMetaClass.getSubclassList to
get descendants.
Modified:
erp5/trunk/products/ERP5Type/dynamic/lazy_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=39751&r1=39750&r2=39751&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/lazy_class.py [utf8] Tue Nov 2 06:28:10 2010
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-import gc, sys
+import sys
from Products.ERP5Type.Base import Base as ERP5Base
from ExtensionClass import Base as ExtensionBase
from ZODB.broken import Broken, PersistentBroken
@@ -13,12 +13,36 @@ ERP5BaseBroken = type('ERP5BaseBroken',
if x[0] not in ('__dict__', '__module__', '__weakref__')))
ExtensionClass = type(ExtensionBase)
+
+class PortalTypeMetaClass(ExtensionClass):
+ """
+ Meta class that will be used by portal type classes
+ """
+ # register which classes subclass portal type classes
+ subclass_register = {} # XXX ideal defaultdict(list) wannabe
+ def __init__(cls, name, bases, dictionary):
+ """
+ This method is called when a portal type class is
+ created, or when a class inheriting a portal type
+ class is created
+ """
+ for parent in bases:
+ if issubclass(type(parent), PortalTypeMetaClass):
+ PortalTypeMetaClass.subclass_register.setdefault(parent, []).append(cls)
+
+ super(PortalTypeMetaClass, cls).__init__(name, bases, dictionary)
+
+ @classmethod
+ def getSubclassList(metacls, cls):
+ """
+ Returns classes deriving from cls
+ """
+ return metacls.subclass_register.get(cls, [])
+
def InitializePortalTypeClass(klass):
- # beware of the scary meta type
ExtensionClass.__init__(klass, klass)
- for klass in gc.get_referrers(klass):
- if isinstance(klass, ExtensionClass):
- InitializePortalTypeClass(klass)
+ for klass in PortalTypeMetaClass.getSubclassList(klass):
+ ExtensionClass.__init__(klass, klass)
def generateLazyPortalTypeClass(portal_type_name,
portal_type_class_loader):
@@ -87,4 +111,4 @@ def generateLazyPortalTypeClass(portal_t
# "loading attribute %s.%s..." % (name, attr))
return load(self, attr)
- return type(portal_type_name, (GhostPortalType,), dict())
+ return PortalTypeMetaClass(portal_type_name, (GhostPortalType,), dict())
More information about the Erp5-report
mailing list