def expect(
    obj, attr, value, nullable=False, types=None, not_types=None, convert_to=None
):
    """
    Check, whether the value satisfies expectations

    :param obj:
        an object,
        which will set the value to its attribute.
        It is used to make error messages more specific.

    :param str attr:
        name of an attribute of the object.
        It is used to make error messages more specific.

    :param value:
        checked value itself.

    :param bool nullable:
        accept ``None`` as a valid value.
        Default: ``False`` — does not accept ``None``.

    :param types:
        define acceptable types of the value.
        Default: ``None`` — accept any type.
    :type types: None, type or tuple

    :param not_types:
        define implicitly unacceptable types of the value.
        Default: ``None`` — accept any type.
    :type types: None, type or tuple

    :param type convert_to:
        convert the value to specified type.
        Default: ``None`` — does not convert the value.

    :raises TypeError:
        * if ``types is not None`` and ``not isinstance(value, types)``;
        * if ``not_types is not None`` and ``isinstance(value, not_types)``.

    """
    if nullable and value is None:
        return value
    if types is not None and not isinstance(value, types):
        raise TypeError(
            "%s.%s.%s should be of type %r"
            % (obj.__class__.__module__, obj.__class__.__name__, attr, types)
        )
    if not_types is not None and isinstance(value, not_types):
        raise TypeError(
            "%s.%s.%s should not be of type %r"
            % (obj.__class__.__module__, obj.__class__.__name__, attr, not_types)
        )
    if convert_to is not None and not isinstance(value, convert_to):
        value = convert_to(value)
    return value