fastapi 0.115.11__py3-none-any.whl → 0.115.12__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/dependencies/utils.py +30 -22
- fastapi/openapi/utils.py +28 -7
- fastapi/routing.py +12 -12
- {fastapi-0.115.11.dist-info → fastapi-0.115.12.dist-info}/METADATA +1 -1
- {fastapi-0.115.11.dist-info → fastapi-0.115.12.dist-info}/RECORD +9 -9
- {fastapi-0.115.11.dist-info → fastapi-0.115.12.dist-info}/WHEEL +0 -0
- {fastapi-0.115.11.dist-info → fastapi-0.115.12.dist-info}/entry_points.txt +0 -0
- {fastapi-0.115.11.dist-info → fastapi-0.115.12.dist-info}/licenses/LICENSE +0 -0
fastapi/__init__.py
CHANGED
fastapi/dependencies/utils.py
CHANGED
|
@@ -133,9 +133,9 @@ def get_param_sub_dependant(
|
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant:
|
|
136
|
-
assert callable(
|
|
137
|
-
|
|
138
|
-
)
|
|
136
|
+
assert callable(depends.dependency), (
|
|
137
|
+
"A parameter-less dependency must have a callable dependency"
|
|
138
|
+
)
|
|
139
139
|
return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path)
|
|
140
140
|
|
|
141
141
|
|
|
@@ -302,9 +302,9 @@ def get_dependant(
|
|
|
302
302
|
type_annotation=param_details.type_annotation,
|
|
303
303
|
dependant=dependant,
|
|
304
304
|
):
|
|
305
|
-
assert (
|
|
306
|
-
|
|
307
|
-
)
|
|
305
|
+
assert param_details.field is None, (
|
|
306
|
+
f"Cannot specify multiple FastAPI annotations for {param_name!r}"
|
|
307
|
+
)
|
|
308
308
|
continue
|
|
309
309
|
assert param_details.field is not None
|
|
310
310
|
if isinstance(param_details.field.field_info, params.Body):
|
|
@@ -439,9 +439,9 @@ def analyze_param(
|
|
|
439
439
|
),
|
|
440
440
|
):
|
|
441
441
|
assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}"
|
|
442
|
-
assert (
|
|
443
|
-
|
|
444
|
-
)
|
|
442
|
+
assert field_info is None, (
|
|
443
|
+
f"Cannot specify FastAPI annotation for type {type_annotation!r}"
|
|
444
|
+
)
|
|
445
445
|
# Handle default assignations, neither field_info nor depends was not found in Annotated nor default value
|
|
446
446
|
elif field_info is None and depends is None:
|
|
447
447
|
default_value = value if value is not inspect.Signature.empty else RequiredParam
|
|
@@ -494,9 +494,9 @@ def analyze_param(
|
|
|
494
494
|
field_info=field_info,
|
|
495
495
|
)
|
|
496
496
|
if is_path_param:
|
|
497
|
-
assert is_scalar_field(
|
|
498
|
-
|
|
499
|
-
)
|
|
497
|
+
assert is_scalar_field(field=field), (
|
|
498
|
+
"Path params must be of one of the supported types"
|
|
499
|
+
)
|
|
500
500
|
elif isinstance(field_info, params.Query):
|
|
501
501
|
assert (
|
|
502
502
|
is_scalar_field(field)
|
|
@@ -521,9 +521,9 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
|
|
|
521
521
|
elif field_info_in == params.ParamTypes.header:
|
|
522
522
|
dependant.header_params.append(field)
|
|
523
523
|
else:
|
|
524
|
-
assert (
|
|
525
|
-
|
|
526
|
-
)
|
|
524
|
+
assert field_info_in == params.ParamTypes.cookie, (
|
|
525
|
+
f"non-body parameters must be in path, query, header or cookie: {field.name}"
|
|
526
|
+
)
|
|
527
527
|
dependant.cookie_params.append(field)
|
|
528
528
|
|
|
529
529
|
|
|
@@ -750,9 +750,15 @@ def request_params_to_args(
|
|
|
750
750
|
first_field = fields[0]
|
|
751
751
|
fields_to_extract = fields
|
|
752
752
|
single_not_embedded_field = False
|
|
753
|
+
default_convert_underscores = True
|
|
753
754
|
if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel):
|
|
754
755
|
fields_to_extract = get_cached_model_fields(first_field.type_)
|
|
755
756
|
single_not_embedded_field = True
|
|
757
|
+
# If headers are in a Pydantic model, the way to disable convert_underscores
|
|
758
|
+
# would be with Header(convert_underscores=False) at the Pydantic model level
|
|
759
|
+
default_convert_underscores = getattr(
|
|
760
|
+
first_field.field_info, "convert_underscores", True
|
|
761
|
+
)
|
|
756
762
|
|
|
757
763
|
params_to_process: Dict[str, Any] = {}
|
|
758
764
|
|
|
@@ -763,7 +769,9 @@ def request_params_to_args(
|
|
|
763
769
|
if isinstance(received_params, Headers):
|
|
764
770
|
# Handle fields extracted from a Pydantic Model for a header, each field
|
|
765
771
|
# doesn't have a FieldInfo of type Header with the default convert_underscores=True
|
|
766
|
-
convert_underscores = getattr(
|
|
772
|
+
convert_underscores = getattr(
|
|
773
|
+
field.field_info, "convert_underscores", default_convert_underscores
|
|
774
|
+
)
|
|
767
775
|
if convert_underscores:
|
|
768
776
|
alias = (
|
|
769
777
|
field.alias
|
|
@@ -782,9 +790,9 @@ def request_params_to_args(
|
|
|
782
790
|
|
|
783
791
|
if single_not_embedded_field:
|
|
784
792
|
field_info = first_field.field_info
|
|
785
|
-
assert isinstance(
|
|
786
|
-
|
|
787
|
-
)
|
|
793
|
+
assert isinstance(field_info, params.Param), (
|
|
794
|
+
"Params must be subclasses of Param"
|
|
795
|
+
)
|
|
788
796
|
loc: Tuple[str, ...] = (field_info.in_.value,)
|
|
789
797
|
v_, errors_ = _validate_value_with_model_field(
|
|
790
798
|
field=first_field, value=params_to_process, values=values, loc=loc
|
|
@@ -794,9 +802,9 @@ def request_params_to_args(
|
|
|
794
802
|
for field in fields:
|
|
795
803
|
value = _get_multidict_value(field, received_params)
|
|
796
804
|
field_info = field.field_info
|
|
797
|
-
assert isinstance(
|
|
798
|
-
|
|
799
|
-
)
|
|
805
|
+
assert isinstance(field_info, params.Param), (
|
|
806
|
+
"Params must be subclasses of Param"
|
|
807
|
+
)
|
|
800
808
|
loc = (field_info.in_.value, field.alias)
|
|
801
809
|
v_, errors_ = _validate_value_with_model_field(
|
|
802
810
|
field=field, value=value, values=values, loc=loc
|
fastapi/openapi/utils.py
CHANGED
|
@@ -32,6 +32,7 @@ from fastapi.utils import (
|
|
|
32
32
|
generate_operation_id_for_path,
|
|
33
33
|
is_body_allowed_for_status_code,
|
|
34
34
|
)
|
|
35
|
+
from pydantic import BaseModel
|
|
35
36
|
from starlette.responses import JSONResponse
|
|
36
37
|
from starlette.routing import BaseRoute
|
|
37
38
|
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
|
|
@@ -113,6 +114,13 @@ def _get_openapi_operation_parameters(
|
|
|
113
114
|
(ParamTypes.header, header_params),
|
|
114
115
|
(ParamTypes.cookie, cookie_params),
|
|
115
116
|
]
|
|
117
|
+
default_convert_underscores = True
|
|
118
|
+
if len(flat_dependant.header_params) == 1:
|
|
119
|
+
first_field = flat_dependant.header_params[0]
|
|
120
|
+
if lenient_issubclass(first_field.type_, BaseModel):
|
|
121
|
+
default_convert_underscores = getattr(
|
|
122
|
+
first_field.field_info, "convert_underscores", True
|
|
123
|
+
)
|
|
116
124
|
for param_type, param_group in parameter_groups:
|
|
117
125
|
for param in param_group:
|
|
118
126
|
field_info = param.field_info
|
|
@@ -126,8 +134,21 @@ def _get_openapi_operation_parameters(
|
|
|
126
134
|
field_mapping=field_mapping,
|
|
127
135
|
separate_input_output_schemas=separate_input_output_schemas,
|
|
128
136
|
)
|
|
137
|
+
name = param.alias
|
|
138
|
+
convert_underscores = getattr(
|
|
139
|
+
param.field_info,
|
|
140
|
+
"convert_underscores",
|
|
141
|
+
default_convert_underscores,
|
|
142
|
+
)
|
|
143
|
+
if (
|
|
144
|
+
param_type == ParamTypes.header
|
|
145
|
+
and param.alias == param.name
|
|
146
|
+
and convert_underscores
|
|
147
|
+
):
|
|
148
|
+
name = param.name.replace("_", "-")
|
|
149
|
+
|
|
129
150
|
parameter = {
|
|
130
|
-
"name":
|
|
151
|
+
"name": name,
|
|
131
152
|
"in": param_type.value,
|
|
132
153
|
"required": param.required,
|
|
133
154
|
"schema": param_schema,
|
|
@@ -364,9 +385,9 @@ def get_openapi_path(
|
|
|
364
385
|
openapi_response = operation_responses.setdefault(
|
|
365
386
|
status_code_key, {}
|
|
366
387
|
)
|
|
367
|
-
assert isinstance(
|
|
368
|
-
|
|
369
|
-
)
|
|
388
|
+
assert isinstance(process_response, dict), (
|
|
389
|
+
"An additional response must be a dict"
|
|
390
|
+
)
|
|
370
391
|
field = route.response_fields.get(additional_status_code)
|
|
371
392
|
additional_field_schema: Optional[Dict[str, Any]] = None
|
|
372
393
|
if field:
|
|
@@ -434,9 +455,9 @@ def get_fields_from_routes(
|
|
|
434
455
|
route, routing.APIRoute
|
|
435
456
|
):
|
|
436
457
|
if route.body_field:
|
|
437
|
-
assert isinstance(
|
|
438
|
-
|
|
439
|
-
)
|
|
458
|
+
assert isinstance(route.body_field, ModelField), (
|
|
459
|
+
"A request body must be a Pydantic Field"
|
|
460
|
+
)
|
|
440
461
|
body_fields_from_routes.append(route.body_field)
|
|
441
462
|
if route.response_field:
|
|
442
463
|
responses_from_routes.append(route.response_field)
|
fastapi/routing.py
CHANGED
|
@@ -504,9 +504,9 @@ class APIRoute(routing.Route):
|
|
|
504
504
|
status_code = int(status_code)
|
|
505
505
|
self.status_code = status_code
|
|
506
506
|
if self.response_model:
|
|
507
|
-
assert is_body_allowed_for_status_code(
|
|
508
|
-
status_code
|
|
509
|
-
)
|
|
507
|
+
assert is_body_allowed_for_status_code(status_code), (
|
|
508
|
+
f"Status code {status_code} must not have a response body"
|
|
509
|
+
)
|
|
510
510
|
response_name = "Response_" + self.unique_id
|
|
511
511
|
self.response_field = create_model_field(
|
|
512
512
|
name=response_name,
|
|
@@ -537,9 +537,9 @@ class APIRoute(routing.Route):
|
|
|
537
537
|
assert isinstance(response, dict), "An additional response must be a dict"
|
|
538
538
|
model = response.get("model")
|
|
539
539
|
if model:
|
|
540
|
-
assert is_body_allowed_for_status_code(
|
|
541
|
-
additional_status_code
|
|
542
|
-
)
|
|
540
|
+
assert is_body_allowed_for_status_code(additional_status_code), (
|
|
541
|
+
f"Status code {additional_status_code} must not have a response body"
|
|
542
|
+
)
|
|
543
543
|
response_name = f"Response_{additional_status_code}_{self.unique_id}"
|
|
544
544
|
response_field = create_model_field(
|
|
545
545
|
name=response_name, type_=model, mode="serialization"
|
|
@@ -844,9 +844,9 @@ class APIRouter(routing.Router):
|
|
|
844
844
|
)
|
|
845
845
|
if prefix:
|
|
846
846
|
assert prefix.startswith("/"), "A path prefix must start with '/'"
|
|
847
|
-
assert not prefix.endswith(
|
|
848
|
-
"/"
|
|
849
|
-
)
|
|
847
|
+
assert not prefix.endswith("/"), (
|
|
848
|
+
"A path prefix must not end with '/', as the routes will start with '/'"
|
|
849
|
+
)
|
|
850
850
|
self.prefix = prefix
|
|
851
851
|
self.tags: List[Union[str, Enum]] = tags or []
|
|
852
852
|
self.dependencies = list(dependencies or [])
|
|
@@ -1256,9 +1256,9 @@ class APIRouter(routing.Router):
|
|
|
1256
1256
|
"""
|
|
1257
1257
|
if prefix:
|
|
1258
1258
|
assert prefix.startswith("/"), "A path prefix must start with '/'"
|
|
1259
|
-
assert not prefix.endswith(
|
|
1260
|
-
"/"
|
|
1261
|
-
)
|
|
1259
|
+
assert not prefix.endswith("/"), (
|
|
1260
|
+
"A path prefix must not end with '/', as the routes will start with '/'"
|
|
1261
|
+
)
|
|
1262
1262
|
else:
|
|
1263
1263
|
for r in router.routes:
|
|
1264
1264
|
path = getattr(r, "path") # noqa: B009
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi
|
|
3
|
-
Version: 0.115.
|
|
3
|
+
Version: 0.115.12
|
|
4
4
|
Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
|
5
5
|
Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
|
|
6
6
|
Classifier: Intended Audience :: Information Technology
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
fastapi-0.115.
|
|
2
|
-
fastapi-0.115.
|
|
3
|
-
fastapi-0.115.
|
|
4
|
-
fastapi-0.115.
|
|
5
|
-
fastapi/__init__.py,sha256=
|
|
1
|
+
fastapi-0.115.12.dist-info/METADATA,sha256=mV7D-DjELmGAedtcxayASLcleQv41h4mqHQhlqtLu1s,27671
|
|
2
|
+
fastapi-0.115.12.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
|
|
3
|
+
fastapi-0.115.12.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61
|
|
4
|
+
fastapi-0.115.12.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086
|
|
5
|
+
fastapi/__init__.py,sha256=sgu-sth5uRYC--mOXSta-IPYjnDKUrpRSz6LuvKHf9o,1082
|
|
6
6
|
fastapi/__main__.py,sha256=bKePXLdO4SsVSM6r9SVoLickJDcR2c0cTOxZRKq26YQ,37
|
|
7
7
|
fastapi/_compat.py,sha256=Rg7kA7uue4Z6yr8T7hf8b7G6PeC_06mK004Nnykijfk,23953
|
|
8
8
|
fastapi/applications.py,sha256=Ix-o9pQAWhEDf9J0Q1hZ0nBB1uP72c-Y3oiYzvrwqiM,176316
|
|
@@ -12,7 +12,7 @@ fastapi/concurrency.py,sha256=MirfowoSpkMQZ8j_g0ZxaQKpV6eB3G-dB5TgcXCrgEA,1424
|
|
|
12
12
|
fastapi/datastructures.py,sha256=b2PEz77XGq-u3Ur1Inwk0AGjOsQZO49yF9C7IPJ15cY,5766
|
|
13
13
|
fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
fastapi/dependencies/models.py,sha256=Pjl6vx-4nZ5Tta9kJa3-RfQKkXtCpS09-FhMgs9eWNs,1507
|
|
15
|
-
fastapi/dependencies/utils.py,sha256=
|
|
15
|
+
fastapi/dependencies/utils.py,sha256=SwOOdQYOC0E4thJ-n1a0ohslWN9duyasNY_JBdWPTsY,35971
|
|
16
16
|
fastapi/encoders.py,sha256=LvwYmFeOz4tVwvgBoC5rvZnbr7hZr73KGrU8O7zSptU,11068
|
|
17
17
|
fastapi/exception_handlers.py,sha256=MBrIOA-ugjJDivIi4rSsUJBdTsjuzN76q4yh0q1COKw,1332
|
|
18
18
|
fastapi/exceptions.py,sha256=taNixuFEXb67lI1bnX1ubq8y8TseJ4yoPlWjyP0fTzk,4969
|
|
@@ -27,13 +27,13 @@ fastapi/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
27
27
|
fastapi/openapi/constants.py,sha256=adGzmis1L1HJRTE3kJ5fmHS_Noq6tIY6pWv_SFzoFDU,153
|
|
28
28
|
fastapi/openapi/docs.py,sha256=XcQq-ZbQdC5sI0gIGu5MoHK1q-OFaqws7-ORTo6sjY4,10348
|
|
29
29
|
fastapi/openapi/models.py,sha256=PqkxQiqcEgjKuhfUIWPZPQcyTcubtUCB3vcObLsB7VE,15397
|
|
30
|
-
fastapi/openapi/utils.py,sha256=
|
|
30
|
+
fastapi/openapi/utils.py,sha256=e00G_p0IdpiffBUaq31BUyiloXbpld8RryKYnYKisdY,23964
|
|
31
31
|
fastapi/param_functions.py,sha256=JHNPLIYvoAwdnZZavIVsxOat8x23fX_Kl33reh7HKl8,64019
|
|
32
32
|
fastapi/params.py,sha256=g450axUBQgQJODdtM7WBxZbQj9Z64inFvadrgHikBbU,28237
|
|
33
33
|
fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142
|
|
35
35
|
fastapi/responses.py,sha256=QNQQlwpKhQoIPZTTWkpc9d_QGeGZ_aVQPaDV3nQ8m7c,1761
|
|
36
|
-
fastapi/routing.py,sha256=
|
|
36
|
+
fastapi/routing.py,sha256=qwk_Vm1k4vDGdeEskNCVYTK01fDgYikqfOS_lf0DqAc,176216
|
|
37
37
|
fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881
|
|
38
38
|
fastapi/security/api_key.py,sha256=cBI5Z4zWVjL1uJrsjTeLy7MafHPAO2HQPzTrpyoIYWA,9094
|
|
39
39
|
fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141
|
|
@@ -47,4 +47,4 @@ fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66
|
|
|
47
47
|
fastapi/types.py,sha256=nFb36sK3DSoqoyo7Miwy3meKK5UdFBgkAgLSzQlUVyI,383
|
|
48
48
|
fastapi/utils.py,sha256=y8Bj5ttMaI9tS4D60OUgXqKnktBr99NdYUnHHV9LgoY,7948
|
|
49
49
|
fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222
|
|
50
|
-
fastapi-0.115.
|
|
50
|
+
fastapi-0.115.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|