prepare for release:
* diffrent web directory with all web specific content (split doc dir -> doc (data) and web (rendered data))
* update installation
from twisted.internet import defer
import re
from decorator import decorator
from inspect import getcallargs
import types
from .error import ValidateException, InvalidTel, InvalidMail
from .telnumber import Telnumber
def vBool(value, field):
'''Validate function for boolean values
:return: **value**
:raises: :exc:`iro.error.ValidateException`
'''
t=[True, 1, "true", "True", "TRUE"]
f=[False, 0, "false", "False", "FALSE"]
if value in t:
return True
elif value in f:
return False
else:
raise ValidateException(field=field, msg='%s is not boolean' % field)
def vNumber(value,field, nval, minv=None, maxv=None, none_allowed=False):
"""validate function for integer values.
:param integer minv: minimum value
:param integer maxv: maximum value
:param func nval: function that give back a number
:param boolean none_allowed: is None or empty string allowed
:return: **value**
:raises: :exc:`iro.error.ValidateException`
"""
if none_allowed and value in [None,'']:
return None
try:
ret = nval(value)
except ValueError:
raise ValidateException(field=field)
except TypeError:
raise ValidateException(field=field)
if minv is not None and ret < minv:
raise ValidateException(field=field)
if maxv is not None and ret > maxv:
raise ValidateException(field=field)
return ret
def vInteger(value, field, minv=None, maxv=None, none_allowed=False):
"""validate function for integer values.
:param integer minv: minimum value
:param integer maxv: maximum value
:param boolean none_allowed: is None or empty string allowed
:return: **value**
:raises: :exc:`iro.error.ValidateException`
see also :func:vNumber
"""
return vNumber(value, field, int, minv, maxv, none_allowed)
def vFloat(value, field, minv=None, maxv=None, none_allowed=False):
"""validate function for float values.
:param integer minv: minimum value
:param integer maxv: maximum value
:param boolean none_allowed: is None or empty string allowed
:return: **value**
:raises: :exc:`iro.error.ValidateException`
see also :func:vNumber
"""
return vNumber(value, field, float, minv, maxv, none_allowed)
def vHash(value,field,minlength=None,maxlength=None):
'''Validate function for hash values
:param integer minlength: minimum length of value string
:param integer maxlength: maximum length of value string
:return: **value**
:raises: :exc:`iro.error.ValidateException`
'''
if not re.match(r'^[a-f0-9]*$', value.lower()):
raise ValidateException(field=field)
if minlength and len(value)<minlength:
raise ValidateException(field=field)
if maxlength and len(value)>maxlength:
raise ValidateException(field=field)
return value.lower()
def vTel(value,field):
'''Validator for telefon numbers
:return: **value**
:raises: :exc:`iro.error.InvalidTel`
'''
ret = []
for v in value:
try:
tel=Telnumber(v)
if tel not in ret:
ret.append(tel)
except InvalidTel, e:
e.field=field
raise e
return ret
def vEmail(value, field, allowString=True, allowList=True):
'''validator for emailadresses (see wikipeda for strange mailadresses and RFC3696)
valid:
- "very.(),:;<>[]\\".VERY.\\"very@\\\ \\"very\\".unusual"@strange.example.com
- ""@example.org
- "very.unusual.@.unusual.com"@example.com'
not valid:
- Abc.@example.com
- Abc..123@example.com
- thisis."notallowed@example.com
- this\\ still\\"not\\allowed@example.com
:param boolean allowString: value can be a string -> a string is returned
:param boolean allowList: value is a a list -> a list is returned
:return: **value**
:raises: :exc:`iro.error.ValidateException`, :exc:`iro.error.InvalidMail`
'''
ret = []
str_=False
if type(value) is types.StringType:
if not allowString:
raise ValidateException('%s must be a list of email addresses.'%field)
str_=True
value=[value]
elif not allowList:
raise ValidateException('%s must be a email address - No list of email addresses.'%field)
for v in value:
parts= re.match(r'^(.*)@(.+?)$',v)
if not parts:
raise InvalidMail(v,field)
local=parts.group(1)
domain=parts.group(2)
if not re.match(r'^(\[[0-9\.]{7,16}\]|\[[0-9a-f:]{3,}\]|([a-z0-9+\-%_]+\.)+[a-z]{2,6})$',domain.lower()):
raise InvalidMail(v,field)
if local == "":
ret.append(v)
continue
if local.startswith(".") or local.endswith("."):
raise InvalidMail(v,field)
unquote = True
parts = local.split('"')
c=0
i=0
for part in parts:
if unquote and part != "": #unquoted is not allowd so much
if not re.match(r'^[^\\,\[\];\(\)@<>: ]+$',part) or ".." in part:
raise InvalidMail(v,field)
if i == 0:
if unquote and part != "" and len(parts) > 1 and part[-1] != '.': #quoted parts must be seperated by a dot
raise InvalidMail(v,field)
unquote = not unquote
c+=1
elif part == '' or part[-1] != "\\":
if unquote and part != "": #quoted parts must be seperated by a dot
if part[0] != ".":
raise InvalidMail(v,field)
if i < len(parts)-1 and part[-1] != '.':
raise InvalidMail(v,field)
unquote = not unquote
c += 1
i += 1
if c%2 == 0 and c > 1: #no single quote allowed
raise InvalidMail(v,field)
if v not in ret:
ret.append(v)
if str_:
ret=ret[0]
return ret
def validate(kwd,func, need=True,*args,**kargs):
'''validate decorator.
:param string kwd: keyword to validate
:param func func: validate function
:param boolean need: ``False`` -- ``None`` is a valid value for kwd
:params args: arguments for validate function
:params kargs: keyword arguments for validate function
.. note:: this decorator can handle function that returns a defer object.
use it like this::
@validate(kwd=userhash, func=vuserhash)
f(userhash)
that will validate ``userhash`` with the function **vuserhash**.
Every validate function should raise an Exception, if the the value is not valid.
All **args** and **kargs** are used to call the validate function.
if **need** is True, the kwd can't be `None`.
'''
@decorator
def v(f,*a,**k):
kp=getcallargs(f,*a,**k)
def dfunc(*x,**y):
return None
try:
if kp[kwd] is not None:
dfunc=func
elif need:
raise ValidateException(field=kwd,msg="%s is nessasary"%kwd)
except KeyError:
if need:
raise ValidateException(field=kwd,msg="%s is nessasary"%kwd)
kp[kwd] = None
def _gotResult(value):
kp[kwd] = value
e = defer.maybeDeferred(f,**kp)
return e
d = defer.maybeDeferred(dfunc, kp[kwd],kwd,*args,**kargs)
return d.addCallback(_gotResult)
return v