dschema 0.3.1.3a1
Python dictionary validation by schema.
License: BSD 3-Clause
Requires Python: >=3.4

About dschema
=============

.. |codecov| image:: https://codecov.io/gh/Teriks/dschema/branch/master/graph/badge.svg
   :target: https://codecov.io/gh/Teriks/dschema

.. |Master Documentation Status| image:: https://readthedocs.org/projects/dschema/badge/?version=latest
   :target: http://dschema.readthedocs.io/en/latest/?badge=latest

.. |pypi| image:: https://badge.fury.io/py/dschema.svg
   :target: https://badge.fury.io/py/dschema

|pypi| |Master Documentation Status| |codecov|

dschema is a small library for validating the content of python dictionary objects against a schema.

The schema can be defined in code or entirely as text (parsed from json generally)

dschema was mainly made for validating config files written in JSON.


Example
=======

See documentation link for more examples

.. code-block:: python

    import re
    import phonenumbers
    import dschema


    # https://github.com/daviddrysdale/python-phonenumbers
    # pip install phonenumbers


    def phone_type(number):
        # Exceptions are validation errors
        # Very similar design to the "argparse" module
        return phonenumbers.parse(number)


    def ssn_type(ssn):
        if re.match('^\d{3}-?\d{2}-?\d{4}$', ssn):
            return ssn
        else:
            raise ValueError('"{}" is not a valid SSN.')


    schema = {
        'person': {
            'first_name': dschema.prop(required=True),
            'last_name': dschema.prop(required=True),
            'phone': dschema.prop(required=True, type=phone_type),
            'ssn': dschema.prop(required=True, type='ssn_type'),

            dschema.Required: True
            # "person" namespace is required, you must specify
            # even if "person" itself contains required properties
        },

        # Allow a raw dictionary value to pass through

        'other_info': dschema.prop(default=dict(), dict=True),

        # default to False if not present

        'subscribed': dschema.prop(default=False, type=bool)
    }

    validator = dschema.Validator(schema)

    # you can use this to add types that are recognized by name.
    # which is useful if you want your schema to be entirely textual

    validator.add_type('ssn_type', ssn_type)

    # you will need to define default types on your own
    # if you want to reference them by name

    # validator.add_type('int', int)


    data = {
        'person': {
            'first_name': "John",
            'last_name': "Smith",
            'phone': '+1 234 5678 9000',
            'ssn': '123-45-6789'
        },

        'other_info': {
            'website': 'www.johnsmith.com',
        }
    }

    # If namespace is left False, a plain dictionary is returned

    result = validator.validate(data, namespace=True)

    print(result)

    # Prints: (un-indented)

    # Namespace(
    #     person=Namespace(
    #         first_name='John',
    #         last_name='Smith',
    #         phone=PhoneNumber(...),
    #         ssn='123-45-6789'),
    #     other_info={'website': 'www.johnsmith.com'},
    #     subscribed=False
    # )


    # Each Namespace is just a dynamic object

    print(result.person.first_name)  # -> John
    print(result.person.last_name)  # -> Smith

    print(result.person.phone)
    # - > Country Code: 1 National Number: 23456789000

    print(result.person.ssn)  # -> 123-45-6789

    print(result.other_info)  # -> {'website': 'www.johnsmith.com'}

    print(result.subscribed)  # -> False (default)