[Erp5-report] r40763 arnaud.fontaine - in /erp5/trunk/products/ERP5Type: Core/ PropertyShee...

nobody at svn.erp5.org nobody at svn.erp5.org
Fri Nov 26 11:35:00 CET 2010


Author: arnaud.fontaine
Date: Fri Nov 26 11:34:51 2010
New Revision: 40763

URL: http://svn.erp5.org?rev=40763&view=rev
Log:
Add Category Membership Arity Constraint for ZODB Property Sheets

Added:
    erp5/trunk/products/ERP5Type/Core/CategoryMembershipArityConstraint.py
      - copied, changed from r40596, erp5/trunk/products/ERP5Type/Constraint/CategoryMembershipArity.py
    erp5/trunk/products/ERP5Type/PropertySheet/CategoryMembershipArityConstraint.py
Modified:
    erp5/trunk/products/ERP5Type/PropertySheet/__init__.py
    erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py

Copied: erp5/trunk/products/ERP5Type/Core/CategoryMembershipArityConstraint.py (from r40596, erp5/trunk/products/ERP5Type/Constraint/CategoryMembershipArity.py)
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Core/CategoryMembershipArityConstraint.py?p2=erp5/trunk/products/ERP5Type/Core/CategoryMembershipArityConstraint.py&p1=erp5/trunk/products/ERP5Type/Constraint/CategoryMembershipArity.py&r1=40596&r2=40763&rev=40763&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Constraint/CategoryMembershipArity.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Core/CategoryMembershipArityConstraint.py [utf8] Fri Nov 26 11:34:51 2010
@@ -1,8 +1,9 @@
 ##############################################################################
 #
-# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
-#                    Sebastien Robin <seb at nexedi.com>
-#                    Romain Courteaud <romain at nexedi.com>
+# Copyright (c) 2002-2010 Nexedi SARL and Contributors. All Rights Reserved.
+#                         Sebastien Robin <seb at nexedi.com>
+#                         Romain Courteaud <romain at nexedi.com>
+#                         Arnaud Fontaine <arnaud.fontaine at nexedi.com>
 #
 # WARNING: This program as such is intended to be used by professional
 # programmers who take the whole responsability of assessing all potential
@@ -27,90 +28,82 @@
 #
 ##############################################################################
 
-from Constraint import Constraint
+from Products.ERP5Type.mixin.constraint import ConstraintMixin
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions, PropertySheet
 
-class CategoryMembershipArity(Constraint):
+class CategoryMembershipArityConstraint(ConstraintMixin):
   """
-    This constraint checks if an object respects the arity.
+  This constraint checks if an object respects the arity.
 
-    For example we can check if every Order has at least one source.
-    Configuration example:
-    { 'id'            : 'source',
-      'description'   : '',
-      'type'          : 'CategoryMembershipArity',
-      'min_arity'     : '1',
-      'max_arity'     : '1',
-      'portal_type'   : ('Organisation', ),
-      'base_category' : ('source',)
-      'condition'     : 'python: object.getPortalType() == 'Foo',
-    },
+  This is only relevant for ZODB Property Sheets (filesystem Property
+  Sheets rely on Products.ERP5Type.Constraint.CategoryMembershipArity
+  instead).
+
+  For example, if we would like to check whether the object respects a
+  minimum arity of '1' and a maximum arity of '1 for the Portal Type
+  'Organisation' and the Base Category 'source', then we would create
+  a 'Category Membership Arity Constraint' within that Property Sheet
+  and set 'Minimum arity' to '1', 'Maximum Arity' to '1', 'Portal
+  Types' to 'Organisation', 'Base Categories' to 'source', then set
+  the 'Predicate' if necessary (known as 'condition' for filesystem
+  Property Sheets).
   """
+  meta_type = 'ERP5 Category Membership Arity Constraint'
+  portal_type = 'Category Membership Arity Constraint'
 
-  _message_id_list = ['message_arity_too_small',
-                   'message_arity_not_in_range',
-                   'message_arity_with_portal_type_to_small',
-                   'message_arity_with_portal_type_not_in_range']
-
-  message_arity_too_small = "Arity Error for Relation ${base_category}"\
-                          ", arity is equal to ${current_arity} but "\
-                          "should be at least ${min_arity}"
-  message_arity_not_in_range = "Arity Error for Relation ${base_category}"\
-                          ", arity is equal to ${current_arity} but "\
-                          "should be between ${min_arity} and ${max_arity}"
-  message_arity_with_portal_type_to_small = "Arity Error for Relation"\
-                          " ${base_category} and Type ${portal_type}"\
-                          ", arity is equal to ${current_arity} but "\
-                          "should be at least ${min_arity}"
-
-  message_arity_with_portal_type_not_in_range = "Arity Error for Relation"\
-                          " ${base_category} and Type ${portal_type}"\
-                          ", arity is equal to ${current_arity} but "\
-                          "should be between ${min_arity} and ${max_arity}"
-
-  def _calculateArity(self, obj):
-    base_category = self.constraint_definition['base_category']
-    portal_type = self.constraint_definition['portal_type']
-    return len(obj.getCategoryMembershipList(base_category,
-                                              portal_type=portal_type))
+  # Declarative security
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  property_sheets = (PropertySheet.SimpleItem,
+                     PropertySheet.Predicate,
+                     PropertySheet.Reference,
+                     PropertySheet.CategoryMembershipArityConstraint)
+
+  def _calculateArity(self, obj, base_category_list, portal_type_list):
+    return len(obj.getCategoryMembershipList(base_category_list,
+                                             portal_type=portal_type_list))
 
   def checkConsistency(self, obj, fixit=0):
