Package konval :: Module basevalidator
[hide private]
[frames] | no frames]

Source Code for Module konval.basevalidator

  1  """ 
  2  Abstract base class for easy construction of validators. 
  3   
  4  """ 
  5   
  6  __docformat__ = "restructuredtext en" 
  7   
  8   
  9  ### IMPORTS 
 10   
 11  import exceptions 
 12   
 13  import impl 
 14   
 15  __all__ = [ 
 16          'BaseValidator', 
 17          'WrappingValidator', 
 18  ] 
 19   
 20   
 21  ### CONSTANTS & DEFINES 
 22   
 23  ### IMPLEMENTATION ### 
 24   
25 -class BaseValidator (object):
26 """ 27 A base class for custom validators. 28 29 The aim to make construction of new validators easy and quick. Ideally, with 30 this as a base class, most subclasses should only need to override one method 31 (``convert_value`` or ``validate_value``) and perhaps supply a c'tor if some state 32 needs to be stored. 33 """ 34
35 - def __call__ (self, value):
36 """ 37 Converts and validates user input. 38 39 :Parameters: 40 value 41 value to be checked or transformed 42 43 :Returns: 44 the transformed or validated value 45 46 This converts the passed value (via `convert`) and then validates it (via 47 `validate`). It should throw an error if any problems. This is the primary 48 entry-point for validator objects and could be overridden in a subclass if 49 required. However, it would probably be easier done in other methods 50 called by this. 51 """ 52 ## Main: 53 value = self.convert(value) 54 self.validate (value) 55 ## Postconditions & return: 56 return value
57
58 - def convert (self, value):
59 """ 60 Transform a value to the desired form. 61 62 :Parameters: 63 value 64 value to be transformed 65 66 :Returns: 67 the transformed value 68 69 This attempts to convert the passed value (via `convert_value`) and if 70 successful returns the new value. If any exception is thrown by conversion, 71 `raise_conversion_error` is called with the bad value and error (if any). 72 Behaviour could be customised by overriding this in a subclass, but 73 `convert_value` may be a better target. 74 """ 75 try: 76 conv_val = self.convert_value (value) 77 return conv_val 78 except exceptions.Exception, err: 79 self.raise_conversion_error (value, err) 80 except: 81 self.raise_conversion_error (value, None)
82
83 - def convert_value (self, value):
84 """ 85 Transform a value to the desired form. 86 87 :Parameters: 88 value 89 value to be transformed 90 91 :Returns: 92 the transformed value 93 94 This is the workhorse method that is called by `convert` to transform 95 passed values. As such, errors are signalled by throwing a meaningful 96 exception. This is one of the obvious and easiest places to customize 97 behaviour by overriding in a subclass. 98 """ 99 return value
100
101 - def raise_conversion_error (self, bad_val, err):
102 """ 103 Raise an error for a conversion problem. 104 105 :Parameters: 106 bad_val 107 The value that failed to convert. 108 err : Exception, None 109 The exception caught during conversion. 110 111 Override in subclass if need be, for specific exception types and 112 messages. 113 """ 114 # TODO: shift to base class 115 raise exceptions.ValueError (self.make_conversion_error_msg (bad_val, 116 err))
117
118 - def make_conversion_error_msg (self, bad_val, err):
119 """ 120 Generate an error message for a conversion problem. 121 122 Parameters as per `raise_conversion_error`. Override in subclass if need 123 be, for more specific and meaningful messages. 124 """ 125 # TODO: shift to base class 126 return "can't convert '%s'" % bad_val
127
128 - def validate (self, value):
129 """ 130 Is this value correct or of the correct form? 131 132 :Parameters: 133 value 134 value to be checked 135 136 This checks the passed value (via `validate_value`) and if successful 137 returns the new value. If any exception is thrown by validation, 138 `raise_validation_error` is called with the bad value and error (if any). 139 Behaviour could be customised by overriding this in a subclass, but 140 `validate_value` may be a better target. 141 """ 142 # NOTE: override in subclass 143 # probably a series of assertions 144 try: 145 if self.validate_value (value): 146 return 147 else: 148 raise 149 except exceptions.Exception, err: 150 self.raise_validation_error (value, err) 151 except: 152 self.raise_validation_error (value, None)
153
154 - def validate_value (self, value):
155 """ 156 Check a value is of the desired form. 157 158 :Parameters: 159 value 160 value to be checked 161 162 :Returns: 163 success of validation. 164 165 This is the workhorse method that is called by `validate` to check 166 passed values. As such, errors are signalled by either by throwing a 167 meaningful exception or by returning false. This is one of the obvious 168 and easiest places to customize behaviour by overriding in a subclass. 169 """ 170 return True
171
172 - def raise_validation_error (self, bad_val, err):
173 """ 174 Generate an error message for a validation problem. 175 176 :Parameters: 177 bad_val 178 The value that failed to validate. 179 err : Exception, None 180 The exception caught during validation. 181 182 Override in subclass if need be, for specific exception types and 183 messages. 184 """ 185 # TODO: shift to base class 186 raise exceptions.ValueError (self.make_validation_error_msg (bad_val, 187 err))
188
189 - def make_validation_error_msg (self, bad_val, err):
190 """ 191 Generate an error message for a validation problem. 192 193 Parameters as per `raise_validation_error`. Override in subclass if need 194 be, for more specific and meaningful messages. 195 """ 196 # TODO: shift to base class 197 return "can't validate '%s'" % (bad_val)
198 199
200 -class WrappingValidator (BaseValidator):
201 """ 202 Wraps functions and possible error messages in a validator. 203 204 This allows converting and validating functions to be easily encapsulated 205 in a validator. Given the design of konval (any function that accepts & 206 returns a value can be used as a validator), this is only slightly useful. 207 However it does allow useful error messages to be incorporated. 208 209 For example:: 210 211 >>> from string import * 212 >>> v = WrappingValidator (conv_fn=upper, conv_msg='not a string') 213 >>> v('abc') 214 'ABC' 215 >>> v(1) 216 Traceback (most recent call last): 217 ... 218 ValueError: not a string 219 >>> v = WrappingValidator (val_fn=lambda x: len(x) < 4) 220 >>> v('abc') 221 'abc' 222 >>> v(1) 223 Traceback (most recent call last): 224 ... 225 ValueError: can't validate '1' 226 227 Idea flinched from FormEncode. 228 229 """ 230
231 - def __init__ (self, conv_fn=None, conv_msg=None, val_fn=None, val_msg=None):
232 """ 233 C'tor accepting functors for validation & conversion. 234 235 :Parameters: 236 conv_fn : callable 237 performs conversion, should accept value and return transformed 238 conv_msg : str 239 string for error message in event of conversion failure 240 val_fn : callable 241 performs validation, should accept value and return success 242 val_msg : str 243 string for error message in event of validation failure 244 245 `conv_fn` and `val_fn` can be any callable object (e.g. a class with 246 `__call__`, lambda). Note that validation function should return not the 247 value but validation success, or just raise an exception. Error 248 message strings can include the keyword substitutions 'bad_val' and 'err' 249 for the value that raised the exception and the exception itself. 250 """ 251 252 self.conv_fn = conv_fn 253 self.conv_msg = conv_msg 254 self.val_fn = val_fn 255 self.val_msg = val_msg
256
257 - def convert_value (self, value):
258 if self.conv_fn: 259 return self.conv_fn (value) 260 else: 261 return value
262
263 - def make_conversion_error_msg (self, bad_val, err):
264 if self.conv_msg: 265 return self.conv_msg % {'bad_val': bad_val, 'err': err} 266 else: 267 return BaseValidator.make_conversion_error_msg (self, bad_val, err)
268
269 - def validate_value (self, value):
270 if self.val_fn: 271 return self.val_fn (value) 272 else: 273 return True
274
275 - def make_validation_error_msg (self, bad_val, err):
276 if self.val_msg: 277 return self.val_msg % {'bad_val': bad_val, 'err': err} 278 else: 279 return BaseValidator.make_validation_error_msg (self, bad_val, err)
280 281 282 283 ## DEBUG & TEST ### 284 285 if __name__ == "__main__": 286 import doctest 287 doctest.testmod() 288 289 290 291 ### END ####################################################################### 292