112
112
You specify this check with : ::
114
114
option('option 1', 'option 2', 'option 3')
116
You can supply a default value (returned if no value is supplied)
117
using the default keyword argument.
119
You specify a list argument for default using a list constructor syntax in
122
checkname(arg1, arg2, default=list('val 1', 'val 2', 'val 3'))
124
A badly formatted set of arguments will raise a ``VdtParamError``.
117
127
__docformat__ = "restructuredtext en"
119
__version__ = '0.2.0'
129
__version__ = '0.2.1'
121
131
__revision__ = '$Id: validate.py 123 2005-09-08 08:54:28Z fuzzyman $'
160
170
StringTypes = (str, unicode)
173
_list_arg = re.compile(r'''
175
([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*list\(
180
(?:".*?")| # double quotes
181
(?:'.*?')| # single quotes
182
(?:[^'",\s\)][^,\)]*?) # unquoted
187
(?:".*?")| # double quotes
188
(?:'.*?')| # single quotes
189
(?:[^'",\s\)][^,\)]*?) # unquoted
194
''', re.VERBOSE) # two groups
196
_list_members = re.compile(r'''
198
(?:".*?")| # double quotes
199
(?:'.*?')| # single quotes
200
(?:[^'",\s=][^,=]*?) # unquoted
203
(?:\s*,\s*)|(?:\s*$) # comma
205
''', re.VERBOSE) # one group
211
[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*list\(
215
(?:".*?")| # double quotes
216
(?:'.*?')| # single quotes
217
(?:[^'",\s\)][^,\)]*?) # unquoted
222
(?:".*?")| # double quotes
223
(?:'.*?')| # single quotes
224
(?:[^'",\s\)][^,\)]*?) # unquoted
229
(?:".*?")| # double quotes
230
(?:'.*?')| # single quotes
231
(?:[^'",\s=][^,=]*?)| # unquoted
232
(?: # keyword argument
233
[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*
235
(?:".*?")| # double quotes
236
(?:'.*?')| # single quotes
237
(?:[^'",\s=][^,=]*?) # unquoted
243
(?:\s*,\s*)|(?:\s*$) # comma
248
_matchstring = '^%s*' % _paramstring
162
250
# Python pre 2.2.1 doesn't have bool
433
521
http://www.voidspace.org.uk/python/configobj.html
436
# this regex pulls values out of a comma separated line
437
_paramfinder = re.compile(r'''(?:'.*?')|(?:".*?")|(?:[^'",\s][^,]*)''')
438
# this regex is used for finding keyword arguments
439
_key_arg = re.compile(r'^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*)$')
440
524
# this regex does the initial parsing of the checks
441
525
_func_re = re.compile(r'(.+?)\((.*)\)')
527
# this regex takes apart keyword arguments
528
_key_arg = re.compile(r'^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*)$')
531
# this regex finds keyword=list(....) type values
532
_list_arg = _list_arg
534
# this regex takes individual values out of lists - in one pass
535
_list_members = _list_members
537
# These regexes check a set of arguments for validity
538
# and then pull the members out
539
_paramfinder = re.compile(_paramstring, re.VERBOSE)
540
_matchfinder = re.compile(_matchstring, re.VERBOSE)
443
543
def __init__(self, functions=None):
445
545
>>> vtri = Validator()
487
587
fun_match = self._func_re.match(check)
489
589
fun_name = fun_match.group(1)
590
arg_string = fun_match.group(2)
591
arg_match = self._matchfinder.match(arg_string)
592
if arg_match is None:
492
597
# pull out args of group 2
493
for arg in self._paramfinder.findall(fun_match.group(2)):
598
for arg in self._paramfinder.findall(arg_string):
494
599
# args may need whitespace removing (before removing quotes)
495
600
arg = arg.strip()
601
listmatch = self._list_arg.match(arg)
603
key, val = self._list_handle(listmatch)
604
fun_kwargs[key] = val
496
606
keymatch = self._key_arg.match(arg)
498
val = keymatch.group(2)
499
if (val[0] in ("'", '"')) and (val[0] == val[-1]):
608
val = self._unquote(keymatch.group(2))
501
609
fun_kwargs[keymatch.group(1)] = val
504
if (arg[0] in ("'", '"')) and (arg[0] == arg[-1]):
612
fun_args.append(self._unquote(arg))
508
614
# allows for function names without (args)
509
615
(fun_name, fun_args, fun_kwargs) = (check, (), {})
527
return self.functions[fun_name](value, *fun_args, **fun_kwargs)
633
fun = self.functions[fun_name]
529
635
raise VdtUnknownCheckError(fun_name)
639
return fun(value, *fun_args, **fun_kwargs)
641
def _unquote(self, val):
642
"""Unquote a value if necessary."""
643
if (len(val) > 2) and (val[0] in ("'", '"')) and (val[0] == val[-1]):
647
def _list_handle(self, listmatch):
648
"""Take apart a ``keyword=list('val, 'val')`` type string."""
650
name = listmatch.group(1)
651
args = listmatch.group(2)
652
for arg in self._list_members.findall(args):
653
out.append(self._unquote(arg))
531
656
def _pass(self, value):
1059
1184
raise VdtValueError(value)
1187
def _test(value, *args, **keywargs):
1189
A function that exists for test purposes.
1192
... '3, 6, min=1, max=3, test=list(a, b, c)',
1196
... 'min=1, test="a b c"',
1197
... 'min=5, test="a, b, c"',
1198
... 'min=1, max=3, test="a, b, c"',
1199
... 'min=-100, test=-99',
1201
... '3, 6, test="36"',
1202
... '3, 6, test="a, b, c"',
1203
... '3, max=3, test=list("a", "b", "c")',
1204
... '''3, max=3, test=list("'a'", 'b', "x=(c)")''',
1205
... "test='x=fish(3)'",
1207
>>> v = Validator({'test': _test})
1208
>>> for entry in checks:
1209
... print v.check(('test(%s)' % entry), 3)
1210
(3, ('3', '6'), {'test': ['a', 'b', 'c'], 'max': '3', 'min': '1'})
1214
(3, (), {'test': 'a b c', 'min': '1'})
1215
(3, (), {'test': 'a, b, c', 'min': '5'})
1216
(3, (), {'test': 'a, b, c', 'max': '3', 'min': '1'})
1217
(3, (), {'test': '-99', 'min': '-100'})
1218
(3, (), {'max': '3', 'min': '1'})
1219
(3, ('3', '6'), {'test': '36'})
1220
(3, ('3', '6'), {'test': 'a, b, c'})
1221
(3, ('3',), {'test': ['a', 'b', 'c'], 'max': '3'})
1222
(3, ('3',), {'test': ["'a'", 'b', 'x=(c)'], 'max': '3'})
1223
(3, (), {'test': 'x=fish(3)'})
1225
return (value, args, keywargs)
1062
1228
if __name__ == '__main__':
1063
1229
# run the code tests in doctest format
1084
Lists passed as function arguments need additional quotes. Ugly, could do
1087
1250
If we could pull tuples out of arguments, it would be easier
1088
1251
to specify arguments for 'mixed_lists'.
1259
Fixed bug so we can handle keyword argument values with commas.
1261
We now use a list constructor for passing list values to keyword arguments
1262
(including ``default``) : ::
1264
default=list("val", "val", "val")
1266
Added the ``_test`` test. {sm;:-)}
1273
Moved a function call outside a try...except block.