61 changed files with 1512 additions and 526 deletions
@ -12,7 +12,7 @@ jobs: |
|||
steps: |
|||
- uses: actions/checkout@v3 |
|||
- name: Download Artifact Docs |
|||
uses: dawidd6/[email protected]2.0 |
|||
uses: dawidd6/[email protected]3.0 |
|||
with: |
|||
github_token: ${{ secrets.GITHUB_TOKEN }} |
|||
workflow: build-docs.yml |
|||
|
@ -17,23 +17,21 @@ jobs: |
|||
- name: Set up Python |
|||
uses: actions/setup-python@v4 |
|||
with: |
|||
python-version: "3.6" |
|||
python-version: "3.7" |
|||
- uses: actions/cache@v3 |
|||
id: cache |
|||
with: |
|||
path: ${{ env.pythonLocation }} |
|||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish |
|||
- name: Install Flit |
|||
- name: Install build dependencies |
|||
if: steps.cache.outputs.cache-hit != 'true' |
|||
run: pip install flit |
|||
- name: Install Dependencies |
|||
if: steps.cache.outputs.cache-hit != 'true' |
|||
run: flit install --symlink |
|||
run: pip install build |
|||
- name: Build distribution |
|||
run: python -m build |
|||
- name: Publish |
|||
env: |
|||
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }} |
|||
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }} |
|||
run: bash scripts/publish.sh |
|||
uses: pypa/[email protected] |
|||
with: |
|||
password: ${{ secrets.PYPI_API_TOKEN }} |
|||
- name: Dump GitHub context |
|||
env: |
|||
GITHUB_CONTEXT: ${{ toJson(github) }} |
|||
|
@ -0,0 +1,466 @@ |
|||
|
|||
{!../../../docs/missing-translation.md!} |
|||
|
|||
|
|||
<p align="center"> |
|||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a> |
|||
</p> |
|||
<p align="center"> |
|||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em> |
|||
</p> |
|||
<p align="center"> |
|||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank"> |
|||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test"> |
|||
</a> |
|||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank"> |
|||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage"> |
|||
</a> |
|||
<a href="https://pypi.org/project/fastapi" target="_blank"> |
|||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version"> |
|||
</a> |
|||
</p> |
|||
|
|||
--- |
|||
|
|||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a> |
|||
|
|||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a> |
|||
|
|||
--- |
|||
|
|||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. |
|||
|
|||
The key features are: |
|||
|
|||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). |
|||
|
|||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * |
|||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * |
|||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging. |
|||
* **Easy**: Designed to be easy to use and learn. Less time reading docs. |
|||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. |
|||
* **Robust**: Get production-ready code. With automatic interactive documentation. |
|||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>. |
|||
|
|||
<small>* estimation based on tests on an internal development team, building production applications.</small> |
|||
|
|||
## Sponsors |
|||
|
|||
<!-- sponsors --> |
|||
|
|||
{% if sponsors %} |
|||
{% for sponsor in sponsors.gold -%} |
|||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> |
|||
{% endfor -%} |
|||
{%- for sponsor in sponsors.silver -%} |
|||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
<!-- /sponsors --> |
|||
|
|||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a> |
|||
|
|||
## Opinions |
|||
|
|||
"_[...] 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._" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" |
|||
|
|||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" |
|||
|
|||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div> |
|||
|
|||
--- |
|||
|
|||
## **Typer**, the FastAPI of CLIs |
|||
|
|||
<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> |
|||
|
|||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>. |
|||
|
|||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 |
|||
|
|||
## Requirements |
|||
|
|||
Python 3.7+ |
|||
|
|||
FastAPI stands on the shoulders of giants: |
|||
|
|||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts. |
|||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts. |
|||
|
|||
## Installation |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install fastapi |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>. |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install "uvicorn[standard]" |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
## Example |
|||
|
|||
### Create it |
|||
|
|||
* Create a file `main.py` with: |
|||
|
|||
```Python |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/") |
|||
def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
def read_item(item_id: int, q: Optional[str] = None): |
|||
return {"item_id": item_id, "q": q} |
|||
``` |
|||
|
|||
<details markdown="1"> |
|||
<summary>Or use <code>async def</code>...</summary> |
|||
|
|||
If your code uses `async` / `await`, use `async def`: |
|||
|
|||
```Python hl_lines="9 14" |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/") |
|||
async def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
async def read_item(item_id: int, q: Optional[str] = None): |
|||
return {"item_id": item_id, "q": q} |
|||
``` |
|||
|
|||
**Note**: |
|||
|
|||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>. |
|||
|
|||
</details> |
|||
|
|||
### Run it |
|||
|
|||
Run the server with: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ uvicorn main:app --reload |
|||
|
|||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
|||
INFO: Started reloader process [28720] |
|||
INFO: Started server process [28722] |
|||
INFO: Waiting for application startup. |
|||
INFO: Application startup complete. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
<details markdown="1"> |
|||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary> |
|||
|
|||
The command `uvicorn main:app` refers to: |
|||
|
|||
* `main`: the file `main.py` (the Python "module"). |
|||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. |
|||
* `--reload`: make the server restart after code changes. Only do this for development. |
|||
|
|||
</details> |
|||
|
|||
### Check it |
|||
|
|||
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>. |
|||
|
|||
You will see the JSON response as: |
|||
|
|||
```JSON |
|||
{"item_id": 5, "q": "somequery"} |
|||
``` |
|||
|
|||
You already created an API that: |
|||
|
|||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. |
|||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_). |
|||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. |
|||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. |
|||
|
|||
### Interactive API docs |
|||
|
|||
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>. |
|||
|
|||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>): |
|||
|
|||
 |
|||
|
|||
### Alternative API docs |
|||
|
|||
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>. |
|||
|
|||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>): |
|||
|
|||
 |
|||
|
|||
## Example upgrade |
|||
|
|||
Now modify the file `main.py` to receive a body from a `PUT` request. |
|||
|
|||
Declare the body using standard Python types, thanks to Pydantic. |
|||
|
|||
```Python hl_lines="4 9-12 25-27" |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI |
|||
from pydantic import BaseModel |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
price: float |
|||
is_offer: Optional[bool] = None |
|||
|
|||
|
|||
@app.get("/") |
|||
def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
def read_item(item_id: int, q: Optional[str] = None): |
|||
return {"item_id": item_id, "q": q} |
|||
|
|||
|
|||
@app.put("/items/{item_id}") |
|||
def update_item(item_id: int, item: Item): |
|||
return {"item_name": item.name, "item_id": item_id} |
|||
``` |
|||
|
|||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above). |
|||
|
|||
### Interactive API docs upgrade |
|||
|
|||
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>. |
|||
|
|||
* The interactive API documentation will be automatically updated, including the new body: |
|||
|
|||
 |
|||
|
|||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: |
|||
|
|||
 |
|||
|
|||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: |
|||
|
|||
 |
|||
|
|||
### Alternative API docs upgrade |
|||
|
|||
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>. |
|||
|
|||
* The alternative documentation will also reflect the new query parameter and body: |
|||
|
|||
 |
|||
|
|||
### Recap |
|||
|
|||
In summary, you declare **once** the types of parameters, body, etc. as function parameters. |
|||
|
|||
You do that with standard modern Python types. |
|||
|
|||
You don't have to learn a new syntax, the methods or classes of a specific library, etc. |
|||
|
|||
Just standard **Python 3.6+**. |
|||
|
|||
For example, for an `int`: |
|||
|
|||
```Python |
|||
item_id: int |
|||
``` |
|||
|
|||
or for a more complex `Item` model: |
|||
|
|||
```Python |
|||
item: Item |
|||
``` |
|||
|
|||
...and with that single declaration you get: |
|||
|
|||
* Editor support, including: |
|||
* Completion. |
|||
* Type checks. |
|||
* Validation of data: |
|||
* Automatic and clear errors when the data is invalid. |
|||
* Validation even for deeply nested JSON objects. |
|||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from: |
|||
* JSON. |
|||
* Path parameters. |
|||
* Query parameters. |
|||
* Cookies. |
|||
* Headers. |
|||
* Forms. |
|||
* Files. |
|||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON): |
|||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). |
|||
* `datetime` objects. |
|||
* `UUID` objects. |
|||
* Database models. |
|||
* ...and many more. |
|||
* Automatic interactive API documentation, including 2 alternative user interfaces: |
|||
* Swagger UI. |
|||
* ReDoc. |
|||
|
|||
--- |
|||
|
|||
Coming back to the previous code example, **FastAPI** will: |
|||
|
|||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. |
|||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. |
|||
* If it is not, the client will see a useful, clear error. |
|||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. |
|||
* As the `q` parameter is declared with `= None`, it is optional. |
|||
* Without the `None` it would be required (as is the body in the case with `PUT`). |
|||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON: |
|||
* Check that it has a required attribute `name` that should be a `str`. |
|||
* Check that it has a required attribute `price` that has to be a `float`. |
|||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. |
|||
* All this would also work for deeply nested JSON objects. |
|||
* Convert from and to JSON automatically. |
|||
* Document everything with OpenAPI, that can be used by: |
|||
* Interactive documentation systems. |
|||
* Automatic client code generation systems, for many languages. |
|||
* Provide 2 interactive documentation web interfaces directly. |
|||
|
|||
--- |
|||
|
|||
We just scratched the surface, but you already get the idea of how it all works. |
|||
|
|||
Try changing the line with: |
|||
|
|||
```Python |
|||
return {"item_name": item.name, "item_id": item_id} |
|||
``` |
|||
|
|||
...from: |
|||
|
|||
```Python |
|||
... "item_name": item.name ... |
|||
``` |
|||
|
|||
...to: |
|||
|
|||
```Python |
|||
... "item_price": item.price ... |
|||
``` |
|||
|
|||
...and see how your editor will auto-complete the attributes and know their types: |
|||
|
|||
 |
|||
|
|||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>. |
|||
|
|||
**Spoiler alert**: the tutorial - user guide includes: |
|||
|
|||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. |
|||
* How to set **validation constraints** as `maximum_length` or `regex`. |
|||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system. |
|||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. |
|||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). |
|||
* Many extra features (thanks to Starlette) as: |
|||
* **WebSockets** |
|||
* **GraphQL** |
|||
* extremely easy tests based on `requests` and `pytest` |
|||
* **CORS** |
|||
* **Cookie Sessions** |
|||
* ...and more. |
|||
|
|||
## Performance |
|||
|
|||
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). (*) |
|||
|
|||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>. |
|||
|
|||
## Optional Dependencies |
|||
|
|||
Used by Pydantic: |
|||
|
|||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>. |
|||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation. |
|||
|
|||
Used by Starlette: |
|||
|
|||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`. |
|||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration. |
|||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`. |
|||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support. |
|||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). |
|||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support. |
|||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`. |
|||
|
|||
Used by FastAPI / Starlette: |
|||
|
|||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application. |
|||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`. |
|||
|
|||
You can install all of these with `pip install fastapi[all]`. |
|||
|
|||
## License |
|||
|
|||
This project is licensed under the terms of the MIT license. |
@ -0,0 +1,203 @@ |
|||
# Основные свойства |
|||
|
|||
## Основные свойства FastAPI |
|||
|
|||
**FastAPI** предлагает вам следующее: |
|||
|
|||
### Использование открытых стандартов |
|||
|
|||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> для создания API, включая объявления <abbr title="также известных, как HTTP-методы, такие, как: POST, GET, PUT, DELETE">операций</abbr> <abbr title="известные как: эндпоинты, маршруты, 'ручки' и т.п.">пути</abbr>, параметров, тела запроса, безопасности и т.д. |
|||
|
|||
|
|||
* Автоматическое документирование моделей данных в соответствии с <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (так как спецификация OpenAPI сама основана на JSON Schema). |
|||
* Разработан, придерживаясь этих стандартов, после тщательного их изучения. Эти стандарты изначально включены во фреймфорк, а не являются дополнительной надстройкой. |
|||
* Это также позволяет использовать автоматическую **генерацию клиентского кода** на многих языках. |
|||
|
|||
### Автоматически генерируемая документация |
|||
|
|||
Интерактивная документация для API и исследования пользовательских веб-интерфейсов. Поскольку этот фреймворк основан на OpenAPI, существует несколько вариантов документирования, 2 из которых включены по умолчанию. |
|||
|
|||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, с интерактивным взаимодействием, вызывает и тестирует ваш API прямо из браузера. |
|||
|
|||
 |
|||
|
|||
* Альтернативная документация API в <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>. |
|||
|
|||
 |
|||
|
|||
### Только современный Python |
|||
|
|||
Все эти возможности основаны на стандартных **аннотациях типов Python 3.6** (благодаря Pydantic). Не нужно изучать новый синтаксис. Только лишь стандартный современный Python. |
|||
|
|||
Если вам нужно освежить знания, как использовать аннотации типов в Python (даже если вы не используете FastAPI), выделите 2 минуты и просмотрите краткое руководство: [Введение в аннотации типов Python¶ |
|||
](python-types.md){.internal-link target=_blank}. |
|||
|
|||
Вы пишете на стандартном Python с аннотациями типов: |
|||
|
|||
```Python |
|||
from datetime import date |
|||
|
|||
from pydantic import BaseModel |
|||
|
|||
# Объявляем параметр user_id с типом `str` |
|||
# и получаем поддержку редактора внутри функции |
|||
def main(user_id: str): |
|||
return user_id |
|||
|
|||
|
|||
# Модель Pydantic |
|||
class User(BaseModel): |
|||
id: int |
|||
name: str |
|||
joined: date |
|||
``` |
|||
|
|||
Это можно использовать так: |
|||
|
|||
```Python |
|||
my_user: User = User(id=3, name="John Doe", joined="2018-07-19") |
|||
|
|||
second_user_data = { |
|||
"id": 4, |
|||
"name": "Mary", |
|||
"joined": "2018-11-30", |
|||
} |
|||
|
|||
my_second_user: User = User(**second_user_data) |
|||
``` |
|||
|
|||
!!! Информация |
|||
`**second_user_data` означает: |
|||
|
|||
Передать ключи и значения словаря `second_user_data`, в качестве аргументов типа "ключ-значение", это эквивалентно: `User(id=4, name="Mary", joined="2018-11-30")` . |
|||
|
|||
### Поддержка редакторов (IDE) |
|||
|
|||
Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода. |
|||
|
|||
В опросе Python-разработчиков было выяснено, <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">что наиболее часто используемой функцией редакторов, является "автодополнение"</a>. |
|||
|
|||
Вся структура **FastAPI** основана на удовлетворении этой возможности. Автодополнение работает везде. |
|||
|
|||
Вам редко нужно будет возвращаться к документации. |
|||
|
|||
Вот как ваш редактор может вам помочь: |
|||
|
|||
* в <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>: |
|||
|
|||
 |
|||
|
|||
* в <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>: |
|||
|
|||
 |
|||
|
|||
Вы будете получать автодополнение кода даже там, где вы считали это невозможным раньше. |
|||
Как пример, ключ `price` внутри тела JSON (который может быть вложенным), приходящего в запросе. |
|||
|
|||
Больше никаких неправильных имён ключей, метания по документации или прокручивания кода вверх и вниз, в попытках узнать - использовали вы ранее `username` или `user_name`. |
|||
|
|||
### Краткость |
|||
FastAPI имеет продуманные значения **по умолчанию** для всего, с произвольными настройками везде. Все параметры могут быть тонко подстроены так, чтобы делать то, что вам нужно и определять необходимый вам API. |
|||
|
|||
Но, по умолчанию, всё это **"и так работает"**. |
|||
|
|||
### Проверка значений |
|||
|
|||
* Проверка значений для большинства (или всех?) **типов данных** Python, включая: |
|||
* Объекты JSON (`dict`). |
|||
* Массивы JSON (`list`) с установленными типами элементов. |
|||
* Строковые (`str`) поля с ограничением минимальной и максимальной длины. |
|||
* Числа (`int`, `float`) с минимальными и максимальными значениями и т.п. |
|||
|
|||
* Проверка для более экзотических типов, таких как: |
|||
* URL. |
|||
* Email. |
|||
* UUID. |
|||
* ...и другие. |
|||
|
|||
Все проверки обрабатываются хорошо зарекомендовавшим себя и надежным **Pydantic**. |
|||
|
|||
### Безопасность и аутентификация |
|||
|
|||
Встроеные функции безопасности и аутентификации. Без каких-либо компромиссов с базами данных или моделями данных. |
|||
|
|||
Все схемы безопасности, определённые в OpenAPI, включая: |
|||
|
|||
* HTTP Basic. |
|||
* **OAuth2** (также с **токенами JWT**). Ознакомьтесь с руководством [OAuth2 с JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. |
|||
* Ключи API в: |
|||
* Заголовках. |
|||
* Параметрах запросов. |
|||
* Cookies и т.п. |
|||
|
|||
Вдобавок все функции безопасности от Starlette (включая **сессионные cookies**). |
|||
|
|||
Все инструменты и компоненты спроектированы для многократного использования и легко интегрируются с вашими системами, хранилищами данных, реляционными и NoSQL базами данных и т. д. |
|||
|
|||
### Внедрение зависимостей |
|||
|
|||
FastAPI включает в себя чрезвычайно простую в использовании, но чрезвычайно мощную систему <abbr title='известную как: "components", "resources", "services", "providers"'><strong>Внедрения зависимостей</strong></abbr>. |
|||
|
|||
* Даже зависимости могут иметь зависимости, создавая иерархию или **"графы" зависимостей**. |
|||
* Всё **автоматически обрабатывается** фреймворком. |
|||
* Все зависимости могут запрашивать данные из запросов и **дополнять операции пути** ограничениями и автоматической документацией. |
|||
* **Автоматическая проверка** даже для параметров *операций пути*, определенных в зависимостях. |
|||
* Поддержка сложных систем аутентификации пользователей, **соединений с базами данных** и т.д. |
|||
* **Никаких компромиссов** с базами данных, интерфейсами и т.д. Но легкая интеграция со всеми ними. |
|||
|
|||
### Нет ограничений на "Плагины" |
|||
|
|||
Или, другими словами, нет сложностей с ними, импортируйте и используйте нужный вам код. |
|||
|
|||
Любая интеграция разработана настолько простой в использовании (с зависимостями), что вы можете создать "плагин" для своего приложения в пару строк кода, используя ту же структуру и синтаксис, что и для ваших *операций пути*. |
|||
|
|||
### Проверен |
|||
|
|||
* 100% <abbr title="Количество автоматически проверямого кода">покрытие тестами</abbr>. |
|||
* 100% <abbr title="Аннотации типов Python, благодаря которым ваш редактор и другие инструменты могут обеспечить вам лучшую поддержку">аннотирование типов</abbr> в кодовой базе. |
|||
* Используется в реально работающих приложениях. |
|||
|
|||
## Основные свойства Starlette |
|||
|
|||
**FastAPI** основан на <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a> и полностью совместим с ним. Так что, любой дополнительный код Starlette, который у вас есть, будет также работать. |
|||
|
|||
На самом деле, `FastAPI` - это класс, унаследованный от `Starlette`. Таким образом, если вы уже знаете или используете Starlette, большая часть функционала будет работать так же. |
|||
|
|||
С **FastAPI** вы получаете все возможности **Starlette** (так как FastAPI это всего лишь Starlette на стероидах): |
|||
|
|||
* Серьёзно впечатляющая производительность. Это <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">один из самых быстрых фреймворков на Python</a>, наравне с приложениями использующими **NodeJS** или **Go**. |
|||
* Поддержка **WebSocket**. |
|||
* Фоновые задачи для процессов. |
|||
* События запуска и выключения. |
|||
* Тестовый клиент построен на библиотеке `requests`. |
|||
* **CORS**, GZip, статические файлы, потоковые ответы. |
|||
* Поддержка **сессий и cookie**. |
|||
* 100% покрытие тестами. |
|||
* 100% аннотирование типов в кодовой базе. |
|||
|
|||
## Особенности и возможности Pydantic |
|||
|
|||
**FastAPI** основан на <a href="https://pydantic-docs.helpmanual.io" class="external-link" target="_blank"><strong>Pydantic</strong></a> и полностью совместим с ним. Так что, любой дополнительный код Pydantic, который у вас есть, будет также работать. |
|||
|
|||
Включая внешние библиотеки, также основанные на Pydantic, такие как: <abbr title="Object-Relational Mapper">ORM'ы</abbr>, <abbr title="Object-Document Mapper">ODM'ы</abbr> для баз данных. |
|||
|
|||
Это также означает, что во многих случаях вы можете передавать тот же объект, который получили из запроса, **непосредственно в базу данных**, так как всё проверяется автоматически. |
|||
|
|||
И наоборот, во многих случаях вы можете просто передать объект, полученный из базы данных, **непосредственно клиенту**. |
|||
|
|||
С **FastAPI** вы получаете все возможности **Pydantic** (так как, FastAPI основан на Pydantic, для обработки данных): |
|||
|
|||
* **Никакой нервотрёпки** : |
|||
* Не нужно изучать новых схем в микроязыках. |
|||
* Если вы знаете аннотации типов в Python, вы знаете, как использовать Pydantic. |
|||
* Прекрасно сочетается с вашими **<abbr title="Интегрированное окружение для разработки, похожее на текстовый редактор">IDE</abbr>/<abbr title="программа проверяющая ошибки в коде">linter</abbr>/мозгом**: |
|||
* Потому что структуры данных pydantic - это всего лишь экземпляры классов, определённых вами. Автодополнение, проверка кода, mypy и ваша интуиция - всё будет работать с вашими проверенными данными. |
|||
* **Быстродействие**: |
|||
* В <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">тестовых замерах</a> Pydantic быстрее, чем все другие проверенные библиотеки. |
|||
* Проверка **сложных структур**: |
|||
* Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing` (входит в стандартную библиотеку Python). |
|||
* Валидаторы позволяют четко и легко определять, проверять и документировать сложные схемы данных в виде JSON Schema. |
|||
* У вас могут быть глубоко **вложенные объекты JSON** и все они будут проверены и аннотированы. |
|||
* **Расширяемость**: |
|||
* Pydantic позволяет определять пользовательские типы данных или расширять проверку методами модели, с помощью проверочных декораторов. |
|||
* 100% покрытие тестами. |
@ -0,0 +1,42 @@ |
|||
# JSON 兼容编码器 |
|||
|
|||
在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的数据类型(如`dict`、`list`等)。 |
|||
|
|||
比如,如果您需要将其存储在数据库中。 |
|||
|
|||
对于这种要求, **FastAPI**提供了`jsonable_encoder()`函数。 |
|||
|
|||
## 使用`jsonable_encoder` |
|||
|
|||
让我们假设你有一个数据库名为`fake_db`,它只能接收与JSON兼容的数据。 |
|||
|
|||
例如,它不接收`datetime`这类的对象,因为这些对象与JSON不兼容。 |
|||
|
|||
因此,`datetime`对象必须将转换为包含<a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO格式化</a>的`str`类型对象。 |
|||
|
|||
同样,这个数据库也不会接收Pydantic模型(带有属性的对象),而只接收`dict`。 |
|||
|
|||
对此你可以使用`jsonable_encoder`。 |
|||
|
|||
它接收一个对象,比如Pydantic模型,并会返回一个JSON兼容的版本: |
|||
|
|||
=== "Python 3.6 and above" |
|||
|
|||
```Python hl_lines="5 22" |
|||
{!> ../../../docs_src/encoder/tutorial001.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10 and above" |
|||
|
|||
```Python hl_lines="4 21" |
|||
{!> ../../../docs_src/encoder/tutorial001_py310.py!} |
|||
``` |
|||
|
|||
在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。 |
|||
|
|||
调用它的结果后就可以使用Python标准编码中的<a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>。 |
|||
|
|||
这个操作不会返回一个包含JSON格式(作为字符串)数据的庞大的`str`。它将返回一个Python标准数据结构(例如`dict`),其值和子值都与JSON兼容。 |
|||
|
|||
!!! note |
|||
`jsonable_encoder`实际上是FastAPI内部用来转换数据的。但是它在许多其他场景中也很有用。 |
@ -1,2 +1,3 @@ |
|||
from starlette.websockets import WebSocket as WebSocket # noqa |
|||
from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa |
|||
from starlette.websockets import WebSocketState as WebSocketState # noqa |
|||
|
@ -1,12 +1,16 @@ |
|||
[build-system] |
|||
requires = ["flit"] |
|||
build-backend = "flit.buildapi" |
|||
requires = ["hatchling"] |
|||
build-backend = "hatchling.build" |
|||
|
|||
[tool.flit.metadata] |
|||
module = "fastapi" |
|||
author = "Sebastián Ramírez" |
|||
author-email = "[email protected]" |
|||
home-page = "https://github.com/tiangolo/fastapi" |
|||
[project] |
|||
name = "fastapi" |
|||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" |
|||
readme = "README.md" |
|||
requires-python = ">=3.7" |
|||
license = "MIT" |
|||
authors = [ |
|||
{ name = "Sebastián Ramírez", email = "[email protected]" }, |
|||
] |
|||
classifiers = [ |
|||
"Intended Audience :: Information Technology", |
|||
"Intended Audience :: System Administrators", |
|||
@ -26,7 +30,6 @@ classifiers = [ |
|||
"Intended Audience :: Developers", |
|||
"License :: OSI Approved :: MIT License", |
|||
"Programming Language :: Python :: 3 :: Only", |
|||
"Programming Language :: Python :: 3.6", |
|||
"Programming Language :: Python :: 3.7", |
|||
"Programming Language :: Python :: 3.8", |
|||
"Programming Language :: Python :: 3.9", |
|||
@ -34,40 +37,44 @@ classifiers = [ |
|||
"Topic :: Internet :: WWW/HTTP :: HTTP Servers", |
|||
"Topic :: Internet :: WWW/HTTP", |
|||
] |
|||
requires = [ |
|||
"starlette==0.19.1", |
|||
dependencies = [ |
|||
"starlette==0.20.4", |
|||
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0", |
|||
] |
|||
description-file = "README.md" |
|||
requires-python = ">=3.6.1" |
|||
dynamic = ["version"] |
|||
|
|||
[tool.flit.metadata.urls] |
|||
[project.urls] |
|||
Homepage = "https://github.com/tiangolo/fastapi" |
|||
Documentation = "https://fastapi.tiangolo.com/" |
|||
|
|||
[tool.flit.metadata.requires-extra] |
|||
[project.optional-dependencies] |
|||
test = [ |
|||
"pytest >=6.2.4,<7.0.0", |
|||
"pytest >=7.1.3,<8.0.0", |
|||
"pytest-cov >=2.12.0,<4.0.0", |
|||
"mypy ==0.910", |
|||
"mypy ==0.971", |
|||
"flake8 >=3.8.3,<6.0.0", |
|||
"black == 22.3.0", |
|||
"black == 22.8.0", |
|||
"isort >=5.0.6,<6.0.0", |
|||
"requests >=2.24.0,<3.0.0", |
|||
"httpx >=0.14.0,<0.19.0", |
|||
"httpx >=0.23.0,<0.24.0", |
|||
"email_validator >=1.1.1,<2.0.0", |
|||
"sqlalchemy >=1.3.18,<1.5.0", |
|||
# TODO: once removing databases from tutorial, upgrade SQLAlchemy |
|||
# probably when including SQLModel |
|||
"sqlalchemy >=1.3.18,<=1.4.41", |
|||
"peewee >=3.13.3,<4.0.0", |
|||
"databases[sqlite] >=0.3.2,<0.6.0", |
|||
"databases[sqlite] >=0.3.2,<0.7.0", |
|||
"orjson >=3.2.1,<4.0.0", |
|||
"ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0", |
|||
"python-multipart >=0.0.5,<0.0.6", |
|||
"flask >=1.1.2,<3.0.0", |
|||
"anyio[trio] >=3.2.1,<4.0.0", |
|||
"python-jose[cryptography] >=3.3.0,<4.0.0", |
|||
"pyyaml >=5.3.1,<7.0.0", |
|||
"passlib[bcrypt] >=1.7.2,<2.0.0", |
|||
|
|||
# types |
|||
"types-ujson ==4.2.1", |
|||
"types-ujson ==5.4.0", |
|||
"types-orjson ==3.6.2", |
|||
"types-dataclasses ==0.6.5; python_version<'3.7'", |
|||
] |
|||
doc = [ |
|||
"mkdocs >=1.1.2,<2.0.0", |
|||
@ -76,15 +83,13 @@ doc = [ |
|||
"mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0", |
|||
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x |
|||
# "typer-cli >=0.0.12,<0.0.13", |
|||
"typer >=0.4.1,<0.5.0", |
|||
"typer[all] >=0.6.1,<0.7.0", |
|||
"pyyaml >=5.3.1,<7.0.0", |
|||
] |
|||
dev = [ |
|||
"python-jose[cryptography] >=3.3.0,<4.0.0", |
|||
"passlib[bcrypt] >=1.7.2,<2.0.0", |
|||
"autoflake >=1.4.0,<2.0.0", |
|||
"flake8 >=3.8.3,<6.0.0", |
|||
"uvicorn[standard] >=0.12.0,<0.18.0", |
|||
"uvicorn[standard] >=0.12.0,<0.19.0", |
|||
"pre-commit >=2.17.0,<3.0.0", |
|||
] |
|||
all = [ |
|||
@ -96,9 +101,12 @@ all = [ |
|||
"ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0", |
|||
"orjson >=3.2.1,<4.0.0", |
|||
"email_validator >=1.1.1,<2.0.0", |
|||
"uvicorn[standard] >=0.12.0,<0.18.0", |
|||
"uvicorn[standard] >=0.12.0,<0.19.0", |
|||
] |
|||
|
|||
[tool.hatch.version] |
|||
path = "fastapi/__init__.py" |
|||
|
|||
[tool.isort] |
|||
profile = "black" |
|||
known_third_party = ["fastapi", "pydantic", "starlette"] |
|||
@ -128,6 +136,6 @@ filterwarnings = [ |
|||
# TODO: needed by asyncio in Python 3.9.7 https://bugs.python.org/issue45097, try to remove on 3.9.8 |
|||
'ignore:The loop argument is deprecated since Python 3\.8, and scheduled for removal in Python 3\.10:DeprecationWarning:asyncio', |
|||
'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', |
|||
# TODO: remove after dropping support for Python 3.6 |
|||
'ignore:Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.:UserWarning:jose', |
|||
# see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28 |
|||
'ignore::trio.TrioDeprecationWarning', |
|||
] |
|||
|
@ -0,0 +1,97 @@ |
|||
from typing import Any |
|||
|
|||
from fastapi import FastAPI, Response |
|||
from fastapi.testclient import TestClient |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.delete( |
|||
"/{id}", |
|||
status_code=204, |
|||
) |
|||
async def delete_deployment( |
|||
id: int, |
|||
response: Response, |
|||
) -> Any: |
|||
response.status_code = 400 |
|||
return {"msg": "Status overwritten", "id": id} |
|||
|
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
openapi_schema = { |
|||
"openapi": "3.0.2", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/{id}": { |
|||
"delete": { |
|||
"summary": "Delete Deployment", |
|||
"operationId": "delete_deployment__id__delete", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Id", "type": "integer"}, |
|||
"name": "id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"responses": { |
|||
"204": {"description": "Successful Response"}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == openapi_schema |
|||
|
|||
|
|||
def test_dependency_set_status_code(): |
|||
response = client.delete("/1") |
|||
assert response.status_code == 400 and response.content |
|||
assert response.json() == {"msg": "Status overwritten", "id": 1} |
@ -5,8 +5,6 @@ from unittest.mock import MagicMock |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py37 |
|||
|
|||
openapi_schema = { |
|||
"openapi": "3.0.2", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
@ -340,14 +338,12 @@ def client(): |
|||
test_db.unlink() |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_openapi_schema(client): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == openapi_schema |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_create_user(client): |
|||
test_user = {"email": "[email protected]", "password": "secret"} |
|||
response = client.post("/users/", json=test_user) |
|||
@ -359,7 +355,6 @@ def test_create_user(client): |
|||
assert response.status_code == 400, response.text |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_get_user(client): |
|||
response = client.get("/users/1") |
|||
assert response.status_code == 200, response.text |
|||
@ -368,13 +363,11 @@ def test_get_user(client): |
|||
assert "id" in data |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_inexistent_user(client): |
|||
response = client.get("/users/999") |
|||
assert response.status_code == 404, response.text |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_get_users(client): |
|||
response = client.get("/users/") |
|||
assert response.status_code == 200, response.text |
|||
@ -386,7 +379,6 @@ def test_get_users(client): |
|||
time.sleep = MagicMock() |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_get_slowusers(client): |
|||
response = client.get("/slowusers/") |
|||
assert response.status_code == 200, response.text |
|||
@ -395,7 +387,6 @@ def test_get_slowusers(client): |
|||
assert "id" in data[0] |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_create_item(client): |
|||
item = {"title": "Foo", "description": "Something that fights"} |
|||
response = client.post("/users/1/items/", json=item) |
|||
@ -419,7 +410,6 @@ def test_create_item(client): |
|||
assert item_to_check["description"] == item["description"] |
|||
|
|||
|
|||
@needs_py37 |
|||
def test_read_items(client): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 200, response.text |
|||
|
Loading…
Reference in new issue