Back to index

plone3  3.1.7
chain.py
Go to the documentation of this file.
00001 """
00002 """
00003 try:
00004     from Products.validation.interfaces.IValidator import IValidator, IValidationChain
00005 except ImportError:
00006     from interfaces.IValidator import IValidator, IValidationChain
00007 
00008 from types import StringType, TupleType, ListType, UnicodeType
00009 from config import validation as validationService
00010 from exceptions import UnknowValidatorError, FalseValidatorError, AlreadyRegisteredValidatorError
00011 
00012 try:
00013     from types import StringTypes
00014 except ImportError:
00015     StringTypes = (UnicodeType, StringType)
00016 
00017 V_REQUIRED   = 1
00018 V_SUFFICIENT = 2
00019 
00020 
00021 class ValidationChain:
00022     """
00023     """
00024     __implements__ = IValidationChain
00025      
00026     def __init__(self, name, title='', description='', validators=(),
00027                  register=False):
00028         self.name = name
00029         self.title = title or name
00030         self.description = description
00031         self._v_mode = []
00032         self._chain = []
00033 
00034         if type(validators) not in (TupleType, ListType):
00035             validators = (validators, )
00036         for validator in validators:
00037             if type(validator) in (TupleType, ListType):
00038                 self.append(validator[0], validator[1])
00039             else:
00040                 self.appendRequired(validator)
00041 
00042         if register:
00043             validationService.register(self)
00044                 
00045     def __repr__(self):
00046         """print obj support
00047         """
00048         map = { V_REQUIRED : 'V_REQUIRED', V_SUFFICIENT : 'V_SUFFICIENT' }
00049         val = []
00050         for validator, mode in self:
00051             name = validator.name
00052             val.append("('%s', %s)" % (name, map.get(mode)))
00053         return '(%s)' % ', '.join(val)
00054 
00055     def __len__(self):
00056         """len(obj) suppor
00057         """
00058         assert(len(self._chain), len(self._v_mode))
00059         return len(self._chain)
00060     
00061     def __iter__(self):
00062         """Python 2.3 for i in x support
00063         """
00064         assert(len(self._chain), len(self._v_mode))
00065         return iter(zip(self._chain, self._v_mode))
00066     
00067     def __cmp__(self, key):
00068         if isinstance(key, ValidationChain):
00069             str = repr(key)
00070         else:
00071             str = key
00072         return cmp(repr(self), str)
00073     
00074     def __getitem__(self, idx):
00075         """self[idx] support and Python 2.1 for i in x support
00076         """
00077         assert(len(self._chain), len(self._v_mode))
00078         return self._chain[idx], self._v_mode[idx]
00079         
00080     def append(self, id_or_obj, mode=V_REQUIRED):
00081         """Appends a validator
00082         """
00083         validator = self.setValidator(id_or_obj)
00084         self.setMode(validator, mode)
00085     
00086     def appendRequired(self, id_or_obj):
00087         """Appends a validator as required
00088         """
00089         self.append(id_or_obj, mode=V_REQUIRED)
00090 
00091     def appendSufficient(self, id_or_obj):
00092         """Appends a validator as sufficient
00093         """
00094         self.append(id_or_obj, mode=V_SUFFICIENT)
00095     
00096     def insert(self, id_or_obj, mode=V_REQUIRED, position=0):
00097         """Inserts a validator at position (default 0)
00098         """
00099         validator = self.setValidator(id_or_obj, position=position)
00100         self.setMode(validator, mode, position=position)
00101 
00102     def insertRequired(self, id_or_obj, position=0):
00103         """Inserts a validator as required at position (default 0)
00104         """
00105         self.insert(id_or_obj, mode=V_REQUIRED, position=0)
00106 
00107     def insertSufficient(self, id_or_obj, position=0):
00108         """Inserts a validator as required at position (default 0)
00109         """
00110         self.insert(id_or_obj, mode=V_SUFFICIENT, position=0)
00111 
00112     def setMode(self, validator, mode, position=None):
00113         """Set mode
00114         """
00115         assert(mode in (V_REQUIRED, V_SUFFICIENT))
00116         # validator not required
00117         if position is None:
00118             self._v_mode.append(mode)
00119         else:
00120             self._v_mode.insert(position, mode)
00121         assert(len(self._chain), len(self._v_mode))
00122 
00123     def setValidator(self, id_or_obj, position=None):
00124         """Set validator
00125         """
00126         validator = validationService.validatorFor(id_or_obj)
00127  
00128         if position is None:
00129             self._chain.append(validator)
00130         else:
00131             self._chain.insert(position, validator)
00132 
00133         return validator
00134 
00135     def __call__(self, value, *args, **kwargs):
00136         """Do validation
00137         """
00138         results = {}
00139         failed = False
00140         for validator, mode in self:
00141             name = validator.name
00142             result = validator(value, *args, **kwargs)
00143             if result == True:
00144                 if mode == V_SUFFICIENT:
00145                     return True # validation was successful
00146                 elif mode == V_REQUIRED:
00147                     continue    # go on
00148                 else:
00149                     raise ValidatorError, 'Unknown mode %s' % mode
00150             else:
00151                 if mode == V_SUFFICIENT:
00152                     if type(result) in StringTypes:
00153                         # don't log if validator doesn't return an error msg
00154                         results[name] = result
00155                     continue # no fatal error, go on
00156                 elif mode == V_REQUIRED:
00157                     if type(result) in StringTypes:
00158                         # don't log if validator doesn't return an error msg
00159                         results[name] = result
00160                     failed = True
00161                     break    # fatal error, stop and fail
00162                 else:
00163                     raise ValidatorError, 'Unknown mode %s' % mode
00164         
00165         if failed:
00166             return '\n'.join([
00167                               #'%s: %s' % (name, res)
00168                               '%s' % res
00169                               for name, res in results.items()]
00170                             )
00171         else:
00172             return True
00173 
00174 
00175 def test():
00176     """Little test script
00177     """
00178     isEmptyURL = ValidationChain('isEmptyURL',
00179                                 validators = (('isEmpty', V_SUFFICIENT), ('isURL', V_REQUIRED)),
00180                                 register=True
00181                                )
00182     #
00183     v = validationService.validatorFor('isEmptyURL')
00184     assert(v is isEmptyURL)
00185     assert(v('http://www.example.org') is True)
00186     assert(v('') is True)
00187     assert(type(v('www.example.org')) is StringType) # error
00188 
00189     isIntOrEmpty = ValidationChain('isIntOrEmpty')
00190     isIntOrEmpty.appendSufficient('isEmpty')
00191     from validators.RegexValidator import RegexValidator
00192     isPosInt = RegexValidator('isInt', r'^([+])?\d+$', title='', description='')
00193     isIntOrEmpty.appendRequired(isPosInt)
00194     validationService.register(isIntOrEmpty)
00195 
00196     v = validationService.validatorFor('isIntOrEmpty')
00197     assert(v is isIntOrEmpty)
00198     assert(v('') is True)
00199     assert(v('1') is True)
00200     assert(type(v('-1')) is StringType) # error
00201     assert(type(v('a')) is StringType) # error
00202 
00203 test()
00204 
00205 if __name__ == '__main__':
00206     test()