From d032411c50ba823420797c036a1a72a84798c22c Mon Sep 17 00:00:00 2001 From: Sebastien Robin <seb@nexedi.com> Date: Wed, 10 Aug 2016 12:16:00 +0200 Subject: [PATCH] ERP5Type.dynamic: show up failures in __getattribute__ of lazy_class If for some reasons loadClass was not working, it was failing totally silently without any log. If there is any unexpected error in loadClass, this ended up for example having some tests failing with : RuntimeError: Malformed property definition <persistent broken erp5.portal_type.Acquired Property instance '\x00\x00\x00\x00\x00\x00\x12\xb5'> on /erp5/portal_property_sheets/SimpleItem While only this was displayed in logs : ERP5Type/dynamic/lazy_class.py", line 350, in loadClass class_definition = generatePortalTypeClass(site, portal_type) ... AttributeError: __of__ Which was totally unrelated to the real problem. So a silent initial error was the source of later unrelated errors, making it very difficult to find the initial source of problem. So make sure we have logs as soon as we are not able to load a class. --- product/ERP5Type/dynamic/lazy_class.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/product/ERP5Type/dynamic/lazy_class.py b/product/ERP5Type/dynamic/lazy_class.py index f7f8feb0e9..cddb6749b3 100644 --- a/product/ERP5Type/dynamic/lazy_class.py +++ b/product/ERP5Type/dynamic/lazy_class.py @@ -20,6 +20,7 @@ from zLOG import LOG, WARNING, BLATHER from portal_type_class import generatePortalTypeClass from accessor_holder import AccessorHolderType import persistent_migration +from ZODB.POSException import ConflictError class ERP5BaseBroken(Broken, ERP5Base, PersistentBroken): # PersistentBroken can't be reused directly @@ -108,7 +109,16 @@ class GhostBaseMetaClass(ExtensionClass, AccessorHolderType): return super(cls, self).__getattribute__(attr) #LOG("ERP5Type.Dynamic", BLATHER, # "loading attribute %s.%s..." % (name, attr)) - self.__class__.loadClass() + # Errors in __getattribute__ are ignored silently. Since loadClass calls + # various code, make sure we have explicitely a log in case of failure + try: + self.__class__.loadClass() + except ConflictError: + raise + except Exception, e: + LOG('lazy_class.__getattribute__', WARNING, 'Failed to load class : %r' % (e,), + error=sys.exc_info()) + raise return getattr(self, attr) cls.__getattribute__ = __getattribute__ -- 2.30.9