| from decimal import Decimal |
| from pathlib import Path |
| from typing import TYPE_CHECKING, Any, Callable, Sequence, Set, Tuple, Type, Union |
|
|
| from pydantic.v1.typing import display_as_type |
|
|
| if TYPE_CHECKING: |
| from pydantic.v1.typing import DictStrAny |
|
|
| |
| __all__ = ( |
| 'PydanticTypeError', |
| 'PydanticValueError', |
| 'ConfigError', |
| 'MissingError', |
| 'ExtraError', |
| 'NoneIsNotAllowedError', |
| 'NoneIsAllowedError', |
| 'WrongConstantError', |
| 'NotNoneError', |
| 'BoolError', |
| 'BytesError', |
| 'DictError', |
| 'EmailError', |
| 'UrlError', |
| 'UrlSchemeError', |
| 'UrlSchemePermittedError', |
| 'UrlUserInfoError', |
| 'UrlHostError', |
| 'UrlHostTldError', |
| 'UrlPortError', |
| 'UrlExtraError', |
| 'EnumError', |
| 'IntEnumError', |
| 'EnumMemberError', |
| 'IntegerError', |
| 'FloatError', |
| 'PathError', |
| 'PathNotExistsError', |
| 'PathNotAFileError', |
| 'PathNotADirectoryError', |
| 'PyObjectError', |
| 'SequenceError', |
| 'ListError', |
| 'SetError', |
| 'FrozenSetError', |
| 'TupleError', |
| 'TupleLengthError', |
| 'ListMinLengthError', |
| 'ListMaxLengthError', |
| 'ListUniqueItemsError', |
| 'SetMinLengthError', |
| 'SetMaxLengthError', |
| 'FrozenSetMinLengthError', |
| 'FrozenSetMaxLengthError', |
| 'AnyStrMinLengthError', |
| 'AnyStrMaxLengthError', |
| 'StrError', |
| 'StrRegexError', |
| 'NumberNotGtError', |
| 'NumberNotGeError', |
| 'NumberNotLtError', |
| 'NumberNotLeError', |
| 'NumberNotMultipleError', |
| 'DecimalError', |
| 'DecimalIsNotFiniteError', |
| 'DecimalMaxDigitsError', |
| 'DecimalMaxPlacesError', |
| 'DecimalWholeDigitsError', |
| 'DateTimeError', |
| 'DateError', |
| 'DateNotInThePastError', |
| 'DateNotInTheFutureError', |
| 'TimeError', |
| 'DurationError', |
| 'HashableError', |
| 'UUIDError', |
| 'UUIDVersionError', |
| 'ArbitraryTypeError', |
| 'ClassError', |
| 'SubclassError', |
| 'JsonError', |
| 'JsonTypeError', |
| 'PatternError', |
| 'DataclassTypeError', |
| 'CallableError', |
| 'IPvAnyAddressError', |
| 'IPvAnyInterfaceError', |
| 'IPvAnyNetworkError', |
| 'IPv4AddressError', |
| 'IPv6AddressError', |
| 'IPv4NetworkError', |
| 'IPv6NetworkError', |
| 'IPv4InterfaceError', |
| 'IPv6InterfaceError', |
| 'ColorError', |
| 'StrictBoolError', |
| 'NotDigitError', |
| 'LuhnValidationError', |
| 'InvalidLengthForBrand', |
| 'InvalidByteSize', |
| 'InvalidByteSizeUnit', |
| 'MissingDiscriminator', |
| 'InvalidDiscriminator', |
| ) |
|
|
|
|
| def cls_kwargs(cls: Type['PydanticErrorMixin'], ctx: 'DictStrAny') -> 'PydanticErrorMixin': |
| """ |
| For built-in exceptions like ValueError or TypeError, we need to implement |
| __reduce__ to override the default behaviour (instead of __getstate__/__setstate__) |
| By default pickle protocol 2 calls `cls.__new__(cls, *args)`. |
| Since we only use kwargs, we need a little constructor to change that. |
| Note: the callable can't be a lambda as pickle looks in the namespace to find it |
| """ |
| return cls(**ctx) |
|
|
|
|
| class PydanticErrorMixin: |
| code: str |
| msg_template: str |
|
|
| def __init__(self, **ctx: Any) -> None: |
| self.__dict__ = ctx |
|
|
| def __str__(self) -> str: |
| return self.msg_template.format(**self.__dict__) |
|
|
| def __reduce__(self) -> Tuple[Callable[..., 'PydanticErrorMixin'], Tuple[Type['PydanticErrorMixin'], 'DictStrAny']]: |
| return cls_kwargs, (self.__class__, self.__dict__) |
|
|
|
|
| class PydanticTypeError(PydanticErrorMixin, TypeError): |
| pass |
|
|
|
|
| class PydanticValueError(PydanticErrorMixin, ValueError): |
| pass |
|
|
|
|
| class ConfigError(RuntimeError): |
| pass |
|
|
|
|
| class MissingError(PydanticValueError): |
| msg_template = 'field required' |
|
|
|
|
| class ExtraError(PydanticValueError): |
| msg_template = 'extra fields not permitted' |
|
|
|
|
| class NoneIsNotAllowedError(PydanticTypeError): |
| code = 'none.not_allowed' |
| msg_template = 'none is not an allowed value' |
|
|
|
|
| class NoneIsAllowedError(PydanticTypeError): |
| code = 'none.allowed' |
| msg_template = 'value is not none' |
|
|
|
|
| class WrongConstantError(PydanticValueError): |
| code = 'const' |
|
|
| def __str__(self) -> str: |
| permitted = ', '.join(repr(v) for v in self.permitted) |
| return f'unexpected value; permitted: {permitted}' |
|
|
|
|
| class NotNoneError(PydanticTypeError): |
| code = 'not_none' |
| msg_template = 'value is not None' |
|
|
|
|
| class BoolError(PydanticTypeError): |
| msg_template = 'value could not be parsed to a boolean' |
|
|
|
|
| class BytesError(PydanticTypeError): |
| msg_template = 'byte type expected' |
|
|
|
|
| class DictError(PydanticTypeError): |
| msg_template = 'value is not a valid dict' |
|
|
|
|
| class EmailError(PydanticValueError): |
| msg_template = 'value is not a valid email address' |
|
|
|
|
| class UrlError(PydanticValueError): |
| code = 'url' |
|
|
|
|
| class UrlSchemeError(UrlError): |
| code = 'url.scheme' |
| msg_template = 'invalid or missing URL scheme' |
|
|
|
|
| class UrlSchemePermittedError(UrlError): |
| code = 'url.scheme' |
| msg_template = 'URL scheme not permitted' |
|
|
| def __init__(self, allowed_schemes: Set[str]): |
| super().__init__(allowed_schemes=allowed_schemes) |
|
|
|
|
| class UrlUserInfoError(UrlError): |
| code = 'url.userinfo' |
| msg_template = 'userinfo required in URL but missing' |
|
|
|
|
| class UrlHostError(UrlError): |
| code = 'url.host' |
| msg_template = 'URL host invalid' |
|
|
|
|
| class UrlHostTldError(UrlError): |
| code = 'url.host' |
| msg_template = 'URL host invalid, top level domain required' |
|
|
|
|
| class UrlPortError(UrlError): |
| code = 'url.port' |
| msg_template = 'URL port invalid, port cannot exceed 65535' |
|
|
|
|
| class UrlExtraError(UrlError): |
| code = 'url.extra' |
| msg_template = 'URL invalid, extra characters found after valid URL: {extra!r}' |
|
|
|
|
| class EnumMemberError(PydanticTypeError): |
| code = 'enum' |
|
|
| def __str__(self) -> str: |
| permitted = ', '.join(repr(v.value) for v in self.enum_values) |
| return f'value is not a valid enumeration member; permitted: {permitted}' |
|
|
|
|
| class IntegerError(PydanticTypeError): |
| msg_template = 'value is not a valid integer' |
|
|
|
|
| class FloatError(PydanticTypeError): |
| msg_template = 'value is not a valid float' |
|
|
|
|
| class PathError(PydanticTypeError): |
| msg_template = 'value is not a valid path' |
|
|
|
|
| class _PathValueError(PydanticValueError): |
| def __init__(self, *, path: Path) -> None: |
| super().__init__(path=str(path)) |
|
|
|
|
| class PathNotExistsError(_PathValueError): |
| code = 'path.not_exists' |
| msg_template = 'file or directory at path "{path}" does not exist' |
|
|
|
|
| class PathNotAFileError(_PathValueError): |
| code = 'path.not_a_file' |
| msg_template = 'path "{path}" does not point to a file' |
|
|
|
|
| class PathNotADirectoryError(_PathValueError): |
| code = 'path.not_a_directory' |
| msg_template = 'path "{path}" does not point to a directory' |
|
|
|
|
| class PyObjectError(PydanticTypeError): |
| msg_template = 'ensure this value contains valid import path or valid callable: {error_message}' |
|
|
|
|
| class SequenceError(PydanticTypeError): |
| msg_template = 'value is not a valid sequence' |
|
|
|
|
| class IterableError(PydanticTypeError): |
| msg_template = 'value is not a valid iterable' |
|
|
|
|
| class ListError(PydanticTypeError): |
| msg_template = 'value is not a valid list' |
|
|
|
|
| class SetError(PydanticTypeError): |
| msg_template = 'value is not a valid set' |
|
|
|
|
| class FrozenSetError(PydanticTypeError): |
| msg_template = 'value is not a valid frozenset' |
|
|
|
|
| class DequeError(PydanticTypeError): |
| msg_template = 'value is not a valid deque' |
|
|
|
|
| class TupleError(PydanticTypeError): |
| msg_template = 'value is not a valid tuple' |
|
|
|
|
| class TupleLengthError(PydanticValueError): |
| code = 'tuple.length' |
| msg_template = 'wrong tuple length {actual_length}, expected {expected_length}' |
|
|
| def __init__(self, *, actual_length: int, expected_length: int) -> None: |
| super().__init__(actual_length=actual_length, expected_length=expected_length) |
|
|
|
|
| class ListMinLengthError(PydanticValueError): |
| code = 'list.min_items' |
| msg_template = 'ensure this value has at least {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class ListMaxLengthError(PydanticValueError): |
| code = 'list.max_items' |
| msg_template = 'ensure this value has at most {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class ListUniqueItemsError(PydanticValueError): |
| code = 'list.unique_items' |
| msg_template = 'the list has duplicated items' |
|
|
|
|
| class SetMinLengthError(PydanticValueError): |
| code = 'set.min_items' |
| msg_template = 'ensure this value has at least {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class SetMaxLengthError(PydanticValueError): |
| code = 'set.max_items' |
| msg_template = 'ensure this value has at most {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class FrozenSetMinLengthError(PydanticValueError): |
| code = 'frozenset.min_items' |
| msg_template = 'ensure this value has at least {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class FrozenSetMaxLengthError(PydanticValueError): |
| code = 'frozenset.max_items' |
| msg_template = 'ensure this value has at most {limit_value} items' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class AnyStrMinLengthError(PydanticValueError): |
| code = 'any_str.min_length' |
| msg_template = 'ensure this value has at least {limit_value} characters' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class AnyStrMaxLengthError(PydanticValueError): |
| code = 'any_str.max_length' |
| msg_template = 'ensure this value has at most {limit_value} characters' |
|
|
| def __init__(self, *, limit_value: int) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class StrError(PydanticTypeError): |
| msg_template = 'str type expected' |
|
|
|
|
| class StrRegexError(PydanticValueError): |
| code = 'str.regex' |
| msg_template = 'string does not match regex "{pattern}"' |
|
|
| def __init__(self, *, pattern: str) -> None: |
| super().__init__(pattern=pattern) |
|
|
|
|
| class _NumberBoundError(PydanticValueError): |
| def __init__(self, *, limit_value: Union[int, float, Decimal]) -> None: |
| super().__init__(limit_value=limit_value) |
|
|
|
|
| class NumberNotGtError(_NumberBoundError): |
| code = 'number.not_gt' |
| msg_template = 'ensure this value is greater than {limit_value}' |
|
|
|
|
| class NumberNotGeError(_NumberBoundError): |
| code = 'number.not_ge' |
| msg_template = 'ensure this value is greater than or equal to {limit_value}' |
|
|
|
|
| class NumberNotLtError(_NumberBoundError): |
| code = 'number.not_lt' |
| msg_template = 'ensure this value is less than {limit_value}' |
|
|
|
|
| class NumberNotLeError(_NumberBoundError): |
| code = 'number.not_le' |
| msg_template = 'ensure this value is less than or equal to {limit_value}' |
|
|
|
|
| class NumberNotFiniteError(PydanticValueError): |
| code = 'number.not_finite_number' |
| msg_template = 'ensure this value is a finite number' |
|
|
|
|
| class NumberNotMultipleError(PydanticValueError): |
| code = 'number.not_multiple' |
| msg_template = 'ensure this value is a multiple of {multiple_of}' |
|
|
| def __init__(self, *, multiple_of: Union[int, float, Decimal]) -> None: |
| super().__init__(multiple_of=multiple_of) |
|
|
|
|
| class DecimalError(PydanticTypeError): |
| msg_template = 'value is not a valid decimal' |
|
|
|
|
| class DecimalIsNotFiniteError(PydanticValueError): |
| code = 'decimal.not_finite' |
| msg_template = 'value is not a valid decimal' |
|
|
|
|
| class DecimalMaxDigitsError(PydanticValueError): |
| code = 'decimal.max_digits' |
| msg_template = 'ensure that there are no more than {max_digits} digits in total' |
|
|
| def __init__(self, *, max_digits: int) -> None: |
| super().__init__(max_digits=max_digits) |
|
|
|
|
| class DecimalMaxPlacesError(PydanticValueError): |
| code = 'decimal.max_places' |
| msg_template = 'ensure that there are no more than {decimal_places} decimal places' |
|
|
| def __init__(self, *, decimal_places: int) -> None: |
| super().__init__(decimal_places=decimal_places) |
|
|
|
|
| class DecimalWholeDigitsError(PydanticValueError): |
| code = 'decimal.whole_digits' |
| msg_template = 'ensure that there are no more than {whole_digits} digits before the decimal point' |
|
|
| def __init__(self, *, whole_digits: int) -> None: |
| super().__init__(whole_digits=whole_digits) |
|
|
|
|
| class DateTimeError(PydanticValueError): |
| msg_template = 'invalid datetime format' |
|
|
|
|
| class DateError(PydanticValueError): |
| msg_template = 'invalid date format' |
|
|
|
|
| class DateNotInThePastError(PydanticValueError): |
| code = 'date.not_in_the_past' |
| msg_template = 'date is not in the past' |
|
|
|
|
| class DateNotInTheFutureError(PydanticValueError): |
| code = 'date.not_in_the_future' |
| msg_template = 'date is not in the future' |
|
|
|
|
| class TimeError(PydanticValueError): |
| msg_template = 'invalid time format' |
|
|
|
|
| class DurationError(PydanticValueError): |
| msg_template = 'invalid duration format' |
|
|
|
|
| class HashableError(PydanticTypeError): |
| msg_template = 'value is not a valid hashable' |
|
|
|
|
| class UUIDError(PydanticTypeError): |
| msg_template = 'value is not a valid uuid' |
|
|
|
|
| class UUIDVersionError(PydanticValueError): |
| code = 'uuid.version' |
| msg_template = 'uuid version {required_version} expected' |
|
|
| def __init__(self, *, required_version: int) -> None: |
| super().__init__(required_version=required_version) |
|
|
|
|
| class ArbitraryTypeError(PydanticTypeError): |
| code = 'arbitrary_type' |
| msg_template = 'instance of {expected_arbitrary_type} expected' |
|
|
| def __init__(self, *, expected_arbitrary_type: Type[Any]) -> None: |
| super().__init__(expected_arbitrary_type=display_as_type(expected_arbitrary_type)) |
|
|
|
|
| class ClassError(PydanticTypeError): |
| code = 'class' |
| msg_template = 'a class is expected' |
|
|
|
|
| class SubclassError(PydanticTypeError): |
| code = 'subclass' |
| msg_template = 'subclass of {expected_class} expected' |
|
|
| def __init__(self, *, expected_class: Type[Any]) -> None: |
| super().__init__(expected_class=display_as_type(expected_class)) |
|
|
|
|
| class JsonError(PydanticValueError): |
| msg_template = 'Invalid JSON' |
|
|
|
|
| class JsonTypeError(PydanticTypeError): |
| code = 'json' |
| msg_template = 'JSON object must be str, bytes or bytearray' |
|
|
|
|
| class PatternError(PydanticValueError): |
| code = 'regex_pattern' |
| msg_template = 'Invalid regular expression' |
|
|
|
|
| class DataclassTypeError(PydanticTypeError): |
| code = 'dataclass' |
| msg_template = 'instance of {class_name}, tuple or dict expected' |
|
|
|
|
| class CallableError(PydanticTypeError): |
| msg_template = '{value} is not callable' |
|
|
|
|
| class EnumError(PydanticTypeError): |
| code = 'enum_instance' |
| msg_template = '{value} is not a valid Enum instance' |
|
|
|
|
| class IntEnumError(PydanticTypeError): |
| code = 'int_enum_instance' |
| msg_template = '{value} is not a valid IntEnum instance' |
|
|
|
|
| class IPvAnyAddressError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 or IPv6 address' |
|
|
|
|
| class IPvAnyInterfaceError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 or IPv6 interface' |
|
|
|
|
| class IPvAnyNetworkError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 or IPv6 network' |
|
|
|
|
| class IPv4AddressError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 address' |
|
|
|
|
| class IPv6AddressError(PydanticValueError): |
| msg_template = 'value is not a valid IPv6 address' |
|
|
|
|
| class IPv4NetworkError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 network' |
|
|
|
|
| class IPv6NetworkError(PydanticValueError): |
| msg_template = 'value is not a valid IPv6 network' |
|
|
|
|
| class IPv4InterfaceError(PydanticValueError): |
| msg_template = 'value is not a valid IPv4 interface' |
|
|
|
|
| class IPv6InterfaceError(PydanticValueError): |
| msg_template = 'value is not a valid IPv6 interface' |
|
|
|
|
| class ColorError(PydanticValueError): |
| msg_template = 'value is not a valid color: {reason}' |
|
|
|
|
| class StrictBoolError(PydanticValueError): |
| msg_template = 'value is not a valid boolean' |
|
|
|
|
| class NotDigitError(PydanticValueError): |
| code = 'payment_card_number.digits' |
| msg_template = 'card number is not all digits' |
|
|
|
|
| class LuhnValidationError(PydanticValueError): |
| code = 'payment_card_number.luhn_check' |
| msg_template = 'card number is not luhn valid' |
|
|
|
|
| class InvalidLengthForBrand(PydanticValueError): |
| code = 'payment_card_number.invalid_length_for_brand' |
| msg_template = 'Length for a {brand} card must be {required_length}' |
|
|
|
|
| class InvalidByteSize(PydanticValueError): |
| msg_template = 'could not parse value and unit from byte string' |
|
|
|
|
| class InvalidByteSizeUnit(PydanticValueError): |
| msg_template = 'could not interpret byte unit: {unit}' |
|
|
|
|
| class MissingDiscriminator(PydanticValueError): |
| code = 'discriminated_union.missing_discriminator' |
| msg_template = 'Discriminator {discriminator_key!r} is missing in value' |
|
|
|
|
| class InvalidDiscriminator(PydanticValueError): |
| code = 'discriminated_union.invalid_discriminator' |
| msg_template = ( |
| 'No match for discriminator {discriminator_key!r} and value {discriminator_value!r} ' |
| '(allowed values: {allowed_values})' |
| ) |
|
|
| def __init__(self, *, discriminator_key: str, discriminator_value: Any, allowed_values: Sequence[Any]) -> None: |
| super().__init__( |
| discriminator_key=discriminator_key, |
| discriminator_value=discriminator_value, |
| allowed_values=', '.join(map(repr, allowed_values)), |
| ) |
|
|