1 """
2 Abstract base class for easy construction of validators.
3
4 """
5
6 __docformat__ = "restructuredtext en"
7
8
9
10
11 import exceptions
12
13 import impl
14
15 __all__ = [
16 'BaseValidator',
17 'WrappingValidator',
18 ]
19
20
21
22
23
24
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
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
53 value = self.convert(value)
54 self.validate (value)
55
56 return value
57
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
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
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
115 raise exceptions.ValueError (self.make_conversion_error_msg (bad_val,
116 err))
117
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
126 return "can't convert '%s'" % bad_val
127
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
143
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
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
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
186 raise exceptions.ValueError (self.make_validation_error_msg (bad_val,
187 err))
188
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
197 return "can't validate '%s'" % (bad_val)
198
199
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
258 if self.conv_fn:
259 return self.conv_fn (value)
260 else:
261 return value
262
268
270 if self.val_fn:
271 return self.val_fn (value)
272 else:
273 return True
274
280
281
282
283
284
285 if __name__ == "__main__":
286 import doctest
287 doctest.testmod()
288
289
290
291
292