File size: 4,835 Bytes
4ae0b03 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
"""Pydantic-specific errors."""
from __future__ import annotations as _annotations
import re
from typing_extensions import Literal, Self
from ._migration import getattr_migration
from .version import version_short
__all__ = (
'PydanticUserError',
'PydanticUndefinedAnnotation',
'PydanticImportError',
'PydanticSchemaGenerationError',
'PydanticInvalidForJsonSchema',
'PydanticErrorCodes',
)
# We use this URL to allow for future flexibility about how we host the docs, while allowing for Pydantic
# code in the while with "old" URLs to still work.
# 'u' refers to "user errors" - e.g. errors caused by developers using pydantic, as opposed to validation errors.
DEV_ERROR_DOCS_URL = f'https://errors.pydantic.dev/{version_short()}/u/'
PydanticErrorCodes = Literal[
'class-not-fully-defined',
'custom-json-schema',
'decorator-missing-field',
'discriminator-no-field',
'discriminator-alias-type',
'discriminator-needs-literal',
'discriminator-alias',
'discriminator-validator',
'callable-discriminator-no-tag',
'typed-dict-version',
'model-field-overridden',
'model-field-missing-annotation',
'config-both',
'removed-kwargs',
'invalid-for-json-schema',
'json-schema-already-used',
'base-model-instantiated',
'undefined-annotation',
'schema-for-unknown-type',
'import-error',
'create-model-field-definitions',
'create-model-config-base',
'validator-no-fields',
'validator-invalid-fields',
'validator-instance-method',
'root-validator-pre-skip',
'model-serializer-instance-method',
'validator-field-config-info',
'validator-v1-signature',
'validator-signature',
'field-serializer-signature',
'model-serializer-signature',
'multiple-field-serializers',
'invalid_annotated_type',
'type-adapter-config-unused',
'root-model-extra',
'unevaluable-type-annotation',
'dataclass-init-false-extra-allow',
'clashing-init-and-init-var',
'model-config-invalid-field-name',
'with-config-on-model',
'dataclass-on-model',
]
class PydanticErrorMixin:
"""A mixin class for common functionality shared by all Pydantic-specific errors.
Attributes:
message: A message describing the error.
code: An optional error code from PydanticErrorCodes enum.
"""
def __init__(self, message: str, *, code: PydanticErrorCodes | None) -> None:
self.message = message
self.code = code
def __str__(self) -> str:
if self.code is None:
return self.message
else:
return f'{self.message}\n\nFor further information visit {DEV_ERROR_DOCS_URL}{self.code}'
class PydanticUserError(PydanticErrorMixin, TypeError):
"""An error raised due to incorrect use of Pydantic."""
class PydanticUndefinedAnnotation(PydanticErrorMixin, NameError):
"""A subclass of `NameError` raised when handling undefined annotations during `CoreSchema` generation.
Attributes:
name: Name of the error.
message: Description of the error.
"""
def __init__(self, name: str, message: str) -> None:
self.name = name
super().__init__(message=message, code='undefined-annotation')
@classmethod
def from_name_error(cls, name_error: NameError) -> Self:
"""Convert a `NameError` to a `PydanticUndefinedAnnotation` error.
Args:
name_error: `NameError` to be converted.
Returns:
Converted `PydanticUndefinedAnnotation` error.
"""
try:
name = name_error.name # type: ignore # python > 3.10
except AttributeError:
name = re.search(r".*'(.+?)'", str(name_error)).group(1) # type: ignore[union-attr]
return cls(name=name, message=str(name_error))
class PydanticImportError(PydanticErrorMixin, ImportError):
"""An error raised when an import fails due to module changes between V1 and V2.
Attributes:
message: Description of the error.
"""
def __init__(self, message: str) -> None:
super().__init__(message, code='import-error')
class PydanticSchemaGenerationError(PydanticUserError):
"""An error raised during failures to generate a `CoreSchema` for some type.
Attributes:
message: Description of the error.
"""
def __init__(self, message: str) -> None:
super().__init__(message, code='schema-for-unknown-type')
class PydanticInvalidForJsonSchema(PydanticUserError):
"""An error raised during failures to generate a JSON schema for some `CoreSchema`.
Attributes:
message: Description of the error.
"""
def __init__(self, message: str) -> None:
super().__init__(message, code='invalid-for-json-schema')
__getattr__ = getattr_migration(__name__)
|