# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------
"""
Validation
$Id: Validation.py 932 2004-07-20 06:21:57Z sbigaret $"""
__version__='$Revision: 932 $'[11:-2]
import types
import Modeling
from utils import isListOrTuple
# module constants
from interfaces.Validation import \
REQUIRED, \
TYPE_MISMATCH, \
CUSTOM_KEY_VALIDATION, \
CUSTOM_OBJECT_VALIDATION, \
LOWER_BOUND, \
UPPER_BOUND, \
OBJECT_WIDE, \
DELETE_DENY_KEY, \
OBJECT_WIDE, \
OBJECT_WIDE_KEY, \
MODEL_ERROR
import interfaces
class ValidationException(Exception):
"""
Raised by validation methods validateValue() on Entity, Attributes and
Relationships when they fail
"""
__implements__=(interfaces.Validation.ValidationExceptionInterface)
def __init__(self, aKey=None, anErrorType=''):
"Initializes the exception, possibly with supplied errorType and key"
if aKey is not None:
self._dict={aKey: [anErrorType]}
else:
self._dict={}
def aggregateError(self, anErrorType, aKey):
"""
Adds the supplied error type in the exception's dictionary, using the
provided key
"""
# TBD note: maybe check if 'errorType' was already supplied?
if self._dict.has_key(aKey):
self._dict[aKey].append(anErrorType)
else:
self._dict[aKey]=[anErrorType]
addErrorForKey=aggregateError
def aggregateErrors(self, listOfErrorTypes, aKey):
"""
Adds the supplied errors types in the exception's dictionary, using the
provided key
"""
if not isListOrTuple(listOfErrorTypes):
listOfErrorTypes=(listOfErrorTypes,)
for _errorType in listOfErrorTypes:
self.aggregateError(_errorType, aKey)
addErrorsForKey=aggregateErrors
def aggregateException(self, aValidationError):
"""
Concatenates the supplied Validation.ValidationException to the current
one.
For convenience, parameter can be either a Validation.ValidationException
object, or a dictionary as provided by Validation.ValidationException
errorsDict.
"""
if type(aValidationError) is not types.DictType:
_otherDict=aValidationError.errorsDict()
else:
_otherDict=aValidationError
for _key in _otherDict.keys():
self.aggregateErrors(_otherDict[_key], _key)
concatenateWith=aggregateException
def errorKeys(self):
"Returns keys for exception's dictionary"
return self._dict.keys()
def errorsDict(self):
"Returns the error dictionary"
return self._dict
errors=errorsDict
def keysForErrorType(self, anErrorType):
"Returns the keys for which that error was aggregated"
keys=[]
for key in self.errorKeys():
if anErrorType in self._dict[key]:
keys.append(key)
return keys
def __str__(self):
"Returns a string representation of the exception"
_str=""
for key in self.errorKeys():
_str=_str+"Validation for key %s failed:\n"%key
for value in self.errorsDict()[key]:
_str=_str+"- %s\n"%value
return _str
def __call__(self):
"Returns the receiver's dictionary"
return self._dict
def finalize(self):
"""
Finalize a validation process. If the exception has a non-empty errorsDict
it raises, otherwise simply return
"""
if self._dict: raise self
return
def args(self):
return self._dict
class Validation:
"""
Mix-in class for validation: it defined the default mechanisms used
in CustomObject.
This class is left as an example, but actual methods are now
in CustomObject itself and this mix-in class is not used anymore.
"""
__implements__=(interfaces.Validation.ValidationInterface,)
def validateForDelete(self):
"""
Default implementation simply sends validateObjectForDelete() to the
receiver's ClassDescription.
"""
self.classDescription().validateObjectForDelete(self)
def validateForInsert(self):
"Simply calls validateForSave()"
self.validateForSave(self)
def validateForUpdate(self):
"""
Simply calls validateForSave()
"""
self.classDescription().validateForSave(self)
def validateForSave(self):
"""
Default implementation simply forwards the message to the object's
ClassDescription.
"""
self.classDescription().validateObjectForSave(self)
# Backward compatibility
def validateObject(self):
self.validateForSave()
def validateValueForKey(self, aValue, aKey):
"""
Validate the value hold by 'aKey' attribute/relationship in the object
Default implementation forwards the message to the object's
ClassDescription.
"""
self.classDescription().validateValueForKey(self, aValue, aKey)
|