Skip to main content

Build Status Coverage Status

cfgv

Validate configuration and produce human readable error messages.

Installation

pip install cfgv

Sample error messages

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

API

cfgv.validate(value, schema)

Perform validation on the schema:

  • raises ValidationError on failure
  • returns the value on success (for convenience)

cfgv.apply_defaults(value, schema)

Returns a new value which sets all missing optional values to their defaults.

cfgv.remove_defaults(value, schema)

Returns a new value which removes all optional values that are set to their defaults.

cfgv.load_from_filename(filename, schema, load_strategy, exc_tp=ValidationError)

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,
)

Making a schema

A schema validates a container -- cfgv provides Map and Array for most normal cases.

writing your own schema container

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`)"""

Map(object_name, id_key, *items)

The most basic building block for creating a schema is a Map

  • object_name: will be displayed in error messages
  • id_key: will be used to identify the object in error messages. Set to None if there is no identifying key for the object.
  • items: validator objects such as Required or Optional

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)

Array(of, allow_empty=True)

Used to nest maps inside of arrays. For arrays of scalars, see check_array.

  • of: A Map / Array or other sub-schema.
  • allow_empty: when False, Array will ensure at least one element.

When validated, this will check that each element adheres to the sub-schema.

Validator objects

Validator objects are used to validate key-value-pairs of a Map.

writing your own validator

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 check
  • self.check_fn: the check function
  • self.default: a default value to set.

Required(key, check_fn)

Ensure that a key is present in a Map and adheres to the check function.

RequiredRecurse(key, schema)

Similar to Required, but uses a schema.

Optional(key, check_fn, default)

If a key is present, check that it adheres to the check function.

  • apply_defaults will set the default if it is not present.
  • remove_defaults will remove the value if it is equal to default.

OptionalRecurse(key, schema, default)

Similar to Optional but uses a schema.

  • apply_defaults will set the default 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 to default.

OptionalNoDefault(key, check_fn)

Like Optional, but does not apply_defaults or remove_defaults.

Conditional(key, check_fn, condition_key, condition_value, ensure_absent=False)

  • If condition_key is equal to the condition_value, the specific key will be checked using the check function.
  • If ensure_absent is True and the condition check fails, the key 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.

ConditionalOptional(key, check_fn, default, condition_key, condition_value, ensure_absent=False)

Similar to Conditional and Optional.

ConditionalRecurse(key, schema, condition_key, condition_value, ensure_absent=True)

Similar to Conditional, but uses a schema.

NoAdditionalKeys(keys)

Use in a mapping to ensure that only the keys specified are present.

Equality helpers

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).

Not(val)

Returns True if the value is not equal to val.

In(*values)

Returns True if the value is contained in values.

NotIn(*values)

Returns True if the value is not contained in values.

Check functions

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.

check_any(_)

A noop check function.

check_type(tp, typename=None)

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

check_one_of(possible)

Returns a function that checks that the value is contained in possible.

For example:

Required('language', check_one_of(('javascript', 'python', 'ruby')))

check_regex(v)

Ensures that v is a valid python regular expression.

check_array(inner_check)

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))

check_and(*fns)

Returns a function that performs multiple checks on a value.

For example:

Required('language', check_and(check_string, my_check_language))

Download files

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

Source Distribution

cfgv-1.6.0.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cfgv-1.6.0-py2.py3-none-any.whl (7.3 kB view details)

Uploaded Python 2Python 3

File details

Details for the file cfgv-1.6.0.tar.gz.

File metadata

  • Download URL: cfgv-1.6.0.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

File hashes

Hashes for cfgv-1.6.0.tar.gz
Algorithm Hash digest
SHA256 6e9f2feea5e84bc71e56abd703140d7a2c250fc5ba38b8702fd6a68ed4e3b2ef
MD5 1e08f4a1e2438a3ef6d15e8f19468335
BLAKE2b-256 fd9e0562840cb1144389a7b0e2fccddac2296a4a80bc2d42ba2555b369301da7

See more details on using hashes here.

File details

Details for the file cfgv-1.6.0-py2.py3-none-any.whl.

File metadata

  • Download URL: cfgv-1.6.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

File hashes

Hashes for cfgv-1.6.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 e7f186d4a36c099a9e20b04ac3108bd8bb9b9257e692ce18c8c3764d5cb12172
MD5 34bec2d6aa6150c0f21282d63e54d885
BLAKE2b-256 e73875270ab931b1a0a14a57c7f5120e1742fc531b136c2f1ed84c7f6e64565f

See more details on using hashes here.

Release history Release notifications | RSS feed

3.5.0

2 files

3.4.0

2 files

3.3.1

2 files

3.3.0

2 files

3.2.0

2 files

3.1.0

2 files

3.0.0

2 files

2.0.1

2 files

2.0.0

2 files

This release

1.6.0 This release

2 files

1.5.0

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page