-    """Check the object's consistency.
-      We are looking the definition of the constraing where
-      are defined the minimum and the maximum arity, and the
-      list of objects we wants to check the arity.
     """
-    if not self._checkConstraintCondition(obj):
+    Check the object's consistency. We are looking at the definition
+    of the constraint where the minimum and the maximum arities are
+    defined, and the list of objects we wants to check the arity for
+    """
+    if not self.test(obj):
       return []
-    error_list = []
-    # Retrieve configuration values from PropertySheet (_constraints)
-    base_category = self.constraint_definition['base_category']
-    min_arity = int(self.constraint_definition['min_arity'])
-    max_arity = None
-    if 'max_arity' in self.constraint_definition:
-      max_arity = int(self.constraint_definition['max_arity'])
-    portal_type = self.constraint_definition['portal_type']
+
+    # Retrieve configuration values from PropertySheet
+    base_category_list = self.getConstraintBaseCategoryList()
+    min_arity = self.getMinArity()
+    max_arity = self.getMaxArity()
+    portal_type_list = self.getConstraintPortalTypeList()
+
     # Check arity and compare it with the min and max
-    arity = self._calculateArity(obj)
-    if not (max_arity is None and (min_arity <= arity)
-        or (min_arity <= arity <= max_arity)):
-      mapping = dict(base_category=base_category,
-                     portal_type=str(portal_type),
-                     current_arity=arity,
-                     min_arity=min_arity,
-                     max_arity=max_arity,)
-      # Generate error message
-      if portal_type is not ():
-        if max_arity is None:
-          message_id = 'message_arity_with_portal_type_to_small'
-        else:
-          message_id = 'message_arity_with_portal_type_not_in_range'
+    arity = self._calculateArity(obj, base_category_list, portal_type_list)
+    if (max_arity is None and min_arity <= arity) or \
+       min_arity <= arity <= max_arity:
+      return []
+
+    mapping = dict(base_category=base_category_list,
+                   portal_type=str(portal_type_list),
+                   current_arity=arity,
+                   min_arity=min_arity,
+                   max_arity=max_arity)
+
+    # Generate an error message
+    if len(portal_type_list) == 0:
+      if max_arity is None:
+        message_id = 'message_arity_with_portal_type_too_small'
+      else:
+        message_id = 'message_arity_with_portal_type_not_in_range'
+    else:
+      if max_arity is None:
+        message_id = 'message_arity_too_small'
       else:
-        if max_arity is None:
-          message_id = 'message_arity_too_small'
-        else:
-          message_id = 'message_arity_not_in_range'
-
-      # Add error
-      error_list.append(self._generateError(obj,
-                              self._getMessage(message_id), mapping))
-    return error_list
+        message_id = 'message_arity_not_in_range'
+
+    return [self._generateError(obj,
+                                self._getMessage(message_id),
+                                mapping)]

Added: erp5/trunk/products/ERP5Type/PropertySheet/CategoryMembershipArityConstraint.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/PropertySheet/CategoryMembershipArityConstraint.py?rev=40763&view=auto
==============================================================================
--- erp5/trunk/products/ERP5Type/PropertySheet/CategoryMembershipArityConstraint.py (added)
+++ erp5/trunk/products/ERP5Type/PropertySheet/CategoryMembershipArityConstraint.py [utf8] Fri Nov 26 11:34:51 2010
@@ -0,0 +1,76 @@
+##############################################################################
+#
+# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
+#                    Arnaud Fontaine <arnaud.fontaine at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+class CategoryMembershipArityConstraint:
+    """
+    Define a Category Membership Arity Constraint for ZODB Property Sheets
+    """
+    _properties = (
+        {   'id': 'min_arity',
+            'type': 'int',
+            'description' : 'Minimum arity' },
+        {   'id': 'max_arity',
+            'type': 'int',
+            'description' : 'Maximum arity' },
+        {   'id': 'constraint_portal_type',
+            'type': 'lines',
+            'description' : 'Portal types',
+            'default': () },
+        {   'id': 'constraint_base_category',
+            'type': 'lines',
+            'description' : 'Base categories',
+            'default': () },
+        {   'id': 'message_arity_too_small',
+            'type': 'string',
+            'description' : 'Error message when the arity for the relation '\
+                            'is too small',
+            'default': 'Arity Error for Relation ${base_category}, arity is '\
+                       'equal to ${current_arity} but should be at least '\
+                       '${min_arity}' },
+        {   'id': 'message_arity_not_in_range',
+            'type': 'string',
+            'description' : 'Error message when the arity for the relation '\
+                            'is out of bounds',
+            'default': 'Arity Error for Relation ${base_category}, arity is '\
+                       'equal to ${current_arity} but should be between '\
+                       '${min_arity} and ${max_arity}' },
+        {   'id': 'message_arity_with_portal_type_too_small',
+            'type': 'string',
+            'description' : 'Error message when the arity for the relation '\
+                            'and portal type is too small',
+            'default': 'Arity Error for Relation ${base_category} and Type '\
+                       '${portal_type}, arity is equal to ${current_arity} '\
+                       'but should be at least ${min_arity}' },
+        {   'id': 'message_arity_with_portal_type_not_in_range',
+            'type': 'string',
+            'description' : 'Error message when the arity for the relation '\
+                            'and portal type is out of bounds',
+            'default': 'Arity Error for Relation ${base_category} and Type '\
+                       '${portal_type}, arity is equal to ${current_arity} '\
+                       'but should be between ${min_arity} and ${max_arity}' },
+        )

Modified: erp5/trunk/products/ERP5Type/PropertySheet/__init__.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/PropertySheet/__init__.py?rev=40763&r1=40762&r2=40763&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/PropertySheet/__init__.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/PropertySheet/__init__.py [utf8] Fri Nov 26 11:34:51 2010
@@ -21,3 +21,4 @@ from CategoryExistenceConstraint import 
 from PropertyExistenceConstraint import PropertyExistenceConstraint
 from AttributeEqualityConstraint import AttributeEqualityConstraint
 from ContentExistenceConstraint import ContentExistenceConstraint
+from CategoryMembershipArityConstraint import CategoryMembershipArityConstraint

Modified: erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py?rev=40763&r1=40762&r2=40763&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/testDynamicClassGeneration.py [utf8] Fri Nov 26 11:34:51 2010
@@ -366,10 +366,32 @@ class TestZodbPropertySheet(ERP5TypeTest
       constraint_attribute_value='python: ("sub_category1", "sub_category2")')
 
   def _newContentExistenceConstraint(self):
+    """
+    Create a new Content Existence Constraint within test Property
+    Sheet
+    """
     self.test_property_sheet.newContent(
       reference='test_content_existence_constraint',
       portal_type='Content Existence Constraint',
-      constraint_portal_type='python: ("Folder")')
+      constraint_portal_type='python: ("Content Existence Constraint")')
+
+  def _newCategoryMembershipArityConstraint(self):
+    """
+    Create a new Category Membership Arity Constraint within test
+    Property Sheet
+    """
+    reference = 'test_category_membership_arity_constraint'
+
+    self.getPortal().portal_categories.newContent(
+      id=reference, portal_type='Base Category')
+
+    self.test_property_sheet.newContent(
+      reference=reference,
+      portal_type='Category Membership Arity Constraint',
+      min_arity=1,
+      max_arity=1,
+      constraint_portal_type=('Test Migration',),
+      constraint_base_category=(reference,))
 
   def afterSetUp(self):
     """
