/cerberus-list-schema

Cerburus based validation extended to support list schemas and list transposition to dictionary and python objects

Primary LanguagePythonOtherNOASSERTION

PyPI version Build Status Code style: black

Cerberus List Schema is a Cerberus based validation library with extended methods to support list schemas as well as list transposition to dictionary and python objects.

  • List/array schema support
  • Transposition of lists to python objects via schemas
  • Support for missing values in document

Installation

Cerberus List Schema can be installed using pip.

$ pip install cerberus-list-schema

Extensions

Validation

>>> schema = {
>>>     "type": "list",
>>>     "items": [{"type": "string"}, {"type": "integer", "min": 20}],
>>> }
Simple validation

Lists can now be validated out of context of a dictionary

>>> document = ["Apples", 40]
>>> v = Validator(schema)
>>> v.validate(document)
True

... and usual cerberus validation rules still apply

>>> document = ["Apples", 15]
>>> v.validate(document)
False
>>> v.errors
{'_schema': [{1: ['min value is 20']}]}
Allow incomplete documents

In cerberus, documents that are missing information specified in a list schema will fail. Using Cerberus List Schema you can pass allow_list_missing=True to a Validator object to enable incomplete lists.

>>> document = ["Apples"]
>>> v.validate(document)
False
>>> v.errors
{'_schema': ['length of list should be 2, it is 1']}

>>> v = Validator(schema, allow_list_missing=True)
>>> v.validate(document)
True

Normalization

Normalization as dict

Lists can now be normalized as dict additional to the standard cerberus validation. By default they are given a key equalled to their list index.

>>> document = {"produce": ["Apple", 5, "High"]}
>>> schema = {
>>>     "produce": {
>>>         "type": "list",
>>>         "items": [
>>>             {"type": "string"},
>>>             {"type": "integer", "min": 0},
>>>             {"type": "string"},
>>>         ],
>>>     }
>>> }

>>> v = Validator(schema)
>>> v.normalized_as_dict(document)
{"fruits": {0: "Apple", 1: 5, 2: "High"}}
Naming indexes

However by using the name rule, lists can be assigned to a namable dict. Note that this is different to rename and should be preferred when using the dictionary normalization as rename can produce adverse effects.

>>> document = {"produce": ["Apple", 5, "High"]}
>>> schema = {
>>>     "produce": {
>>>         "type": "list",
>>>         "name": "fruits",
>>>         "items": [
>>>             {"name": "type", "type": "string"},
>>>             {"name": "count", "type": "integer", "min": 0},
>>>             {"name": "quality", "type": "string"},
>>>         ],
>>>     }
>>> }

>>> v = Validator(schema)
>>> v.normalized_as_dict(document)
{'fruits': {'type': 'Apple', 'count': 5, 'quality': 'High'}}
Allowing name conflicts

By default, conflicting names will throw an error. However, allow_name_conflicts can be specified to ignore the error. In this case, previous assignments will be overwritten without error

>>> document = {"produce": ["Apple", "Orange"]}
>>> schema = {
>>>     "produce": {
>>>         "type": "list",
>>>         "items": [
>>>             {"name": "fruit_type", "type": "string"},
>>>             {"name": "fruit_type", "type": "string"},
>>>         ],
>>>     }
>>> }

>>> v = Validator(schema)
>>> v.normalized_as_dict(document)
AttributeError: `name` rule (`fruit_type`) already in use by another field

>>> v.normalized_as_dict(document, allow_name_conflicts=True)
{'produce': {'type': 'Orange'}}

Object Mapping

Lists can now be normalized as dict additional to the standard cerberus validation. By default they are given a key equalled to their list index. However name may be used to rename object property to that provided. (ensuring the name is a valid python variable name)

>>> document = {"produce": ["Apple", 5, "High"], "supplier": ["Greg", "United Kingdom", 7.34]}
>>> schema = {
>>>     "produce": {
>>>         "type": "list",
>>>         "name": "fruits",
>>>         "items": [
>>>             {"name": "type", "type": "string"},
>>>             {"name": "count", "type": "integer", "min": 0},
>>>             {"name": "quality", "type": "string"},
>>>         ],
>>>     },
>>>     "supplier": {
>>>         "type": "list",
>>>         "items": [
>>>             {"type": "string"},
>>>             {"type": "string"},
>>>             {"type": "string", "coerce": int},
>>>         ],
>>>     },
>>> }

>>> v = Validator(schema)
>>> obj = v.normalized_as_object(document)

>>> obj.fruits.type  # note produce has been renamed to fruits
'Apple'
>>> obj.fruits.quality
'High'
>>> obj.supplier[0]
'Greg'
>>> obj.supplier[2]  # w/ coerce as int rule applied
7
Allowing callable properties for unassigned names

Array values without a name property can also be callable by using callable_numbers. This is places an underscore before the key index such that it can be called as a property of an object rather than by index.

>>> document = ["Greg", "United Kingdom", 7.34]
>>> schema = {
>>>    "type": "list",
>>>    "items": [
>>>        {"type": "string"},
>>>        {"type": "string", "name": "country"},
>>>        {"type": "string", "coerce": int},
>>>    ],
>>>}

>>> v = Validator(schema)
>>> obj = v.normalized_as_object(document, callable_numbers=True)

>>> obj._0
'Greg'
>>> obj._1  # value renamed to country

>>> obj.country
'United Kingdom'
>>> obj._2
7

Cerberus

More information about Cerberus and its validators can be found on their GitHub page @ https://github.com/pyeve/cerberus

Complete documentation for Cerberus is available at http://docs.python-cerberus.org