dict_validator.fields package

This package contains most frequently used implementations of dict_validator.Field.

Most common regexp based String field subclasses can be found in dict_validator.fields.regexp.

class dict_validator.fields.Choice(choices, **kwargs)[source]

Bases: dict_validator.field.Field

Accept any type of input as long as it matches on of the choices mentioned in the provided list.

Parameters:choices – list of choices to match against
>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Choice(choices=["ONE", "TWO", 3, 4])
>>> list(validate(Schema, {"field": "ONE"}))
[]
>>> list(validate(Schema, {"field": 4}))
[]
>>> list(validate(Schema, {"field": "4"}))
[(['field'], 'Not among the choices')]
>>> list(validate(Schema, {"field": 1}))
[(['field'], 'Not among the choices')]
>>> list(validate(Schema, {"field": "FOUR"}))
[(['field'], 'Not among the choices')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'choices': ['ONE', 'TWO', 3, 4], 'type': 'Choice'})]
class dict_validator.fields.String(regexp=None, metavar=None, **kwargs)[source]

Bases: dict_validator.field.Field

Match any input of a string type.

Parameters:
  • regexp – optional string value specifying the regular expression to be used for payload validation
  • metavar – a human readable description of what the regexp represents
>>> from dict_validator import validate, describe

Plain string field

>>> class Schema:
...     field = String()
>>> list(validate(Schema, {"field": "foobar"}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a string')]
>>> list(describe(Schema))
[([], {'type': 'Dict'}), (['field'], {'pattern': None, 'type': 'String'})]

String field with a regular expression

>>> class Schema:
...     field = String(r"^[ab]{2}$", metavar="TwoCharAOrB")
>>> list(validate(Schema, {"field": "aa"}))
[]
>>> list(validate(Schema, {"field": "ab"}))
[]
>>> list(validate(Schema, {"field": "aaa"}))
[(['field'], 'Did not match Regexp(TwoCharAOrB)')]
>>> list(validate(Schema, {"field": "cc"}))
[(['field'], 'Did not match Regexp(TwoCharAOrB)')]

Serialized payload must be a string

>>> list(validate(Schema, {"field": 20160710}))
[(['field'], 'Not a string')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)), width=50)
[([], {'type': 'Dict'}),
 (['field'],
  {'pattern': '^[ab]{2}$', 'type': 'String'})]
class dict_validator.fields.Timestamp(granularity=<class 'dict_validator.fields.timestamp_field.Timestamp.DateTime'>, **kwargs)[source]

Bases: dict_validator.field.Field

UTC timestamp. Could be a datetime, a date or time. By default it is datetime.

The timestamp has to be formatted according to: https://en.wikipedia.org/wiki/ISO_8601

The incoming string is deserialized into datetime object. The outgoing datetime object is serialized into a string.

Parameters:granularity – one of [Timestamp.DateTime, Timestamp.Date, Timestamp.Time]
>>> from argparse import Namespace
>>> from pprint import pprint
>>> from dict_validator import validate, describe, deserialize, serialize

By default a DateTime is expected.

>>> class Schema:
...     field = Timestamp()
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'DateTime', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '2016-07-10 13:06:04.698084'}))
[]
>>> list(validate(Schema, {"field": '2016-07-10'}))
[(['field'], 'Not a valid DateTime')]
>>> deserialize(Schema, {"field": "2016-07-10 13:06:04.698084"}).field
datetime.datetime(2016, 7, 10, 13, 6, 4, 698084)
>>> serialize(Schema, Namespace(
...     field=datetime.datetime(2016, 7, 10, 13, 6, 4, 698084)
... ))
{'field': '2016-07-10 13:06:04.698084'}

Accept Date only.

>>> class Schema:
...     field = Timestamp(granularity=Timestamp.Date)
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'Date', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '2016-07-10'}))
[]

Serialized payload must be a string

