Validate configuration and produce human readable error messages.
pip install cfgv
These are easier to see by example. Here's an example where I typo'd true
in a pre-commit configuration.
pre_commit.clientlib.InvalidConfigError:
==> File /home/asottile/workspace/pre-commit/.pre-commit-config.yaml
==> At Config()
==> At key: repos
==> At Repository(repo='https://github.com/pre-commit/pre-commit-hooks')
==> At key: hooks
==> At Hook(id='flake8')
==> At key: always_run
=====> Expected bool got str
Perform validation on the schema:
- raises
ValidationError
on failure - returns the value on success (for convenience)
Returns a new value which sets all missing optional values to their defaults.
Returns a new value which removes all optional values that are set to their defaults.
Load a file given the load_strategy
. Reraise any errors as exc_tp
. All
defaults will be populated in the resulting value.
Most useful when used with functools.partial
as follows:
load_my_cfg = functools.partial(
cfgv.load_from_filename,
schema=MY_SCHEMA,
load_strategy=json.loads,
exc_tp=MyError,
)
A schema validates a container -- cfgv
provides Map
and Array
for
most normal cases.
If the built-in containers below don't quite satisfy your usecase, you can always write your own. Containers use the following interface:
class Container(object):
def check(self, v):
"""check the passed in value (do not modify `v`)"""
def apply_defaults(self, v):
"""return a new value with defaults applied (do not modify `v`)"""
def remove_defaults(self, v):
"""return a new value with defaults removed (do not modify `v`)"""
The most basic building block for creating a schema is a Map
object_name
: will be displayed in error messagesid_key
: will be used to identify the object in error messages. Set toNone
if there is no identifying key for the object.items
: validator objects such asRequired
orOptional
Consider the following schema:
Map(
'Repo', 'url',
Required('url', check_any),
)
In an error message, the map may be displayed as:
Repo(url='https://github.com/pre-commit/pre-commit')
Repo(url=MISSING)
(if the key is not present)
Used to nest maps inside of arrays. For arrays of scalars, see check_array
.
of
: AMap
/Array
or other sub-schema.allow_empty
: whenFalse
,Array
will ensure at least one element.
When validated, this will check that each element adheres to the sub-schema.
Validator objects are used to validate key-value-pairs of a Map
.
If the built-in validators below don't quite satisfy your usecase, you can always write your own. Validators use the following interface:
class Validator(object):
def check(self, dct):
"""check that your specific key has the appropriate value in `dct`"""
def apply_default(self, dct):
"""modify `dct` and set the default value if it is missing"""
def remove_default(self, dct):
"""modify `dct` and remove the default value if it is present"""
It may make sense to borrow functions from the built in validators. They additionally use the following interface(s):
self.key
: the key to checkself.check_fn
: the check functionself.default
: a default value to set.
Ensure that a key is present in a Map
and adheres to the
check function.
Similar to Required
, but uses a schema.
If a key is present, check that it adheres to the check function.
apply_defaults
will set thedefault
if it is not present.remove_defaults
will remove the value if it is equal todefault
.
Similar to Optional
but uses a schema.
apply_defaults
will set thedefault
if it is not present and then validate it with the schema.remove_defaults
will remove defaults using the schema, and then remove the value it if it is equal todefault
.
Like Optional
, but does not apply_defaults
or remove_defaults
.
- If
condition_key
is equal to thecondition_value
, the specifickey
will be checked using the check function. - If
ensure_absent
isTrue
and the condition check fails, thekey
will be checked for absense.
Note that the condition_value
is checked for equality, so any object
implementing __eq__
may be used. A few are provided out of the box
for this purpose, see equality helpers.
Similar to Conditional
and Optional
.
Similar to Conditional
, but uses a schema.
Use in a mapping to ensure that only the keys
specified are present.
Equality helpers at the very least implement __eq__
for their behaviour.
They may also implement def describe_opposite(self):
for use in the
ensure_absent=True
error message (otherwise, the __repr__
will be used).
Returns True
if the value is not equal to val
.
Returns True
if the value is contained in values
.
Returns True
if the value is not contained in values
.
A number of check functions are provided out of the box.
A check function takes a single parameter, the value
, and either raises a
ValidationError
or returns nothing.
A noop check function.
Returns a check function to check for a specific type. Setting typename
will replace the type's name in the error message.
For example:
Required('key', check_type(int))
# 'Expected bytes' in both python2 and python3.
Required('key', check_type(bytes, typename='bytes'))
Several type checking functions are provided out of the box:
check_bool
check_bytes
check_int
check_string
check_text
Returns a function that checks that the value is contained in possible
.
For example:
Required('language', check_one_of(('javascript', 'python', 'ruby')))
Ensures that v
is a valid python regular expression.
Returns a function that checks that a value is a sequence and that each
value in that sequence adheres to the inner_check
.
For example:
Required('args', check_array(check_string))
Returns a function that performs multiple checks on a value.
For example:
Required('language', check_and(check_string, my_check_language))