# Path: src/lupin/validators/validator.py
# class Validator(object):
#     """Validators base class"""
# 
#     def __and__(self, other):
#         """Combine current validator with another one using the & operator
# 
#         Returns:
#             ValidatorsAndCombination
#         """
#         return lupin.ValidatorsAndCombination([self, other])
# 
#     def __or__(self, other):
#         """Combine current validator with another one using the | operator
# 
#         Returns:
#             ValidatorsOrCombination
#         """
#         return lupin.ValidatorsOrCombination([self, other])
# 
# Path: src/lupin/errors.py
# class InvalidType(ValidationError):
#     """Error raised by `Type` validator"""
# 
#     def __init__(self, invalid, expected, path):
#         """
#         Args:
#             invalid (type): invalid type received
#             expected (type): type expected
#             path (list): path of the invalid data
#         """
#         message = "Invalid type, got %s instead of %s" % (invalid, expected)
#         super(InvalidType, self).__init__(message, path)
#         self.invalid = invalid
#         self.expected = expected


from .validator import Validator
from ..errors import InvalidType


class TypedDict(Validator):
    """Validates that keys and values are well typed"""
    def __init__(self, key_type, value_type):
        """
        Args:
            key_type (str): expected type for all keys
            value_type (str): expected type for all values
        """
        self._key_type = key_type
        self._value_type = value_type

    def __call__(self, value, path):
        """Validate items of dict are well typed

        Args:
            value (dict): a dictionnary
            path (list): error path
        """
        if value is None:
            return

        for key, val in value.items():
            if not isinstance(key, self._key_type):

# Path: src/lupin/validators/validator.py
# class Validator(object):
#     """Validators base class"""
# 
#     def __and__(self, other):
#         """Combine current validator with another one using the & operator
# 
#         Returns:
#             ValidatorsAndCombination
#         """
#         return lupin.ValidatorsAndCombination([self, other])
# 
#     def __or__(self, other):
#         """Combine current validator with another one using the | operator
# 
#         Returns:
#             ValidatorsOrCombination
#         """
#         return lupin.ValidatorsOrCombination([self, other])
# 
# Path: src/lupin/errors.py
# class InvalidType(ValidationError):
#     """Error raised by `Type` validator"""
# 
#     def __init__(self, invalid, expected, path):
#         """
#         Args:
#             invalid (type): invalid type received
#             expected (type): type expected
#             path (list): path of the invalid data
#         """
#         message = "Invalid type, got %s instead of %s" % (invalid, expected)
#         super(InvalidType, self).__init__(message, path)
#         self.invalid = invalid
#         self.expected = expected


# Path: src/lupin/validators/typed_dict.py
from .validator import Validator
from ..errors import InvalidType



class TypedDict(Validator):
    """Validates that keys and values are well typed"""
    def __init__(self, key_type, value_type):
        """
        Args:
            key_type (str): expected type for all keys
            value_type (str): expected type for all values
        """
        self._key_type = key_type
        self._value_type = value_type

    def __call__(self, value, path):
        """Validate items of dict are well typed

        Args:
            value (dict): a dictionnary
            path (list): error path
        """
        if value is None:
            return

        for key, val in value.items():
            if not isinstance(key, self._key_type):

                raise InvalidType(invalid=type(key),