Skip to main content

Validate Python dictionaries like JSON schema

Project description

Latest PyPI version Documentation Status License Build status Coverage

logo

A schemadict is a regular Python dictionary which specifies the type and format of values for some given key. To check if a test dictionary is conform with the expected schema, schemadict provides the validate() method. If the test dictionary is ill-defined, an error will be thrown, otherwise None is returned.

Examples

Basic usage

>>> from schemadict import schemadict

>>> schema = schemadict({
...     'name': {
...         'type': str,
...         'min_len': 3,
...         'max_len': 12,
...     },
...     'age': {
...         'type': int,
...         '>=': 0,
...         '<': 150,
...     },
... })
>>>
>>> testdict = {'name': 'Neil', 'age': 55}
>>> schema.validate(testdict)
>>>

>>> testdict = {'name': 'Neil', 'age': -12}
>>> schema.validate(testdict)
Traceback (most recent call last):
    ...
ValueError: 'age' too small: expected >= 0, but was -12
>>>

>>> testdict = {'name': 'Neil', 'age': '55'}
>>> schema.validate(testdict)
Traceback (most recent call last):
    ...
TypeError: unexpected type for 'age': expected <class 'int'>, but was <class 'str'>
>>>

Nested schemadict

It is possible to check individual item in a list. For instance, in the following example we check if each item (of type str) looks like a valid IPv4 address. How each item should look like can be specified with the item_schema keyword.

>>> schema = schemadict({
...     'ip_addrs': {
...         'type': list,
...         'item_schema': {
...             'type': str,
...             'regex': r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$',
...         },
...     },
... })
>>>
>>>
>>> schema.validate({'ip_addrs': ['127.0.0.1', '192.168.1.1']})  # Valid
>>> schema.validate({'ip_addrs': ['127.0.0.1', '192.168.1.1', '1234.5678']})  # Last item invalid
Traceback (most recent call last):
    ...
ValueError: regex mismatch for 'ip_addrs': expected pattern '^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$', got '1234.5678'
>>>

Items in a list (or tuple) may themselves be dictionaries which can be described with schemadicts. In this case, we use the keyword item_schemadict as illustrated in the following example.

>>> schema_city = schemadict({
...     'name': {
...         'type': str
...     },
...     'population': {
...         'type': int,
...         '>=': 0,
...     },
... })
>>>
>>> schema_country = schemadict({
...     'name': {'type': str},
...     'cities': {
...         'type': list,
...         'item_type': dict,
...         'item_schemadict': schema_city,
...     },
... })
>>>
>>> test_country = {
...     'name': 'Neverland',
...     'cities': [
...         {'name': 'Faketown', 'population': 3},
...         {'name': 'Evergreen', 'population': True},
...     ],
... }
>>>
>>> schema_country.validate(test_country)
Traceback (most recent call last):
    ...
TypeError: unexpected type for 'population': expected <class 'int'>, but was <class 'bool'>
>>>

Custom validation functions

Each type (int, bool, str, etc.) defines its own set of validation keywords and corresponding test functions. The dictionary STANDARD_VALIDATORS provided by the schemadict module contains the default validation functions for the Python’s built-in types. However, it is also possible to modify or extend this dictionary with custom validation functions.

>>> from schemadict import schemadict, STANDARD_VALIDATORS

>>> # Add a custom validation function
>>> def is_divisible(key, value, comp_value, _):
...     if value % comp_value != 0:
...             raise ValueError(f"{key!r} is not divisible by {comp_value}")
...
...
...
>>>

>>> # Update the standard validator dictionary
>>> my_validators = STANDARD_VALIDATORS
>>> my_validators[int]['%'] = is_divisible

>>> # Register the updated validator dictionary in the new schemadict instance
>>> s = schemadict({'my_num': {'type': int, '%': 3}}, validators=my_validators)

>>> s.validate({'my_num': 33})
>>> s.validate({'my_num': 4})
Traceback (most recent call last):
    ...
ValueError: 'my_num' is not divisible by 3
>>>

It is also possible to define custom types and custom test functions as shown in the following example.

>>> from schemadict import schemadict, STANDARD_VALIDATORS

>>> class MyOcean:
...     has_dolphins = True
...     has_plastic = False
...
>>>

>>> def has_dolphins(key, value, comp_value, _):
...     if getattr(value, 'has_dolphins') is not comp_value:
...         raise ValueError(f"{key!r} does not have dolphins")
...
>>>

>>> my_validators = STANDARD_VALIDATORS
>>> my_validators.update({MyOcean: {'has_dolphins': has_dolphins}})
>>>

>>> schema_ocean = schemadict(
...     {'ocean': {'type': MyOcean, 'has_dolphins': True}},
...     validators=my_validators,
... )
>>>

>>> ocean1 = MyOcean()
>>> schema_ocean.validate({'ocean': ocean1})
>>>

>>> ocean2 = MyOcean()
>>> ocean2.has_dolphins = False
>>> schema_ocean.validate({'ocean': ocean2})
Traceback (most recent call last):
    ...
ValueError: 'ocean' does not have dolphins

Full documentation: https://schemadict.readthedocs.io/

Features

What schemadict offers:

  • Built-in support for Python’s primitive types

  • Specify required and optional keys

  • Validate nested schemas

  • Add custom validation functions to built-in types

  • Add custom validation functions to custom types

  • Support for Regex checks of strings

Features currently in development

  • Metaschema validation

  • Lazy validation and summary of all errors

  • Allow schema variations: schmea 1 OR schema 2

  • Add support for validation of type number.Number

Installation

Schemadict is available on PyPI and may simply be installed with

pip install schemadict

Idea

Schemadict is loosely inspired by JSON schema and jsonschema, a JSON schema validator for Python.

License

License: Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

schemadict-0.0.9.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

schemadict-0.0.9-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file schemadict-0.0.9.tar.gz.

File metadata

  • Download URL: schemadict-0.0.9.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.4.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.8.0 tqdm/4.30.0 CPython/3.8.2

File hashes

Hashes for schemadict-0.0.9.tar.gz
Algorithm Hash digest
SHA256 99fefbe68f4731173d27cd9f85d250c103d95c67082660c16f40ed8d0c71f84e
MD5 c51a7908ac12c9e3cef2ab5db544130a
BLAKE2b-256 8416b67657b4e874a9a8aeebe2f1f1cfba8c36d0c207b2438a6e90443a012188

See more details on using hashes here.

Provenance

File details

Details for the file schemadict-0.0.9-py3-none-any.whl.

File metadata

  • Download URL: schemadict-0.0.9-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.4.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.8.0 tqdm/4.30.0 CPython/3.8.2

File hashes

Hashes for schemadict-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 29d7686325f57b1da4140bd12a9d84fe0fb5281c69be034866f554fbc59625ed
MD5 9e98665ca55e3275a53f09f67bb1b37f
BLAKE2b-256 d5078651bf06a0dabe42f276721fb43a37a7a5a1f5cef66d7e51a2b401749225

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page