class OpenApiException(Exception):
    """The base exception class for all OpenAPIExceptions"""

class ApiTypeError(OpenApiException, TypeError):
    def __init__(self, msg, invalid_value=None, path_to_item=None, valid_classes=None,
                 key_type=None):
        """ Raises an exception for TypeErrors

        Args:
            msg (str): the exception message

        Keyword Args:
            path_to_item (list): a list of keys an indices to get to the
                                 current_item
                                 None if unset
            valid_classes (tuple): the primitive classes that current item
                                   should be an instance of
                                   None if unset
            key_type (bool): False if our value is a value in a dict
                             True if it is a key in a dict
                             False if our item is an item in a list
                             None if unset
        """
        self.invalid_value = invalid_value
        self.path_to_item = path_to_item
        self.valid_classes = valid_classes
        self.key_type = key_type
        full_msg = msg
        if path_to_item:
            full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
        super(ApiTypeError, self).__init__(full_msg)


class ApiValueError(OpenApiException, ValueError):
    def __init__(self, msg, path_to_item=None):
        """
        Args:
            msg (str): the exception message

        Keyword Args:
            path_to_item (list) the path to the exception in the
                received_data dict. None if unset
        """

        self.path_to_item = path_to_item
        self.full_msg = msg
        if path_to_item:
            self.full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
        super(ApiValueError, self).__init__(self.full_msg)
    
    @property
    def path(self) -> str:
        return ".".join([step for step in self.path_to_item if step != "args[0]"])


def render_path(path_to_item):
    """Returns a string representation of a path"""
    str_path = [str(step) if isinstance(step, int) else step for step in path_to_item]
    return "\"" + ".".join([step for step in str_path if step != "args[0]"])  + "\""