@@ -405,6 +427,10 @@ class TestZodbPropertySheet(ERP5TypeTest
       # Sheet
       self._newContentExistenceConstraint()
 
+      # Create a Category Membership Arity Constraint in the test
+      # Property Sheet
+      self._newCategoryMembershipArityConstraint()
+
       # Create all the test Properties
       for operation_type in ('change', 'delete', 'assign'):
         self._newStandardProperty(operation_type)
@@ -430,7 +456,7 @@ class TestZodbPropertySheet(ERP5TypeTest
         #      the migration has been finished
         type_zodb_property_sheet_list=('TestMigration',),
         type_base_category_list=('test_category_existence_constraint',),
-        type_allowed_content_type_list=('Folder',))
+        type_allowed_content_type_list=('Content Existence Constraint',))
 
     # Create a test module, meaningful to force generation of
     # TestMigration accessor holders and check the constraints
@@ -836,7 +862,18 @@ class TestZodbPropertySheet(ERP5TypeTest
     self._checkConstraint('test_content_existence_constraint',
                           self.test_module.newContent,
                           id='Test Content Existence Constraint',
-                          portal_type='Folder')
+                          portal_type='Content Existence Constraint')
+
+  def testCategoryMembershipArityConstraint(self):
+    """
+    Take the test module and check whether the Category Membership
+    Arity Constraint is there. Until a Base Category is set on the
+    Test Module, the constraint should fail
+    """
+    self._checkConstraint('test_category_membership_arity_constraint',
+                          self.test_module.setCategoryList,
+                          ('test_category_membership_arity_constraint/'\
+                           'Test Migration',))
 
 TestZodbPropertySheet = skip("ZODB Property Sheets code is not enabled yet")(
   TestZodbPropertySheet)




More information about the Erp5-report mailing list