>>> list(validate(Schema, {"field": 20160710}))
[(['field'], 'Not a string')]
>>> deserialize(Schema, {"field": "2016-07-10"}).field
datetime.date(2016, 7, 10)
>>> serialize(Schema, Namespace(
...     field=datetime.date(2016, 7, 10)
... ))
{'field': '2016-07-10'}

Accept Time only.

>>> class Schema:
...     field = Timestamp(granularity=Timestamp.Time)
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'Time', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '13:06:04.698084'}))
[]
>>> deserialize(Schema, {"field": "13:06:04.698084"}).field
datetime.time(13, 6, 4, 698084)
>>> serialize(Schema, Namespace(
...     field=datetime.time(13, 6, 4, 698084)
... ))
{'field': '13:06:04.698084'}
class Date[source]

Bases: object

granulate()

Return date object with same year, month and day.

value = '%Y-%m-%d'
class DateTime[source]

Bases: object

static granulate()

Return datetime object.

value = '%Y-%m-%d %H:%M:%S.%f'
class Time[source]

Bases: object

granulate()

Return time object with same time but with tzinfo=None.

value = '%H:%M:%S.%f'
deserialize(value)[source]
Parameters:value – a payload sent over the wire
Returns:a payload with Python specific data types
serialize(value)[source]
Returns:a payload ready to be sent over the wire
class dict_validator.fields.Number(min=None, max=None, can_be_float=True, **kwargs)[source]

Bases: dict_validator.field.Field

Match integers, floats and longs

Parameters:
  • min – the smallest number allowed
  • max – the largest number allowed
  • can_be_float – True if the number can contain a dot
>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Number(min=10, max=20)
>>> list(validate(Schema, {"field": 15}))
[]
>>> list(validate(Schema, {"field": 5}))
[(['field'], 'Too small')]
>>> list(validate(Schema, {"field": 25}))
[(['field'], 'Too large')]

The number has to be passed as a digit.

>>> list(validate(Schema, {"field": "15"}))
[(['field'], 'Not a valid number')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)), width=50)
[([], {'type': 'Dict'}),
 (['field'],
  {'can_be_float': True,
   'max': 20,
   'min': 10,
   'type': 'Number'})]

To disable floats - set can_be_float to False (it is True by default).

>>> class Schema:
...     field = Number(can_be_float=False)
>>> list(validate(Schema, {"field": 15.0}))
[(['field'], 'Not a valid number')]
class dict_validator.fields.Boolean(description=None, required=True)[source]

Bases: dict_validator.field.Field

Match a boolean.

