from __future__ import annotations from typing import Collection class TOMLKitError(Exception): pass class ParseError(ValueError, TOMLKitError): """ This error occurs when the parser encounters a syntax error in the TOML being parsed. The error references the line and location within the line where the error was encountered. """ def __init__(self, line: int, col: int, message: str | None = None) -> None: self._line = line self._col = col if message is None: message = "TOML parse error" super().__init__(f"{message} at line {self._line} col {self._col}") @property def line(self): return self._line @property def col(self): return self._col class MixedArrayTypesError(ParseError): """ An array was found that had two or more element types. """ def __init__(self, line: int, col: int) -> None: message = "Mixed types found in array" super().__init__(line, col, message=message) class InvalidNumberError(ParseError): """ A numeric field was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid number" super().__init__(line, col, message=message) class InvalidDateTimeError(ParseError): """ A datetime field was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid datetime" super().__init__(line, col, message=message) class InvalidDateError(ParseError): """ A date field was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid date" super().__init__(line, col, message=message) class InvalidTimeError(ParseError): """ A date field was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid time" super().__init__(line, col, message=message) class InvalidNumberOrDateError(ParseError): """ A numeric or date field was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid number or date format" super().__init__(line, col, message=message) class InvalidUnicodeValueError(ParseError): """ A unicode code was improperly specified. """ def __init__(self, line: int, col: int) -> None: message = "Invalid unicode value" super().__init__(line, col, message=message) class UnexpectedCharError(ParseError): """ An unexpected character was found during parsing. """ def __init__(self, line: int, col: int, char: str) -> None: message = f"Unexpected character: {repr(char)}" super().__init__(line, col, message=message) class EmptyKeyError(ParseError): """ An empty key was found during parsing. """ def __init__(self, line: int, col: int) -> None: message = "Empty key" super().__init__(line, col, message=message) class EmptyTableNameError(ParseError): """ An empty table name was found during parsing. """ def __init__(self, line: int, col: int) -> None: message = "Empty table name" super().__init__(line, col, message=message) class InvalidCharInStringError(ParseError): """ The string being parsed contains an invalid character. """ def __init__(self, line: int, col: int, char: str) -> None: message = f"Invalid character {repr(char)} in string" super().__init__(line, col, message=message) class UnexpectedEofError(ParseError): """ The TOML being parsed ended before the end of a statement. """ def __init__(self, line: int, col: int) -> None: message = "Unexpected end of file" super().__init__(line, col, message=message) class InternalParserError(ParseError): """ An error that indicates a bug in the parser. """ def __init__(self, line: int, col: int, message: str | None = None) -> None: msg = "Internal parser error" if message: msg += f" ({message})" super().__init__(line, col, message=msg) class NonExistentKey(KeyError, TOMLKitError): """ A non-existent key was used. """ def __init__(self, key): message = f'Key "{key}" does not exist.' super().__init__(message) class KeyAlreadyPresent(TOMLKitError): """ An already present key was used. """ def __init__(self, key): key = getattr(key, "key", key) message = f'Key "{key}" already exists.' super().__init__(message) class InvalidControlChar(ParseError): def __init__(self, line: int, col: int, char: int, type: str) -> None: display_code = "\\u00" if char < 16: display_code += "0" display_code += hex(char)[2:] message = ( "Control characters (codes less than 0x1f and 0x7f)" f" are not allowed in {type}, " f"use {display_code} instead" ) super().__init__(line, col, message=message) class InvalidStringError(ValueError, TOMLKitError): def __init__(self, value: str, invalid_sequences: Collection[str], delimiter: str): repr_ = repr(value)[1:-1] super().__init__( f"Invalid string: {delimiter}{repr_}{delimiter}. " f"The character sequences {invalid_sequences} are invalid." )