Commit 3202ce7b authored by Jérome Perrin's avatar Jérome Perrin

return error message has "translatable" strings with a mapping, otherwise using

constraints will generate tons of messages.



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@18241 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 6bf9fff1
...@@ -53,33 +53,38 @@ class AttributeEquality(PropertyExistence): ...@@ -53,33 +53,38 @@ class AttributeEquality(PropertyExistence):
if not self._checkConstraintCondition(obj): if not self._checkConstraintCondition(obj):
return [] return []
errors = PropertyExistence.checkConsistency(self, obj, fixit=fixit) errors = PropertyExistence.checkConsistency(self, obj, fixit=fixit)
for attribute_name, attribute_value in self.constraint_definition.items(): for attribute_name, expected_value in self.constraint_definition.items():
error_message = None error_message = None
mapping = dict()
# If property does not exist, error will be raise by # If property does not exist, error will be raise by
# PropertyExistence Constraint. # PropertyExistence Constraint.
if obj.hasProperty(attribute_name): if obj.hasProperty(attribute_name):
identical = 1 identical = 1
if type(attribute_value) in (type(()), type([])): if isinstance(expected_value, (list, tuple)):
# List type # List type
if len(obj.getProperty(attribute_name)) != len(attribute_value): if len(obj.getProperty(attribute_name)) != len(expected_value):
identical = 0 identical = 0
else: else:
for item in obj.getProperty(attribute_name): for item in obj.getProperty(attribute_name):
if item not in attribute_value: if item not in expected_value:
identical = 0 identical = 0
break break
else: else:
# Other type # Other type
identical = (attribute_value == obj.getProperty(attribute_name)) identical = (expected_value == obj.getProperty(attribute_name))
if not identical: if not identical:
# Generate error_message # Generate error_message
error_message = "Attribute %s is '%s' but should be '%s'" % \ error_message = "Attribute ${attribute_name} value is "\
(attribute_name, obj.getProperty(attribute_name), "${current_value} but should be ${expected_value}"
attribute_value) mapping(attribute_name=attribute_name,
attribute_value=obj.getProperty(attribute_name),
expected_value=expected_value)
# Generate error # Generate error
if error_message is not None: if error_message is not None:
if fixit: if fixit:
obj._setProperty(attribute_name, attribute_value) obj._setProperty(attribute_name, expected_value)
error_message += " (Fixed)" error_message = "Attribute ${attribute_name} value is "\
errors.append(self._generateError(obj, error_message)) "${current_value} but should be ${expected_value} (Fixed)"
errors.append(self._generateError(obj, error_message, mapping))
return errors return errors
...@@ -55,21 +55,21 @@ class CategoryExistence(Constraint): ...@@ -55,21 +55,21 @@ class CategoryExistence(Constraint):
for base_category in self.constraint_definition.keys(): for base_category in self.constraint_definition.keys():
if base_category in ('portal_type', ): if base_category in ('portal_type', ):
continue continue
mapping = dict(base_category=base_category)
# Check existence of base category # Check existence of base category
error_message = "Category existence error for base category '%s': " % \
base_category
if base_category not in obj.getBaseCategoryList(): if base_category not in obj.getBaseCategoryList():
error_message += " this document has no such category" error_message = "Category existence error for base category "\
"${base_category}, this document has no such category"
elif len(obj.getCategoryMembershipList(base_category, elif len(obj.getCategoryMembershipList(base_category,
portal_type = self.constraint_definition\ portal_type = self.constraint_definition\
.get('portal_type', ()))) == 0: .get('portal_type', ()))) == 0:
error_message += " this category was not defined" error_message = "Category existence error for base category "\
"${base_category}, this category is not defined"
else: else:
error_message = None error_message = None
# Raise error # Raise error
if error_message: if error_message:
errors.append(self._generateError(obj, error_message)) errors.append(self._generateError(obj, error_message, mapping))
return errors return errors
...@@ -63,7 +63,7 @@ class CategoryMembershipArity(Constraint): ...@@ -63,7 +63,7 @@ class CategoryMembershipArity(Constraint):
if not self._checkConstraintCondition(obj): if not self._checkConstraintCondition(obj):
return [] return []
errors = [] errors = []
# Retrieve values inside de PropertySheet (_constraints) # Retrieve configuration values from PropertySheet (_constraints)
base_category = self.constraint_definition['base_category'] base_category = self.constraint_definition['base_category']
min_arity = int(self.constraint_definition['min_arity']) min_arity = int(self.constraint_definition['min_arity'])
max_arity = None max_arity = None
...@@ -74,19 +74,33 @@ class CategoryMembershipArity(Constraint): ...@@ -74,19 +74,33 @@ class CategoryMembershipArity(Constraint):
arity = self._calculateArity(obj) arity = self._calculateArity(obj)
if not (max_arity is None and (min_arity <= arity) if not (max_arity is None and (min_arity <= arity)
or (min_arity <= arity <= max_arity)): or (min_arity <= arity <= max_arity)):
mapping = dict(base_category=base_category,
portal_type=portal_type,
current_arity=arity,
min_arity=min_arity,
max_arity=max_arity,)
# Generate error message # Generate error message
error_message = "Arity error for relation '%s'" % \
base_category
if portal_type is not (): if portal_type is not ():
error_message += " and portal_type: '%s'" % str(portal_type)
if max_arity is None: if max_arity is None:
error_message += \ error_message = "Arity Error for Relation ${base_category}"\
", arity is equal to %i but should be at least %i" % \ " and Type ${portal_type}"\
(arity, min_arity) ", arity is equal to ${current_arity} but "\
"should be at least ${min_arity}"
else: else:
error_message += \ error_message = "Arity Error for Relation ${base_category}"\
", arity is equal to %i but should be between %i and %i" % \ " and Type ${portal_type}"\
(arity, min_arity, max_arity) ", arity is equal to ${current_arity} but "\
"should be between ${min_arity} and ${max_arity}"
else:
if max_arity is None:
error_message = "Arity Error for Relation ${base_category}"\
", arity is equal to ${current_arity} but "\
"should be at least ${min_arity}"
else:
error_message = "Arity Error for Relation ${base_category}"\
", arity is equal to ${current_arity} but "\
"should be between ${min_arity} and ${max_arity}"
# Add error # Add error
errors.append(self._generateError(obj, error_message)) errors.append(self._generateError(obj, error_message, mapping))
return errors return errors
...@@ -46,17 +46,24 @@ class ContentExistence(Constraint): ...@@ -46,17 +46,24 @@ class ContentExistence(Constraint):
each string corresponds to an error. each string corresponds to an error.
We are checking that object contains a subobject. We are checking that object contains a subobject.
""" """
from Products.ERP5Type.Message import Message
obj = object obj = object
errors = [] errors = []
if self._checkConstraintCondition(object): if self._checkConstraintCondition(object):
# Retrieve configuration values from PropertySheet (_constraints) # Retrieve configuration values from PropertySheet (_constraints)
portal_type = self.constraint_definition['portal_type'] portal_type = self.constraint_definition.get('portal_type', ())
if not len(obj.contentValues(portal_type=portal_type)): if not len(obj.contentValues(portal_type=portal_type)):
# Generate error message # Generate error message
error_message = "Does not contain any subobject" mapping = {}
error_message = "The document does not contain any subobject"
if portal_type is not (): if portal_type is not ():
error_message += " of portal type: '%s'" % str(portal_type) error_message += " of portal type ${portal_type}"
# XXX maybe this could be factored out
if isinstance(portal_type, basestring):
portal_type = (portal_type, )
mapping['portal_type'] = str(Message('erp5_ui', ' or ')).join(
[str(Message('erp5_ui', pt)) for pt in portal_type])
# Add error # Add error
errors.append(self._generateError(obj, error_message)) errors.append(self._generateError(obj, error_message, mapping))
return errors return errors
...@@ -59,20 +59,25 @@ class PortalTypeClass(Constraint): ...@@ -59,20 +59,25 @@ class PortalTypeClass(Constraint):
type_info = types_tool._getOb(obj.getPortalType(), None) type_info = types_tool._getOb(obj.getPortalType(), None)
if type_info is None : if type_info is None :
errors.append(self._generateError(obj, errors.append(self._generateError(obj,
"Type information for '%s' not registred with the TypeTool")) "Type Information ${type_name} not registred with the TypeTool",
mapping=dict(type_name=obj.getPortalType())))
elif type_info.content_meta_type != obj.meta_type : elif type_info.content_meta_type != obj.meta_type :
errors.append(self._generateError(obj, errors.append(self._generateError(obj,
"Meta type is inconsistant with portal type definition."\ "Meta type is inconsistant with portal type definition."\
" Portal type meta type is '%s' class meta type is '%s' " % ( " Portal type meta type is ${portal_type_meta_type}"\
type_info.content_meta_type, obj.meta_type ))) " class meta type is ${class_meta_type} ",
mapping=dict(portal_type_meta_type=type_info.content_meta_type,
class_meta_type=obj.meta_type)))
else : else :
portal_type_class = self._getClassForPortalType(obj, type_info) portal_type_class = self._getClassForPortalType(obj, type_info)
obj_class = str(obj.__class__) obj_class = str(obj.__class__)
if portal_type_class != obj_class : if portal_type_class != obj_class :
errors.append(self._generateError(obj, errors.append(self._generateError(obj,
"__class__ is inconsistant with portal type definition."\ "__class__ is inconsistant with portal type definition."\
" Portal_type class is %s, document class is %s" % ( " Portal Type class is ${portal_type_class},"
portal_type_class, obj_class))) " document class is ${document_class}",
mapping=dict(portal_type_class=portal_type_class,
document_class=obj_class)))
# TODO fixit argument can be implemented here. # TODO fixit argument can be implemented here.
return errors return errors
......
...@@ -55,18 +55,19 @@ class PropertyExistence(Constraint): ...@@ -55,18 +55,19 @@ class PropertyExistence(Constraint):
# For each attribute name, we check if defined # For each attribute name, we check if defined
for property_id in self.constraint_definition.keys(): for property_id in self.constraint_definition.keys():
# Check existence of property # Check existence of property
error_message = \ mapping = dict(property_id=property_id)
"Property existence error for property '%s': " % property_id
if not obj.hasProperty(property_id): if not obj.hasProperty(property_id):
error_message += " this document has no such property" error_message = "Property existence error for property "\
"${property_id}, this document has no such property"
elif obj.getProperty(property_id) is None: elif obj.getProperty(property_id) is None:
# If value is '', attribute is considered a defined # If value is '', attribute is considered a defined
# XXX is this the default API ? # XXX is this the default API ?
error_message += " this property was not defined" error_message = "Property existence error for property "\
"${property_id}, this property is not defined"
else: else:
error_message = None error_message = None
# Return error # Return error
error = self._generateError(obj, error_message) error = self._generateError(obj, error_message, mapping)
if error is not None: if error is not None:
errors.append(error) errors.append(error)
return errors return errors
...@@ -88,25 +88,36 @@ class PropertyTypeValidity(Constraint): ...@@ -88,25 +88,36 @@ class PropertyTypeValidity(Constraint):
wrong_type = not isinstance(value, self._type_dict[property_type]) wrong_type = not isinstance(value, self._type_dict[property_type])
except KeyError: except KeyError:
wrong_type = 0 wrong_type = 0
error_message = "Attribute %s is defined with unknown type %s" % \ errors.append(self._generateError(obj,
(property_id, property_type) "Attribute ${attribute_name} is defined with "
errors.append(self._generateError(obj, error_message)) "an unknown type ${type_name}",
mapping=dict(attribute_name=property_id,
type_name=property_type)))
if wrong_type: if wrong_type:
# Type is wrong, so, raise constraint error # Type is wrong, so, raise constraint error
error_message = \ error_message = "Attribute ${attribute_name} should be of type"\
"Attribute %s should be of type %s but is of type %s" % \ " ${expected_type} but is of type ${actual_type}"
(property_id, property_type, str(type(value))) mapping = dict(attribute_name=property_id,
expected_type=property_type,
actual_type=str(type(value)))
if fixit: if fixit:
# try to cast to correct type # try to cast to correct type
if wrong_type: if wrong_type:
try: try:
value = self._type_dict[property_type][0](value) value = self._type_dict[property_type][0](value)
except (KeyError, ValueError), error: except (KeyError, ValueError), error:
error_message += " (Type cast failed : %s)" % error error_message = "Attribute ${attribute_name} should be of type"\
" ${expected_type} but is of type ${actual_type} (Type cast"\
" failed with error ${type_cast_error}"
mapping['type_cast_error'] = str(error)
else: else:
obj.setProperty(property_id, value) obj.setProperty(property_id, value)
error_message += " (Fixed)" error_message = "Attribute ${attribute_name} should be of type"\
errors.append(self._generateError(obj, error_message)) " ${expected_type} but is of type ${actual_type} (Fixed)"
errors.append(self._generateError(obj, error_message, mapping))
elif fixit: elif fixit:
oldvalue = getattr(obj, property_id, value) oldvalue = getattr(obj, property_id, value)
if oldvalue != value: if oldvalue != value:
......
...@@ -47,20 +47,24 @@ class StringAttributeMatch(PropertyExistence): ...@@ -47,20 +47,24 @@ class StringAttributeMatch(PropertyExistence):
each string corresponds to an error. each string corresponds to an error.
Check that each attribute does not match the RE Check that each attribute does not match the RE
""" """
errors = PropertyExistence.checkConsistency(self, object, fixit=fixit) error_list = PropertyExistence.checkConsistency(
if not errors: self, object, fixit=fixit)
for attribute_name, attribute_value in self.constraint_definition.items(): if not error_list:
for attribute_name, regular_expression in\
self.constraint_definition.items():
error_message = None error_message = None
# If property does not exist, error will be raise by # If property does not exist, error will be raised by
# PropertyExistence Constraint. # PropertyExistence Constraint.
current_value = object.getProperty(attribute_name) current_value = object.getProperty(attribute_name)
regexp = re.compile(attribute_value) regexp = re.compile(regular_expression)
if (current_value is not None) and \ if (current_value is not None) and \
(regexp.match(current_value) is None): (regexp.match(current_value) is None):
# Generate error_message
error_message = "Attribute %s is '%s' and not match '%s'" % \
(attribute_name, current_value,
attribute_value)
# Generate error # Generate error
errors.append(self._generateError(object, error_message)) error_list.append(self._generateError(object,
return errors "Attribute ${attribute_name} is ${attribute_value} and"
" does not match ${regular_expression}.",
mapping=dict(attribute_name=attribute_name,
attribute_value=repr(current_value),
regular_expression=repr(regular_expression))))
return error_list
...@@ -70,6 +70,7 @@ class TALESConstraint(Constraint): ...@@ -70,6 +70,7 @@ class TALESConstraint(Constraint):
LOG('ERP5Type', PROBLEM, 'TALESConstraint error on "%s" on %s' % LOG('ERP5Type', PROBLEM, 'TALESConstraint error on "%s" on %s' %
(self.constraint_definition['expression'], obj), error=sys.exc_info()) (self.constraint_definition['expression'], obj), error=sys.exc_info())
errors.append(self._generateError(obj, errors.append(self._generateError(obj,
'Error while evaluating expression: %s' % str(e))) 'Error while evaluating expression: ${error_text}',
mapping=dict(error_text=str(e))))
return errors return errors
...@@ -282,6 +282,11 @@ class TestConstraint(PropertySheetTestCase): ...@@ -282,6 +282,11 @@ class TestConstraint(PropertySheetTestCase):
error_list = sequence.get('error_list') error_list = sequence.get('error_list')
self.failUnless(error_list != [], self.failUnless(error_list != [],
"error_list : %s" % error_list) "error_list : %s" % error_list)
# call getTranslatedMessage, to make sure messages have a valid mapping.
for error in error_list:
self.assertNotEquals('',
error.getTranslatedMessage())
def stepCreateConstraint(self, sequence=None, def stepCreateConstraint(self, sequence=None,
sequence_list=None, **kw): sequence_list=None, **kw):
...@@ -964,7 +969,9 @@ class TestConstraint(PropertySheetTestCase): ...@@ -964,7 +969,9 @@ class TestConstraint(PropertySheetTestCase):
base_category=('group',), base_category=('group',),
klass_name='CategoryMembershipArity', klass_name='CategoryMembershipArity',
min_arity=1) min_arity=1)
self.assertEquals(1, len(constraint.checkConsistency(obj))) message_list = constraint.checkConsistency(obj)
self.assertEquals(1, len(message_list))
self.assertNotEquals('', message_list[0].getTranslatedMessage())
obj.setGroup('testGroup1') obj.setGroup('testGroup1')
self.assertEquals(0, len(constraint.checkConsistency(obj))) self.assertEquals(0, len(constraint.checkConsistency(obj)))
...@@ -976,7 +983,9 @@ class TestConstraint(PropertySheetTestCase): ...@@ -976,7 +983,9 @@ class TestConstraint(PropertySheetTestCase):
base_category=('group',), base_category=('group',),
klass_name='CategoryAcquiredMembershipArity', klass_name='CategoryAcquiredMembershipArity',
min_arity=1) min_arity=1)
self.assertEquals(1, len(constraint.checkConsistency(obj))) message_list = constraint.checkConsistency(obj)
self.assertEquals(1, len(message_list))
self.assertNotEquals('', message_list[0].getTranslatedMessage())
obj.setGroup('testGroup1') obj.setGroup('testGroup1')
self.assertEquals(0, len(constraint.checkConsistency(obj))) self.assertEquals(0, len(constraint.checkConsistency(obj)))
...@@ -1106,7 +1115,9 @@ class TestConstraint(PropertySheetTestCase): ...@@ -1106,7 +1115,9 @@ class TestConstraint(PropertySheetTestCase):
base_category=('group',), base_category=('group',),
klass_name='CategoryRelatedMembershipArity', klass_name='CategoryRelatedMembershipArity',
min_arity=1) min_arity=1)
self.assertEquals(1, len(constraint.checkConsistency(obj))) message_list = constraint.checkConsistency(obj)
self.assertEquals(1, len(message_list))
self.assertNotEquals('', message_list[0].getTranslatedMessage())
related_obj.setGroupValue(obj) related_obj.setGroupValue(obj)
get_transaction().commit() get_transaction().commit()
self.tic() self.tic()
...@@ -1141,7 +1152,9 @@ class TestConstraint(PropertySheetTestCase): ...@@ -1141,7 +1152,9 @@ class TestConstraint(PropertySheetTestCase):
obj = self._makeOne() obj = self._makeOne()
self.assertEquals([], constraint.checkConsistency(obj)) self.assertEquals([], constraint.checkConsistency(obj))
obj.setTitle('foo') obj.setTitle('foo')
self.assertEquals(1, len(constraint.checkConsistency(obj))) message_list = constraint.checkConsistency(obj)
self.assertEquals(1, len(message_list))
self.assertNotEquals('', message_list[0].getTranslatedMessage())
def test_TALESConstraintInvalidExpression(self): def test_TALESConstraintInvalidExpression(self):
"""Tests TALESConstraint with an invalid expression """Tests TALESConstraint with an invalid expression
...@@ -1152,7 +1165,9 @@ class TestConstraint(PropertySheetTestCase): ...@@ -1152,7 +1165,9 @@ class TestConstraint(PropertySheetTestCase):
expression='python: None / 3') # ValueError expression='python: None / 3') # ValueError
obj = self._makeOne() obj = self._makeOne()
# an error during expression evaluation simply makes a consistency error # an error during expression evaluation simply makes a consistency error
self.assertEquals(1, len(constraint.checkConsistency(obj))) message_list = constraint.checkConsistency(obj)
self.assertEquals(1, len(message_list))
self.assertNotEquals('', message_list[0].getTranslatedMessage())
# an error during expression compilation is reraised to the programmer # an error during expression compilation is reraised to the programmer
constraint = self._createGenericConstraint( constraint = self._createGenericConstraint(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment