fastapi 0.96.1__py3-none-any.whl → 0.100.0b1__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.py +597 -0
- fastapi/applications.py +51 -27
- fastapi/datastructures.py +31 -4
- fastapi/dependencies/models.py +1 -1
- fastapi/dependencies/utils.py +76 -120
- fastapi/encoders.py +91 -13
- fastapi/exception_handlers.py +11 -2
- fastapi/exceptions.py +20 -8
- fastapi/middleware/asyncexitstack.py +13 -16
- fastapi/openapi/constants.py +1 -0
- fastapi/openapi/models.py +203 -57
- fastapi/openapi/utils.py +65 -44
- fastapi/param_functions.py +15 -1
- fastapi/params.py +57 -8
- fastapi/routing.py +126 -61
- fastapi/security/api_key.py +9 -3
- fastapi/security/oauth2.py +32 -21
- fastapi/types.py +9 -1
- fastapi/utils.py +62 -60
- {fastapi-0.96.1.dist-info → fastapi-0.100.0b1.dist-info}/METADATA +3 -37
- fastapi-0.100.0b1.dist-info/RECORD +48 -0
- fastapi-0.96.1.dist-info/RECORD +0 -47
- {fastapi-0.96.1.dist-info → fastapi-0.100.0b1.dist-info}/WHEEL +0 -0
- {fastapi-0.96.1.dist-info → fastapi-0.100.0b1.dist-info}/licenses/LICENSE +0 -0
fastapi/openapi/utils.py
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import http.client
|
|
2
2
|
import inspect
|
|
3
3
|
import warnings
|
|
4
|
-
from enum import Enum
|
|
5
4
|
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
|
|
6
5
|
|
|
7
6
|
from fastapi import routing
|
|
7
|
+
from fastapi._compat import (
|
|
8
|
+
GenerateJsonSchema,
|
|
9
|
+
ModelField,
|
|
10
|
+
Undefined,
|
|
11
|
+
get_compat_model_name_map,
|
|
12
|
+
get_definitions,
|
|
13
|
+
get_schema_from_model_field,
|
|
14
|
+
lenient_issubclass,
|
|
15
|
+
)
|
|
8
16
|
from fastapi.datastructures import DefaultPlaceholder
|
|
9
17
|
from fastapi.dependencies.models import Dependant
|
|
10
18
|
from fastapi.dependencies.utils import get_flat_dependant, get_flat_params
|
|
11
19
|
from fastapi.encoders import jsonable_encoder
|
|
12
|
-
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX
|
|
20
|
+
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX, REF_TEMPLATE
|
|
13
21
|
from fastapi.openapi.models import OpenAPI
|
|
14
22
|
from fastapi.params import Body, Param
|
|
15
23
|
from fastapi.responses import Response
|
|
24
|
+
from fastapi.types import ModelNameMap
|
|
16
25
|
from fastapi.utils import (
|
|
17
26
|
deep_dict_update,
|
|
18
27
|
generate_operation_id_for_path,
|
|
19
|
-
get_model_definitions,
|
|
20
28
|
is_body_allowed_for_status_code,
|
|
21
29
|
)
|
|
22
|
-
from pydantic import BaseModel
|
|
23
|
-
from pydantic.fields import ModelField, Undefined
|
|
24
|
-
from pydantic.schema import (
|
|
25
|
-
field_schema,
|
|
26
|
-
get_flat_models_from_fields,
|
|
27
|
-
get_model_name_map,
|
|
28
|
-
)
|
|
29
|
-
from pydantic.utils import lenient_issubclass
|
|
30
30
|
from starlette.responses import JSONResponse
|
|
31
31
|
from starlette.routing import BaseRoute
|
|
32
32
|
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
|
|
@@ -88,7 +88,8 @@ def get_openapi_security_definitions(
|
|
|
88
88
|
def get_openapi_operation_parameters(
|
|
89
89
|
*,
|
|
90
90
|
all_route_params: Sequence[ModelField],
|
|
91
|
-
|
|
91
|
+
schema_generator: GenerateJsonSchema,
|
|
92
|
+
model_name_map: ModelNameMap,
|
|
92
93
|
) -> List[Dict[str, Any]]:
|
|
93
94
|
parameters = []
|
|
94
95
|
for param in all_route_params:
|
|
@@ -96,13 +97,16 @@ def get_openapi_operation_parameters(
|
|
|
96
97
|
field_info = cast(Param, field_info)
|
|
97
98
|
if not field_info.include_in_schema:
|
|
98
99
|
continue
|
|
100
|
+
param_schema = get_schema_from_model_field(
|
|
101
|
+
field=param,
|
|
102
|
+
schema_generator=schema_generator,
|
|
103
|
+
model_name_map=model_name_map,
|
|
104
|
+
)
|
|
99
105
|
parameter = {
|
|
100
106
|
"name": param.alias,
|
|
101
107
|
"in": field_info.in_.value,
|
|
102
108
|
"required": param.required,
|
|
103
|
-
"schema":
|
|
104
|
-
param, model_name_map=model_name_map, ref_prefix=REF_PREFIX
|
|
105
|
-
)[0],
|
|
109
|
+
"schema": param_schema,
|
|
106
110
|
}
|
|
107
111
|
if field_info.description:
|
|
108
112
|
parameter["description"] = field_info.description
|
|
@@ -119,13 +123,16 @@ def get_openapi_operation_parameters(
|
|
|
119
123
|
def get_openapi_operation_request_body(
|
|
120
124
|
*,
|
|
121
125
|
body_field: Optional[ModelField],
|
|
122
|
-
|
|
126
|
+
schema_generator: GenerateJsonSchema,
|
|
127
|
+
model_name_map: ModelNameMap,
|
|
123
128
|
) -> Optional[Dict[str, Any]]:
|
|
124
129
|
if not body_field:
|
|
125
130
|
return None
|
|
126
131
|
assert isinstance(body_field, ModelField)
|
|
127
|
-
body_schema
|
|
128
|
-
body_field,
|
|
132
|
+
body_schema = get_schema_from_model_field(
|
|
133
|
+
field=body_field,
|
|
134
|
+
schema_generator=schema_generator,
|
|
135
|
+
model_name_map=model_name_map,
|
|
129
136
|
)
|
|
130
137
|
field_info = cast(Body, body_field.field_info)
|
|
131
138
|
request_media_type = field_info.media_type
|
|
@@ -181,7 +188,7 @@ def get_openapi_operation_metadata(
|
|
|
181
188
|
file_name = getattr(route.endpoint, "__globals__", {}).get("__file__")
|
|
182
189
|
if file_name:
|
|
183
190
|
message += f" at {file_name}"
|
|
184
|
-
warnings.warn(message)
|
|
191
|
+
warnings.warn(message, stacklevel=1)
|
|
185
192
|
operation_ids.add(operation_id)
|
|
186
193
|
operation["operationId"] = operation_id
|
|
187
194
|
if route.deprecated:
|
|
@@ -190,7 +197,11 @@ def get_openapi_operation_metadata(
|
|
|
190
197
|
|
|
191
198
|
|
|
192
199
|
def get_openapi_path(
|
|
193
|
-
*,
|
|
200
|
+
*,
|
|
201
|
+
route: routing.APIRoute,
|
|
202
|
+
operation_ids: Set[str],
|
|
203
|
+
schema_generator: GenerateJsonSchema,
|
|
204
|
+
model_name_map: ModelNameMap,
|
|
194
205
|
) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
|
|
195
206
|
path = {}
|
|
196
207
|
security_schemes: Dict[str, Any] = {}
|
|
@@ -218,7 +229,9 @@ def get_openapi_path(
|
|
|
218
229
|
security_schemes.update(security_definitions)
|
|
219
230
|
all_route_params = get_flat_params(route.dependant)
|
|
220
231
|
operation_parameters = get_openapi_operation_parameters(
|
|
221
|
-
all_route_params=all_route_params,
|
|
232
|
+
all_route_params=all_route_params,
|
|
233
|
+
schema_generator=schema_generator,
|
|
234
|
+
model_name_map=model_name_map,
|
|
222
235
|
)
|
|
223
236
|
parameters.extend(operation_parameters)
|
|
224
237
|
if parameters:
|
|
@@ -236,7 +249,9 @@ def get_openapi_path(
|
|
|
236
249
|
operation["parameters"] = list(all_parameters.values())
|
|
237
250
|
if method in METHODS_WITH_BODY:
|
|
238
251
|
request_body_oai = get_openapi_operation_request_body(
|
|
239
|
-
body_field=route.body_field,
|
|
252
|
+
body_field=route.body_field,
|
|
253
|
+
schema_generator=schema_generator,
|
|
254
|
+
model_name_map=model_name_map,
|
|
240
255
|
)
|
|
241
256
|
if request_body_oai:
|
|
242
257
|
operation["requestBody"] = request_body_oai
|
|
@@ -250,8 +265,9 @@ def get_openapi_path(
|
|
|
250
265
|
cb_definitions,
|
|
251
266
|
) = get_openapi_path(
|
|
252
267
|
route=callback,
|
|
253
|
-
model_name_map=model_name_map,
|
|
254
268
|
operation_ids=operation_ids,
|
|
269
|
+
schema_generator=schema_generator,
|
|
270
|
+
model_name_map=model_name_map,
|
|
255
271
|
)
|
|
256
272
|
callbacks[callback.name] = {callback.path: cb_path}
|
|
257
273
|
operation["callbacks"] = callbacks
|
|
@@ -277,10 +293,10 @@ def get_openapi_path(
|
|
|
277
293
|
response_schema = {"type": "string"}
|
|
278
294
|
if lenient_issubclass(current_response_class, JSONResponse):
|
|
279
295
|
if route.response_field:
|
|
280
|
-
response_schema
|
|
281
|
-
route.response_field,
|
|
296
|
+
response_schema = get_schema_from_model_field(
|
|
297
|
+
field=route.response_field,
|
|
298
|
+
schema_generator=schema_generator,
|
|
282
299
|
model_name_map=model_name_map,
|
|
283
|
-
ref_prefix=REF_PREFIX,
|
|
284
300
|
)
|
|
285
301
|
else:
|
|
286
302
|
response_schema = {}
|
|
@@ -309,8 +325,10 @@ def get_openapi_path(
|
|
|
309
325
|
field = route.response_fields.get(additional_status_code)
|
|
310
326
|
additional_field_schema: Optional[Dict[str, Any]] = None
|
|
311
327
|
if field:
|
|
312
|
-
additional_field_schema
|
|
313
|
-
field
|
|
328
|
+
additional_field_schema = get_schema_from_model_field(
|
|
329
|
+
field=field,
|
|
330
|
+
schema_generator=schema_generator,
|
|
331
|
+
model_name_map=model_name_map,
|
|
314
332
|
)
|
|
315
333
|
media_type = route_response_media_type or "application/json"
|
|
316
334
|
additional_schema = (
|
|
@@ -332,10 +350,8 @@ def get_openapi_path(
|
|
|
332
350
|
openapi_response["description"] = description
|
|
333
351
|
http422 = str(HTTP_422_UNPROCESSABLE_ENTITY)
|
|
334
352
|
if (all_route_params or route.body_field) and not any(
|
|
335
|
-
[
|
|
336
|
-
|
|
337
|
-
for status in [http422, "4XX", "default"]
|
|
338
|
-
]
|
|
353
|
+
status in operation["responses"]
|
|
354
|
+
for status in [http422, "4XX", "default"]
|
|
339
355
|
):
|
|
340
356
|
operation["responses"][http422] = {
|
|
341
357
|
"description": "Validation Error",
|
|
@@ -358,13 +374,13 @@ def get_openapi_path(
|
|
|
358
374
|
return path, security_schemes, definitions
|
|
359
375
|
|
|
360
376
|
|
|
361
|
-
def
|
|
377
|
+
def get_fields_from_routes(
|
|
362
378
|
routes: Sequence[BaseRoute],
|
|
363
|
-
) ->
|
|
379
|
+
) -> List[ModelField]:
|
|
364
380
|
body_fields_from_routes: List[ModelField] = []
|
|
365
381
|
responses_from_routes: List[ModelField] = []
|
|
366
382
|
request_fields_from_routes: List[ModelField] = []
|
|
367
|
-
callback_flat_models:
|
|
383
|
+
callback_flat_models: List[ModelField] = []
|
|
368
384
|
for route in routes:
|
|
369
385
|
if getattr(route, "include_in_schema", None) and isinstance(
|
|
370
386
|
route, routing.APIRoute
|
|
@@ -379,13 +395,12 @@ def get_flat_models_from_routes(
|
|
|
379
395
|
if route.response_fields:
|
|
380
396
|
responses_from_routes.extend(route.response_fields.values())
|
|
381
397
|
if route.callbacks:
|
|
382
|
-
callback_flat_models
|
|
398
|
+
callback_flat_models.extend(get_fields_from_routes(route.callbacks))
|
|
383
399
|
params = get_flat_params(route.dependant)
|
|
384
400
|
request_fields_from_routes.extend(params)
|
|
385
401
|
|
|
386
|
-
flat_models = callback_flat_models
|
|
387
|
-
body_fields_from_routes + responses_from_routes + request_fields_from_routes
|
|
388
|
-
known_models=set(),
|
|
402
|
+
flat_models = callback_flat_models + list(
|
|
403
|
+
body_fields_from_routes + responses_from_routes + request_fields_from_routes
|
|
389
404
|
)
|
|
390
405
|
return flat_models
|
|
391
406
|
|
|
@@ -418,15 +433,21 @@ def get_openapi(
|
|
|
418
433
|
components: Dict[str, Dict[str, Any]] = {}
|
|
419
434
|
paths: Dict[str, Dict[str, Any]] = {}
|
|
420
435
|
operation_ids: Set[str] = set()
|
|
421
|
-
|
|
422
|
-
model_name_map =
|
|
423
|
-
|
|
424
|
-
|
|
436
|
+
all_fields = get_fields_from_routes(routes)
|
|
437
|
+
model_name_map = get_compat_model_name_map(all_fields)
|
|
438
|
+
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
|
|
439
|
+
definitions = get_definitions(
|
|
440
|
+
fields=all_fields,
|
|
441
|
+
schema_generator=schema_generator,
|
|
442
|
+
model_name_map=model_name_map,
|
|
425
443
|
)
|
|
426
444
|
for route in routes:
|
|
427
445
|
if isinstance(route, routing.APIRoute):
|
|
428
446
|
result = get_openapi_path(
|
|
429
|
-
route=route,
|
|
447
|
+
route=route,
|
|
448
|
+
operation_ids=operation_ids,
|
|
449
|
+
schema_generator=schema_generator,
|
|
450
|
+
model_name_map=model_name_map,
|
|
430
451
|
)
|
|
431
452
|
if result:
|
|
432
453
|
path, security_schemes, path_definitions = result
|
fastapi/param_functions.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, Callable, Dict, Optional, Sequence
|
|
2
2
|
|
|
3
3
|
from fastapi import params
|
|
4
|
-
from
|
|
4
|
+
from fastapi._compat import Undefined
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def Path( # noqa: N802
|
|
@@ -16,6 +16,7 @@ def Path( # noqa: N802
|
|
|
16
16
|
le: Optional[float] = None,
|
|
17
17
|
min_length: Optional[int] = None,
|
|
18
18
|
max_length: Optional[int] = None,
|
|
19
|
+
pattern: Optional[str] = None,
|
|
19
20
|
regex: Optional[str] = None,
|
|
20
21
|
example: Any = Undefined,
|
|
21
22
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -34,6 +35,7 @@ def Path( # noqa: N802
|
|
|
34
35
|
le=le,
|
|
35
36
|
min_length=min_length,
|
|
36
37
|
max_length=max_length,
|
|
38
|
+
pattern=pattern,
|
|
37
39
|
regex=regex,
|
|
38
40
|
example=example,
|
|
39
41
|
examples=examples,
|
|
@@ -55,6 +57,7 @@ def Query( # noqa: N802
|
|
|
55
57
|
le: Optional[float] = None,
|
|
56
58
|
min_length: Optional[int] = None,
|
|
57
59
|
max_length: Optional[int] = None,
|
|
60
|
+
pattern: Optional[str] = None,
|
|
58
61
|
regex: Optional[str] = None,
|
|
59
62
|
example: Any = Undefined,
|
|
60
63
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -73,6 +76,7 @@ def Query( # noqa: N802
|
|
|
73
76
|
le=le,
|
|
74
77
|
min_length=min_length,
|
|
75
78
|
max_length=max_length,
|
|
79
|
+
pattern=pattern,
|
|
76
80
|
regex=regex,
|
|
77
81
|
example=example,
|
|
78
82
|
examples=examples,
|
|
@@ -95,6 +99,7 @@ def Header( # noqa: N802
|
|
|
95
99
|
le: Optional[float] = None,
|
|
96
100
|
min_length: Optional[int] = None,
|
|
97
101
|
max_length: Optional[int] = None,
|
|
102
|
+
pattern: Optional[str] = None,
|
|
98
103
|
regex: Optional[str] = None,
|
|
99
104
|
example: Any = Undefined,
|
|
100
105
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -114,6 +119,7 @@ def Header( # noqa: N802
|
|
|
114
119
|
le=le,
|
|
115
120
|
min_length=min_length,
|
|
116
121
|
max_length=max_length,
|
|
122
|
+
pattern=pattern,
|
|
117
123
|
regex=regex,
|
|
118
124
|
example=example,
|
|
119
125
|
examples=examples,
|
|
@@ -135,6 +141,7 @@ def Cookie( # noqa: N802
|
|
|
135
141
|
le: Optional[float] = None,
|
|
136
142
|
min_length: Optional[int] = None,
|
|
137
143
|
max_length: Optional[int] = None,
|
|
144
|
+
pattern: Optional[str] = None,
|
|
138
145
|
regex: Optional[str] = None,
|
|
139
146
|
example: Any = Undefined,
|
|
140
147
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -153,6 +160,7 @@ def Cookie( # noqa: N802
|
|
|
153
160
|
le=le,
|
|
154
161
|
min_length=min_length,
|
|
155
162
|
max_length=max_length,
|
|
163
|
+
pattern=pattern,
|
|
156
164
|
regex=regex,
|
|
157
165
|
example=example,
|
|
158
166
|
examples=examples,
|
|
@@ -176,6 +184,7 @@ def Body( # noqa: N802
|
|
|
176
184
|
le: Optional[float] = None,
|
|
177
185
|
min_length: Optional[int] = None,
|
|
178
186
|
max_length: Optional[int] = None,
|
|
187
|
+
pattern: Optional[str] = None,
|
|
179
188
|
regex: Optional[str] = None,
|
|
180
189
|
example: Any = Undefined,
|
|
181
190
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -194,6 +203,7 @@ def Body( # noqa: N802
|
|
|
194
203
|
le=le,
|
|
195
204
|
min_length=min_length,
|
|
196
205
|
max_length=max_length,
|
|
206
|
+
pattern=pattern,
|
|
197
207
|
regex=regex,
|
|
198
208
|
example=example,
|
|
199
209
|
examples=examples,
|
|
@@ -214,6 +224,7 @@ def Form( # noqa: N802
|
|
|
214
224
|
le: Optional[float] = None,
|
|
215
225
|
min_length: Optional[int] = None,
|
|
216
226
|
max_length: Optional[int] = None,
|
|
227
|
+
pattern: Optional[str] = None,
|
|
217
228
|
regex: Optional[str] = None,
|
|
218
229
|
example: Any = Undefined,
|
|
219
230
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -231,6 +242,7 @@ def Form( # noqa: N802
|
|
|
231
242
|
le=le,
|
|
232
243
|
min_length=min_length,
|
|
233
244
|
max_length=max_length,
|
|
245
|
+
pattern=pattern,
|
|
234
246
|
regex=regex,
|
|
235
247
|
example=example,
|
|
236
248
|
examples=examples,
|
|
@@ -251,6 +263,7 @@ def File( # noqa: N802
|
|
|
251
263
|
le: Optional[float] = None,
|
|
252
264
|
min_length: Optional[int] = None,
|
|
253
265
|
max_length: Optional[int] = None,
|
|
266
|
+
pattern: Optional[str] = None,
|
|
254
267
|
regex: Optional[str] = None,
|
|
255
268
|
example: Any = Undefined,
|
|
256
269
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -268,6 +281,7 @@ def File( # noqa: N802
|
|
|
268
281
|
le=le,
|
|
269
282
|
min_length=min_length,
|
|
270
283
|
max_length=max_length,
|
|
284
|
+
pattern=pattern,
|
|
271
285
|
regex=regex,
|
|
272
286
|
example=example,
|
|
273
287
|
examples=examples,
|
fastapi/params.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Any, Callable, Dict, Optional, Sequence
|
|
2
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Type
|
|
3
3
|
|
|
4
|
-
from pydantic.fields import FieldInfo
|
|
4
|
+
from pydantic.fields import FieldInfo
|
|
5
|
+
|
|
6
|
+
from ._compat import PYDANTIC_V2, Undefined
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class ParamTypes(Enum):
|
|
@@ -18,6 +20,7 @@ class Param(FieldInfo):
|
|
|
18
20
|
self,
|
|
19
21
|
default: Any = Undefined,
|
|
20
22
|
*,
|
|
23
|
+
annotation: Optional[Type[Any]] = None,
|
|
21
24
|
alias: Optional[str] = None,
|
|
22
25
|
title: Optional[str] = None,
|
|
23
26
|
description: Optional[str] = None,
|
|
@@ -27,6 +30,7 @@ class Param(FieldInfo):
|
|
|
27
30
|
le: Optional[float] = None,
|
|
28
31
|
min_length: Optional[int] = None,
|
|
29
32
|
max_length: Optional[int] = None,
|
|
33
|
+
pattern: Optional[str] = None,
|
|
30
34
|
regex: Optional[str] = None,
|
|
31
35
|
example: Any = Undefined,
|
|
32
36
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -36,9 +40,8 @@ class Param(FieldInfo):
|
|
|
36
40
|
):
|
|
37
41
|
self.deprecated = deprecated
|
|
38
42
|
self.example = example
|
|
39
|
-
self.examples = examples
|
|
40
43
|
self.include_in_schema = include_in_schema
|
|
41
|
-
|
|
44
|
+
kwargs = dict(
|
|
42
45
|
default=default,
|
|
43
46
|
alias=alias,
|
|
44
47
|
title=title,
|
|
@@ -49,9 +52,19 @@ class Param(FieldInfo):
|
|
|
49
52
|
le=le,
|
|
50
53
|
min_length=min_length,
|
|
51
54
|
max_length=max_length,
|
|
52
|
-
regex=regex,
|
|
53
55
|
**extra,
|
|
54
56
|
)
|
|
57
|
+
if PYDANTIC_V2:
|
|
58
|
+
kwargs["annotation"] = annotation
|
|
59
|
+
kwargs["pattern"] = pattern or regex
|
|
60
|
+
else:
|
|
61
|
+
# TODO: pv2 figure out how to deprecate regex
|
|
62
|
+
kwargs["regex"] = pattern or regex
|
|
63
|
+
|
|
64
|
+
super().__init__(**kwargs)
|
|
65
|
+
# TODO: pv2 decide how to handle OpenAPI examples vs JSON Schema examples
|
|
66
|
+
# and how to deprecate OpenAPI examples
|
|
67
|
+
self.examples = examples # type: ignore[assignment]
|
|
55
68
|
|
|
56
69
|
def __repr__(self) -> str:
|
|
57
70
|
return f"{self.__class__.__name__}({self.default})"
|
|
@@ -64,6 +77,7 @@ class Path(Param):
|
|
|
64
77
|
self,
|
|
65
78
|
default: Any = ...,
|
|
66
79
|
*,
|
|
80
|
+
annotation: Optional[Type[Any]] = None,
|
|
67
81
|
alias: Optional[str] = None,
|
|
68
82
|
title: Optional[str] = None,
|
|
69
83
|
description: Optional[str] = None,
|
|
@@ -73,6 +87,7 @@ class Path(Param):
|
|
|
73
87
|
le: Optional[float] = None,
|
|
74
88
|
min_length: Optional[int] = None,
|
|
75
89
|
max_length: Optional[int] = None,
|
|
90
|
+
pattern: Optional[str] = None,
|
|
76
91
|
regex: Optional[str] = None,
|
|
77
92
|
example: Any = Undefined,
|
|
78
93
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -84,6 +99,7 @@ class Path(Param):
|
|
|
84
99
|
self.in_ = self.in_
|
|
85
100
|
super().__init__(
|
|
86
101
|
default=default,
|
|
102
|
+
annotation=annotation,
|
|
87
103
|
alias=alias,
|
|
88
104
|
title=title,
|
|
89
105
|
description=description,
|
|
@@ -93,6 +109,7 @@ class Path(Param):
|
|
|
93
109
|
le=le,
|
|
94
110
|
min_length=min_length,
|
|
95
111
|
max_length=max_length,
|
|
112
|
+
pattern=pattern,
|
|
96
113
|
regex=regex,
|
|
97
114
|
deprecated=deprecated,
|
|
98
115
|
example=example,
|
|
@@ -109,6 +126,7 @@ class Query(Param):
|
|
|
109
126
|
self,
|
|
110
127
|
default: Any = Undefined,
|
|
111
128
|
*,
|
|
129
|
+
annotation: Optional[Type[Any]] = None,
|
|
112
130
|
alias: Optional[str] = None,
|
|
113
131
|
title: Optional[str] = None,
|
|
114
132
|
description: Optional[str] = None,
|
|
@@ -118,6 +136,7 @@ class Query(Param):
|
|
|
118
136
|
le: Optional[float] = None,
|
|
119
137
|
min_length: Optional[int] = None,
|
|
120
138
|
max_length: Optional[int] = None,
|
|
139
|
+
pattern: Optional[str] = None,
|
|
121
140
|
regex: Optional[str] = None,
|
|
122
141
|
example: Any = Undefined,
|
|
123
142
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -127,6 +146,7 @@ class Query(Param):
|
|
|
127
146
|
):
|
|
128
147
|
super().__init__(
|
|
129
148
|
default=default,
|
|
149
|
+
annotation=annotation,
|
|
130
150
|
alias=alias,
|
|
131
151
|
title=title,
|
|
132
152
|
description=description,
|
|
@@ -136,6 +156,7 @@ class Query(Param):
|
|
|
136
156
|
le=le,
|
|
137
157
|
min_length=min_length,
|
|
138
158
|
max_length=max_length,
|
|
159
|
+
pattern=pattern,
|
|
139
160
|
regex=regex,
|
|
140
161
|
deprecated=deprecated,
|
|
141
162
|
example=example,
|
|
@@ -152,6 +173,7 @@ class Header(Param):
|
|
|
152
173
|
self,
|
|
153
174
|
default: Any = Undefined,
|
|
154
175
|
*,
|
|
176
|
+
annotation: Optional[Type[Any]] = None,
|
|
155
177
|
alias: Optional[str] = None,
|
|
156
178
|
convert_underscores: bool = True,
|
|
157
179
|
title: Optional[str] = None,
|
|
@@ -162,6 +184,7 @@ class Header(Param):
|
|
|
162
184
|
le: Optional[float] = None,
|
|
163
185
|
min_length: Optional[int] = None,
|
|
164
186
|
max_length: Optional[int] = None,
|
|
187
|
+
pattern: Optional[str] = None,
|
|
165
188
|
regex: Optional[str] = None,
|
|
166
189
|
example: Any = Undefined,
|
|
167
190
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -172,6 +195,7 @@ class Header(Param):
|
|
|
172
195
|
self.convert_underscores = convert_underscores
|
|
173
196
|
super().__init__(
|
|
174
197
|
default=default,
|
|
198
|
+
annotation=annotation,
|
|
175
199
|
alias=alias,
|
|
176
200
|
title=title,
|
|
177
201
|
description=description,
|
|
@@ -181,6 +205,7 @@ class Header(Param):
|
|
|
181
205
|
le=le,
|
|
182
206
|
min_length=min_length,
|
|
183
207
|
max_length=max_length,
|
|
208
|
+
pattern=pattern,
|
|
184
209
|
regex=regex,
|
|
185
210
|
deprecated=deprecated,
|
|
186
211
|
example=example,
|
|
@@ -197,6 +222,7 @@ class Cookie(Param):
|
|
|
197
222
|
self,
|
|
198
223
|
default: Any = Undefined,
|
|
199
224
|
*,
|
|
225
|
+
annotation: Optional[Type[Any]] = None,
|
|
200
226
|
alias: Optional[str] = None,
|
|
201
227
|
title: Optional[str] = None,
|
|
202
228
|
description: Optional[str] = None,
|
|
@@ -206,6 +232,7 @@ class Cookie(Param):
|
|
|
206
232
|
le: Optional[float] = None,
|
|
207
233
|
min_length: Optional[int] = None,
|
|
208
234
|
max_length: Optional[int] = None,
|
|
235
|
+
pattern: Optional[str] = None,
|
|
209
236
|
regex: Optional[str] = None,
|
|
210
237
|
example: Any = Undefined,
|
|
211
238
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -215,6 +242,7 @@ class Cookie(Param):
|
|
|
215
242
|
):
|
|
216
243
|
super().__init__(
|
|
217
244
|
default=default,
|
|
245
|
+
annotation=annotation,
|
|
218
246
|
alias=alias,
|
|
219
247
|
title=title,
|
|
220
248
|
description=description,
|
|
@@ -224,6 +252,7 @@ class Cookie(Param):
|
|
|
224
252
|
le=le,
|
|
225
253
|
min_length=min_length,
|
|
226
254
|
max_length=max_length,
|
|
255
|
+
pattern=pattern,
|
|
227
256
|
regex=regex,
|
|
228
257
|
deprecated=deprecated,
|
|
229
258
|
example=example,
|
|
@@ -238,6 +267,7 @@ class Body(FieldInfo):
|
|
|
238
267
|
self,
|
|
239
268
|
default: Any = Undefined,
|
|
240
269
|
*,
|
|
270
|
+
annotation: Optional[Type[Any]] = None,
|
|
241
271
|
embed: bool = False,
|
|
242
272
|
media_type: str = "application/json",
|
|
243
273
|
alias: Optional[str] = None,
|
|
@@ -249,6 +279,7 @@ class Body(FieldInfo):
|
|
|
249
279
|
le: Optional[float] = None,
|
|
250
280
|
min_length: Optional[int] = None,
|
|
251
281
|
max_length: Optional[int] = None,
|
|
282
|
+
pattern: Optional[str] = None,
|
|
252
283
|
regex: Optional[str] = None,
|
|
253
284
|
example: Any = Undefined,
|
|
254
285
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -257,8 +288,7 @@ class Body(FieldInfo):
|
|
|
257
288
|
self.embed = embed
|
|
258
289
|
self.media_type = media_type
|
|
259
290
|
self.example = example
|
|
260
|
-
|
|
261
|
-
super().__init__(
|
|
291
|
+
kwargs = dict(
|
|
262
292
|
default=default,
|
|
263
293
|
alias=alias,
|
|
264
294
|
title=title,
|
|
@@ -269,9 +299,20 @@ class Body(FieldInfo):
|
|
|
269
299
|
le=le,
|
|
270
300
|
min_length=min_length,
|
|
271
301
|
max_length=max_length,
|
|
272
|
-
regex=regex,
|
|
273
302
|
**extra,
|
|
274
303
|
)
|
|
304
|
+
if PYDANTIC_V2:
|
|
305
|
+
kwargs["annotation"] = annotation
|
|
306
|
+
kwargs["pattern"] = pattern or regex
|
|
307
|
+
else:
|
|
308
|
+
# TODO: pv2 figure out how to deprecate regex
|
|
309
|
+
kwargs["regex"] = pattern or regex
|
|
310
|
+
super().__init__(
|
|
311
|
+
**kwargs,
|
|
312
|
+
)
|
|
313
|
+
# TODO: pv2 decide how to handle OpenAPI examples vs JSON Schema examples
|
|
314
|
+
# and how to deprecate OpenAPI examples
|
|
315
|
+
self.examples = examples # type: ignore[assignment]
|
|
275
316
|
|
|
276
317
|
def __repr__(self) -> str:
|
|
277
318
|
return f"{self.__class__.__name__}({self.default})"
|
|
@@ -282,6 +323,7 @@ class Form(Body):
|
|
|
282
323
|
self,
|
|
283
324
|
default: Any = Undefined,
|
|
284
325
|
*,
|
|
326
|
+
annotation: Optional[Type[Any]] = None,
|
|
285
327
|
media_type: str = "application/x-www-form-urlencoded",
|
|
286
328
|
alias: Optional[str] = None,
|
|
287
329
|
title: Optional[str] = None,
|
|
@@ -292,6 +334,7 @@ class Form(Body):
|
|
|
292
334
|
le: Optional[float] = None,
|
|
293
335
|
min_length: Optional[int] = None,
|
|
294
336
|
max_length: Optional[int] = None,
|
|
337
|
+
pattern: Optional[str] = None,
|
|
295
338
|
regex: Optional[str] = None,
|
|
296
339
|
example: Any = Undefined,
|
|
297
340
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -299,6 +342,7 @@ class Form(Body):
|
|
|
299
342
|
):
|
|
300
343
|
super().__init__(
|
|
301
344
|
default=default,
|
|
345
|
+
annotation=annotation,
|
|
302
346
|
embed=True,
|
|
303
347
|
media_type=media_type,
|
|
304
348
|
alias=alias,
|
|
@@ -310,6 +354,7 @@ class Form(Body):
|
|
|
310
354
|
le=le,
|
|
311
355
|
min_length=min_length,
|
|
312
356
|
max_length=max_length,
|
|
357
|
+
pattern=pattern,
|
|
313
358
|
regex=regex,
|
|
314
359
|
example=example,
|
|
315
360
|
examples=examples,
|
|
@@ -322,6 +367,7 @@ class File(Form):
|
|
|
322
367
|
self,
|
|
323
368
|
default: Any = Undefined,
|
|
324
369
|
*,
|
|
370
|
+
annotation: Optional[Type[Any]] = None,
|
|
325
371
|
media_type: str = "multipart/form-data",
|
|
326
372
|
alias: Optional[str] = None,
|
|
327
373
|
title: Optional[str] = None,
|
|
@@ -332,6 +378,7 @@ class File(Form):
|
|
|
332
378
|
le: Optional[float] = None,
|
|
333
379
|
min_length: Optional[int] = None,
|
|
334
380
|
max_length: Optional[int] = None,
|
|
381
|
+
pattern: Optional[str] = None,
|
|
335
382
|
regex: Optional[str] = None,
|
|
336
383
|
example: Any = Undefined,
|
|
337
384
|
examples: Optional[Dict[str, Any]] = None,
|
|
@@ -339,6 +386,7 @@ class File(Form):
|
|
|
339
386
|
):
|
|
340
387
|
super().__init__(
|
|
341
388
|
default=default,
|
|
389
|
+
annotation=annotation,
|
|
342
390
|
media_type=media_type,
|
|
343
391
|
alias=alias,
|
|
344
392
|
title=title,
|
|
@@ -349,6 +397,7 @@ class File(Form):
|
|
|
349
397
|
le=le,
|
|
350
398
|
min_length=min_length,
|
|
351
399
|
max_length=max_length,
|
|
400
|
+
pattern=pattern,
|
|
352
401
|
regex=regex,
|
|
353
402
|
example=example,
|
|
354
403
|
examples=examples,
|