Today I present you a my own Colander Validators! This includes tests that uses those validators! Check them out!

This episode is a series about colander

S0-E9/E30 :)

Colander Validator Extended

Did you ever needed to create a more advanced validation than what Colander offers? I did!

There is a way to create your own validations for elements. You can even extend pre-existing validations and add your own stuff in it.

Let's say that you want to make sure at the validation step that data you will pass-on will have leading zero in one field.

There are no validators like that in standard Colander library - you would need to extend it.

Ofcourse you could use Regexp also.

Let's make that, shall we ? :)

import json
import colander


class LeadingZeroValidator(object):
    """ Validator for specific check if value has leading 0"""

    def __call__(self, node, value):
        if str(value)[0] != "0":
            raise colander.Invalid(node, "No leading 0: %s"%(value))

class User(colander.MappingSchema):
    id = colander.SchemaNode(colander.String(), validator=LeadingZeroValidator())
    name = colander.SchemaNode(colander.String())


class Users(colander.SequenceSchema):
    user = User()


class Data(colander.MappingSchema):
    users = Users()
    list_name = colander.SchemaNode(colander.String())


def get_example_data():
    return {
        "users": [
            {
                "id": "2",
                "name": "Anselmos",
            },
            {
                "id": "2",
                "name": "Somlesna",
            }
        ],
        "list_name": "name_of_users"
    }


def get_validation_data(dict_data):

    api_data = json.dumps(dict_data)
    # print api_data
    json_loaded = json.loads(api_data)
    dicted = dict(json_loaded)
    return dicted


def make_validation(data):

    serialized = Data().serialize(data)
    deserialized = Data().deserialize(data)


if __name__ == '__main__':
    data = get_validation_data(get_example_data())
    make_validation(data)

This code will now give information at the make_validation step (Data().deserialize(data)), that there is element with no leading zero value.

Using Colander in Unittests

Now let's make a unittest that will validate if our LeadingZeroValidator is working properly:

import unittest
import json
import colander

from extended_validation1 import get_validation_data, make_validation
from extended_validation1 import LeadingZeroValidator

class TestLeadingZeroValidator(unittest.TestCase):

    def test_simplest_leading_zero(self):
        test_case = "01"
        validator = LeadingZeroValidator()
        validator("", test_case)

    def test_simplest_failing_leading_zero(self):
        test_case = "1"
        validator = LeadingZeroValidator()
        with self.assertRaises(colander.Invalid) as context:
            validator("", test_case)

    def test_invalid_assert_raises(self):
        dict_1 = {
            "users": [
                {
                    "id": "2",
                    "name": "Anselmos",
                },
                {
                    "id": "02",
                    "name": "Somlesna",
                }
            ],
            "list_name": "name_of_users"
        }

        testcase1 = get_validation_data(dict_1)
        with self.assertRaises(colander.Invalid) as context:
            make_validation(testcase1)

    def test_invalid_not_raises(self):
        dict_1 = {
            "users": [
                {
                    "id": "01",
                    "name": "2Anselmos",
                },
                {
                    "id": "02",
                    "name": "2Somlesna",
                }
            ],
            "list_name": "name_of_users"
        }

        testcase1 = get_validation_data(dict_1)
        make_validation(testcase1)

if __name__ == '__main__':
    unittest.main()

And it does :) how sweet.

Where to go from here ?

You may check also information about SchemaTypes and creating your own SchemaType! :)

Acknowledgements

Thanks!

That's it :) Comment, share or don't :)

If you have any suggestions what I should blog about in the next articles - please give me a hint :)

BTW - today is the last day when I eat junk food - why ? Because I'm starting another challenge for not eating junk food for the time of fasting - so at least 40 days :) - So Keep finger crossed for me :)

See you tomorrow! Cheers!



Comments

comments powered by Disqus