>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Boolean()
>>> list(validate(Schema, {"field": True}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a boolean')]
>>> list(describe(Schema))
[([], {'type': 'Dict'}), (['field'], {'type': 'Boolean'})]
class dict_validator.fields.WildcardDict(key_schema=None, value_schema=None, **kwargs)[source]

Bases: dict_validator.field.Field

Match a dict with any dict with any key/value pairs.

Parameters:
  • key_schema – Field subclass to be used to validate/serialize/deserialize the keys. Optional. If undefined the keys are accepted as is.
  • value_schema – Field subclass to be used to validate/serialize/deserialize the values. Optional. If undefined the values are accepted as is.
>>> from dict_validator import validate, describe, serialize, deserialize
>>> class Schema:
...     field = WildcardDict()
>>> list(validate(Schema, {"field": {}}))
[]
>>> list(validate(Schema, {"field": {"key": "value"}}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a dict')]
>>> from pprint import pprint

In field’s description there are two special nodes: {KEY} and {VALUE} that respectively correspond to the schemas applied to keys and values of the payload.

>>> pprint(list(describe(Schema)), width=70)
[([], {'type': 'Dict'}),
 (['field'], {'type': 'WildcardDict'}),
 (['field', '{KEY}'], {'type': 'Any'}),
 (['field', '{VALUE}'], {'type': 'Any'})]

If it is need it is possible to have validation for keys, values or both. This can be achieved by defining respective schemas.

>>> class SampleOnly(Field):
...
...     def _validate(self, value):
...         if not value.startswith("sample"):
...             return "Not a sample"
...
...     def serialize(self, value):
...         return value.lstrip("py(").rstrip(")")
...
...     def deserialize(self, value):
...         return "py(" +  value + ")"
>>> class Schema:
...     field = WildcardDict(key_schema=SampleOnly(),
...                          value_schema=SampleOnly())
>>> pprint(list(describe(Schema)), width=70)
[([], {'type': 'Dict'}),
 (['field'], {'type': 'WildcardDict'}),
 (['field', '{KEY}'], {'type': 'SampleOnly'}),
 (['field', '{VALUE}'], {'type': 'SampleOnly'})]
>>> list(validate(Schema, {"field": {
...     "sample_field": "sample_value"
... }}))
[]
>>> list(validate(Schema, {"field": {
...     "foobar": "sample_value"
... }}))
[(['field', 'foobar'], 'Key error: Not a sample')]
>>> list(validate(Schema, {"field": {
...     "sample_field": "foobar"
... }}))
[(['field', 'sample_field'], 'Value error: Not a sample')]
>>> from argparse import Namespace
>>> serialize(Schema, Namespace(
...     field={"py(foobar)": "py(sample_value)"}
... ))
{'field': {'foobar': 'sample_value'}}
>>> deserialize(Schema, {"field": {"foobar": "sample_value"}}).field
{'py(foobar)': 'py(sample_value)'}
describe()[source]

Do not override.

Yield:(path, {…description…}), e.g ([“parent”, “child”], {“required”: False})
deserialize(value)[source]
Parameters:value – a payload sent over the wire
Returns:a payload with Python specific data types
serialize(value)[source]
Returns:a payload ready to be sent over the wire

Submodules

class dict_validator.fields.boolean_field.Boolean(description=None, required=True)[source]

Bases: dict_validator.field.Field

Match a boolean.

>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Boolean()
>>> list(validate(Schema, {"field": True}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a boolean')]
>>> list(describe(Schema))
[([], {'type': 'Dict'}), (['field'], {'type': 'Boolean'})]
class dict_validator.fields.choice_field.Choice(choices, **kwargs)[source]

Bases: dict_validator.field.Field

Accept any type of input as long as it matches on of the choices mentioned in the provided list.

Parameters:choices – list of choices to match against
>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Choice(choices=["ONE", "TWO", 3, 4])
>>> list(validate(Schema, {"field": "ONE"}))
[]
>>> list(validate(Schema, {"field": 4}))
[]
>>> list(validate(Schema, {"field": "4"}))
[(['field'], 'Not among the choices')]
>>> list(validate(Schema, {"field": 1}))
[(['field'], 'Not among the choices')]
>>> list(validate(Schema, {"field": "FOUR"}))
[(['field'], 'Not among the choices')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'choices': ['ONE', 'TWO', 3, 4], 'type': 'Choice'})]
class dict_validator.fields.number_field.Number(min=None, max=None, can_be_float=True, **kwargs)[source]

Bases: dict_validator.field.Field

Match integers, floats and longs

Parameters:
  • min – the smallest number allowed
  • max – the largest number allowed
  • can_be_float – True if the number can contain a dot
>>> from dict_validator import validate, describe
>>> class Schema:
...     field = Number(min=10, max=20)
>>> list(validate(Schema, {"field": 15}))
[]
>>> list(validate(Schema, {"field": 5}))
[(['field'], 'Too small')]
>>> list(validate(Schema, {"field": 25}))
[(['field'], 'Too large')]

The number has to be passed as a digit.

>>> list(validate(Schema, {"field": "15"}))
[(['field'], 'Not a valid number')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)), width=50)
[([], {'type': 'Dict'}),
 (['field'],
  {'can_be_float': True,
   'max': 20,
   'min': 10,
   'type': 'Number'})]

To disable floats - set can_be_float to False (it is True by default).

>>> class Schema:
...     field = Number(can_be_float=False)
>>> list(validate(Schema, {"field": 15.0}))
[(['field'], 'Not a valid number')]
class dict_validator.fields.string_field.String(regexp=None, metavar=None, **kwargs)[source]

Bases: dict_validator.field.Field

Match any input of a string type.

Parameters:
  • regexp – optional string value specifying the regular expression to be used for payload validation
  • metavar – a human readable description of what the regexp represents
>>> from dict_validator import validate, describe

Plain string field

>>> class Schema:
...     field = String()
>>> list(validate(Schema, {"field": "foobar"}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a string')]
>>> list(describe(Schema))
[([], {'type': 'Dict'}), (['field'], {'pattern': None, 'type': 'String'})]

String field with a regular expression

>>> class Schema:
...     field = String(r"^[ab]{2}$", metavar="TwoCharAOrB")
>>> list(validate(Schema, {"field": "aa"}))
[]
>>> list(validate(Schema, {"field": "ab"}))
[]
>>> list(validate(Schema, {"field": "aaa"}))
[(['field'], 'Did not match Regexp(TwoCharAOrB)')]
>>> list(validate(Schema, {"field": "cc"}))
[(['field'], 'Did not match Regexp(TwoCharAOrB)')]

Serialized payload must be a string

>>> list(validate(Schema, {"field": 20160710}))
[(['field'], 'Not a string')]
>>> from pprint import pprint
>>> pprint(list(describe(Schema)), width=50)
[([], {'type': 'Dict'}),
 (['field'],
  {'pattern': '^[ab]{2}$', 'type': 'String'})]
class dict_validator.fields.timestamp_field.Timestamp(granularity=<class 'dict_validator.fields.timestamp_field.Timestamp.DateTime'>, **kwargs)[source]

Bases: dict_validator.field.Field

UTC timestamp. Could be a datetime, a date or time. By default it is datetime.

The timestamp has to be formatted according to: https://en.wikipedia.org/wiki/ISO_8601

The incoming string is deserialized into datetime object. The outgoing datetime object is serialized into a string.

Parameters:granularity – one of [Timestamp.DateTime, Timestamp.Date, Timestamp.Time]
>>> from argparse import Namespace
>>> from pprint import pprint
>>> from dict_validator import validate, describe, deserialize, serialize

By default a DateTime is expected.

>>> class Schema:
...     field = Timestamp()
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'DateTime', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '2016-07-10 13:06:04.698084'}))
[]
>>> list(validate(Schema, {"field": '2016-07-10'}))
[(['field'], 'Not a valid DateTime')]
>>> deserialize(Schema, {"field": "2016-07-10 13:06:04.698084"}).field
datetime.datetime(2016, 7, 10, 13, 6, 4, 698084)
>>> serialize(Schema, Namespace(
...     field=datetime.datetime(2016, 7, 10, 13, 6, 4, 698084)
... ))
{'field': '2016-07-10 13:06:04.698084'}

Accept Date only.

>>> class Schema:
...     field = Timestamp(granularity=Timestamp.Date)
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'Date', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '2016-07-10'}))
[]

Serialized payload must be a string

>>> list(validate(Schema, {"field": 20160710}))
[(['field'], 'Not a string')]
>>> deserialize(Schema, {"field": "2016-07-10"}).field
datetime.date(2016, 7, 10)
>>> serialize(Schema, Namespace(
...     field=datetime.date(2016, 7, 10)
... ))
{'field': '2016-07-10'}

Accept Time only.

>>> class Schema:
...     field = Timestamp(granularity=Timestamp.Time)
>>> pprint(list(describe(Schema)))
[([], {'type': 'Dict'}),
 (['field'], {'granularity': 'Time', 'type': 'Timestamp'})]
>>> list(validate(Schema, {"field": '13:06:04.698084'}))
[]
>>> deserialize(Schema, {"field": "13:06:04.698084"}).field
datetime.time(13, 6, 4, 698084)
>>> serialize(Schema, Namespace(
...     field=datetime.time(13, 6, 4, 698084)
... ))
{'field': '13:06:04.698084'}
class Date[source]

Bases: object

granulate()

Return date object with same year, month and day.

value = '%Y-%m-%d'
class DateTime[source]

Bases: object

static granulate()

Return datetime object.

value = '%Y-%m-%d %H:%M:%S.%f'
class Time[source]

Bases: object

granulate()

