diff --git a/product/ERP5Type/dynamic/accessor_holder.py b/product/ERP5Type/dynamic/accessor_holder.py index a2543d6419a4cd5d6ef8097ba618cafb14c48230..ecebf4f93290ba60600dcf2ef19e354bba1f0c75 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 ba6273de3bdfa064fa5f168299cbccc504014395..bafc3052d4bc5767c7770b7ef98751936fcf1d2f 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 d1ea86aade2184c84e2c81725a3853fa4dfeb549..47be906e02cbf9834fb50761cd61cf70a8934d61 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.