1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
"""Module to convert voluptuous schemas to dictionaries."""
from collections.abc import Mapping
import voluptuous as vol
TYPES_MAP = {
int: 'integer',
str: 'string',
float: 'float',
bool: 'boolean',
}
UNSUPPORTED = object()
def convert(schema, *, custom_serializer=None):
"""Convert a voluptuous schema to a dictionary."""
# pylint: disable=too-many-return-statements,too-many-branches
if isinstance(schema, vol.Schema):
schema = schema.schema
if custom_serializer:
val = custom_serializer(schema)
if val is not UNSUPPORTED:
return val
if isinstance(schema, Mapping):
val = []
for key, value in schema.items():
description = None
if isinstance(key, vol.Marker):
pkey = key.schema
description = key.description
else:
pkey = key
pval = convert(value, custom_serializer=custom_serializer)
pval['name'] = pkey
if description is not None:
pval['description'] = description
if isinstance(key, (vol.Required, vol.Optional)):
pval[key.__class__.__name__.lower()] = True
if key.default is not vol.UNDEFINED:
pval['default'] = key.default()
val.append(pval)
return val
if isinstance(schema, vol.All):
val = {}
for validator in schema.validators:
val.update(convert(validator, custom_serializer=custom_serializer))
return val
if isinstance(schema, (vol.Clamp, vol.Range)):
val = {}
if schema.min is not None:
val['valueMin'] = schema.min
if schema.max is not None:
val['valueMax'] = schema.max
return val
if isinstance(schema, vol.Length):
val = {}
if schema.min is not None:
val['lengthMin'] = schema.min
if schema.max is not None:
val['lengthMax'] = schema.max
return val
if isinstance(schema, vol.Datetime):
return {
'type': 'datetime',
'format': schema.format,
}
if isinstance(schema, vol.In):
if isinstance(schema.container, Mapping):
return {
'type': 'select',
'options': list(schema.container.items()),
}
return {
'type': 'select',
'options': [(item, item) for item in schema.container]
}
if schema in (vol.Lower, vol.Upper, vol.Capitalize, vol.Title, vol.Strip):
return {
schema.__name__.lower(): True,
}
if schema in (vol.Email, vol.Url, vol.FqdnUrl):
return {
'format': schema.__name__.lower(),
}
if isinstance(schema, vol.Coerce):
schema = schema.type
if schema in TYPES_MAP:
return {'type': TYPES_MAP[schema]}
if isinstance(schema, (str, int, float, bool)):
return {'type': 'constant', 'value': schema}
raise ValueError('Unable to convert schema: {}'.format(schema))
|