From 155020b91eb81caaeee7861e30ecdc3ef17694cb Mon Sep 17 00:00:00 2001
From: Arnaud Fontaine <arnaud.fontaine@nexedi.com>
Date: Fri, 4 Mar 2011 14:36:38 +0000
Subject: [PATCH] Upon resetting, delete constraints and _categories attributes
 on accessor holders before deleting the class itself because a reference on
 the class will still be kept as bases of erp5.portal_type, thus this ensures
 that erp5.portal_type.Foo will be 'unghost' when accessing constraints and
 _categories.

Also, move testInstanceBaseCategoryList to TestPortalTypeClass as the
issue is initially specific to portal type class.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@43982 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/dynamic/accessor_holder.py   | 12 +++++++++
 .../tests/testDynamicClassGeneration.py       | 26 +++++++++++++++++++
 product/ERP5Type/tests/testERP5Type.py        | 18 -------------
 3 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/product/ERP5Type/dynamic/accessor_holder.py b/product/ERP5Type/dynamic/accessor_holder.py
index a2543d6419..ecebf4f932 100644
--- a/product/ERP5Type/dynamic/accessor_holder.py
+++ b/product/ERP5Type/dynamic/accessor_holder.py
@@ -99,6 +99,18 @@ class AccessorHolderModuleType(ModuleType):
     """
     for klass in self.__dict__.values():
       if isinstance(klass, AccessorHolderType):
+        # Delete these attributes (computed on the portal type class
+        # from its accessor holder) before deleting the class itself
+        # because a reference on the class will still be kept as bases
+        # of erp5.portal_type, thus this ensures that
+        # erp5.portal_type.Foo will be 'unghost' thanks to
+        # PortalTypeMetaClass.__getattr__
+        for attribute in ('constraints', '_categories'):
+          try:
+            delattr(klass, attribute)
+          except AttributeError:
+            pass
+
         delattr(self, klass.__name__)
 
 def _generateBaseAccessorHolder(portal):
diff --git a/product/ERP5Type/tests/testDynamicClassGeneration.py b/product/ERP5Type/tests/testDynamicClassGeneration.py
index ba6273de3b..bafc3052d4 100644
--- a/product/ERP5Type/tests/testDynamicClassGeneration.py
+++ b/product/ERP5Type/tests/testDynamicClassGeneration.py
@@ -270,6 +270,32 @@ class TestPortalTypeClass(ERP5TypeTestCase):
     module_class.loadClass()
     self.assertFalse(issubclass(module_class, Folder))
 
+  def testAttributeValueComputedFromAccessorHolderList(self):
+    """
+    Check that attributes such as constraints and _categories,
+    containing respectively all the constraints and categories define
+    on their Property Sheets, loads the portal type class as some
+    static getters (for example getInstanceBaseCategoryList() use
+    _categories directly)
+    """
+    import erp5.portal_type
+
+    synchronizeDynamicModules(self.portal, force=True)
+    self.assertTrue(erp5.portal_type.Person.__isghost__)
+    self.assertTrue('constraints' not in erp5.portal_type.Person.__dict__)
+
+    getattr(erp5.portal_type.Person, 'constraints')
+    self.assertTrue(not erp5.portal_type.Person.__isghost__)
+    self.assertTrue('constraints' in erp5.portal_type.Person.__dict__)
+
+    synchronizeDynamicModules(self.portal, force=True)
+    self.assertTrue(erp5.portal_type.Person.__isghost__)
+    self.assertTrue('_categories' not in erp5.portal_type.Person.__dict__)
+
+    getattr(erp5.portal_type.Person, '_categories')
+    self.assertTrue(not erp5.portal_type.Person.__isghost__)
+    self.assertTrue('_categories' in erp5.portal_type.Person.__dict__)
+
 class TestZodbPropertySheet(ERP5TypeTestCase):
   """
   XXX: WORK IN PROGRESS
diff --git a/product/ERP5Type/tests/testERP5Type.py b/product/ERP5Type/tests/testERP5Type.py
index d1ea86aade..47be906e02 100644
--- a/product/ERP5Type/tests/testERP5Type.py
+++ b/product/ERP5Type/tests/testERP5Type.py
@@ -3075,24 +3075,6 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
         property_id_dict[property_id] = 1
       self.assertEqual([], non_unique_property_id_list)
 
-class TestInstanceBaseCategoryList(ERP5TypeTestCase):
-  def getBusinessTemplateList(self):
-    return 'erp5_base',
-
-  def test_getInstanceBaseCategoryList(self):
-    portal = self.getPortalObject()
-    person_portal_type = self.portal.portal_types['Person']
-    person_category_list = person_portal_type.getInstanceBaseCategoryList()
-    self.assertNotEqual([], list(person_category_list))
-
-  def test_getInstanceBaseCategoryList_afterReset(self):
-    self.getTypesTool().resetDynamicDocumentsOnceAtTransactionBoundary()
-    transaction.commit()
-    portal = self.getPortalObject()
-    person_portal_type = self.portal.portal_types['Person']
-    person_category_list = person_portal_type.getInstanceBaseCategoryList()
-    self.assertNotEqual([], list(person_category_list))
-
 class TestAccessControl(ERP5TypeTestCase):
   # Isolate test in a dedicaced class in order not to break other tests
   # when this one fails.
-- 
2.30.9