From 01c600151902887eda31c46e225418bd792306f8 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 21 Jan 2014 13:00:12 -0500 Subject: [PATCH] Implement SubclassOf, rename Classy to InstanceOf --- tests/test_validator.py | 22 ++++++++++++++++------ validator/__init__.py | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/tests/test_validator.py b/tests/test_validator.py index a8a7264..fa38f76 100644 --- a/tests/test_validator.py +++ b/tests/test_validator.py @@ -62,7 +62,6 @@ def test_blank_validator(self): assert not validate(validator, int_value)[0] assert not validate(validator, bool_value)[0] - def test_in_validator(self): validator = { "truthiness": [Truthy()], @@ -139,12 +138,12 @@ def test_range_validator(self): } assert validate(validator, test_case)[0] - def test_classy_validator(self): + def test_instanceof_validator(self): validator = { - "classy": [Required, Classy(unicode)], - "subclassy": [Required, Classy(basestring)], - "not_classy": [Required, Not(Classy(unicode))], - "not_subclassy": [Required, Not(Classy(basestring))] + "classy": [Required, InstanceOf(unicode)], + "subclassy": [Required, InstanceOf(basestring)], + "not_classy": [Required, Not(InstanceOf(unicode))], + "not_subclassy": [Required, Not(InstanceOf(basestring))] } test_case = { "classy": u"unicode_string", @@ -154,6 +153,17 @@ def test_classy_validator(self): } assert validate(validator, test_case)[0] + def test_subclassof_validator(self): + validator = { + "is_subclass": [Required, SubclassOf(basestring)], + "not_subclass": [Required, Not(SubclassOf(basestring))], + } + test_case = { + "is_subclass": unicode, + "not_subclass": int + } + assert validate(validator, test_case)[0] + def test_pattern_validator(self): validator = { "match": [Required, Pattern('\d\d\%')], diff --git a/validator/__init__.py b/validator/__init__.py index 1cf0965..03a747d 100644 --- a/validator/__init__.py +++ b/validator/__init__.py @@ -55,10 +55,12 @@ def not_lambda(value): not_lambda.err_message = "must not be blank" elif validator.__name__ == "range_lambda": not_lambda.err_message = "must not fall between %s and %s" % (validator.start, validator.end) - elif validator.__name__ == "class_lambda": + elif validator.__name__ == "instanceof_lambda": not_lambda.err_message = "must not be an instance of %s or its subclasses" % validator.base_class elif validator.__name__ == "pattern_lambda": not_lambda.err_message = "must not match regex pattern %s" % validator.pattern + elif validator.__name__ == "subclassof_lambda": + not_lambda.err_message = "must not be a subclass of %s" % validator.base_class return not_lambda @@ -171,7 +173,7 @@ def Required(field, dictionary): return (field in dictionary) -def Classy(base_class): +def InstanceOf(base_class): """ Use to specify that the value of the key being @@ -181,20 +183,41 @@ def Classy(base_class): # Example: validations = { - "field": [Classy(basestring)] + "field": [InstanceOf(basestring)] } passes = {"field": ""} # is a <'str'>, subclass of basestring fails = {"field": str} # is a <'type'> - """ - def class_lambda(value): + def instanceof_lambda(value): return isinstance(value, base_class) - class_lambda.base_class = base_class - class_lambda.err_message = "must be an instance of %s or its subclasses" % base_class.__name__ - return class_lambda + instanceof_lambda.base_class = base_class + instanceof_lambda.err_message = "must be an instance of %s or its subclasses" % base_class.__name__ + return instanceof_lambda + +def SubclassOf(base_class): + """ + Use to specify that the + value of the key being + validated must be a subclass + of the passed in base class. + + # Example: + validations = { + "field": [SubclassOf(basestring)] + } + passes = {"field": str} # is a subclass of basestring + fails = {"field": int} + """ + + def subclassof_lambda(class_): + return issubclass(class_, base_class) + + subclassof_lambda.base_class = base_class + subclassof_lambda.err_message = "must be a subclass of %s" % base_class.__name__ + return subclassof_lambda def Pattern(pattern): """