""" """ try: from Products.validation.interfaces.IValidator import IValidator, IValidationChain except ImportError: from interfaces.IValidator import IValidator, IValidationChain from types import StringType, TupleType, ListType, UnicodeType from config import validation as validationService from exceptions import UnknowValidatorError, FalseValidatorError, AlreadyRegisteredValidatorError try: from types import StringTypes except ImportError: StringTypes = (UnicodeType, StringType) V_REQUIRED = 1 V_SUFFICIENT = 2 class ValidationChain: """ """ __implements__ = IValidationChain def __init__(self, name, title='', description='', validators=(), register=False): self.name = name self.title = title or name self.description = description self._v_mode = [] self._chain = [] if type(validators) not in (TupleType, ListType): validators = (validators, ) for validator in validators: if type(validator) in (TupleType, ListType): self.append(validator[0], validator[1]) else: self.appendRequired(validator) if register: validationService.register(self) def __repr__(self): """print obj support """ map = { V_REQUIRED : 'V_REQUIRED', V_SUFFICIENT : 'V_SUFFICIENT' } val = [] for validator, mode in self: name = validator.name val.append("('%s', %s)" % (name, map.get(mode))) return '(%s)' % ', '.join(val) def __len__(self): """len(obj) suppor """ assert(len(self._chain), len(self._v_mode)) return len(self._chain) def __iter__(self): """Python 2.3 for i in x support """ assert(len(self._chain), len(self._v_mode)) return iter(zip(self._chain, self._v_mode)) def __cmp__(self, key): if isinstance(key, ValidationChain): str = repr(key) else: str = key return cmp(repr(self), str) def __getitem__(self, idx): """self[idx] support and Python 2.1 for i in x support """ assert(len(self._chain), len(self._v_mode)) return self._chain[idx], self._v_mode[idx] def append(self, id_or_obj, mode=V_REQUIRED): """Appends a validator """ validator = self.setValidator(id_or_obj) self.setMode(validator, mode) def appendRequired(self, id_or_obj): """Appends a validator as required """ self.append(id_or_obj, mode=V_REQUIRED) def appendSufficient(self, id_or_obj): """Appends a validator as sufficient """ self.append(id_or_obj, mode=V_SUFFICIENT) def insert(self, id_or_obj, mode=V_REQUIRED, position=0): """Inserts a validator at position (default 0) """ validator = self.setValidator(id_or_obj, position=position) self.setMode(validator, mode, position=position) def insertRequired(self, id_or_obj, position=0): """Inserts a validator as required at position (default 0) """ self.insert(id_or_obj, mode=V_REQUIRED, position=0) def insertSufficient(self, id_or_obj, position=0): """Inserts a validator as required at position (default 0) """ self.insert(id_or_obj, mode=V_SUFFICIENT, position=0) def setMode(self, validator, mode, position=None): """Set mode """ assert(mode in (V_REQUIRED, V_SUFFICIENT)) # validator not required if position is None: self._v_mode.append(mode) else: self._v_mode.insert(position, mode) assert(len(self._chain), len(self._v_mode)) def setValidator(self, id_or_obj, position=None): """Set validator """ validator = validationService.validatorFor(id_or_obj) if position is None: self._chain.append(validator) else: self._chain.insert(position, validator) return validator def __call__(self, value, *args, **kwargs): """Do validation """ results = {} failed = False for validator, mode in self: name = validator.name result = validator(value, *args, **kwargs) if result == True: if mode == V_SUFFICIENT: return True # validation was successful elif mode == V_REQUIRED: continue # go on else: raise ValidatorError, 'Unknown mode %s' % mode else: if mode == V_SUFFICIENT: if type(result) in StringTypes: # don't log if validator doesn't return an error msg results[name] = result continue # no fatal error, go on elif mode == V_REQUIRED: if type(result) in StringTypes: # don't log if validator doesn't return an error msg results[name] = result failed = True break # fatal error, stop and fail else: raise ValidatorError, 'Unknown mode %s' % mode if failed: return '\n'.join([ #'%s: %s' % (name, res) '%s' % res for name, res in results.items()] ) else: return True def test(): """Little test script """ isEmptyURL = ValidationChain('isEmptyURL', validators = (('isEmpty', V_SUFFICIENT), ('isURL', V_REQUIRED)), register=True ) # v = validationService.validatorFor('isEmptyURL') assert(v is isEmptyURL) assert(v('http://www.example.org') is True) assert(v('') is True) assert(type(v('www.example.org')) is StringType) # error isIntOrEmpty = ValidationChain('isIntOrEmpty') isIntOrEmpty.appendSufficient('isEmpty') from validators.RegexValidator import RegexValidator isPosInt = RegexValidator('isInt', r'^([+])?\d+$', title='', description='') isIntOrEmpty.appendRequired(isPosInt) validationService.register(isIntOrEmpty) v = validationService.validatorFor('isIntOrEmpty') assert(v is isIntOrEmpty) assert(v('') is True) assert(v('1') is True) assert(type(v('-1')) is StringType) # error assert(type(v('a')) is StringType) # error test() if __name__ == '__main__': test()