Created
September 6, 2012 09:08
-
-
Save tonyseek/3653441 to your computer and use it in GitHub Desktop.
Simple validator for Quixote request input.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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