Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pydantic/errors.py: 80%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

46 statements  

1"""Pydantic-specific errors.""" 

2 

3from __future__ import annotations as _annotations 

4 

5import re 

6from typing import Any, ClassVar, Literal 

7 

8from typing_extensions import Self 

9from typing_inspection.introspection import Qualifier 

10 

11from pydantic._internal import _repr 

12 

13from ._migration import getattr_migration 

14from .version import version_short 

15 

16__all__ = ( 

17 'PydanticUserError', 

18 'PydanticUndefinedAnnotation', 

19 'PydanticImportError', 

20 'PydanticSchemaGenerationError', 

21 'PydanticInvalidForJsonSchema', 

22 'PydanticForbiddenQualifier', 

23 'PydanticErrorCodes', 

24) 

25 

26# We use this URL to allow for future flexibility about how we host the docs, while allowing for Pydantic 

27# code in the while with "old" URLs to still work. 

28# 'u' refers to "user errors" - e.g. errors caused by developers using pydantic, as opposed to validation errors. 

29DEV_ERROR_DOCS_URL = f'https://errors.pydantic.dev/{version_short()}/u/' 

30PydanticErrorCodes = Literal[ 

31 'class-not-fully-defined', 

32 'custom-json-schema', 

33 'decorator-missing-field', 

34 'discriminator-no-field', 

35 'discriminator-alias-type', 

36 'discriminator-needs-literal', 

37 'discriminator-alias', 

38 'discriminator-validator', 

39 'callable-discriminator-no-tag', 

40 'typed-dict-version', 

41 'model-field-overridden', 

42 'model-field-missing-annotation', 

43 'config-both', 

44 'removed-kwargs', 

45 'circular-reference-schema', 

46 'invalid-for-json-schema', 

47 'json-schema-already-used', 

48 'base-model-instantiated', 

49 'undefined-annotation', 

50 'schema-for-unknown-type', 

51 'import-error', 

52 'create-model-field-definitions', 

53 'validator-no-fields', 

54 'validator-invalid-fields', 

55 'validator-instance-method', 

56 'validator-input-type', 

57 'root-validator-pre-skip', 

58 'model-serializer-instance-method', 

59 'validator-field-config-info', 

60 'validator-v1-signature', 

61 'validator-signature', 

62 'field-serializer-signature', 

63 'model-serializer-signature', 

64 'multiple-field-serializers', 

65 'invalid-annotated-type', 

66 'type-adapter-config-unused', 

67 'root-model-extra', 

68 'unevaluable-type-annotation', 

69 'dataclass-init-false-extra-allow', 

70 'clashing-init-and-init-var', 

71 'model-config-invalid-field-name', 

72 'with-config-on-model', 

73 'dataclass-on-model', 

74 'validate-call-type', 

75 'unpack-typed-dict', 

76 'overlapping-unpack-typed-dict', 

77 'invalid-self-type', 

78 'validate-by-alias-and-name-false', 

79] 

80 

81 

82class PydanticErrorMixin: 

83 """A mixin class for common functionality shared by all Pydantic-specific errors. 

84 

85 Attributes: 

86 message: A message describing the error. 

87 code: An optional error code from PydanticErrorCodes enum. 

88 """ 

89 

90 def __init__(self, message: str, *, code: PydanticErrorCodes | None) -> None: 

91 self.message = message 

92 self.code = code 

93 

94 def __str__(self) -> str: 

95 if self.code is None: 

96 return self.message 

97 else: 

98 return f'{self.message}\n\nFor further information visit {DEV_ERROR_DOCS_URL}{self.code}' 

99 

100 

101class PydanticUserError(PydanticErrorMixin, TypeError): 

102 """An error raised due to incorrect use of Pydantic.""" 

103 

104 

105class PydanticUndefinedAnnotation(PydanticErrorMixin, NameError): 

106 """A subclass of `NameError` raised when handling undefined annotations during `CoreSchema` generation. 

107 

108 Attributes: 

109 name: Name of the error. 

110 message: Description of the error. 

111 """ 

112 

113 def __init__(self, name: str, message: str) -> None: 

114 self.name = name 

115 super().__init__(message=message, code='undefined-annotation') 

116 

117 @classmethod 

118 def from_name_error(cls, name_error: NameError) -> Self: 

119 """Convert a `NameError` to a `PydanticUndefinedAnnotation` error. 

120 

121 Args: 

122 name_error: `NameError` to be converted. 

123 

124 Returns: 

125 Converted `PydanticUndefinedAnnotation` error. 

126 """ 

127 try: 

128 name = name_error.name # type: ignore # python > 3.10 

129 except AttributeError: 

130 name = re.search(r".*'(.+?)'", str(name_error)).group(1) # type: ignore[union-attr] 

131 return cls(name=name, message=str(name_error)) 

132 

133 

134class PydanticImportError(PydanticErrorMixin, ImportError): 

135 """An error raised when an import fails due to module changes between V1 and V2. 

136 

137 Attributes: 

138 message: Description of the error. 

139 """ 

140 

141 def __init__(self, message: str) -> None: 

142 super().__init__(message, code='import-error') 

143 

144 

145class PydanticSchemaGenerationError(PydanticUserError): 

146 """An error raised during failures to generate a `CoreSchema` for some type. 

147 

148 Attributes: 

149 message: Description of the error. 

150 """ 

151 

152 def __init__(self, message: str) -> None: 

153 super().__init__(message, code='schema-for-unknown-type') 

154 

155 

156class PydanticInvalidForJsonSchema(PydanticUserError): 

157 """An error raised during failures to generate a JSON schema for some `CoreSchema`. 

158 

159 Attributes: 

160 message: Description of the error. 

161 """ 

162 

163 def __init__(self, message: str) -> None: 

164 super().__init__(message, code='invalid-for-json-schema') 

165 

166 

167class PydanticForbiddenQualifier(PydanticUserError): 

168 """An error raised if a forbidden type qualifier is found in a type annotation.""" 

169 

170 _qualifier_repr_map: ClassVar[dict[Qualifier, str]] = { 

171 'required': 'typing.Required', 

172 'not_required': 'typing.NotRequired', 

173 'read_only': 'typing.ReadOnly', 

174 'class_var': 'typing.ClassVar', 

175 'init_var': 'dataclasses.InitVar', 

176 'final': 'typing.Final', 

177 } 

178 

179 def __init__(self, qualifier: Qualifier, annotation: Any) -> None: 

180 super().__init__( 

181 message=( 

182 f'The annotation {_repr.display_as_type(annotation)!r} contains the {self._qualifier_repr_map[qualifier]!r} ' 

183 f'type qualifier, which is invalid in the context it is defined.' 

184 ), 

185 code=None, 

186 ) 

187 

188 

189__getattr__ = getattr_migration(__name__)