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