Metadata-Version: 2.1
Name: cfgv
Version: 3.1.0
Summary: Validate configuration and produce human readable error messages.
Home-page: https://github.com/asottile/cfgv
Author: Anthony Sottile
Author-email: asottile@umich.edu
License: MIT
Description: [![Build Status](https://dev.azure.com/asottile/asottile/_apis/build/status/asottile.cfgv?branchName=master)](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=24&branchName=master)
        [![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/asottile/asottile/24/master.svg)](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=24&branchName=master)
        
        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](https://pre-commit.com) 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:
        
        ```python
        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:
        
        ```python
        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:
        
        ```python
        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:
        
        ```python
        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](#check-functions)
        - `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](#check-functions).
        
        ### `RequiredRecurse(key, schema)`
        
        Similar to `Required`, but uses a [schema](#making-a-schema).
        
        ### `Optional(key, check_fn, default)`
        
        If a key is present, check that it adheres to the
        [check function](#check-functions).
        
        - `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](#making-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](#check-functions).
        - 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](#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](#making-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:
        
        ```python
        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:
        
        ```python
        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:
        
        ```python
        Required('args', check_array(check_string))
        ```
        
        ### `check_and(*fns)`
        
        Returns a function that performs multiple checks on a value.
        
        For example:
        
        ```python
        Required('language', check_and(check_string, my_check_language))
        ```
        
Platform: UNKNOWN
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.6.1
Description-Content-Type: text/markdown
