Created
September 27, 2017 07:32
-
-
Save zetafish/f7a1b93217f7db51352a39d42142ddde to your computer and use it in GitHub Desktop.
validateur.py
This file contains hidden or 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
from abc import ABCMeta, abstractmethod | |
from collections import defaultdict | |
import json | |
import functools | |
class Validator(object): | |
__metaclass__ = ABCMeta | |
@abstractmethod | |
def __call__(self, *args, **kwargs): | |
raise NotImplementedError | |
class Check(Validator): | |
def __init__(self, code, f): | |
self.f = f | |
self.code = code | |
def __call__(self, value): | |
if not self.f(value): | |
return self.code | |
def InstanceOf(cls): | |
return Check('wrong-type', lambda v: isinstance(v, cls)) | |
def MaxSize(n): | |
return Check('max-size', lambda v: len(v) <= n) | |
def FreeAdsetName(session, campaign_id): | |
def available(v): | |
return False | |
return Check('duplicate', available) | |
def FreeTemplateSetName(session, advertiser_id): | |
def available(v): | |
return False | |
return Check('duplicate', available) | |
class List(Validator): | |
def __init__(self, validations): | |
self.validations = validations | |
def __call__(self, coll): | |
if not isinstance(coll, list): | |
return 'wrong-type' | |
errors = defaultdict(list) | |
for index, item in enumerate(coll): | |
e = validate(self.validations, item) | |
if e: | |
errors[index].append(e) | |
return errors | |
class Dict(Validator): | |
def __init__(self, validations): | |
self.validations = validations | |
def __call__(self, coll): | |
if not isinstance(coll, dict): | |
return 'wrong-type' | |
return validate(self.validations, coll) | |
def Required(field, dictionary): | |
return (field in dictionary) | |
def validate(validation, dictionary): | |
errors = defaultdict(list) | |
for key, validations in validation.items(): | |
if Required in validations: | |
if not Required(key, dictionary): | |
errors[key] = ['missing'] | |
continue | |
if key not in dictionary: | |
continue | |
validations = [x for x in validations if x != Required] | |
for v in validations: | |
e = v(dictionary[key]) | |
if e: | |
errors[key].append(e) | |
return errors | |
# def templateset_create(): | |
# rules = { | |
# 'name': [Required, | |
# MaxSize(70), | |
# FreeTemplateSetName(session, advertiser_id)] | |
# } | |
import pytest | |
from validateur import Required, validate, InstanceOf, List, Dict,\ | |
MaxSize | |
def test_missing_required_field(): | |
schema = {'name': [Required]} | |
v = validate(schema, {}) | |
assert v == {'name': ['missing']} | |
def test_required_as_list(): | |
schema = {'name': [Required]} | |
v = validate(schema, {}) | |
assert v == {'name': ['missing']} | |
def test_ignore_unknown_fields(): | |
schema = {'name': [Required]} | |
v = validate(schema, {'name': 'X', 'age': 1}) | |
assert v == {} | |
def test_missing_optional_field(): | |
schema = {'name': [InstanceOf(basestring)]} | |
v = validate(schema, {}) | |
assert v == {} | |
def test_instance_of(): | |
schema = {'name': [InstanceOf(basestring)]} | |
v = validate(schema, {'name': 3.1}) | |
assert v == {'name': ['wrong-type']} | |
def test_multiple_errors(): | |
schema = {'name': [InstanceOf(int), | |
InstanceOf(float)]} | |
v = validate(schema, {'name': 'x'}) | |
assert v == {'name': ['wrong-type', 'wrong-type']} | |
def test_list(): | |
schema = {'places': [Required, | |
List({'name': [Required, | |
InstanceOf(basestring)]})]} | |
v = validate(schema, {}) | |
assert v == {'places': ['missing']} | |
v = validate(schema, {'places': [{}, | |
{'name': 'x'}, | |
{'name': 5}]}) | |
assert v == {'places': [{0: [{'name': ['missing']}], | |
2: [{'name': ['wrong-type']}]}]} | |
def test_dict(): | |
schema = {'places': [Required, | |
Dict({'name': [Required]})]} | |
v = validate(schema, {'places': {}}) | |
assert v == {'places': [{'name': ['missing']}]} | |
@pytest.parameterize('doc,v',[ | |
[{'name': 'abc'}, {}], | |
[{'name': 'abcd'}, {'max-size'}] | |
]) | |
def test_max_size(doc, v): | |
schema = {'name': [Required, MaxSize(3)]} | |
assert validate(schema, doc) == v |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment