fastapi 0.116.2__py3-none-any.whl → 0.117.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.py +2 -1
- fastapi/applications.py +28 -0
- fastapi/dependencies/utils.py +20 -9
- fastapi/encoders.py +2 -1
- fastapi/openapi/models.py +8 -2
- fastapi/openapi/utils.py +3 -0
- fastapi/routing.py +8 -2
- fastapi/security/api_key.py +3 -3
- fastapi/utils.py +1 -0
- {fastapi-0.116.2.dist-info → fastapi-0.117.1.dist-info}/METADATA +26 -26
- {fastapi-0.116.2.dist-info → fastapi-0.117.1.dist-info}/RECORD +15 -15
- {fastapi-0.116.2.dist-info → fastapi-0.117.1.dist-info}/WHEEL +0 -0
- {fastapi-0.116.2.dist-info → fastapi-0.117.1.dist-info}/entry_points.txt +0 -0
- {fastapi-0.116.2.dist-info → fastapi-0.117.1.dist-info}/licenses/LICENSE +0 -0
fastapi/__init__.py
CHANGED
fastapi/_compat.py
CHANGED
|
@@ -393,9 +393,10 @@ else:
|
|
|
393
393
|
)
|
|
394
394
|
definitions.update(m_definitions)
|
|
395
395
|
model_name = model_name_map[model]
|
|
396
|
+
definitions[model_name] = m_schema
|
|
397
|
+
for m_schema in definitions.values():
|
|
396
398
|
if "description" in m_schema:
|
|
397
399
|
m_schema["description"] = m_schema["description"].split("\f")[0]
|
|
398
|
-
definitions[model_name] = m_schema
|
|
399
400
|
return definitions
|
|
400
401
|
|
|
401
402
|
def is_pv1_scalar_field(field: ModelField) -> bool:
|
fastapi/applications.py
CHANGED
|
@@ -810,6 +810,32 @@ class FastAPI(Starlette):
|
|
|
810
810
|
"""
|
|
811
811
|
),
|
|
812
812
|
] = True,
|
|
813
|
+
openapi_external_docs: Annotated[
|
|
814
|
+
Optional[Dict[str, Any]],
|
|
815
|
+
Doc(
|
|
816
|
+
"""
|
|
817
|
+
This field allows you to provide additional external documentation links.
|
|
818
|
+
If provided, it must be a dictionary containing:
|
|
819
|
+
|
|
820
|
+
* `description`: A brief description of the external documentation.
|
|
821
|
+
* `url`: The URL pointing to the external documentation. The value **MUST**
|
|
822
|
+
be a valid URL format.
|
|
823
|
+
|
|
824
|
+
**Example**:
|
|
825
|
+
|
|
826
|
+
```python
|
|
827
|
+
from fastapi import FastAPI
|
|
828
|
+
|
|
829
|
+
external_docs = {
|
|
830
|
+
"description": "Detailed API Reference",
|
|
831
|
+
"url": "https://example.com/api-docs",
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
app = FastAPI(openapi_external_docs=external_docs)
|
|
835
|
+
```
|
|
836
|
+
"""
|
|
837
|
+
),
|
|
838
|
+
] = None,
|
|
813
839
|
**extra: Annotated[
|
|
814
840
|
Any,
|
|
815
841
|
Doc(
|
|
@@ -838,6 +864,7 @@ class FastAPI(Starlette):
|
|
|
838
864
|
self.swagger_ui_parameters = swagger_ui_parameters
|
|
839
865
|
self.servers = servers or []
|
|
840
866
|
self.separate_input_output_schemas = separate_input_output_schemas
|
|
867
|
+
self.openapi_external_docs = openapi_external_docs
|
|
841
868
|
self.extra = extra
|
|
842
869
|
self.openapi_version: Annotated[
|
|
843
870
|
str,
|
|
@@ -992,6 +1019,7 @@ class FastAPI(Starlette):
|
|
|
992
1019
|
tags=self.openapi_tags,
|
|
993
1020
|
servers=self.servers,
|
|
994
1021
|
separate_input_output_schemas=self.separate_input_output_schemas,
|
|
1022
|
+
external_docs=self.openapi_external_docs,
|
|
995
1023
|
)
|
|
996
1024
|
return self.openapi_schema
|
|
997
1025
|
|
fastapi/dependencies/utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
+
import sys
|
|
2
3
|
from contextlib import AsyncExitStack, contextmanager
|
|
3
4
|
from copy import copy, deepcopy
|
|
4
5
|
from dataclasses import dataclass
|
|
@@ -73,6 +74,11 @@ from starlette.responses import Response
|
|
|
73
74
|
from starlette.websockets import WebSocket
|
|
74
75
|
from typing_extensions import Annotated, get_args, get_origin
|
|
75
76
|
|
|
77
|
+
if sys.version_info >= (3, 13): # pragma: no cover
|
|
78
|
+
from inspect import iscoroutinefunction
|
|
79
|
+
else: # pragma: no cover
|
|
80
|
+
from asyncio import iscoroutinefunction
|
|
81
|
+
|
|
76
82
|
multipart_not_installed_error = (
|
|
77
83
|
'Form data requires "python-multipart" to be installed. \n'
|
|
78
84
|
'You can install "python-multipart" with: \n\n'
|
|
@@ -248,6 +254,8 @@ def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
|
|
|
248
254
|
if isinstance(annotation, str):
|
|
249
255
|
annotation = ForwardRef(annotation)
|
|
250
256
|
annotation = evaluate_forwardref(annotation, globalns, globalns)
|
|
257
|
+
if annotation is type(None):
|
|
258
|
+
return None
|
|
251
259
|
return annotation
|
|
252
260
|
|
|
253
261
|
|
|
@@ -529,11 +537,11 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
|
|
|
529
537
|
|
|
530
538
|
def is_coroutine_callable(call: Callable[..., Any]) -> bool:
|
|
531
539
|
if inspect.isroutine(call):
|
|
532
|
-
return
|
|
540
|
+
return iscoroutinefunction(call)
|
|
533
541
|
if inspect.isclass(call):
|
|
534
542
|
return False
|
|
535
543
|
dunder_call = getattr(call, "__call__", None) # noqa: B004
|
|
536
|
-
return
|
|
544
|
+
return iscoroutinefunction(dunder_call)
|
|
537
545
|
|
|
538
546
|
|
|
539
547
|
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
|
|
@@ -587,7 +595,8 @@ async def solve_dependencies(
|
|
|
587
595
|
response = Response()
|
|
588
596
|
del response.headers["content-length"]
|
|
589
597
|
response.status_code = None # type: ignore
|
|
590
|
-
|
|
598
|
+
if dependency_cache is None:
|
|
599
|
+
dependency_cache = {}
|
|
591
600
|
sub_dependant: Dependant
|
|
592
601
|
for sub_dependant in dependant.dependencies:
|
|
593
602
|
sub_dependant.call = cast(Callable[..., Any], sub_dependant.call)
|
|
@@ -624,7 +633,6 @@ async def solve_dependencies(
|
|
|
624
633
|
embed_body_fields=embed_body_fields,
|
|
625
634
|
)
|
|
626
635
|
background_tasks = solved_result.background_tasks
|
|
627
|
-
dependency_cache.update(solved_result.dependency_cache)
|
|
628
636
|
if solved_result.errors:
|
|
629
637
|
errors.extend(solved_result.errors)
|
|
630
638
|
continue
|
|
@@ -864,20 +872,19 @@ async def _extract_form_body(
|
|
|
864
872
|
received_body: FormData,
|
|
865
873
|
) -> Dict[str, Any]:
|
|
866
874
|
values = {}
|
|
867
|
-
first_field = body_fields[0]
|
|
868
|
-
first_field_info = first_field.field_info
|
|
869
875
|
|
|
870
876
|
for field in body_fields:
|
|
871
877
|
value = _get_multidict_value(field, received_body)
|
|
878
|
+
field_info = field.field_info
|
|
872
879
|
if (
|
|
873
|
-
isinstance(
|
|
880
|
+
isinstance(field_info, params.File)
|
|
874
881
|
and is_bytes_field(field)
|
|
875
882
|
and isinstance(value, UploadFile)
|
|
876
883
|
):
|
|
877
884
|
value = await value.read()
|
|
878
885
|
elif (
|
|
879
886
|
is_bytes_sequence_field(field)
|
|
880
|
-
and isinstance(
|
|
887
|
+
and isinstance(field_info, params.File)
|
|
881
888
|
and value_is_sequence(value)
|
|
882
889
|
):
|
|
883
890
|
# For types
|
|
@@ -916,7 +923,11 @@ async def request_body_to_args(
|
|
|
916
923
|
|
|
917
924
|
fields_to_extract: List[ModelField] = body_fields
|
|
918
925
|
|
|
919
|
-
if
|
|
926
|
+
if (
|
|
927
|
+
single_not_embedded_field
|
|
928
|
+
and lenient_issubclass(first_field.type_, BaseModel)
|
|
929
|
+
and isinstance(received_body, FormData)
|
|
930
|
+
):
|
|
920
931
|
fields_to_extract = get_cached_model_fields(first_field.type_)
|
|
921
932
|
|
|
922
933
|
if isinstance(received_body, FormData):
|
fastapi/encoders.py
CHANGED
|
@@ -219,7 +219,7 @@ def jsonable_encoder(
|
|
|
219
219
|
if not PYDANTIC_V2:
|
|
220
220
|
encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined]
|
|
221
221
|
if custom_encoder:
|
|
222
|
-
encoders
|
|
222
|
+
encoders = {**encoders, **custom_encoder}
|
|
223
223
|
obj_dict = _model_dump(
|
|
224
224
|
obj,
|
|
225
225
|
mode="json",
|
|
@@ -241,6 +241,7 @@ def jsonable_encoder(
|
|
|
241
241
|
sqlalchemy_safe=sqlalchemy_safe,
|
|
242
242
|
)
|
|
243
243
|
if dataclasses.is_dataclass(obj):
|
|
244
|
+
assert not isinstance(obj, type)
|
|
244
245
|
obj_dict = dataclasses.asdict(obj)
|
|
245
246
|
return jsonable_encoder(
|
|
246
247
|
obj_dict,
|
fastapi/openapi/models.py
CHANGED
|
@@ -121,6 +121,12 @@ class ExternalDocumentation(BaseModelWithConfig):
|
|
|
121
121
|
url: AnyUrl
|
|
122
122
|
|
|
123
123
|
|
|
124
|
+
# Ref JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation#name-type
|
|
125
|
+
SchemaType = Literal[
|
|
126
|
+
"array", "boolean", "integer", "null", "number", "object", "string"
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
124
130
|
class Schema(BaseModelWithConfig):
|
|
125
131
|
# Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu
|
|
126
132
|
# Core Vocabulary
|
|
@@ -145,7 +151,7 @@ class Schema(BaseModelWithConfig):
|
|
|
145
151
|
dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None
|
|
146
152
|
prefixItems: Optional[List["SchemaOrBool"]] = None
|
|
147
153
|
# TODO: uncomment and remove below when deprecating Pydantic v1
|
|
148
|
-
# It
|
|
154
|
+
# It generates a list of schemas for tuples, before prefixItems was available
|
|
149
155
|
# items: Optional["SchemaOrBool"] = None
|
|
150
156
|
items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None
|
|
151
157
|
contains: Optional["SchemaOrBool"] = None
|
|
@@ -157,7 +163,7 @@ class Schema(BaseModelWithConfig):
|
|
|
157
163
|
unevaluatedProperties: Optional["SchemaOrBool"] = None
|
|
158
164
|
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
|
|
159
165
|
# A Vocabulary for Structural Validation
|
|
160
|
-
type: Optional[
|
|
166
|
+
type: Optional[Union[SchemaType, List[SchemaType]]] = None
|
|
161
167
|
enum: Optional[List[Any]] = None
|
|
162
168
|
const: Optional[Any] = None
|
|
163
169
|
multipleOf: Optional[float] = Field(default=None, gt=0)
|
fastapi/openapi/utils.py
CHANGED
|
@@ -488,6 +488,7 @@ def get_openapi(
|
|
|
488
488
|
contact: Optional[Dict[str, Union[str, Any]]] = None,
|
|
489
489
|
license_info: Optional[Dict[str, Union[str, Any]]] = None,
|
|
490
490
|
separate_input_output_schemas: bool = True,
|
|
491
|
+
external_docs: Optional[Dict[str, Any]] = None,
|
|
491
492
|
) -> Dict[str, Any]:
|
|
492
493
|
info: Dict[str, Any] = {"title": title, "version": version}
|
|
493
494
|
if summary:
|
|
@@ -565,4 +566,6 @@ def get_openapi(
|
|
|
565
566
|
output["webhooks"] = webhook_paths
|
|
566
567
|
if tags:
|
|
567
568
|
output["tags"] = tags
|
|
569
|
+
if external_docs:
|
|
570
|
+
output["externalDocs"] = external_docs
|
|
568
571
|
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore
|
fastapi/routing.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import dataclasses
|
|
3
2
|
import email.message
|
|
4
3
|
import inspect
|
|
5
4
|
import json
|
|
5
|
+
import sys
|
|
6
6
|
from contextlib import AsyncExitStack, asynccontextmanager
|
|
7
7
|
from enum import Enum, IntEnum
|
|
8
8
|
from typing import (
|
|
@@ -76,6 +76,11 @@ from starlette.types import AppType, ASGIApp, Lifespan, Scope
|
|
|
76
76
|
from starlette.websockets import WebSocket
|
|
77
77
|
from typing_extensions import Annotated, Doc, deprecated
|
|
78
78
|
|
|
79
|
+
if sys.version_info >= (3, 13): # pragma: no cover
|
|
80
|
+
from inspect import iscoroutinefunction
|
|
81
|
+
else: # pragma: no cover
|
|
82
|
+
from asyncio import iscoroutinefunction
|
|
83
|
+
|
|
79
84
|
|
|
80
85
|
def _prepare_response_content(
|
|
81
86
|
res: Any,
|
|
@@ -120,6 +125,7 @@ def _prepare_response_content(
|
|
|
120
125
|
for k, v in res.items()
|
|
121
126
|
}
|
|
122
127
|
elif dataclasses.is_dataclass(res):
|
|
128
|
+
assert not isinstance(res, type)
|
|
123
129
|
return dataclasses.asdict(res)
|
|
124
130
|
return res
|
|
125
131
|
|
|
@@ -231,7 +237,7 @@ def get_request_handler(
|
|
|
231
237
|
embed_body_fields: bool = False,
|
|
232
238
|
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
|
|
233
239
|
assert dependant.call is not None, "dependant.call must be a function"
|
|
234
|
-
is_coroutine =
|
|
240
|
+
is_coroutine = iscoroutinefunction(dependant.call)
|
|
235
241
|
is_body_form = body_field and isinstance(body_field.field_info, params.Form)
|
|
236
242
|
if isinstance(response_class, DefaultPlaceholder):
|
|
237
243
|
actual_response_class: Type[Response] = response_class.value
|
fastapi/security/api_key.py
CHANGED
|
@@ -100,7 +100,7 @@ class APIKeyQuery(APIKeyBase):
|
|
|
100
100
|
] = True,
|
|
101
101
|
):
|
|
102
102
|
self.model: APIKey = APIKey(
|
|
103
|
-
**{"in": APIKeyIn.query},
|
|
103
|
+
**{"in": APIKeyIn.query},
|
|
104
104
|
name=name,
|
|
105
105
|
description=description,
|
|
106
106
|
)
|
|
@@ -188,7 +188,7 @@ class APIKeyHeader(APIKeyBase):
|
|
|
188
188
|
] = True,
|
|
189
189
|
):
|
|
190
190
|
self.model: APIKey = APIKey(
|
|
191
|
-
**{"in": APIKeyIn.header},
|
|
191
|
+
**{"in": APIKeyIn.header},
|
|
192
192
|
name=name,
|
|
193
193
|
description=description,
|
|
194
194
|
)
|
|
@@ -276,7 +276,7 @@ class APIKeyCookie(APIKeyBase):
|
|
|
276
276
|
] = True,
|
|
277
277
|
):
|
|
278
278
|
self.model: APIKey = APIKey(
|
|
279
|
-
**{"in": APIKeyIn.cookie},
|
|
279
|
+
**{"in": APIKeyIn.cookie},
|
|
280
280
|
name=name,
|
|
281
281
|
description=description,
|
|
282
282
|
)
|
fastapi/utils.py
CHANGED
|
@@ -137,6 +137,7 @@ def create_cloned_field(
|
|
|
137
137
|
new_field.alias = field.alias # type: ignore[misc]
|
|
138
138
|
new_field.class_validators = field.class_validators # type: ignore[attr-defined]
|
|
139
139
|
new_field.default = field.default # type: ignore[misc]
|
|
140
|
+
new_field.default_factory = field.default_factory # type: ignore[attr-defined]
|
|
140
141
|
new_field.required = field.required # type: ignore[misc]
|
|
141
142
|
new_field.model_config = field.model_config # type: ignore[attr-defined]
|
|
142
143
|
new_field.field_info = field.field_info
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.117.1
|
|
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
|
|
@@ -43,21 +43,21 @@ Requires-Dist: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4
|
|
|
43
43
|
Requires-Dist: typing-extensions>=4.8.0
|
|
44
44
|
Provides-Extra: standard
|
|
45
45
|
Requires-Dist: fastapi-cli[standard]>=0.0.8; extra == "standard"
|
|
46
|
-
Requires-Dist: httpx
|
|
46
|
+
Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "standard"
|
|
47
47
|
Requires-Dist: jinja2>=3.1.5; extra == "standard"
|
|
48
48
|
Requires-Dist: python-multipart>=0.0.18; extra == "standard"
|
|
49
49
|
Requires-Dist: email-validator>=2.0.0; extra == "standard"
|
|
50
50
|
Requires-Dist: uvicorn[standard]>=0.12.0; extra == "standard"
|
|
51
51
|
Provides-Extra: standard-no-fastapi-cloud-cli
|
|
52
52
|
Requires-Dist: fastapi-cli[standard-no-fastapi-cloud-cli]>=0.0.8; extra == "standard-no-fastapi-cloud-cli"
|
|
53
|
-
Requires-Dist: httpx
|
|
53
|
+
Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "standard-no-fastapi-cloud-cli"
|
|
54
54
|
Requires-Dist: jinja2>=3.1.5; extra == "standard-no-fastapi-cloud-cli"
|
|
55
55
|
Requires-Dist: python-multipart>=0.0.18; extra == "standard-no-fastapi-cloud-cli"
|
|
56
56
|
Requires-Dist: email-validator>=2.0.0; extra == "standard-no-fastapi-cloud-cli"
|
|
57
57
|
Requires-Dist: uvicorn[standard]>=0.12.0; extra == "standard-no-fastapi-cloud-cli"
|
|
58
58
|
Provides-Extra: all
|
|
59
59
|
Requires-Dist: fastapi-cli[standard]>=0.0.8; extra == "all"
|
|
60
|
-
Requires-Dist: httpx
|
|
60
|
+
Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "all"
|
|
61
61
|
Requires-Dist: jinja2>=3.1.5; extra == "all"
|
|
62
62
|
Requires-Dist: python-multipart>=0.0.18; extra == "all"
|
|
63
63
|
Requires-Dist: itsdangerous>=1.1.0; extra == "all"
|
|
@@ -114,7 +114,7 @@ The key features are:
|
|
|
114
114
|
|
|
115
115
|
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
|
116
116
|
|
|
117
|
-
## Sponsors
|
|
117
|
+
## Sponsors
|
|
118
118
|
|
|
119
119
|
<!-- sponsors -->
|
|
120
120
|
|
|
@@ -139,7 +139,7 @@ The key features are:
|
|
|
139
139
|
|
|
140
140
|
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
|
141
141
|
|
|
142
|
-
## Opinions
|
|
142
|
+
## Opinions
|
|
143
143
|
|
|
144
144
|
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
|
145
145
|
|
|
@@ -185,7 +185,7 @@ The key features are:
|
|
|
185
185
|
|
|
186
186
|
---
|
|
187
187
|
|
|
188
|
-
## **Typer**, the FastAPI of CLIs
|
|
188
|
+
## **Typer**, the FastAPI of CLIs
|
|
189
189
|
|
|
190
190
|
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
|
191
191
|
|
|
@@ -193,14 +193,14 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
|
|
193
193
|
|
|
194
194
|
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
|
195
195
|
|
|
196
|
-
## Requirements
|
|
196
|
+
## Requirements
|
|
197
197
|
|
|
198
198
|
FastAPI stands on the shoulders of giants:
|
|
199
199
|
|
|
200
200
|
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
|
201
201
|
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
|
202
202
|
|
|
203
|
-
## Installation
|
|
203
|
+
## Installation
|
|
204
204
|
|
|
205
205
|
Create and activate a <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> and then install FastAPI:
|
|
206
206
|
|
|
@@ -216,9 +216,9 @@ $ pip install "fastapi[standard]"
|
|
|
216
216
|
|
|
217
217
|
**Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals.
|
|
218
218
|
|
|
219
|
-
## Example
|
|
219
|
+
## Example
|
|
220
220
|
|
|
221
|
-
### Create it
|
|
221
|
+
### Create it
|
|
222
222
|
|
|
223
223
|
Create a file `main.py` with:
|
|
224
224
|
|
|
@@ -269,7 +269,7 @@ If you don't know, check the _"In a hurry?"_ section about <a href="https://fast
|
|
|
269
269
|
|
|
270
270
|
</details>
|
|
271
271
|
|
|
272
|
-
### Run it
|
|
272
|
+
### Run it
|
|
273
273
|
|
|
274
274
|
Run the server with:
|
|
275
275
|
|
|
@@ -311,7 +311,7 @@ You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-
|
|
|
311
311
|
|
|
312
312
|
</details>
|
|
313
313
|
|
|
314
|
-
### Check it
|
|
314
|
+
### Check it
|
|
315
315
|
|
|
316
316
|
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
|
317
317
|
|
|
@@ -328,7 +328,7 @@ You already created an API that:
|
|
|
328
328
|
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
|
329
329
|
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
|
330
330
|
|
|
331
|
-
### Interactive API docs
|
|
331
|
+
### Interactive API docs
|
|
332
332
|
|
|
333
333
|
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
|
334
334
|
|
|
@@ -336,7 +336,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
|
|
|
336
336
|
|
|
337
337
|

|
|
338
338
|
|
|
339
|
-
### Alternative API docs
|
|
339
|
+
### Alternative API docs
|
|
340
340
|
|
|
341
341
|
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
|
342
342
|
|
|
@@ -344,7 +344,7 @@ You will see the alternative automatic documentation (provided by <a href="https
|
|
|
344
344
|
|
|
345
345
|

|
|
346
346
|
|
|
347
|
-
## Example upgrade
|
|
347
|
+
## Example upgrade
|
|
348
348
|
|
|
349
349
|
Now modify the file `main.py` to receive a body from a `PUT` request.
|
|
350
350
|
|
|
@@ -382,7 +382,7 @@ def update_item(item_id: int, item: Item):
|
|
|
382
382
|
|
|
383
383
|
The `fastapi dev` server should reload automatically.
|
|
384
384
|
|
|
385
|
-
### Interactive API docs upgrade
|
|
385
|
+
### Interactive API docs upgrade
|
|
386
386
|
|
|
387
387
|
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
|
388
388
|
|
|
@@ -398,7 +398,7 @@ Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_bl
|
|
|
398
398
|
|
|
399
399
|

|
|
400
400
|
|
|
401
|
-
### Alternative API docs upgrade
|
|
401
|
+
### Alternative API docs upgrade
|
|
402
402
|
|
|
403
403
|
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
|
404
404
|
|
|
@@ -406,7 +406,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
|
|
|
406
406
|
|
|
407
407
|

|
|
408
408
|
|
|
409
|
-
### Recap
|
|
409
|
+
### Recap
|
|
410
410
|
|
|
411
411
|
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
|
412
412
|
|
|
@@ -518,17 +518,17 @@ For a more complete example including more features, see the <a href="https://fa
|
|
|
518
518
|
* **Cookie Sessions**
|
|
519
519
|
* ...and more.
|
|
520
520
|
|
|
521
|
-
## Performance
|
|
521
|
+
## Performance
|
|
522
522
|
|
|
523
523
|
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
|
524
524
|
|
|
525
525
|
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
|
526
526
|
|
|
527
|
-
## Dependencies
|
|
527
|
+
## Dependencies
|
|
528
528
|
|
|
529
529
|
FastAPI depends on Pydantic and Starlette.
|
|
530
530
|
|
|
531
|
-
### `standard` Dependencies
|
|
531
|
+
### `standard` Dependencies
|
|
532
532
|
|
|
533
533
|
When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies:
|
|
534
534
|
|
|
@@ -548,15 +548,15 @@ Used by FastAPI:
|
|
|
548
548
|
* `fastapi-cli[standard]` - to provide the `fastapi` command.
|
|
549
549
|
* This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
|
|
550
550
|
|
|
551
|
-
### Without `standard` Dependencies
|
|
551
|
+
### Without `standard` Dependencies
|
|
552
552
|
|
|
553
553
|
If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`.
|
|
554
554
|
|
|
555
|
-
### Without `fastapi-cloud-cli`
|
|
555
|
+
### Without `fastapi-cloud-cli`
|
|
556
556
|
|
|
557
557
|
If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
|
|
558
558
|
|
|
559
|
-
### Additional Optional Dependencies
|
|
559
|
+
### Additional Optional Dependencies
|
|
560
560
|
|
|
561
561
|
There are some additional dependencies you might want to install.
|
|
562
562
|
|
|
@@ -570,6 +570,6 @@ Additional optional FastAPI dependencies:
|
|
|
570
570
|
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
|
571
571
|
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
|
572
572
|
|
|
573
|
-
## License
|
|
573
|
+
## License
|
|
574
574
|
|
|
575
575
|
This project is licensed under the terms of the MIT license.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
fastapi-0.
|
|
2
|
-
fastapi-0.
|
|
3
|
-
fastapi-0.
|
|
4
|
-
fastapi-0.
|
|
5
|
-
fastapi/__init__.py,sha256=
|
|
1
|
+
fastapi-0.117.1.dist-info/METADATA,sha256=CSMeNXJKTuCRib4fhSOBx_tdb_N2YOd8vfHzaDAx_X0,28135
|
|
2
|
+
fastapi-0.117.1.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
|
|
3
|
+
fastapi-0.117.1.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61
|
|
4
|
+
fastapi-0.117.1.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086
|
|
5
|
+
fastapi/__init__.py,sha256=71oE4uLHKzglF1IOxDbfcd-YwW2Qeu5emeUz00x0S98,1081
|
|
6
6
|
fastapi/__main__.py,sha256=bKePXLdO4SsVSM6r9SVoLickJDcR2c0cTOxZRKq26YQ,37
|
|
7
|
-
fastapi/_compat.py,sha256=
|
|
8
|
-
fastapi/applications.py,sha256=
|
|
7
|
+
fastapi/_compat.py,sha256=EQyNY-qrN3cjwI1r69JVAROc2lQCvi6W1we6_7jx_gc,24274
|
|
8
|
+
fastapi/applications.py,sha256=Sr6fkAYFmuyIT4b0Rm33NQzO8oz4-DEc3PLTxp4LJgU,177570
|
|
9
9
|
fastapi/background.py,sha256=rouLirxUANrcYC824MSMypXL_Qb2HYg2YZqaiEqbEKI,1768
|
|
10
10
|
fastapi/cli.py,sha256=OYhZb0NR_deuT5ofyPF2NoNBzZDNOP8Salef2nk-HqA,418
|
|
11
11
|
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=
|
|
16
|
-
fastapi/encoders.py,sha256=
|
|
15
|
+
fastapi/dependencies/utils.py,sha256=WVgX-cF_H318wOlsZSiAP2mX6-puEsx_MAQ6AHSzITE,36814
|
|
16
|
+
fastapi/encoders.py,sha256=r_fOgMylrlnCDTh3W9u2W0ZsHTJqIhLpU6QipHMy0m8,11119
|
|
17
17
|
fastapi/exception_handlers.py,sha256=YVcT8Zy021VYYeecgdyh5YEUjEIHKcLspbkSf4OfbJI,1275
|
|
18
18
|
fastapi/exceptions.py,sha256=taNixuFEXb67lI1bnX1ubq8y8TseJ4yoPlWjyP0fTzk,4969
|
|
19
19
|
fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54
|
|
@@ -26,16 +26,16 @@ fastapi/middleware/wsgi.py,sha256=Z3Ue-7wni4lUZMvH3G9ek__acgYdJstbnpZX_HQAboY,79
|
|
|
26
26
|
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=zSDv4xY6XHcKsaG4zyk1HqSnrZtfZFBB0J7ZBk5YHPE,10345
|
|
29
|
-
fastapi/openapi/models.py,sha256=
|
|
30
|
-
fastapi/openapi/utils.py,sha256=
|
|
29
|
+
fastapi/openapi/models.py,sha256=m1BNHxf_RiDTK1uCfMre6XZN5y7krZNA62QEP_2EV9s,15625
|
|
30
|
+
fastapi/openapi/utils.py,sha256=ZI-nwdT2PtX8kaRPJylZo4LJHjYAcoVGxkd181P75x4,23997
|
|
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=4zaZIdeq8VtsBLCxmmEgnfHqDD6USTc_l8BxUe1ye4M,176533
|
|
37
37
|
fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881
|
|
38
|
-
fastapi/security/api_key.py,sha256=
|
|
38
|
+
fastapi/security/api_key.py,sha256=di-0gQ8MKugi2YfmlMoDHk-QMF_vnLGJRFOA6tcZ7fA,9016
|
|
39
39
|
fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141
|
|
40
40
|
fastapi/security/http.py,sha256=rWR2x-5CUsjWmRucYthwRig6MG1o-boyrr4Xo-PuuxU,13606
|
|
41
41
|
fastapi/security/oauth2.py,sha256=M1AFIDT7G3oQChq83poI3eg8ZDeibcvnGmya2CTS7JY,22036
|
|
@@ -45,6 +45,6 @@ fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69
|
|
|
45
45
|
fastapi/templating.py,sha256=4zsuTWgcjcEainMJFAlW6-gnslm6AgOS1SiiDWfmQxk,76
|
|
46
46
|
fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66
|
|
47
47
|
fastapi/types.py,sha256=nFb36sK3DSoqoyo7Miwy3meKK5UdFBgkAgLSzQlUVyI,383
|
|
48
|
-
fastapi/utils.py,sha256=
|
|
48
|
+
fastapi/utils.py,sha256=S59stPvKPUJ7MSkke3FaegSyig_4Uwhd32jnLiMF1jE,8032
|
|
49
49
|
fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222
|
|
50
|
-
fastapi-0.
|
|
50
|
+
fastapi-0.117.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|