Certifies a dictionary, checking it against an optional schema.

    The schema should be a dictionary, with keys corresponding to the expected keys in `value`,
    but with the values replaced by functions which will be called to with the corresponding
    value in the input.

    A simple example:

        >>> certifier = certify_dict(schema={
        ...    'id': certify_key(kind='Model'),
        ...    'count': certify_int(min=0),
        ...    })
        >>> certifier({'id': self.key, 'count': self.count})

    :param dict|Mapping|MutableMapping value:
        The value to be certified.
    :param dict schema:
        The schema against which the value should be checked.
    :param bool allow_extra:
        Set to `True` to ignore extra keys.
    :param bool required:
        Whether the value can't be `None`. Defaults to True.
    :param callable key_certifier:
        callable that receives the key to certify (ignoring schema keys).
    :param callable value_certifier:
        callable that receives the value to certify (ignoring schema values).
    :param bool include_collections:
        Include types from collections.
    :return:
        The certified dict.
    :rtype:
        dict|Mapping|MutableMapping
    :raises CertifierTypeError:
        The type is invalid
    :raises CertifierValueError:
        The value is invalid

def certify_dict(
    value, schema=None, allow_extra=False, required=True, key_certifier=None, value_certifier=None,
    include_collections=False,
):
    """
    Certifies a dictionary, checking it against an optional schema.

    The schema should be a dictionary, with keys corresponding to the expected keys in `value`,
    but with the values replaced by functions which will be called to with the corresponding
    value in the input.

    A simple example:

        >>> certifier = certify_dict(schema={
        ...    'id': certify_key(kind='Model'),
        ...    'count': certify_int(min=0),
        ...    })
        >>> certifier({'id': self.key, 'count': self.count})

    :param dict|Mapping|MutableMapping value:
        The value to be certified.
    :param dict schema:
        The schema against which the value should be checked.
    :param bool allow_extra:
        Set to `True` to ignore extra keys.
    :param bool required:
        Whether the value can't be `None`. Defaults to True.
    :param callable key_certifier:
        callable that receives the key to certify (ignoring schema keys).
    :param callable value_certifier:
        callable that receives the value to certify (ignoring schema values).
    :param bool include_collections:
        Include types from collections.
    :return:
        The certified dict.
    :rtype:
        dict|Mapping|MutableMapping
    :raises CertifierTypeError:
        The type is invalid
    :raises CertifierValueError:
        The value is invalid
    """
    cls = dict

    # Certify our kwargs:
    certify_params(
        (certify_bool, 'allow_extra', allow_extra),
        (certify_bool, 'include_collections', include_collections),
    )
    if certify_required(
        value=value,
        required=required,
    ):
        return

    # Check the type(s):
    types = [cls]
    if include_collections:
        types.extend([Mapping, MutableMapping])
    types = tuple(types)
    if not isinstance(value, types):
        raise CertifierTypeError(
            message="Expected {t} but the type is {cls!r}".format(
                cls=cls,
                t=value.__class__.__name__,
            ),
            value=value,
            required=required,
        )
    certify_dict_schema(
        value=value,
        schema=schema,
        key_certifier=key_certifier,
        value_certifier=value_certifier,
        required=required,
        allow_extra=allow_extra,
    )