fastapi 0.118.3__py3-none-any.whl → 0.119.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fastapi might be problematic. Click here for more details.
- fastapi/__init__.py +1 -1
- fastapi/_compat/__init__.py +50 -0
- fastapi/_compat/main.py +362 -0
- fastapi/_compat/may_v1.py +123 -0
- fastapi/_compat/model_field.py +53 -0
- fastapi/_compat/shared.py +211 -0
- fastapi/_compat/v1.py +312 -0
- fastapi/_compat/v2.py +459 -0
- fastapi/applications.py +2 -2
- fastapi/datastructures.py +6 -7
- fastapi/dependencies/utils.py +75 -35
- fastapi/encoders.py +11 -4
- fastapi/openapi/utils.py +5 -18
- fastapi/routing.py +4 -2
- fastapi/temp_pydantic_v1_params.py +724 -0
- fastapi/utils.py +69 -36
- {fastapi-0.118.3.dist-info → fastapi-0.119.1.dist-info}/METADATA +4 -4
- {fastapi-0.118.3.dist-info → fastapi-0.119.1.dist-info}/RECORD +21 -14
- fastapi/_compat.py +0 -680
- {fastapi-0.118.3.dist-info → fastapi-0.119.1.dist-info}/WHEEL +0 -0
- {fastapi-0.118.3.dist-info → fastapi-0.119.1.dist-info}/entry_points.txt +0 -0
- {fastapi-0.118.3.dist-info → fastapi-0.119.1.dist-info}/licenses/LICENSE +0 -0
fastapi/__init__.py
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from .main import BaseConfig as BaseConfig
|
|
2
|
+
from .main import PydanticSchemaGenerationError as PydanticSchemaGenerationError
|
|
3
|
+
from .main import RequiredParam as RequiredParam
|
|
4
|
+
from .main import Undefined as Undefined
|
|
5
|
+
from .main import UndefinedType as UndefinedType
|
|
6
|
+
from .main import Url as Url
|
|
7
|
+
from .main import Validator as Validator
|
|
8
|
+
from .main import _get_model_config as _get_model_config
|
|
9
|
+
from .main import _is_error_wrapper as _is_error_wrapper
|
|
10
|
+
from .main import _is_model_class as _is_model_class
|
|
11
|
+
from .main import _is_model_field as _is_model_field
|
|
12
|
+
from .main import _is_undefined as _is_undefined
|
|
13
|
+
from .main import _model_dump as _model_dump
|
|
14
|
+
from .main import _model_rebuild as _model_rebuild
|
|
15
|
+
from .main import copy_field_info as copy_field_info
|
|
16
|
+
from .main import create_body_model as create_body_model
|
|
17
|
+
from .main import evaluate_forwardref as evaluate_forwardref
|
|
18
|
+
from .main import get_annotation_from_field_info as get_annotation_from_field_info
|
|
19
|
+
from .main import get_cached_model_fields as get_cached_model_fields
|
|
20
|
+
from .main import get_compat_model_name_map as get_compat_model_name_map
|
|
21
|
+
from .main import get_definitions as get_definitions
|
|
22
|
+
from .main import get_missing_field_error as get_missing_field_error
|
|
23
|
+
from .main import get_schema_from_model_field as get_schema_from_model_field
|
|
24
|
+
from .main import is_bytes_field as is_bytes_field
|
|
25
|
+
from .main import is_bytes_sequence_field as is_bytes_sequence_field
|
|
26
|
+
from .main import is_scalar_field as is_scalar_field
|
|
27
|
+
from .main import is_scalar_sequence_field as is_scalar_sequence_field
|
|
28
|
+
from .main import is_sequence_field as is_sequence_field
|
|
29
|
+
from .main import serialize_sequence_value as serialize_sequence_value
|
|
30
|
+
from .main import (
|
|
31
|
+
with_info_plain_validator_function as with_info_plain_validator_function,
|
|
32
|
+
)
|
|
33
|
+
from .may_v1 import CoreSchema as CoreSchema
|
|
34
|
+
from .may_v1 import GetJsonSchemaHandler as GetJsonSchemaHandler
|
|
35
|
+
from .may_v1 import JsonSchemaValue as JsonSchemaValue
|
|
36
|
+
from .may_v1 import _normalize_errors as _normalize_errors
|
|
37
|
+
from .model_field import ModelField as ModelField
|
|
38
|
+
from .shared import PYDANTIC_V2 as PYDANTIC_V2
|
|
39
|
+
from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE
|
|
40
|
+
from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1
|
|
41
|
+
from .shared import field_annotation_is_scalar as field_annotation_is_scalar
|
|
42
|
+
from .shared import (
|
|
43
|
+
is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation,
|
|
44
|
+
)
|
|
45
|
+
from .shared import (
|
|
46
|
+
is_uploadfile_sequence_annotation as is_uploadfile_sequence_annotation,
|
|
47
|
+
)
|
|
48
|
+
from .shared import lenient_issubclass as lenient_issubclass
|
|
49
|
+
from .shared import sequence_types as sequence_types
|
|
50
|
+
from .shared import value_is_sequence as value_is_sequence
|
fastapi/_compat/main.py
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from functools import lru_cache
|
|
3
|
+
from typing import (
|
|
4
|
+
Any,
|
|
5
|
+
Dict,
|
|
6
|
+
List,
|
|
7
|
+
Sequence,
|
|
8
|
+
Tuple,
|
|
9
|
+
Type,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from fastapi._compat import may_v1
|
|
13
|
+
from fastapi._compat.shared import PYDANTIC_V2, lenient_issubclass
|
|
14
|
+
from fastapi.types import ModelNameMap
|
|
15
|
+
from pydantic import BaseModel
|
|
16
|
+
from typing_extensions import Literal
|
|
17
|
+
|
|
18
|
+
from .model_field import ModelField
|
|
19
|
+
|
|
20
|
+
if PYDANTIC_V2:
|
|
21
|
+
from .v2 import BaseConfig as BaseConfig
|
|
22
|
+
from .v2 import FieldInfo as FieldInfo
|
|
23
|
+
from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError
|
|
24
|
+
from .v2 import RequiredParam as RequiredParam
|
|
25
|
+
from .v2 import Undefined as Undefined
|
|
26
|
+
from .v2 import UndefinedType as UndefinedType
|
|
27
|
+
from .v2 import Url as Url
|
|
28
|
+
from .v2 import Validator as Validator
|
|
29
|
+
from .v2 import evaluate_forwardref as evaluate_forwardref
|
|
30
|
+
from .v2 import get_missing_field_error as get_missing_field_error
|
|
31
|
+
from .v2 import (
|
|
32
|
+
with_info_plain_validator_function as with_info_plain_validator_function,
|
|
33
|
+
)
|
|
34
|
+
else:
|
|
35
|
+
from .v1 import BaseConfig as BaseConfig # type: ignore[assignment]
|
|
36
|
+
from .v1 import FieldInfo as FieldInfo
|
|
37
|
+
from .v1 import ( # type: ignore[assignment]
|
|
38
|
+
PydanticSchemaGenerationError as PydanticSchemaGenerationError,
|
|
39
|
+
)
|
|
40
|
+
from .v1 import RequiredParam as RequiredParam
|
|
41
|
+
from .v1 import Undefined as Undefined
|
|
42
|
+
from .v1 import UndefinedType as UndefinedType
|
|
43
|
+
from .v1 import Url as Url # type: ignore[assignment]
|
|
44
|
+
from .v1 import Validator as Validator
|
|
45
|
+
from .v1 import evaluate_forwardref as evaluate_forwardref
|
|
46
|
+
from .v1 import get_missing_field_error as get_missing_field_error
|
|
47
|
+
from .v1 import ( # type: ignore[assignment]
|
|
48
|
+
with_info_plain_validator_function as with_info_plain_validator_function,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@lru_cache
|
|
53
|
+
def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
|
|
54
|
+
if lenient_issubclass(model, may_v1.BaseModel):
|
|
55
|
+
from fastapi._compat import v1
|
|
56
|
+
|
|
57
|
+
return v1.get_model_fields(model)
|
|
58
|
+
else:
|
|
59
|
+
from . import v2
|
|
60
|
+
|
|
61
|
+
return v2.get_model_fields(model) # type: ignore[return-value]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _is_undefined(value: object) -> bool:
|
|
65
|
+
if isinstance(value, may_v1.UndefinedType):
|
|
66
|
+
return True
|
|
67
|
+
elif PYDANTIC_V2:
|
|
68
|
+
from . import v2
|
|
69
|
+
|
|
70
|
+
return isinstance(value, v2.UndefinedType)
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _get_model_config(model: BaseModel) -> Any:
|
|
75
|
+
if isinstance(model, may_v1.BaseModel):
|
|
76
|
+
from fastapi._compat import v1
|
|
77
|
+
|
|
78
|
+
return v1._get_model_config(model)
|
|
79
|
+
elif PYDANTIC_V2:
|
|
80
|
+
from . import v2
|
|
81
|
+
|
|
82
|
+
return v2._get_model_config(model)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _model_dump(
|
|
86
|
+
model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any
|
|
87
|
+
) -> Any:
|
|
88
|
+
if isinstance(model, may_v1.BaseModel):
|
|
89
|
+
from fastapi._compat import v1
|
|
90
|
+
|
|
91
|
+
return v1._model_dump(model, mode=mode, **kwargs)
|
|
92
|
+
elif PYDANTIC_V2:
|
|
93
|
+
from . import v2
|
|
94
|
+
|
|
95
|
+
return v2._model_dump(model, mode=mode, **kwargs)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _is_error_wrapper(exc: Exception) -> bool:
|
|
99
|
+
if isinstance(exc, may_v1.ErrorWrapper):
|
|
100
|
+
return True
|
|
101
|
+
elif PYDANTIC_V2:
|
|
102
|
+
from . import v2
|
|
103
|
+
|
|
104
|
+
return isinstance(exc, v2.ErrorWrapper)
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
|
|
109
|
+
if isinstance(field_info, may_v1.FieldInfo):
|
|
110
|
+
from fastapi._compat import v1
|
|
111
|
+
|
|
112
|
+
return v1.copy_field_info(field_info=field_info, annotation=annotation)
|
|
113
|
+
else:
|
|
114
|
+
assert PYDANTIC_V2
|
|
115
|
+
from . import v2
|
|
116
|
+
|
|
117
|
+
return v2.copy_field_info(field_info=field_info, annotation=annotation)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def create_body_model(
|
|
121
|
+
*, fields: Sequence[ModelField], model_name: str
|
|
122
|
+
) -> Type[BaseModel]:
|
|
123
|
+
if fields and isinstance(fields[0], may_v1.ModelField):
|
|
124
|
+
from fastapi._compat import v1
|
|
125
|
+
|
|
126
|
+
return v1.create_body_model(fields=fields, model_name=model_name)
|
|
127
|
+
else:
|
|
128
|
+
assert PYDANTIC_V2
|
|
129
|
+
from . import v2
|
|
130
|
+
|
|
131
|
+
return v2.create_body_model(fields=fields, model_name=model_name) # type: ignore[arg-type]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def get_annotation_from_field_info(
|
|
135
|
+
annotation: Any, field_info: FieldInfo, field_name: str
|
|
136
|
+
) -> Any:
|
|
137
|
+
if isinstance(field_info, may_v1.FieldInfo):
|
|
138
|
+
from fastapi._compat import v1
|
|
139
|
+
|
|
140
|
+
return v1.get_annotation_from_field_info(
|
|
141
|
+
annotation=annotation, field_info=field_info, field_name=field_name
|
|
142
|
+
)
|
|
143
|
+
else:
|
|
144
|
+
assert PYDANTIC_V2
|
|
145
|
+
from . import v2
|
|
146
|
+
|
|
147
|
+
return v2.get_annotation_from_field_info(
|
|
148
|
+
annotation=annotation, field_info=field_info, field_name=field_name
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def is_bytes_field(field: ModelField) -> bool:
|
|
153
|
+
if isinstance(field, may_v1.ModelField):
|
|
154
|
+
from fastapi._compat import v1
|
|
155
|
+
|
|
156
|
+
return v1.is_bytes_field(field)
|
|
157
|
+
else:
|
|
158
|
+
assert PYDANTIC_V2
|
|
159
|
+
from . import v2
|
|
160
|
+
|
|
161
|
+
return v2.is_bytes_field(field) # type: ignore[arg-type]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def is_bytes_sequence_field(field: ModelField) -> bool:
|
|
165
|
+
if isinstance(field, may_v1.ModelField):
|
|
166
|
+
from fastapi._compat import v1
|
|
167
|
+
|
|
168
|
+
return v1.is_bytes_sequence_field(field)
|
|
169
|
+
else:
|
|
170
|
+
assert PYDANTIC_V2
|
|
171
|
+
from . import v2
|
|
172
|
+
|
|
173
|
+
return v2.is_bytes_sequence_field(field) # type: ignore[arg-type]
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def is_scalar_field(field: ModelField) -> bool:
|
|
177
|
+
if isinstance(field, may_v1.ModelField):
|
|
178
|
+
from fastapi._compat import v1
|
|
179
|
+
|
|
180
|
+
return v1.is_scalar_field(field)
|
|
181
|
+
else:
|
|
182
|
+
assert PYDANTIC_V2
|
|
183
|
+
from . import v2
|
|
184
|
+
|
|
185
|
+
return v2.is_scalar_field(field) # type: ignore[arg-type]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def is_scalar_sequence_field(field: ModelField) -> bool:
|
|
189
|
+
if isinstance(field, may_v1.ModelField):
|
|
190
|
+
from fastapi._compat import v1
|
|
191
|
+
|
|
192
|
+
return v1.is_scalar_sequence_field(field)
|
|
193
|
+
else:
|
|
194
|
+
assert PYDANTIC_V2
|
|
195
|
+
from . import v2
|
|
196
|
+
|
|
197
|
+
return v2.is_scalar_sequence_field(field) # type: ignore[arg-type]
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def is_sequence_field(field: ModelField) -> bool:
|
|
201
|
+
if isinstance(field, may_v1.ModelField):
|
|
202
|
+
from fastapi._compat import v1
|
|
203
|
+
|
|
204
|
+
return v1.is_sequence_field(field)
|
|
205
|
+
else:
|
|
206
|
+
assert PYDANTIC_V2
|
|
207
|
+
from . import v2
|
|
208
|
+
|
|
209
|
+
return v2.is_sequence_field(field) # type: ignore[arg-type]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
|
|
213
|
+
if isinstance(field, may_v1.ModelField):
|
|
214
|
+
from fastapi._compat import v1
|
|
215
|
+
|
|
216
|
+
return v1.serialize_sequence_value(field=field, value=value)
|
|
217
|
+
else:
|
|
218
|
+
assert PYDANTIC_V2
|
|
219
|
+
from . import v2
|
|
220
|
+
|
|
221
|
+
return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type]
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _model_rebuild(model: Type[BaseModel]) -> None:
|
|
225
|
+
if lenient_issubclass(model, may_v1.BaseModel):
|
|
226
|
+
from fastapi._compat import v1
|
|
227
|
+
|
|
228
|
+
v1._model_rebuild(model)
|
|
229
|
+
elif PYDANTIC_V2:
|
|
230
|
+
from . import v2
|
|
231
|
+
|
|
232
|
+
v2._model_rebuild(model)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
|
|
236
|
+
v1_model_fields = [
|
|
237
|
+
field for field in fields if isinstance(field, may_v1.ModelField)
|
|
238
|
+
]
|
|
239
|
+
if v1_model_fields:
|
|
240
|
+
from fastapi._compat import v1
|
|
241
|
+
|
|
242
|
+
v1_flat_models = v1.get_flat_models_from_fields(
|
|
243
|
+
v1_model_fields, known_models=set()
|
|
244
|
+
)
|
|
245
|
+
all_flat_models = v1_flat_models
|
|
246
|
+
else:
|
|
247
|
+
all_flat_models = set()
|
|
248
|
+
if PYDANTIC_V2:
|
|
249
|
+
from . import v2
|
|
250
|
+
|
|
251
|
+
v2_model_fields = [
|
|
252
|
+
field for field in fields if isinstance(field, v2.ModelField)
|
|
253
|
+
]
|
|
254
|
+
v2_flat_models = v2.get_flat_models_from_fields(
|
|
255
|
+
v2_model_fields, known_models=set()
|
|
256
|
+
)
|
|
257
|
+
all_flat_models = all_flat_models.union(v2_flat_models)
|
|
258
|
+
|
|
259
|
+
model_name_map = v2.get_model_name_map(all_flat_models)
|
|
260
|
+
return model_name_map
|
|
261
|
+
from fastapi._compat import v1
|
|
262
|
+
|
|
263
|
+
model_name_map = v1.get_model_name_map(all_flat_models)
|
|
264
|
+
return model_name_map
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def get_definitions(
|
|
268
|
+
*,
|
|
269
|
+
fields: List[ModelField],
|
|
270
|
+
model_name_map: ModelNameMap,
|
|
271
|
+
separate_input_output_schemas: bool = True,
|
|
272
|
+
) -> Tuple[
|
|
273
|
+
Dict[
|
|
274
|
+
Tuple[ModelField, Literal["validation", "serialization"]],
|
|
275
|
+
may_v1.JsonSchemaValue,
|
|
276
|
+
],
|
|
277
|
+
Dict[str, Dict[str, Any]],
|
|
278
|
+
]:
|
|
279
|
+
if sys.version_info < (3, 14):
|
|
280
|
+
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
|
|
281
|
+
v1_field_maps, v1_definitions = may_v1.get_definitions(
|
|
282
|
+
fields=v1_fields,
|
|
283
|
+
model_name_map=model_name_map,
|
|
284
|
+
separate_input_output_schemas=separate_input_output_schemas,
|
|
285
|
+
)
|
|
286
|
+
if not PYDANTIC_V2:
|
|
287
|
+
return v1_field_maps, v1_definitions
|
|
288
|
+
else:
|
|
289
|
+
from . import v2
|
|
290
|
+
|
|
291
|
+
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)]
|
|
292
|
+
v2_field_maps, v2_definitions = v2.get_definitions(
|
|
293
|
+
fields=v2_fields,
|
|
294
|
+
model_name_map=model_name_map,
|
|
295
|
+
separate_input_output_schemas=separate_input_output_schemas,
|
|
296
|
+
)
|
|
297
|
+
all_definitions = {**v1_definitions, **v2_definitions}
|
|
298
|
+
all_field_maps = {**v1_field_maps, **v2_field_maps}
|
|
299
|
+
return all_field_maps, all_definitions
|
|
300
|
+
|
|
301
|
+
# Pydantic v1 is not supported since Python 3.14
|
|
302
|
+
else:
|
|
303
|
+
from . import v2
|
|
304
|
+
|
|
305
|
+
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)]
|
|
306
|
+
v2_field_maps, v2_definitions = v2.get_definitions(
|
|
307
|
+
fields=v2_fields,
|
|
308
|
+
model_name_map=model_name_map,
|
|
309
|
+
separate_input_output_schemas=separate_input_output_schemas,
|
|
310
|
+
)
|
|
311
|
+
return v2_field_maps, v2_definitions
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def get_schema_from_model_field(
|
|
315
|
+
*,
|
|
316
|
+
field: ModelField,
|
|
317
|
+
model_name_map: ModelNameMap,
|
|
318
|
+
field_mapping: Dict[
|
|
319
|
+
Tuple[ModelField, Literal["validation", "serialization"]],
|
|
320
|
+
may_v1.JsonSchemaValue,
|
|
321
|
+
],
|
|
322
|
+
separate_input_output_schemas: bool = True,
|
|
323
|
+
) -> Dict[str, Any]:
|
|
324
|
+
if isinstance(field, may_v1.ModelField):
|
|
325
|
+
from fastapi._compat import v1
|
|
326
|
+
|
|
327
|
+
return v1.get_schema_from_model_field(
|
|
328
|
+
field=field,
|
|
329
|
+
model_name_map=model_name_map,
|
|
330
|
+
field_mapping=field_mapping,
|
|
331
|
+
separate_input_output_schemas=separate_input_output_schemas,
|
|
332
|
+
)
|
|
333
|
+
else:
|
|
334
|
+
assert PYDANTIC_V2
|
|
335
|
+
from . import v2
|
|
336
|
+
|
|
337
|
+
return v2.get_schema_from_model_field(
|
|
338
|
+
field=field, # type: ignore[arg-type]
|
|
339
|
+
model_name_map=model_name_map,
|
|
340
|
+
field_mapping=field_mapping, # type: ignore[arg-type]
|
|
341
|
+
separate_input_output_schemas=separate_input_output_schemas,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _is_model_field(value: Any) -> bool:
|
|
346
|
+
if isinstance(value, may_v1.ModelField):
|
|
347
|
+
return True
|
|
348
|
+
elif PYDANTIC_V2:
|
|
349
|
+
from . import v2
|
|
350
|
+
|
|
351
|
+
return isinstance(value, v2.ModelField)
|
|
352
|
+
return False
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _is_model_class(value: Any) -> bool:
|
|
356
|
+
if lenient_issubclass(value, may_v1.BaseModel):
|
|
357
|
+
return True
|
|
358
|
+
elif PYDANTIC_V2:
|
|
359
|
+
from . import v2
|
|
360
|
+
|
|
361
|
+
return lenient_issubclass(value, v2.BaseModel) # type: ignore[attr-defined]
|
|
362
|
+
return False
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import Any, Dict, List, Literal, Sequence, Tuple, Type, Union
|
|
3
|
+
|
|
4
|
+
from fastapi.types import ModelNameMap
|
|
5
|
+
|
|
6
|
+
if sys.version_info >= (3, 14):
|
|
7
|
+
|
|
8
|
+
class AnyUrl:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
class BaseConfig:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
class BaseModel:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
class Color:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
class CoreSchema:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
class ErrorWrapper:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
class FieldInfo:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
class GetJsonSchemaHandler:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
class JsonSchemaValue:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
class ModelField:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
class NameEmail:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
class RequiredParam:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
class SecretBytes:
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
class SecretStr:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
class Undefined:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
class UndefinedType:
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
class Url:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
from .v2 import ValidationError, create_model
|
|
60
|
+
|
|
61
|
+
def get_definitions(
|
|
62
|
+
*,
|
|
63
|
+
fields: List[ModelField],
|
|
64
|
+
model_name_map: ModelNameMap,
|
|
65
|
+
separate_input_output_schemas: bool = True,
|
|
66
|
+
) -> Tuple[
|
|
67
|
+
Dict[
|
|
68
|
+
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
|
69
|
+
],
|
|
70
|
+
Dict[str, Dict[str, Any]],
|
|
71
|
+
]:
|
|
72
|
+
return {}, {} # pragma: no cover
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
from .v1 import AnyUrl as AnyUrl
|
|
77
|
+
from .v1 import BaseConfig as BaseConfig
|
|
78
|
+
from .v1 import BaseModel as BaseModel
|
|
79
|
+
from .v1 import Color as Color
|
|
80
|
+
from .v1 import CoreSchema as CoreSchema
|
|
81
|
+
from .v1 import ErrorWrapper as ErrorWrapper
|
|
82
|
+
from .v1 import FieldInfo as FieldInfo
|
|
83
|
+
from .v1 import GetJsonSchemaHandler as GetJsonSchemaHandler
|
|
84
|
+
from .v1 import JsonSchemaValue as JsonSchemaValue
|
|
85
|
+
from .v1 import ModelField as ModelField
|
|
86
|
+
from .v1 import NameEmail as NameEmail
|
|
87
|
+
from .v1 import RequiredParam as RequiredParam
|
|
88
|
+
from .v1 import SecretBytes as SecretBytes
|
|
89
|
+
from .v1 import SecretStr as SecretStr
|
|
90
|
+
from .v1 import Undefined as Undefined
|
|
91
|
+
from .v1 import UndefinedType as UndefinedType
|
|
92
|
+
from .v1 import Url as Url
|
|
93
|
+
from .v1 import ValidationError, create_model
|
|
94
|
+
from .v1 import get_definitions as get_definitions
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
RequestErrorModel: Type[BaseModel] = create_model("Request")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
|
|
101
|
+
use_errors: List[Any] = []
|
|
102
|
+
for error in errors:
|
|
103
|
+
if isinstance(error, ErrorWrapper):
|
|
104
|
+
new_errors = ValidationError( # type: ignore[call-arg]
|
|
105
|
+
errors=[error], model=RequestErrorModel
|
|
106
|
+
).errors()
|
|
107
|
+
use_errors.extend(new_errors)
|
|
108
|
+
elif isinstance(error, list):
|
|
109
|
+
use_errors.extend(_normalize_errors(error))
|
|
110
|
+
else:
|
|
111
|
+
use_errors.append(error)
|
|
112
|
+
return use_errors
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _regenerate_error_with_loc(
|
|
116
|
+
*, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...]
|
|
117
|
+
) -> List[Dict[str, Any]]:
|
|
118
|
+
updated_loc_errors: List[Any] = [
|
|
119
|
+
{**err, "loc": loc_prefix + err.get("loc", ())}
|
|
120
|
+
for err in _normalize_errors(errors)
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
return updated_loc_errors
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Dict,
|
|
4
|
+
List,
|
|
5
|
+
Tuple,
|
|
6
|
+
Union,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from fastapi.types import IncEx
|
|
10
|
+
from pydantic.fields import FieldInfo
|
|
11
|
+
from typing_extensions import Literal, Protocol
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ModelField(Protocol):
|
|
15
|
+
field_info: "FieldInfo"
|
|
16
|
+
name: str
|
|
17
|
+
mode: Literal["validation", "serialization"] = "validation"
|
|
18
|
+
_version: Literal["v1", "v2"] = "v1"
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def alias(self) -> str: ...
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def required(self) -> bool: ...
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def default(self) -> Any: ...
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def type_(self) -> Any: ...
|
|
31
|
+
|
|
32
|
+
def get_default(self) -> Any: ...
|
|
33
|
+
|
|
34
|
+
def validate(
|
|
35
|
+
self,
|
|
36
|
+
value: Any,
|
|
37
|
+
values: Dict[str, Any] = {}, # noqa: B006
|
|
38
|
+
*,
|
|
39
|
+
loc: Tuple[Union[int, str], ...] = (),
|
|
40
|
+
) -> Tuple[Any, Union[List[Dict[str, Any]], None]]: ...
|
|
41
|
+
|
|
42
|
+
def serialize(
|
|
43
|
+
self,
|
|
44
|
+
value: Any,
|
|
45
|
+
*,
|
|
46
|
+
mode: Literal["json", "python"] = "json",
|
|
47
|
+
include: Union[IncEx, None] = None,
|
|
48
|
+
exclude: Union[IncEx, None] = None,
|
|
49
|
+
by_alias: bool = True,
|
|
50
|
+
exclude_unset: bool = False,
|
|
51
|
+
exclude_defaults: bool = False,
|
|
52
|
+
exclude_none: bool = False,
|
|
53
|
+
) -> Any: ...
|