Return time object with same time but with tzinfo=None.

value = '%H:%M:%S.%f'
deserialize(value)[source]
Parameters:value – a payload sent over the wire
Returns:a payload with Python specific data types
serialize(value)[source]
Returns:a payload ready to be sent over the wire
class dict_validator.fields.wildcard_dict_field.Any(description=None, required=True)[source]

Bases: dict_validator.field.Field

Wildcard value.

class dict_validator.fields.wildcard_dict_field.WildcardDict(key_schema=None, value_schema=None, **kwargs)[source]

Bases: dict_validator.field.Field

Match a dict with any dict with any key/value pairs.

Parameters:
  • key_schema – Field subclass to be used to validate/serialize/deserialize the keys. Optional. If undefined the keys are accepted as is.
  • value_schema – Field subclass to be used to validate/serialize/deserialize the values. Optional. If undefined the values are accepted as is.
>>> from dict_validator import validate, describe, serialize, deserialize
>>> class Schema:
...     field = WildcardDict()
>>> list(validate(Schema, {"field": {}}))
[]
>>> list(validate(Schema, {"field": {"key": "value"}}))
[]
>>> list(validate(Schema, {"field": 11}))
[(['field'], 'Not a dict')]
>>> from pprint import pprint

In field’s description there are two special nodes: {KEY} and {VALUE} that respectively correspond to the schemas applied to keys and values of the payload.

>>> pprint(list(describe(Schema)), width=70)
[([], {'type': 'Dict'}),
 (['field'], {'type': 'WildcardDict'}),
 (['field', '{KEY}'], {'type': 'Any'}),
 (['field', '{VALUE}'], {'type': 'Any'})]

If it is need it is possible to have validation for keys, values or both. This can be achieved by defining respective schemas.

>>> class SampleOnly(Field):
...
...     def _validate(self, value):
...         if not value.startswith("sample"):
...             return "Not a sample"
...
...     def serialize(self, value):
...         return value.lstrip("py(").rstrip(")")
...
...     def deserialize(self, value):
...         return "py(" +  value + ")"
>>> class Schema:
...     field = WildcardDict(key_schema=SampleOnly(),
...                          value_schema=SampleOnly())
>>> pprint(list(describe(Schema)), width=70)
[([], {'type': 'Dict'}),
 (['field'], {'type': 'WildcardDict'}),
 (['field', '{KEY}'], {'type': 'SampleOnly'}),
 (['field', '{VALUE}'], {'type': 'SampleOnly'})]
>>> list(validate(Schema, {"field": {
...     "sample_field": "sample_value"
... }}))
[]
>>> list(validate(Schema, {"field": {
...     "foobar": "sample_value"
... }}))
[(['field', 'foobar'], 'Key error: Not a sample')]
>>> list(validate(Schema, {"field": {
...     "sample_field": "foobar"
... }}))
[(['field', 'sample_field'], 'Value error: Not a sample')]
>>> from argparse import Namespace
>>> serialize(Schema, Namespace(
...     field={"py(foobar)": "py(sample_value)"}
... ))
{'field': {'foobar': 'sample_value'}}
>>> deserialize(Schema, {"field": {"foobar": "sample_value"}}).field
{'py(foobar)': 'py(sample_value)'}
describe()[source]

Do not override.

Yield:(path, {…description…}), e.g ([“parent”, “child”], {“required”: False})
deserialize(value)[source]
Parameters:value – a payload sent over the wire
Returns:a payload with Python specific data types
serialize(value)[source]
Returns:a payload ready to be sent over the wire