/ptah/form/validator.py

https://github.com/mcdonc/ptah · Python · 196 lines · 173 code · 10 blank · 13 comment · 7 complexity · d728e0069a3b168b65ec02512de0ce5b MD5 · raw file

  1. """ Code from `colander` package """
  2. import re
  3. from interfaces import _, Invalid
  4. class All(object):
  5. """ Composite validator which succeeds if none of its
  6. subvalidators raises an :class:`Invalid` exception"""
  7. def __init__(self, *validators):
  8. self.validators = list(validators)
  9. def __call__(self, field, value):
  10. msgs = []
  11. for validator in self.validators:
  12. try:
  13. validator(field, value)
  14. except Invalid, e:
  15. msgs.append(e.msg)
  16. if msgs:
  17. raise Invalid(field, msgs)
  18. class Function(object):
  19. """ Validator which accepts a function and an optional message;
  20. the function is called with the ``value`` during validation.
  21. If the function returns anything falsy (``None``, ``False``, the
  22. empty string, ``0``, an object with a ``__nonzero__`` that returns
  23. ``False``, etc) when called during validation, an
  24. :exc:`ptah.form.Invalid` exception is raised (validation fails);
  25. its msg will be the value of the ``message`` argument passed to
  26. this class' constructor.
  27. If the function returns a stringlike object (a ``str`` or
  28. ``unicode`` object) that is *not* the empty string , a
  29. :exc:`ptah.form.Invalid` exception is raised using the stringlike
  30. value returned from the function as the exeption message
  31. (validation fails).
  32. If the function returns anything *except* a stringlike object
  33. object which is truthy (e.g. ``True``, the integer ``1``, an
  34. object with a ``__nonzero__`` that returns ``True``, etc), an
  35. :exc:`ptah.form.Invalid` exception is *not* raised (validation
  36. succeeds).
  37. The default value for the ``message`` when not provided via the
  38. constructor is ``Invalid value``.
  39. """
  40. def __init__(self, function, message=_('Invalid value')):
  41. self.function = function
  42. self.message = message
  43. def __call__(self, field, value):
  44. result = self.function(value)
  45. if not result:
  46. raise Invalid(field, self.message)
  47. if isinstance(result, basestring):
  48. raise Invalid(field, result)
  49. class Regex(object):
  50. """ Regular expression validator.
  51. Initialize it with the string regular expression ``regex``
  52. that will be compiled and matched against ``value`` when
  53. validator is called. If ``msg`` is supplied, it will be the
  54. error message to be used; otherwise, defaults to 'String does
  55. not match expected pattern'.
  56. The ``regex`` argument may also be a pattern object (the
  57. result of ``re.compile``) instead of a string.
  58. When calling, if ``value`` matches the regular expression,
  59. validation succeeds; otherwise, :exc:`ptah.form.Invalid` is
  60. raised with the ``msg`` error message.
  61. """
  62. def __init__(self, regex, msg=None):
  63. if isinstance(regex, basestring):
  64. self.match_object = re.compile(regex)
  65. else:
  66. self.match_object = regex
  67. if msg is None:
  68. self.msg = _("String does not match expected pattern")
  69. else:
  70. self.msg = msg
  71. def __call__(self, field, value):
  72. if self.match_object.match(value) is None:
  73. raise Invalid(field, self.msg)
  74. class Email(Regex):
  75. """ Email address validator. If ``msg`` is supplied, it will be
  76. the error message to be used when raising :exc:`ptah.form.Invalid`;
  77. otherwise, defaults to 'Invalid email address'.
  78. """
  79. def __init__(self, msg=None):
  80. if msg is None:
  81. msg = _("Invalid email address")
  82. super(Email, self).__init__(
  83. u'(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$', msg=msg)
  84. class Range(object):
  85. """ Validator which succeeds if the value it is passed is greater
  86. or equal to ``min`` and less than or equal to ``max``. If ``min``
  87. is not specified, or is specified as ``None``, no lower bound
  88. exists. If ``max`` is not specified, or is specified as ``None``,
  89. no upper bound exists.
  90. ``min_err`` is used to form the ``msg`` of the
  91. :exc:`ptah.form.Invalid` error when reporting a validation failure
  92. caused by a value not meeting the minimum. If ``min_err`` is
  93. specified, it must be a string. The string may contain the
  94. replacement targets ``${min}`` and ``${val}``, representing the
  95. minimum value and the provided value respectively. If it is not
  96. provided, it defaults to ``'${val} is less than minimum value
  97. ${min}'``.
  98. ``max_err`` is used to form the ``msg`` of the
  99. :exc:`ptah.form.Invalid` error when reporting a validation failure
  100. caused by a value exceeding the maximum. If ``max_err`` is
  101. specified, it must be a string. The string may contain the
  102. replacement targets ``${max}`` and ``${val}``, representing the
  103. maximum value and the provided value respectively. If it is not
  104. provided, it defaults to ``'${val} is greater than maximum value
  105. ${max}'``.
  106. """
  107. min_err = _('${val} is less than minimum value ${min}')
  108. max_err = _('${val} is greater than maximum value ${max}')
  109. def __init__(self, min=None, max=None, min_err=None, max_err=None):
  110. self.min = min
  111. self.max = max
  112. if min_err is not None:
  113. self.min_err = min_err
  114. if max_err is not None:
  115. self.max_err = max_err
  116. def __call__(self, field, value):
  117. if self.min is not None:
  118. if value < self.min:
  119. min_err = _(self.min_err, mapping={'val':value, 'min':self.min})
  120. raise Invalid(field, min_err)
  121. if self.max is not None:
  122. if value > self.max:
  123. max_err = _(self.max_err, mapping={'val':value, 'max':self.max})
  124. raise Invalid(field, max_err)
  125. class Length(object):
  126. """ Validator which succeeds if the value passed to it has a
  127. length between a minimum and maximum. The value is most often a
  128. string."""
  129. def __init__(self, min=None, max=None):
  130. self.min = min
  131. self.max = max
  132. def __call__(self, field, value):
  133. if self.min is not None:
  134. if len(value) < self.min:
  135. min_err = _('Shorter than minimum length ${min}',
  136. mapping={'min':self.min})
  137. raise Invalid(field, min_err)
  138. if self.max is not None:
  139. if len(value) > self.max:
  140. max_err = _('Longer than maximum length ${max}',
  141. mapping={'max':self.max})
  142. raise Invalid(field, max_err)
  143. class OneOf(object):
  144. """ Validator which succeeds if the value passed to it is one of
  145. a fixed set of values """
  146. def __init__(self, choices):
  147. self.choices = choices
  148. def __call__(self, field, value):
  149. if not value in self.choices:
  150. choices = ', '.join(['%s' % x for x in self.choices])
  151. err = _('"${val}" is not one of ${choices}',
  152. mapping={'val':value, 'choices':choices})
  153. raise Invalid(field, err)