Skip to content

Instantly share code, notes, and snippets.

@tonyseek
Created September 6, 2012 09:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tonyseek/3653441 to your computer and use it in GitHub Desktop.
Save tonyseek/3653441 to your computer and use it in GitHub Desktop.
Simple validator for Quixote request input.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from functools import partial
from unittest import TestCase, main
from quixote.errors import QueryError
from validators import validate, ValidateError
class MockRequest(object):
"""The mock object to instead of Quixote's request object."""
def __init__(self, forms):
self.forms = forms
def get_form_var(self, key):
return self.forms.get(key)
class ValidatorTest(TestCase):
"""The test case of built-in validators."""
def setUp(self):
self.forms = {}
self.request = MockRequest(self.forms)
self.validate = partial(validate, self.request)
def test_email(self):
correct_email = "tonyseek@tonyseek.com"
wrong_email = "tonyseek"
assert_correct = partial(self.assert_correct, ["myemail:email"],
"myemail", correct_email)
self.forms["myemail"] = correct_email
assert_correct()
self.forms["myemail"] = " \t %s " % correct_email
assert_correct()
self.forms["myemail"] = wrong_email
with self.assertRaises(ValidateError):
assert_correct()
def test_url(self):
correct_url = "http://www.tonyseek.com"
wrong_url = "xxx@fe*("
assert_correct = partial(self.assert_correct, ["blogurl:url"],
"blogurl", correct_url)
self.forms["blogurl"] = correct_url
assert_correct()
self.forms["blogurl"] = " \t %s " % correct_url
assert_correct()
self.forms["blogurl"] = wrong_url
with self.assertRaises(ValidateError):
assert_correct()
def test_integer(self):
assert_age = partial(self.assert_correct, ["age:int"], "age")
self.forms["age"] = "20"
assert_age(20)
self.forms["age"] = " 20 \t"
assert_age(20)
self.forms["age"] = "a20"
with self.assertRaises(ValidateError):
assert_age(20)
def test_text(self):
assert_correct = partial(self.assert_correct, ["name:str"],
"name", "TonySeek")
self.forms["name"] = "TonySeek"
assert_correct()
self.forms["blogurl"] = " \t TonySeek "
assert_correct()
def assert_correct(self, fields, key, expect_value):
self.assertEqual(self.validate(fields).get(key), expect_value)
def test_http_400(self):
with self.assertRaises(QueryError):
self.validate([])["noexists"]
if __name__ == "__main__":
main()
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import re
from quixote.errors import QueryError
class FormDict(dict):
"""A dict alike object but raise QueryError while accessing a exists key."""
def __getitem__(self, key):
try:
return super(FormDict, self).__getitem__(key)
except KeyError as key_error:
raise QueryError(private_msg=key_error.message)
#: registity table
validators = {}
#: those regex patterns are copied from wtforms library.
#: https://bitbucket.org/simplecodes/wtforms
re_email = re.compile(r"^.+@[^.].*\.[a-z]{2,10}$", re.IGNORECASE)
re_url = re.compile(r"^[a-z]+://([^/:]+\.[a-z]{2,10}|([0-9]{1,3}\.){3}"
r"[0-9]{1,3})(:[0-9]+)?(\/.*)?$", re.IGNORECASE)
def validate(request, fields):
"""Validates data of request form fields.
Example:
> validate(request, ["user_email:email", "user_blog:url"])
{'user_email': 'xxx@example.com', 'url_blog': 'http://xxx.com'}
> validate(request, ["user_email:email", "user_blog:url"])
Traceback:
...
ValidateError: user_name is not valid email
"""
data = FormDict()
for field in fields:
field_name, field_type = field.strip().rsplit(":", 1)
raw_value = (request.get_form_var(field_name) or "").strip()
if raw_value:
data[field_name] = validators[field_type](field_name, raw_value)
return data
def validator(name):
"""A decorator to register new validator."""
def decorator(func):
validators[name] = func
return func
return decorator
@validator("str")
@validator("string")
@validator("text")
def validate_text(name, value):
return value.strip()
@validator("integer")
@validator("int")
def validate_integer(name, value):
if not value.isdigit():
raise ValidateError(field_name=name, field_type="integer")
return int(value)
@validator("email")
def validate_email(name, value):
if not re_email.match(value):
raise ValidateError(field_name=name, field_type="email")
return value
@validator("url")
def validate_url(name, value):
if not re_url.match(value):
raise ValidateError(field_name=name, field_type="url")
return value
class ValidateError(ValueError):
"""Failed to validate some field."""
MSG = "%s must be a valid %s"
def __init__(self, message=None, field_name="", field_type=""):
message = message or self.MSG % (field_name.capitalize(), field_type)
super(ValidateError, self).__init__(message)
self.field_name = field_name
self.field_type = field_type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment