Browse Source

Merge branch 'master' into dev-getquery

pull/4573/head
jujumilk3 3 years ago
parent
commit
c678efe213
  1. 4
      .github/actions/people/app/main.py
  2. 7
      .github/workflows/build-docs.yml
  3. 2
      .github/workflows/preview-docs.yml
  4. 18
      .github/workflows/publish.yml
  5. 8
      .github/workflows/test.yml
  6. 8
      .pre-commit-config.yaml
  7. 8
      README.md
  8. 2
      SECURITY.md
  9. 466
      docs/az/docs/index.md
  10. 2
      docs/de/docs/index.md
  11. 8
      docs/en/data/external_links.yml
  12. 232
      docs/en/data/github_sponsors.yml
  13. 222
      docs/en/data/people.yml
  14. 2
      docs/en/docs/advanced/dataclasses.md
  15. 44
      docs/en/docs/contributing.md
  16. 8
      docs/en/docs/index.md
  17. 113
      docs/en/docs/release-notes.md
  18. 2
      docs/en/docs/tutorial/query-params-str-validations.md
  19. 2
      docs/en/docs/tutorial/response-model.md
  20. 2
      docs/es/docs/index.md
  21. 2
      docs/fr/docs/index.md
  22. 2
      docs/id/docs/index.md
  23. 2
      docs/it/docs/index.md
  24. 45
      docs/ja/docs/contributing.md
  25. 2
      docs/ja/docs/index.md
  26. 2
      docs/ko/docs/index.md
  27. 2
      docs/nl/docs/index.md
  28. 2
      docs/pl/docs/index.md
  29. 44
      docs/pt/docs/contributing.md
  30. 2
      docs/pt/docs/index.md
  31. 1
      docs/pt/mkdocs.yml
  32. 203
      docs/ru/docs/features.md
  33. 2
      docs/ru/docs/index.md
  34. 1
      docs/ru/mkdocs.yml
  35. 2
      docs/sq/docs/index.md
  36. 2
      docs/sv/docs/index.md
  37. 2
      docs/tr/docs/index.md
  38. 2
      docs/uk/docs/index.md
  39. 44
      docs/zh/docs/contributing.md
  40. 42
      docs/zh/docs/tutorial/encoder.md
  41. 63
      docs/zh/docs/tutorial/request-files.md
  42. 1
      docs/zh/mkdocs.yml
  43. 2
      fastapi/__init__.py
  44. 3
      fastapi/applications.py
  45. 30
      fastapi/concurrency.py
  46. 15
      fastapi/dependencies/utils.py
  47. 10
      fastapi/encoders.py
  48. 16
      fastapi/exception_handlers.py
  49. 4
      fastapi/routing.py
  50. 2
      fastapi/security/api_key.py
  51. 10
      fastapi/utils.py
  52. 1
      fastapi/websockets.py
  53. 66
      pyproject.toml
  54. 5
      scripts/docs.py
  55. 63
      tests/test_additional_responses_router.py
  56. 16
      tests/test_jsonable_encoder.py
  57. 97
      tests/test_reponse_set_reponse_code_empty.py
  58. 46
      tests/test_starlette_exception.py
  59. 10
      tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py
  60. 11
      tests/test_union_inherited_body.py
  61. 1
      tests/utils.py

4
.github/actions/people/app/main.py

@ -260,6 +260,7 @@ class Settings(BaseSettings):
input_token: SecretStr input_token: SecretStr
input_standard_token: SecretStr input_standard_token: SecretStr
github_repository: str github_repository: str
httpx_timeout: int = 30
def get_graphql_response( def get_graphql_response(
@ -270,9 +271,10 @@ def get_graphql_response(
response = httpx.post( response = httpx.post(
github_graphql_url, github_graphql_url,
headers=headers, headers=headers,
timeout=settings.httpx_timeout,
json={"query": query, "variables": variables, "operationName": "Q"}, json={"query": query, "variables": variables, "operationName": "Q"},
) )
if not response.status_code == 200: if response.status_code != 200:
logging.error(f"Response was not 200, after: {after}") logging.error(f"Response was not 200, after: {after}")
logging.error(response.text) logging.error(response.text)
raise RuntimeError(response.text) raise RuntimeError(response.text)

7
.github/workflows/build-docs.yml

@ -23,17 +23,14 @@ jobs:
with: with:
path: ${{ env.pythonLocation }} path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v03 key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v03
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m pip install flit
- name: Install docs extras - name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --deps production --extras doc run: pip install .[doc]
- name: Install Material for MkDocs Insiders - name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build Docs - name: Build Docs
run: python3.7 ./scripts/docs.py build-all run: python ./scripts/docs.py build-all
- name: Zip docs - name: Zip docs
run: bash ./scripts/zip-docs.sh run: bash ./scripts/zip-docs.sh
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3

2
.github/workflows/preview-docs.yml

@ -12,7 +12,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Download Artifact Docs - name: Download Artifact Docs
uses: dawidd6/[email protected]2.0 uses: dawidd6/[email protected]3.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-docs.yml workflow: build-docs.yml

18
.github/workflows/publish.yml

@ -17,23 +17,21 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: "3.6" python-version: "3.7"
- uses: actions/cache@v3 - uses: actions/cache@v3
id: cache id: cache
with: with:
path: ${{ env.pythonLocation }} path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
- name: Install Flit - name: Install build dependencies
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: pip install flit run: pip install build
- name: Install Dependencies - name: Build distribution
if: steps.cache.outputs.cache-hit != 'true' run: python -m build
run: flit install --symlink
- name: Publish - name: Publish
env: uses: pypa/[email protected]
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }} with:
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }} password: ${{ secrets.PYPI_API_TOKEN }}
run: bash scripts/publish.sh
- name: Dump GitHub context - name: Dump GitHub context
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}

8
.github/workflows/test.yml

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] python-version: ["3.7", "3.8", "3.9", "3.10"]
fail-fast: false fail-fast: false
steps: steps:
@ -26,14 +26,10 @@ jobs:
with: with:
path: ${{ env.pythonLocation }} path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02 key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: pip install flit
- name: Install Dependencies - name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: flit install --symlink run: pip install -e .[all,dev,doc,test]
- name: Lint - name: Lint
if: ${{ matrix.python-version != '3.6' }}
run: bash scripts/lint.sh run: bash scripts/lint.sh
- name: Test - name: Test
run: bash scripts/test.sh run: bash scripts/test.sh

8
.pre-commit-config.yaml

@ -12,14 +12,14 @@ repos:
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.37.3 rev: v3.1.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: args:
- --py3-plus - --py3-plus
- --keep-runtime-typing - --keep-runtime-typing
- repo: https://github.com/myint/autoflake - repo: https://github.com/PyCQA/autoflake
rev: v1.4 rev: v1.7.6
hooks: hooks:
- id: autoflake - id: autoflake
args: args:
@ -43,7 +43,7 @@ repos:
name: isort (pyi) name: isort (pyi)
types: [pyi] types: [pyi]
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.6.0 rev: 22.10.0
hooks: hooks:
- id: black - id: black
ci: ci:

8
README.md

@ -27,7 +27,7 @@
--- ---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
The key features are: The key features are:
@ -112,7 +112,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:
@ -131,7 +131,7 @@ $ pip install fastapi
</div> </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>. 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://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy"> <div class="termy">
@ -328,7 +328,7 @@ 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. You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**. Just standard **Python 3.7+**.
For example, for an `int`: For example, for an `int`:

2
SECURITY.md

@ -6,7 +6,7 @@ Learn more about it below. 👇
## Versions ## Versions
The latest versions of FastAPI are supported. The latest version of FastAPI is supported.
You are encouraged to [write tests](https://fastapi.tiangolo.com/tutorial/testing/) for your application and update your FastAPI version frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**. You are encouraged to [write tests](https://fastapi.tiangolo.com/tutorial/testing/) for your application and update your FastAPI version frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**.

466
docs/az/docs/index.md

@ -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>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### 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>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## 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:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* 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:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### 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:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### 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:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
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.

2
docs/de/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

8
docs/en/data/external_links.yml

@ -1,5 +1,13 @@
articles: articles:
english: english:
- author: WayScript
author_link: https://www.wayscript.com
link: https://blog.wayscript.com/fast-api-quickstart/
title: Quickstart Guide to Build and Host Responsive APIs with Fast API and WayScript
- author: New Relic
author_link: https://newrelic.com
link: https://newrelic.com/instant-observability/fastapi/e559ec64-f765-4470-a15f-1901fcebb468
title: How to monitor FastAPI application performance using Python agent
- author: Jean-Baptiste Rocher - author: Jean-Baptiste Rocher
author_link: https://hashnode.com/@jibrocher author_link: https://hashnode.com/@jibrocher
link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app

232
docs/en/data/github_sponsors.yml

@ -1,34 +1,25 @@
sponsors: sponsors:
- - login: github - - login: jina-ai
avatarUrl: https://avatars.githubusercontent.com/u/9919?v=4 avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
url: https://github.com/github url: https://github.com/jina-ai
- - login: Doist - - login: Doist
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
url: https://github.com/Doist url: https://github.com/Doist
- login: cryptapi - login: cryptapi
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
url: https://github.com/cryptapi url: https://github.com/cryptapi
- login: BLUE-DEVIL1134
avatarUrl: https://avatars.githubusercontent.com/u/55914808?u=f283d674fce31be7fb3ed2665b0f20d89958e541&v=4
url: https://github.com/BLUE-DEVIL1134
- login: jina-ai
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
url: https://github.com/jina-ai
- login: DropbaseHQ
avatarUrl: https://avatars.githubusercontent.com/u/85367855?v=4
url: https://github.com/DropbaseHQ
- - login: ObliviousAI - - login: ObliviousAI
avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4
url: https://github.com/ObliviousAI url: https://github.com/ObliviousAI
- login: Lovage-Labs
avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4
url: https://github.com/Lovage-Labs
- login: chaserowbotham - login: chaserowbotham
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4 avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
url: https://github.com/chaserowbotham url: https://github.com/chaserowbotham
- - login: mikeckennedy - - login: mikeckennedy
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
url: https://github.com/mikeckennedy url: https://github.com/mikeckennedy
- login: Trivie
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
url: https://github.com/Trivie
- login: deta - login: deta
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4 avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
url: https://github.com/deta url: https://github.com/deta
@ -44,12 +35,15 @@ sponsors:
- - login: InesIvanova - - login: InesIvanova
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
url: https://github.com/InesIvanova url: https://github.com/InesIvanova
- - login: SendCloud - - login: zopyx
avatarUrl: https://avatars.githubusercontent.com/u/594239?u=8e5ce882664f47fd61002bed51718c78c3799d24&v=4
url: https://github.com/zopyx
- login: SendCloud
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
url: https://github.com/SendCloud url: https://github.com/SendCloud
- login: qaas - login: mercedes-benz
avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4 avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
url: https://github.com/qaas url: https://github.com/mercedes-benz
- login: xoflare - login: xoflare
avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4
url: https://github.com/xoflare url: https://github.com/xoflare
@ -59,15 +53,15 @@ sponsors:
- login: BoostryJP - login: BoostryJP
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
url: https://github.com/BoostryJP url: https://github.com/BoostryJP
- - login: nnfuzzy - - login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/687670?v=4
url: https://github.com/nnfuzzy
- login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4 avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
url: https://github.com/johnadjei url: https://github.com/johnadjei
- login: HiredScore - login: HiredScore
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
url: https://github.com/HiredScore url: https://github.com/HiredScore
- login: Trivie
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
url: https://github.com/Trivie
- login: wdwinslow - login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow url: https://github.com/wdwinslow
@ -80,27 +74,30 @@ sponsors:
- login: tizz98 - login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
url: https://github.com/tizz98 url: https://github.com/tizz98
- login: Vikka
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
url: https://github.com/Vikka
- login: jmaralc - login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc url: https://github.com/jmaralc
- login: marutoraman - login: takashi-yoneya
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
url: https://github.com/marutoraman url: https://github.com/takashi-yoneya
- login: leynier
avatarUrl: https://avatars.githubusercontent.com/u/36774373?u=2284831c821307de562ebde5b59014d5416c7e0d&v=4
url: https://github.com/leynier
- login: mainframeindustries - login: mainframeindustries
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
url: https://github.com/mainframeindustries url: https://github.com/mainframeindustries
- login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- login: DelfinaCare - login: DelfinaCare
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
url: https://github.com/DelfinaCare url: https://github.com/DelfinaCare
- - login: povilasb - - login: povilasb
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
url: https://github.com/povilasb url: https://github.com/povilasb
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
- - login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- - login: Kludex - - login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex url: https://github.com/Kludex
@ -116,6 +113,12 @@ sponsors:
- login: kamalgill - login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
url: https://github.com/kamalgill url: https://github.com/kamalgill
- login: dekoza
avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4
url: https://github.com/dekoza
- login: pamelafox
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
url: https://github.com/pamelafox
- login: deserat - login: deserat
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4 avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
url: https://github.com/deserat url: https://github.com/deserat
@ -128,6 +131,9 @@ sponsors:
- login: koxudaxi - login: koxudaxi
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
url: https://github.com/koxudaxi url: https://github.com/koxudaxi
- login: falkben
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: jqueguiner - login: jqueguiner
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
url: https://github.com/jqueguiner url: https://github.com/jqueguiner
@ -164,12 +170,21 @@ sponsors:
- login: zsinx6 - login: zsinx6
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
url: https://github.com/zsinx6 url: https://github.com/zsinx6
- login: MarekBleschke
avatarUrl: https://avatars.githubusercontent.com/u/3616870?v=4
url: https://github.com/MarekBleschke
- login: aacayaco
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
url: https://github.com/aacayaco
- login: anomaly - login: anomaly
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
url: https://github.com/anomaly url: https://github.com/anomaly
- login: peterHoburg - login: peterHoburg
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
url: https://github.com/peterHoburg url: https://github.com/peterHoburg
- login: jgreys
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=b579fd97033269a5e703ab509c7d5478b146cc2d&v=4
url: https://github.com/jgreys
- login: gorhack - login: gorhack
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
url: https://github.com/gorhack url: https://github.com/gorhack
@ -188,14 +203,11 @@ sponsors:
- login: ennui93 - login: ennui93
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
url: https://github.com/ennui93 url: https://github.com/ennui93
- login: MacroPower
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=e13991efd1e03c44c911f919872e750530ded633&v=4
url: https://github.com/MacroPower
- login: Yaleesa - login: Yaleesa
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4 avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
url: https://github.com/Yaleesa url: https://github.com/Yaleesa
- login: iwpnd - login: iwpnd
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=c485eefca5c6329600cae63dd35e4f5682ce6924&v=4
url: https://github.com/iwpnd url: https://github.com/iwpnd
- login: simw - login: simw
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
@ -203,9 +215,6 @@ sponsors:
- login: pkucmus - login: pkucmus
avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4
url: https://github.com/pkucmus url: https://github.com/pkucmus
- login: ioalloc
avatarUrl: https://avatars.githubusercontent.com/u/6737824?u=6c3a31449f1c92064287171aa9ebe6363a0c9b7b&v=4
url: https://github.com/ioalloc
- login: s3ich4n - login: s3ich4n
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
url: https://github.com/s3ich4n url: https://github.com/s3ich4n
@ -218,9 +227,6 @@ sponsors:
- login: Shackelford-Arden - login: Shackelford-Arden
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
url: https://github.com/Shackelford-Arden url: https://github.com/Shackelford-Arden
- login: Vikka
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
url: https://github.com/Vikka
- login: Ge0f3 - login: Ge0f3
avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
url: https://github.com/Ge0f3 url: https://github.com/Ge0f3
@ -242,9 +248,6 @@ sponsors:
- login: wedwardbeck - login: wedwardbeck
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
url: https://github.com/wedwardbeck url: https://github.com/wedwardbeck
- login: stradivari96
avatarUrl: https://avatars.githubusercontent.com/u/19752586?u=255f5f06a768f518b20cebd6963e840ac49294fd&v=4
url: https://github.com/stradivari96
- login: RedCarpetUp - login: RedCarpetUp
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4 avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
url: https://github.com/RedCarpetUp url: https://github.com/RedCarpetUp
@ -266,33 +269,30 @@ sponsors:
- login: veprimk - login: veprimk
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4 avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
url: https://github.com/veprimk url: https://github.com/veprimk
- login: meysam81 - login: BrettskiPy
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
url: https://github.com/meysam81 url: https://github.com/BrettskiPy
- login: mauroalejandrojm - login: mauroalejandrojm
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4 avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
url: https://github.com/mauroalejandrojm url: https://github.com/mauroalejandrojm
- login: Leay15 - login: Leay15
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
url: https://github.com/Leay15 url: https://github.com/Leay15
- login: ygorpontelo
avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4
url: https://github.com/ygorpontelo
- login: AlrasheedA - login: AlrasheedA
avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4
url: https://github.com/AlrasheedA url: https://github.com/AlrasheedA
- login: ProteinQure - login: ProteinQure
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
url: https://github.com/ProteinQure url: https://github.com/ProteinQure
- login: guligon90
avatarUrl: https://avatars.githubusercontent.com/u/35070513?u=b48c05f669d1ea1d329f90dc70e45f10b569ef55&v=4
url: https://github.com/guligon90
- login: ybressler - login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
url: https://github.com/ybressler url: https://github.com/ybressler
- login: ddilidili - login: ddilidili
avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4
url: https://github.com/ddilidili url: https://github.com/ddilidili
- login: dbanty
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
- login: VictorCalderon - login: VictorCalderon
avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4
url: https://github.com/VictorCalderon url: https://github.com/VictorCalderon
@ -302,27 +302,27 @@ sponsors:
- login: rafsaf - login: rafsaf
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
url: https://github.com/rafsaf url: https://github.com/rafsaf
- login: yezz123
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: dudikbender - login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4 avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
url: https://github.com/dudikbender url: https://github.com/dudikbender
- login: daisuke8000 - login: llamington
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=23a3f2f2925ad3efc27c7420041622b7f5fd2b79&v=4 avatarUrl: https://avatars.githubusercontent.com/u/54869395?u=42ea59b76f49449f41a4d106bb65a130797e8d7c&v=4
url: https://github.com/daisuke8000 url: https://github.com/llamington
- login: dazeddd
avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4
url: https://github.com/dazeddd
- login: yakkonaut - login: yakkonaut
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
url: https://github.com/yakkonaut url: https://github.com/yakkonaut
- login: primer-io - login: patsatsia
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=419516384f798a35e9d9e2dd81282cc46c151b58&v=4
url: https://github.com/primer-io url: https://github.com/patsatsia
- login: around
avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4
url: https://github.com/around
- login: predictionmachine - login: predictionmachine
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4 avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
url: https://github.com/predictionmachine url: https://github.com/predictionmachine
- login: minsau
avatarUrl: https://avatars.githubusercontent.com/u/64386242?u=7e45f24b2958caf946fa3546ea33bacf5cd886f8&v=4
url: https://github.com/minsau
- login: daverin - login: daverin
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
url: https://github.com/daverin url: https://github.com/daverin
@ -339,7 +339,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4 avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
url: https://github.com/linux-china url: https://github.com/linux-china
- login: ddanier - login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?v=4 avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
url: https://github.com/ddanier url: https://github.com/ddanier
- login: jhb - login: jhb
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4 avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
@ -350,8 +350,11 @@ sponsors:
- login: bryanculbertson - login: bryanculbertson
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
url: https://github.com/bryanculbertson url: https://github.com/bryanculbertson
- login: hhatto
avatarUrl: https://avatars.githubusercontent.com/u/150309?u=3e8f63c27bf996bfc68464b0ce3f7a3e40e6ea7f&v=4
url: https://github.com/hhatto
- login: yourkin - login: yourkin
avatarUrl: https://avatars.githubusercontent.com/u/178984?u=fa7c3503b47bf16405b96d21554bc59f07a65523&v=4 avatarUrl: https://avatars.githubusercontent.com/u/178984?u=b43a7e5f8818f7d9083d3b110118d9c27d48a794&v=4
url: https://github.com/yourkin url: https://github.com/yourkin
- login: slafs - login: slafs
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
@ -369,14 +372,11 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4 avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
url: https://github.com/dmig url: https://github.com/dmig
- login: rinckd - login: rinckd
avatarUrl: https://avatars.githubusercontent.com/u/546002?u=1fcc7e664dc86524a0af6837a0c222829c3fd4e5&v=4 avatarUrl: https://avatars.githubusercontent.com/u/546002?u=8ec88ab721a5636346f19dcd677a6f323058be8b&v=4
url: https://github.com/rinckd url: https://github.com/rinckd
- login: securancy - login: securancy
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4 avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
url: https://github.com/securancy url: https://github.com/securancy
- login: falkben
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: hardbyte - login: hardbyte
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4 avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
url: https://github.com/hardbyte url: https://github.com/hardbyte
@ -384,16 +384,16 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4
url: https://github.com/browniebroke url: https://github.com/browniebroke
- login: janfilips - login: janfilips
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4 avatarUrl: https://avatars.githubusercontent.com/u/870699?u=50de77b93d3a0b06887e672d4e8c7b9d643085aa&v=4
url: https://github.com/janfilips url: https://github.com/janfilips
- login: woodrad - login: woodrad
avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4
url: https://github.com/woodrad url: https://github.com/woodrad
- login: Pytlicek - login: Pytlicek
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=01b1f2f7671ce3131e0877d08e2e3f8bdbb0a38a&v=4
url: https://github.com/Pytlicek url: https://github.com/Pytlicek
- login: allen0125 - login: allen0125
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=d4feb3d06a61baa4a69857ce371cc53fb4dffd2c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4
url: https://github.com/allen0125 url: https://github.com/allen0125
- login: WillHogan - login: WillHogan
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
@ -401,9 +401,9 @@ sponsors:
- login: cbonoz - login: cbonoz
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz url: https://github.com/cbonoz
- login: rglsk - login: Debakel
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2857237?u=07df6d11c8feef9306d071cb1c1005a2dd596585&v=4
url: https://github.com/rglsk url: https://github.com/Debakel
- login: paul121 - login: paul121
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
url: https://github.com/paul121 url: https://github.com/paul121
@ -413,6 +413,9 @@ sponsors:
- login: anthonycorletti - login: anthonycorletti
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4 avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
url: https://github.com/anthonycorletti url: https://github.com/anthonycorletti
- login: jonathanhle
avatarUrl: https://avatars.githubusercontent.com/u/3851599?u=76b9c5d2fecd6c3a16e7645231878c4507380d4d&v=4
url: https://github.com/jonathanhle
- login: pawamoy - login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy url: https://github.com/pawamoy
@ -425,15 +428,18 @@ sponsors:
- login: unredundant - login: unredundant
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
url: https://github.com/unredundant url: https://github.com/unredundant
- login: Baghdady92
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
url: https://github.com/Baghdady92
- login: holec - login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec url: https://github.com/holec
- login: hcristea
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
url: https://github.com/hcristea
- login: moonape1226 - login: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/moonape1226 url: https://github.com/moonape1226
- login: davanstrien
avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4
url: https://github.com/davanstrien
- login: yenchenLiu - login: yenchenLiu
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
url: https://github.com/yenchenLiu url: https://github.com/yenchenLiu
@ -449,17 +455,23 @@ sponsors:
- login: satwikkansal - login: satwikkansal
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4 avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
url: https://github.com/satwikkansal url: https://github.com/satwikkansal
- login: mntolia
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
url: https://github.com/mntolia
- login: pheanex - login: pheanex
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
url: https://github.com/pheanex url: https://github.com/pheanex
- login: JimFawkes - login: JimFawkes
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4 avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
url: https://github.com/JimFawkes url: https://github.com/JimFawkes
- login: giuliano-oliveira
avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4
url: https://github.com/giuliano-oliveira
- login: logan-connolly - login: logan-connolly
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4 avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
url: https://github.com/logan-connolly url: https://github.com/logan-connolly
- login: sanghunka - login: sanghunka
avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=960f5426ae08303229f045b9cc2ed463dcd41c15&v=4 avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=7d8fafd8bfe6d7900bb1e52d5a5d5da0c02bc164&v=4
url: https://github.com/sanghunka url: https://github.com/sanghunka
- login: stevenayers - login: stevenayers
avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4
@ -467,12 +479,12 @@ sponsors:
- login: cdsre - login: cdsre
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4 avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
url: https://github.com/cdsre url: https://github.com/cdsre
- login: aprilcoskun
avatarUrl: https://avatars.githubusercontent.com/u/17393603?u=29145243b4c7fadc80c7099471309cc2c04b6bcc&v=4
url: https://github.com/aprilcoskun
- login: jangia - login: jangia
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
url: https://github.com/jangia url: https://github.com/jangia
- login: paulowiz
avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4
url: https://github.com/paulowiz
- login: yannicschroeer - login: yannicschroeer
avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=4df05a7296c207b91c5d7c7a11c29df5ab313e2b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=4df05a7296c207b91c5d7c7a11c29df5ab313e2b&v=4
url: https://github.com/yannicschroeer url: https://github.com/yannicschroeer
@ -485,15 +497,12 @@ sponsors:
- login: mertguvencli - login: mertguvencli
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4 avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
url: https://github.com/mertguvencli url: https://github.com/mertguvencli
- login: elisoncrum - login: ruizdiazever
avatarUrl: https://avatars.githubusercontent.com/u/30413278?u=531190845bb0935dbc1e4f017cda3cb7b4dd0e54&v=4 avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4
url: https://github.com/elisoncrum url: https://github.com/ruizdiazever
- login: HosamAlmoghraby - login: HosamAlmoghraby
avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4 avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4
url: https://github.com/HosamAlmoghraby url: https://github.com/HosamAlmoghraby
- login: kitaramu0401
avatarUrl: https://avatars.githubusercontent.com/u/33246506?u=929e6efa2c518033b8097ba524eb5347a069bb3b&v=4
url: https://github.com/kitaramu0401
- login: engineerjoe440 - login: engineerjoe440
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
url: https://github.com/engineerjoe440 url: https://github.com/engineerjoe440
@ -501,7 +510,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4 avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
url: https://github.com/declon url: https://github.com/declon
- login: alvarobartt - login: alvarobartt
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=ac9ccb8b9164eb5fe7d5276142591aa1b8080daf&v=4 avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=9b38695807eb981d452989699ff72ec2d8f6508e&v=4
url: https://github.com/alvarobartt url: https://github.com/alvarobartt
- login: d-e-h-i-o - login: d-e-h-i-o
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4 avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
@ -516,11 +525,14 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4 avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
url: https://github.com/ilias-ant url: https://github.com/ilias-ant
- login: arrrrrmin - login: arrrrrmin
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=fee5739394fea074cb0b66929d070114a5067aae&v=4 avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=2a812c1a2ec58227ed01778837f255143de9df97&v=4
url: https://github.com/arrrrrmin url: https://github.com/arrrrrmin
- login: BomGard - login: MauriceKuenicke
avatarUrl: https://avatars.githubusercontent.com/u/47395385?u=8e9052f54e0b8dc7285099c438fa29c55a7d6407&v=4 avatarUrl: https://avatars.githubusercontent.com/u/47433175?u=37455bc95c7851db296ac42626f0cacb77ca2443&v=4
url: https://github.com/BomGard url: https://github.com/MauriceKuenicke
- login: hgalytoby
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4
url: https://github.com/hgalytoby
- login: akanz1 - login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1 url: https://github.com/akanz1
@ -548,24 +560,24 @@ sponsors:
- login: alessio-proietti - login: alessio-proietti
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4 avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
url: https://github.com/alessio-proietti url: https://github.com/alessio-proietti
- login: Mr-Sunglasses - login: pondDevThai
avatarUrl: https://avatars.githubusercontent.com/u/81439109?u=a5d0762fdcec26e18a028aef05323de3c6fb195c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4
url: https://github.com/Mr-Sunglasses url: https://github.com/pondDevThai
- - login: backbord - - login: mattwelke
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
url: https://github.com/backbord url: https://github.com/mattwelke
- login: cesarfreire
avatarUrl: https://avatars.githubusercontent.com/u/21126103?u=5d428f77f9b63c741f0e9ca5e15a689017b66fe8&v=4
url: https://github.com/cesarfreire
- login: gabrielmbmb - login: gabrielmbmb
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4 avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
url: https://github.com/gabrielmbmb url: https://github.com/gabrielmbmb
- login: danburonline - login: danburonline
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
url: https://github.com/danburonline url: https://github.com/danburonline
- login: zachspar - login: Moises6669
avatarUrl: https://avatars.githubusercontent.com/u/41600414?u=edf29c197137f51bace3f19a2ba759662640771f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4
url: https://github.com/zachspar url: https://github.com/Moises6669
- login: sownt - login: zahariev-webbersof
avatarUrl: https://avatars.githubusercontent.com/u/44340502?u=c06e3c45fb00a403075172770805fe57ff17b1cf&v=4 avatarUrl: https://avatars.githubusercontent.com/u/68993494?u=b341c94a8aa0624e05e201bcf8ae5b2697e3be2f&v=4
url: https://github.com/sownt url: https://github.com/zahariev-webbersof
- login: aahouzi
avatarUrl: https://avatars.githubusercontent.com/u/75032370?u=82677ee9cd86b3ccf4e13d9cb6765d8de5713e1e&v=4
url: https://github.com/aahouzi

222
docs/en/data/people.yml

@ -1,12 +1,12 @@
maintainers: maintainers:
- login: tiangolo - login: tiangolo
answers: 1248 answers: 1271
prs: 318 prs: 338
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
url: https://github.com/tiangolo url: https://github.com/tiangolo
experts: experts:
- login: Kludex - login: Kludex
count: 352 count: 364
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex url: https://github.com/Kludex
- login: dmontagu - login: dmontagu
@ -15,7 +15,7 @@ experts:
url: https://github.com/dmontagu url: https://github.com/dmontagu
- login: ycd - login: ycd
count: 221 count: 221
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
url: https://github.com/ycd url: https://github.com/ycd
- login: Mause - login: Mause
count: 207 count: 207
@ -25,6 +25,10 @@ experts:
count: 166 count: 166
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10 url: https://github.com/euri10
- login: JarroVGIT
count: 163
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: phy25 - login: phy25
count: 130 count: 130
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
@ -37,10 +41,10 @@ experts:
count: 71 count: 71
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik url: https://github.com/ArcLightSlavik
- login: JarroVGIT - login: iudeen
count: 68 count: 65
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/JarroVGIT url: https://github.com/iudeen
- login: falkben - login: falkben
count: 58 count: 58
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
@ -53,18 +57,18 @@ experts:
count: 46 count: 46
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes url: https://github.com/insomnes
- login: jgould22
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: Dustyposa - login: Dustyposa
count: 43 count: 43
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa url: https://github.com/Dustyposa
- login: adriangb - login: adriangb
count: 40 count: 40
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=75087f0cf0e9f725f3cd18a899218b6c63ae60d3&v=4
url: https://github.com/adriangb url: https://github.com/adriangb
- login: jgould22
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: includeamin - login: includeamin
count: 39 count: 39
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
@ -73,6 +77,10 @@ experts:
count: 37 count: 37
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary url: https://github.com/STeveShary
- login: chbndrhnns
count: 35
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: prostomarkeloff - login: prostomarkeloff
count: 33 count: 33
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
@ -85,20 +93,16 @@ experts:
count: 31 count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
url: https://github.com/krishnardt url: https://github.com/krishnardt
- login: chbndrhnns
count: 30
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: wshayes - login: wshayes
count: 29 count: 29
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes url: https://github.com/wshayes
- login: panla - login: panla
count: 27 count: 29
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla url: https://github.com/panla
- login: acidjunk - login: acidjunk
count: 25 count: 27
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk url: https://github.com/acidjunk
- login: ghandic - login: ghandic
@ -125,14 +129,14 @@ experts:
count: 21 count: 21
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
url: https://github.com/chris-allnutt url: https://github.com/chris-allnutt
- login: odiseo0
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: retnikt - login: retnikt
count: 19 count: 19
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt url: https://github.com/retnikt
- login: odiseo0
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: Hultner - login: Hultner
count: 18 count: 18
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
@ -171,8 +175,12 @@ experts:
url: https://github.com/hellocoldworld url: https://github.com/hellocoldworld
- login: haizaar - login: haizaar
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4 avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4
url: https://github.com/haizaar url: https://github.com/haizaar
- login: yinziyan1206
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
- login: valentin994 - login: valentin994
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4 avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
@ -181,47 +189,39 @@ experts:
count: 12 count: 12
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4 avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
url: https://github.com/David-Lor url: https://github.com/David-Lor
- login: yinziyan1206
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
- login: n8sty - login: n8sty
count: 12 count: 12
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty url: https://github.com/n8sty
- login: lowercase00 - login: zoliknemet
count: 11 count: 12
avatarUrl: https://avatars.githubusercontent.com/u/21188280?v=4 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
url: https://github.com/lowercase00 url: https://github.com/zoliknemet
- login: zamiramir
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
url: https://github.com/zamiramir
last_month_active: last_month_active:
- login: JarroVGIT - login: JarroVGIT
count: 30 count: 27
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT url: https://github.com/JarroVGIT
- login: zoliknemet
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
url: https://github.com/zoliknemet
- login: iudeen - login: iudeen
count: 5 count: 16
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/iudeen url: https://github.com/iudeen
- login: mbroton
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
url: https://github.com/mbroton
- login: csrgxtu
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/5053620?u=9655a3e9661492fcdaaf99193eb16d5cbcc3849e&v=4
url: https://github.com/csrgxtu
- login: Kludex - login: Kludex
count: 5 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex url: https://github.com/Kludex
- login: odiseo0 - login: jgould22
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: jonatasoli
count: 3 count: 3
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jonatasoli url: https://github.com/jgould22
top_contributors: top_contributors:
- login: waynerv - login: waynerv
count: 25 count: 25
@ -236,9 +236,13 @@ top_contributors:
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu url: https://github.com/dmontagu
- login: jaystone776 - login: jaystone776
count: 15 count: 16
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
url: https://github.com/jaystone776 url: https://github.com/jaystone776
- login: Kludex
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: euri10 - login: euri10
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
@ -247,14 +251,14 @@ top_contributors:
count: 12 count: 12
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
url: https://github.com/mariacamilagl url: https://github.com/mariacamilagl
- login: Kludex
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: Smlep - login: Smlep
count: 10 count: 10
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep url: https://github.com/Smlep
- login: dependabot
count: 9
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
url: https://github.com/apps/dependabot
- login: Serrones - login: Serrones
count: 8 count: 8
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
@ -279,10 +283,10 @@ top_contributors:
count: 5 count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031 url: https://github.com/Attsun1031
- login: dependabot - login: ComicShrimp
count: 5 count: 5
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/apps/dependabot url: https://github.com/ComicShrimp
- login: jekirl - login: jekirl
count: 4 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
@ -293,7 +297,7 @@ top_contributors:
url: https://github.com/jfunez url: https://github.com/jfunez
- login: ycd - login: ycd
count: 4 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
url: https://github.com/ycd url: https://github.com/ycd
- login: komtaki - login: komtaki
count: 4 count: 4
@ -303,25 +307,33 @@ top_contributors:
count: 4 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4
url: https://github.com/hitrust url: https://github.com/hitrust
- login: rjNemo
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: lsglucas - login: lsglucas
count: 4 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas url: https://github.com/lsglucas
- login: ComicShrimp
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
- login: NinaHwang - login: NinaHwang
count: 4 count: 4
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang url: https://github.com/NinaHwang
- login: pre-commit-ci
count: 4
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
url: https://github.com/apps/pre-commit-ci
top_reviewers: top_reviewers:
- login: Kludex - login: Kludex
count: 95 count: 101
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex url: https://github.com/Kludex
- login: BilalAlpaslan
count: 64
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: tokusumi - login: tokusumi
count: 49 count: 50
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi url: https://github.com/tokusumi
- login: waynerv - login: waynerv
@ -332,22 +344,18 @@ top_reviewers:
count: 47 count: 47
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4 avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55 url: https://github.com/Laineyzhang55
- login: BilalAlpaslan - login: yezz123
count: 45 count: 46
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/BilalAlpaslan url: https://github.com/yezz123
- login: ycd - login: ycd
count: 45 count: 45
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
url: https://github.com/ycd url: https://github.com/ycd
- login: cikay - login: cikay
count: 41 count: 41
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
url: https://github.com/cikay url: https://github.com/cikay
- login: yezz123
count: 34
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: AdrianDeAnda - login: AdrianDeAnda
count: 33 count: 33
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4
@ -356,10 +364,18 @@ top_reviewers:
count: 31 count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik url: https://github.com/ArcLightSlavik
- login: JarroVGIT
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: cassiobotaro - login: cassiobotaro
count: 25 count: 25
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro url: https://github.com/cassiobotaro
- login: lsglucas
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: dmontagu - login: dmontagu
count: 23 count: 23
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
@ -369,21 +385,13 @@ top_reviewers:
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki url: https://github.com/komtaki
- login: hard-coders - login: hard-coders
count: 19 count: 20
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders url: https://github.com/hard-coders
- login: 0417taehyun - login: 0417taehyun
count: 19 count: 19
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
url: https://github.com/0417taehyun url: https://github.com/0417taehyun
- login: lsglucas
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: JarroVGIT
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: zy7y - login: zy7y
count: 17 count: 17
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4 avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
@ -416,6 +424,10 @@ top_reviewers:
count: 15 count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09 url: https://github.com/delhi09
- login: iudeen
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/iudeen
- login: sh0nk - login: sh0nk
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
@ -424,6 +436,14 @@ top_reviewers:
count: 12 count: 12
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
url: https://github.com/RunningIkkyu url: https://github.com/RunningIkkyu
- login: odiseo0
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: LorhanSohaky
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
url: https://github.com/LorhanSohaky
- login: solomein-sv - login: solomein-sv
count: 11 count: 11
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
@ -440,13 +460,13 @@ top_reviewers:
count: 10 count: 10
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
url: https://github.com/maoyibo url: https://github.com/maoyibo
- login: odiseo0 - login: ComicShrimp
count: 10 count: 10
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/odiseo0 url: https://github.com/ComicShrimp
- login: graingert - login: graingert
count: 9 count: 9
avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4 avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4
url: https://github.com/graingert url: https://github.com/graingert
- login: PandaHun - login: PandaHun
count: 9 count: 9
@ -460,6 +480,10 @@ top_reviewers:
count: 9 count: 9
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
url: https://github.com/bezaca url: https://github.com/bezaca
- login: izaguerreiro
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
url: https://github.com/izaguerreiro
- login: raphaelauv - login: raphaelauv
count: 8 count: 8
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
@ -472,10 +496,6 @@ top_reviewers:
count: 8 count: 8
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4 avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
url: https://github.com/rogerbrinkmann url: https://github.com/rogerbrinkmann
- login: ComicShrimp
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
- login: NinaHwang - login: NinaHwang
count: 8 count: 8
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
@ -488,6 +508,10 @@ top_reviewers:
count: 7 count: 7
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones url: https://github.com/Serrones
- login: jovicon
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
url: https://github.com/jovicon
- login: ryuckel - login: ryuckel
count: 7 count: 7
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4 avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
@ -496,19 +520,3 @@ top_reviewers:
count: 7 count: 7
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4 avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
url: https://github.com/NastasiaSaby url: https://github.com/NastasiaSaby
- login: Mause
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: wakabame
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/35513518?v=4
url: https://github.com/wakabame
- login: AlexandreBiguet
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1483079?u=ff926455cd4cab03c6c49441aa5dc2b21df3e266&v=4
url: https://github.com/AlexandreBiguet
- login: krocdort
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/34248814?v=4
url: https://github.com/krocdort

2
docs/en/docs/advanced/dataclasses.md

@ -8,7 +8,7 @@ But FastAPI also supports using <a href="https://docs.python.org/3/library/datac
{!../../../docs_src/dataclasses/tutorial001.py!} {!../../../docs_src/dataclasses/tutorial001.py!}
``` ```
This is still thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>. This is still supported thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>.
So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses. So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses.

44
docs/en/docs/contributing.md

@ -99,61 +99,29 @@ $ python -m pip install --upgrade pip
!!! tip !!! tip
Every time you install a new package with `pip` under that environment, activate the environment again. Every time you install a new package with `pip` under that environment, activate the environment again.
This makes sure that if you use a terminal program installed by that package (like `flit`), you use the one from your local environment and not any other that could be installed globally. This makes sure that if you use a terminal program installed by that package, you use the one from your local environment and not any other that could be installed globally.
### Flit ### pip
**FastAPI** uses <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> to build, package and publish the project. After activating the environment as described above:
After activating the environment as described above, install `flit`:
<div class="termy"> <div class="termy">
```console ```console
$ pip install flit $ pip install -e .[dev,doc,test]
---> 100% ---> 100%
``` ```
</div> </div>
Now re-activate the environment to make sure you are using the `flit` you just installed (and not a global one).
And now use `flit` to install the development dependencies:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
If you are on Windows, use `--pth-file` instead of `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
It will install all the dependencies and your local FastAPI in your local environment. It will install all the dependencies and your local FastAPI in your local environment.
#### Using your local FastAPI #### Using your local FastAPI
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code. If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
And if you update that local FastAPI source code, as it is installed with `--symlink` (or `--pth-file` on Windows), when you run that Python file again, it will use the fresh version of FastAPI you just edited. And if you update that local FastAPI source code, as it is installed with `-e`, when you run that Python file again, it will use the fresh version of FastAPI you just edited.
That way, you don't have to "install" your local version to be able to test every change. That way, you don't have to "install" your local version to be able to test every change.
@ -171,7 +139,7 @@ $ bash scripts/format.sh
It will also auto-sort all your imports. It will also auto-sort all your imports.
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `--symlink` (or `--pth-file` on Windows). For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `-e`.
## Docs ## Docs

8
docs/en/docs/index.md

@ -27,7 +27,7 @@
--- ---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
The key features are: The key features are:
@ -109,7 +109,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:
@ -128,7 +128,7 @@ $ pip install fastapi
</div> </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>. 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://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy"> <div class="termy">
@ -325,7 +325,7 @@ 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. You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**. Just standard **Python 3.7+**.
For example, for an `int`: For example, for an `int`:

113
docs/en/docs/release-notes.md

@ -2,15 +2,120 @@
## Latest Changes ## Latest Changes
* 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency. PR [#4319](https://github.com/tiangolo/fastapi/pull/4319) by [@cd17822](https://github.com/cd17822). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5408](https://github.com/tiangolo/fastapi/pull/5408) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ♻ Internal small refactor, move `operation_id` parameter position in delete method for consistency with the code. PR [#4474](https://github.com/tiangolo/fastapi/pull/4474) by [@hiel](https://github.com/hiel). * ⬆️ Upgrade Typer to include Rich in scripts for docs. PR [#5502](https://github.com/tiangolo/fastapi/pull/5502) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix calling `mkdocs` for languages as a subprocess to fix/enable MkDocs Material search plugin. PR [#5501](https://github.com/tiangolo/fastapi/pull/5501) by [@tiangolo](https://github.com/tiangolo).
## 0.85.1
### Fixes
* 🐛 Fix support for strings in OpenAPI status codes: `default`, `1XX`, `2XX`, `3XX`, `4XX`, `5XX`. PR [#5187](https://github.com/tiangolo/fastapi/pull/5187) by [@JarroVGIT](https://github.com/JarroVGIT).
### Docs
* 📝 Add WayScript x FastAPI Tutorial to External Links section. PR [#5407](https://github.com/tiangolo/fastapi/pull/5407) by [@moneeka](https://github.com/moneeka).
### Internal
* 👥 Update FastAPI People. PR [#5447](https://github.com/tiangolo/fastapi/pull/5447) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Disable Material for MkDocs search plugin. PR [#5495](https://github.com/tiangolo/fastapi/pull/5495) by [@tiangolo](https://github.com/tiangolo).
* 🔇 Ignore Trio warning in tests for CI. PR [#5483](https://github.com/tiangolo/fastapi/pull/5483) by [@samuelcolvin](https://github.com/samuelcolvin).
## 0.85.0
### Features
* ⬆ Upgrade version required of Starlette from `0.19.1` to `0.20.4`. Initial PR [#4820](https://github.com/tiangolo/fastapi/pull/4820) by [@Kludex](https://github.com/Kludex).
* This includes several bug fixes in Starlette.
* ⬆️ Upgrade Uvicorn max version in public extras: all. From `>=0.12.0,<0.18.0` to `>=0.12.0,<0.19.0`. PR [#5401](https://github.com/tiangolo/fastapi/pull/5401) by [@tiangolo](https://github.com/tiangolo).
### Internal
* ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn. PR [#5400](https://github.com/tiangolo/fastapi/pull/5400) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson. PR [#5399](https://github.com/tiangolo/fastapi/pull/5399) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade mypy and tweak internal type annotations. PR [#5398](https://github.com/tiangolo/fastapi/pull/5398) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test. PR [#5396](https://github.com/tiangolo/fastapi/pull/5396) by [@tiangolo](https://github.com/tiangolo).
## 0.84.0
### Breaking Changes
This version of FastAPI drops support for Python 3.6. 🔥 Please upgrade to a supported version of Python (3.7 or above), Python 3.6 reached the end-of-life a long time ago. 😅☠
* 🔧 Update package metadata, drop support for Python 3.6, move build internals from Flit to Hatch. PR [#5240](https://github.com/tiangolo/fastapi/pull/5240) by [@ofek](https://github.com/ofek).
## 0.83.0
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
### Features
* ✨ Add support in `jsonable_encoder` for include and exclude with dataclasses. PR [#4923](https://github.com/tiangolo/fastapi/pull/4923) by [@DCsunset](https://github.com/DCsunset).
### Fixes
* 🐛 Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen).
* 🐛 Fix empty reponse body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel).
### Docs
* 📝 Update `SECURITY.md`. PR [#5377](https://github.com/tiangolo/fastapi/pull/5377) by [@Kludex](https://github.com/Kludex).
### Internal
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5352](https://github.com/tiangolo/fastapi/pull/5352) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
## 0.82.0
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
### Features
* ✨ Export `WebSocketState` in `fastapi.websockets`. PR [#4376](https://github.com/tiangolo/fastapi/pull/4376) by [@matiuszka](https://github.com/matiuszka).
* ✨ Support Python internal description on Pydantic model's docstring. PR [#3032](https://github.com/tiangolo/fastapi/pull/3032) by [@Kludex](https://github.com/Kludex). * ✨ Support Python internal description on Pydantic model's docstring. PR [#3032](https://github.com/tiangolo/fastapi/pull/3032) by [@Kludex](https://github.com/Kludex).
* ✨ Update `ORJSONResponse` to support non `str` keys and serializing Numpy arrays. PR [#3892](https://github.com/tiangolo/fastapi/pull/3892) by [@baby5](https://github.com/baby5). * ✨ Update `ORJSONResponse` to support non `str` keys and serializing Numpy arrays. PR [#3892](https://github.com/tiangolo/fastapi/pull/3892) by [@baby5](https://github.com/baby5).
* 🔧 Update sponsors, disable ImgWhale. PR [#5338](https://github.com/tiangolo/fastapi/pull/5338) by [@tiangolo](https://github.com/tiangolo).
### Fixes
* 🐛 Allow exit code for dependencies with `yield` to always execute, by removing capacity limiter for them, to e.g. allow closing DB connections without deadlocks. PR [#5122](https://github.com/tiangolo/fastapi/pull/5122) by [@adriangb](https://github.com/adriangb).
* 🐛 Fix FastAPI People GitHub Action: set HTTPX timeout for GraphQL query request. PR [#5222](https://github.com/tiangolo/fastapi/pull/5222) by [@iudeen](https://github.com/iudeen).
* 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency. PR [#4319](https://github.com/tiangolo/fastapi/pull/4319) by [@cd17822](https://github.com/cd17822).
* 🐛 Fix support for path parameters in WebSockets. PR [#3879](https://github.com/tiangolo/fastapi/pull/3879) by [@davidbrochart](https://github.com/davidbrochart).
### Docs
* ✏ Update Hypercorn link, now pointing to GitHub. PR [#5346](https://github.com/tiangolo/fastapi/pull/5346) by [@baconfield](https://github.com/baconfield).
* ✏ Tweak wording in `docs/en/docs/advanced/dataclasses.md`. PR [#3698](https://github.com/tiangolo/fastapi/pull/3698) by [@pfackeldey](https://github.com/pfackeldey).
* 📝 Add note about Python 3.10 `X | Y` operator in explanation about Response Models. PR [#5307](https://github.com/tiangolo/fastapi/pull/5307) by [@MendyLanda](https://github.com/MendyLanda).
* 📝 Add link to New Relic article: "How to monitor FastAPI application performance using Python agent". PR [#5260](https://github.com/tiangolo/fastapi/pull/5260) by [@sjyothi54](https://github.com/sjyothi54).
* 📝 Update docs for `ORJSONResponse` with details about improving performance. PR [#2615](https://github.com/tiangolo/fastapi/pull/2615) by [@falkben](https://github.com/falkben). * 📝 Update docs for `ORJSONResponse` with details about improving performance. PR [#2615](https://github.com/tiangolo/fastapi/pull/2615) by [@falkben](https://github.com/falkben).
* 📝 Add docs for creating a custom Response class. PR [#5331](https://github.com/tiangolo/fastapi/pull/5331) by [@tiangolo](https://github.com/tiangolo). * 📝 Add docs for creating a custom Response class. PR [#5331](https://github.com/tiangolo/fastapi/pull/5331) by [@tiangolo](https://github.com/tiangolo).
* 📝 Add tip about using alias for form data fields. PR [#5329](https://github.com/tiangolo/fastapi/pull/5329) by [@tiangolo](https://github.com/tiangolo). * 📝 Add tip about using alias for form data fields. PR [#5329](https://github.com/tiangolo/fastapi/pull/5329) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix support for path parameters in WebSockets. PR [#3879](https://github.com/tiangolo/fastapi/pull/3879) by [@davidbrochart](https://github.com/davidbrochart).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/features.md`. PR [#5315](https://github.com/tiangolo/fastapi/pull/5315) by [@Xewus](https://github.com/Xewus).
* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/request-files.md`. PR [#4529](https://github.com/tiangolo/fastapi/pull/4529) by [@ASpathfinder](https://github.com/ASpathfinder).
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/encoder.md`. PR [#4969](https://github.com/tiangolo/fastapi/pull/4969) by [@Zssaer](https://github.com/Zssaer).
* 🌐 Fix MkDocs file line for Portuguese translation of `background-task.md`. PR [#5242](https://github.com/tiangolo/fastapi/pull/5242) by [@ComicShrimp](https://github.com/ComicShrimp).
### Internal
* 👥 Update FastAPI People. PR [#5347](https://github.com/tiangolo/fastapi/pull/5347) by [@github-actions[bot]](https://github.com/apps/github-actions).
* ⬆ Bump dawidd6/action-download-artifact from 2.22.0 to 2.23.0. PR [#5321](https://github.com/tiangolo/fastapi/pull/5321) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5318](https://github.com/tiangolo/fastapi/pull/5318) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ✏ Fix a small code highlight line error. PR [#5256](https://github.com/tiangolo/fastapi/pull/5256) by [@hjlarry](https://github.com/hjlarry).
* ♻ Internal small refactor, move `operation_id` parameter position in delete method for consistency with the code. PR [#4474](https://github.com/tiangolo/fastapi/pull/4474) by [@hiel](https://github.com/hiel).
* 🔧 Update sponsors, disable ImgWhale. PR [#5338](https://github.com/tiangolo/fastapi/pull/5338) by [@tiangolo](https://github.com/tiangolo).
## 0.81.0 ## 0.81.0

2
docs/en/docs/tutorial/query-params-str-validations.md

@ -216,7 +216,7 @@ To do that, you can declare that `None` is a valid type but still use `default=.
=== "Python 3.6 and above" === "Python 3.6 and above"
```Python hl_lines="8" ```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006c.py!} {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
``` ```

2
docs/en/docs/tutorial/response-model.md

@ -168,7 +168,7 @@ Your response model could have default values, like:
{!> ../../../docs_src/response_model/tutorial004_py310.py!} {!> ../../../docs_src/response_model/tutorial004_py310.py!}
``` ```
* `description: Union[str, None] = None` has a default of `None`. * `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
* `tax: float = 10.5` has a default of `10.5`. * `tax: float = 10.5` has a default of `10.5`.
* `tags: List[str] = []` as a default of an empty list: `[]`. * `tags: List[str] = []` as a default of an empty list: `[]`.

2
docs/es/docs/index.md

@ -106,7 +106,7 @@ Si estás construyendo un app de <abbr title="Interfaz de línea de comandos en
## Requisitos ## Requisitos
Python 3.6+ Python 3.7+
FastAPI está sobre los hombros de gigantes: FastAPI está sobre los hombros de gigantes:

2
docs/fr/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

2
docs/id/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

2
docs/it/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

45
docs/ja/docs/contributing.md

@ -88,62 +88,29 @@ $ python -m venv env
!!! tip "豆知識" !!! tip "豆知識"
この環境で`pip`を使って新しいパッケージをインストールするたびに、仮想環境を再度有効化します。 この環境で`pip`を使って新しいパッケージをインストールするたびに、仮想環境を再度有効化します。
これにより、そのパッケージによってインストールされたターミナルのプログラム (`flit`など) を使用する場合、ローカル環境のものを使用し、グローバルにインストールされたものは使用されなくなります。 これにより、そのパッケージによってインストールされたターミナルのプログラム を使用する場合、ローカル環境のものを使用し、グローバルにインストールされたものは使用されなくなります。
### Flit ### pip
**FastAPI**は<a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> を使って、ビルド、パッケージ化、公開します。 上記のように環境を有効化した後:
上記のように環境を有効化した後、`flit`をインストールします:
<div class="termy"> <div class="termy">
```console ```console
$ pip install flit $ pip install -e .[dev,doc,test]
---> 100% ---> 100%
``` ```
</div> </div>
次に、環境を再び有効化して、インストールしたばかりの`flit` (グローバルではない) を使用していることを確認します。
そして、`flit`を使用して開発のための依存関係をインストールします:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
Windowsユーザーは、`--symlink`のかわりに`--pth-file`を使用します:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
これで、すべての依存関係とFastAPIを、ローカル環境にインストールします。 これで、すべての依存関係とFastAPIを、ローカル環境にインストールします。
#### ローカル環境でFastAPIを使う #### ローカル環境でFastAPIを使う
FastAPIをインポートして使用するPythonファイルを作成し、ローカル環境で実行すると、ローカルのFastAPIソースコードが使用されます。 FastAPIをインポートして使用するPythonファイルを作成し、ローカル環境で実行すると、ローカルのFastAPIソースコードが使用されます。
そして、`--symlink` (Windowsでは` --pth-file`) でインストールされているローカルのFastAPIソースコードを更新した場合、そのPythonファイルを再度実行すると、更新したばかりの新しいバージョンのFastAPIが使用されます。 そして、`-e` でインストールされているローカルのFastAPIソースコードを更新した場合、そのPythonファイルを再度実行すると、更新したばかりの新しいバージョンのFastAPIが使用されます。
これにより、ローカルバージョンを「インストール」しなくても、すべての変更をテストできます。 これにより、ローカルバージョンを「インストール」しなくても、すべての変更をテストできます。
@ -161,7 +128,7 @@ $ bash scripts/format.sh
また、すべてのインポートを自動でソートします。 また、すべてのインポートを自動でソートします。
正しく並べ替えるには、上記セクションのコマンドで `--symlink` (Windowsの場合は` --pth-file`) を使い、FastAPIをローカル環境にインストールしている必要があります。 正しく並べ替えるには、上記セクションのコマンドで `-e` を使い、FastAPIをローカル環境にインストールしている必要があります。
### インポートの整形 ### インポートの整形

2
docs/ja/docs/index.md

@ -107,7 +107,7 @@ FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以
## 必要条件 ## 必要条件
Python 3.6+ Python 3.7+
FastAPI は巨人の肩の上に立っています。 FastAPI は巨人の肩の上に立っています。

2
docs/ko/docs/index.md

@ -107,7 +107,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
## 요구사항 ## 요구사항
Python 3.6+ Python 3.7+
FastAPI는 거인들의 어깨 위에 서 있습니다: FastAPI는 거인들의 어깨 위에 서 있습니다:

2
docs/nl/docs/index.md

@ -114,7 +114,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

2
docs/pl/docs/index.md

@ -106,7 +106,7 @@ Jeżeli tworzysz aplikacje <abbr title="aplikacja z interfejsem konsolowym">CLI<
## Wymagania ## Wymagania
Python 3.6+ Python 3.7+
FastAPI oparty jest na: FastAPI oparty jest na:

44
docs/pt/docs/contributing.md

@ -89,61 +89,29 @@ Se ele exibir o binário `pip` em `env/bin/pip` então funcionou. 🎉
!!! tip !!! tip
Toda vez que você instalar um novo pacote com `pip` nesse ambiente, ative o ambiente novamente. Toda vez que você instalar um novo pacote com `pip` nesse ambiente, ative o ambiente novamente.
Isso garante que se você usar um programa instalado por aquele pacote (como `flit`), você utilizará aquele de seu ambiente local e não outro que possa estar instalado globalmente. Isso garante que se você usar um programa instalado por aquele pacote, você utilizará aquele de seu ambiente local e não outro que possa estar instalado globalmente.
### Flit ### pip
**FastAPI** utiliza <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> para construir, empacotar e publicar o projeto. Após ativar o ambiente como descrito acima:
Após ativar o ambiente como descrito acima, instale o `flit`:
<div class="termy"> <div class="termy">
```console ```console
$ pip install flit $ pip install -e .[dev,doc,test]
---> 100% ---> 100%
``` ```
</div> </div>
Ative novamente o ambiente para ter certeza que você esteja utilizando o `flit` que você acabou de instalar (e não um global).
E agora use `flit` para instalar as dependências de desenvolvimento:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
Se você está no Windows, use `--pth-file` ao invés de `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
Isso irá instalar todas as dependências e seu FastAPI local em seu ambiente local. Isso irá instalar todas as dependências e seu FastAPI local em seu ambiente local.
#### Usando seu FastAPI local #### Usando seu FastAPI local
Se você cria um arquivo Python que importa e usa FastAPI, e roda com Python de seu ambiente local, ele irá utilizar o código fonte de seu FastAPI local. Se você cria um arquivo Python que importa e usa FastAPI, e roda com Python de seu ambiente local, ele irá utilizar o código fonte de seu FastAPI local.
E se você atualizar o código fonte do FastAPI local, como ele é instalado com `--symlink` (ou `--pth-file` no Windows), quando você rodar aquele arquivo Python novamente, ele irá utilizar a nova versão do FastAPI que você acabou de editar. E se você atualizar o código fonte do FastAPI local, como ele é instalado com `-e`, quando você rodar aquele arquivo Python novamente, ele irá utilizar a nova versão do FastAPI que você acabou de editar.
Desse modo, você não tem que "instalar" sua versão local para ser capaz de testar cada mudança. Desse modo, você não tem que "instalar" sua versão local para ser capaz de testar cada mudança.
@ -161,7 +129,7 @@ $ bash scripts/format.sh
Ele irá organizar também todos os seus imports. Ele irá organizar também todos os seus imports.
Para que ele organize os imports corretamente, você precisa ter o FastAPI instalado localmente em seu ambiente, com o comando na seção acima usando `--symlink` (ou `--pth-file` no Windows). Para que ele organize os imports corretamente, você precisa ter o FastAPI instalado localmente em seu ambiente, com o comando na seção acima usando `-e`.
### Formato dos imports ### Formato dos imports

2
docs/pt/docs/index.md

@ -100,7 +100,7 @@ Se você estiver construindo uma aplicação <abbr title="Command Line Interface
## Requisitos ## Requisitos
Python 3.6+ Python 3.7+
FastAPI está nos ombros de gigantes: FastAPI está nos ombros de gigantes:

1
docs/pt/mkdocs.yml

@ -74,6 +74,7 @@ nav:
- tutorial/handling-errors.md - tutorial/handling-errors.md
- Segurança: - Segurança:
- tutorial/security/index.md - tutorial/security/index.md
- tutorial/background-tasks.md
- Guia de Usuário Avançado: - Guia de Usuário Avançado:
- advanced/index.md - advanced/index.md
- Implantação: - Implantação:

203
docs/ru/docs/features.md

@ -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 прямо из браузера.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Альтернативная документация API в <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Только современный 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>:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
* в <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Вы будете получать автодополнение кода даже там, где вы считали это невозможным раньше.
Как пример, ключ `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% покрытие тестами.

2
docs/ru/docs/index.md

@ -109,7 +109,7 @@ FastAPI — это современный, быстрый (высокопрои
## Зависимости ## Зависимости
Python 3.6+ Python 3.7+
FastAPI стоит на плечах гигантов: FastAPI стоит на плечах гигантов:

1
docs/ru/mkdocs.yml

@ -58,6 +58,7 @@ nav:
- tr: /tr/ - tr: /tr/
- uk: /uk/ - uk: /uk/
- zh: /zh/ - zh: /zh/
- features.md
- python-types.md - python-types.md
- Учебник - руководство пользователя: - Учебник - руководство пользователя:
- tutorial/background-tasks.md - tutorial/background-tasks.md

2
docs/sq/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

2
docs/sv/docs/index.md

@ -114,7 +114,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

2
docs/tr/docs/index.md

@ -119,7 +119,7 @@ Eğer API yerine <abbr title="Command Line Interface">komut satırı uygulaması
## Gereksinimler ## Gereksinimler
Python 3.6+ Python 3.7+
FastAPI iki devin omuzları üstünde duruyor: FastAPI iki devin omuzları üstünde duruyor:

2
docs/uk/docs/index.md

@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements ## Requirements
Python 3.6+ Python 3.7+
FastAPI stands on the shoulders of giants: FastAPI stands on the shoulders of giants:

44
docs/zh/docs/contributing.md

@ -88,61 +88,29 @@ $ python -m venv env
!!! tip !!! tip
每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。 每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。
这样可以确保你在使用由该软件包安装的终端程序(如 `flit`时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。 这样可以确保你在使用由该软件包安装的终端程序时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。
### Flit ### pip
**FastAPI** 使用 <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> 来构建、打包和发布项目。 如上所述激活环境后:
如上所述激活环境后,安装 `flit`
<div class="termy"> <div class="termy">
```console ```console
$ pip install flit $ pip install -e .[dev,doc,test]
---> 100% ---> 100%
``` ```
</div> </div>
现在重新激活环境,以确保你正在使用的是刚刚安装的 `flit`(而不是全局环境的)。
然后使用 `flit` 来安装开发依赖:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
If you are on Windows, use `--pth-file` instead of `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
这将在虚拟环境中安装所有依赖和本地版本的 FastAPI。 这将在虚拟环境中安装所有依赖和本地版本的 FastAPI。
#### 使用本地 FastAPI #### 使用本地 FastAPI
如果你创建一个导入并使用 FastAPI 的 Python 文件,然后使用虚拟环境中的 Python 运行它,它将使用你本地的 FastAPI 源码。 如果你创建一个导入并使用 FastAPI 的 Python 文件,然后使用虚拟环境中的 Python 运行它,它将使用你本地的 FastAPI 源码。
并且如果你更改该本地 FastAPI 的源码,由于它是通过 `--symlink` (或 Windows 上的 `--pth-file`安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。 并且如果你更改该本地 FastAPI 的源码,由于它是通过 `-e` 安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。
这样,你不必再去重新"安装"你的本地版本即可测试所有更改。 这样,你不必再去重新"安装"你的本地版本即可测试所有更改。
@ -160,7 +128,7 @@ $ bash scripts/format.sh
它还会自动对所有导入代码进行整理。 它还会自动对所有导入代码进行整理。
为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `--symlink`(或 Windows 上的 `--pth-file` 为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `-e`
### 格式化导入 ### 格式化导入

42
docs/zh/docs/tutorial/encoder.md

@ -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内部用来转换数据的。但是它在许多其他场景中也很有用。

63
docs/zh/docs/tutorial/request-files.md

@ -44,9 +44,9 @@
不过,很多情况下,`UploadFile` 更好用。 不过,很多情况下,`UploadFile` 更好用。
## 含 `UploadFile` `File` 参数 ## 含 `UploadFile`文件参数
定义 `File` 参数时使用 `UploadFile` 定义文件参数时使用 `UploadFile`
```Python hl_lines="12" ```Python hl_lines="12"
{!../../../docs_src/request_files/tutorial001.py!} {!../../../docs_src/request_files/tutorial001.py!}
@ -94,7 +94,7 @@ contents = myfile.file.read()
!!! note "`async` 技术细节" !!! note "`async` 技术细节"
使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `awiat` 操作完成。 使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `await` 操作完成。
!!! note "Starlette 技术细节" !!! note "Starlette 技术细节"
@ -120,6 +120,30 @@ contents = myfile.file.read()
这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## 可选文件上传
您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
=== "Python 3.6 及以上版本"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
=== "Python 3.9 及以上版本"
```Python hl_lines="7 14"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
## 带有额外元数据的 `UploadFile`
您也可以将 `File()``UploadFile` 一起使用,例如,设置额外的元数据:
```Python hl_lines="13"
{!../../../docs_src/request_files/tutorial001_03.py!}
```
## 多文件上传 ## 多文件上传
FastAPI 支持同时上传多个文件。 FastAPI 支持同时上传多个文件。
@ -128,19 +152,20 @@ FastAPI 支持同时上传多个文件。
上传多个文件时,要声明含 `bytes``UploadFile` 的列表(`List`): 上传多个文件时,要声明含 `bytes``UploadFile` 的列表(`List`):
```Python hl_lines="10 15" === "Python 3.6 及以上版本"
{!../../../docs_src/request_files/tutorial002.py!}
```
接收的也是含 `bytes``UploadFile` 的列表(`list`)。 ```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
!!! note "笔记" === "Python 3.9 及以上版本"
注意,截至 2019 年 4 月 14 日,Swagger UI 不支持在同一个表单字段中上传多个文件。详见 <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a><a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>. ```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
不过,**FastAPI** 已通过 OpenAPI 标准与之兼容。 接收的也是含 `bytes``UploadFile` 的列表(`list`)
因此,只要 Swagger UI 或任何其他支持 OpenAPI 的工具支持多文件上传,都将与 **FastAPI** 兼容。
!!! note "技术细节" !!! note "技术细节"
@ -148,6 +173,22 @@ FastAPI 支持同时上传多个文件。
`fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。 `fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。
### 带有额外元数据的多文件上传
和之前的方式一样, 您可以为 `File()` 设置额外参数, 即使是 `UploadFile`:
=== "Python 3.6 及以上版本"
```Python hl_lines="18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
=== "Python 3.9 及以上版本"
```Python hl_lines="16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
## 小结 ## 小结
本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。 本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。

1
docs/zh/mkdocs.yml

@ -85,6 +85,7 @@ nav:
- tutorial/request-forms-and-files.md - tutorial/request-forms-and-files.md
- tutorial/handling-errors.md - tutorial/handling-errors.md
- tutorial/path-operation-configuration.md - tutorial/path-operation-configuration.md
- tutorial/encoder.md
- tutorial/body-updates.md - tutorial/body-updates.md
- 依赖项: - 依赖项:
- tutorial/dependencies/index.md - tutorial/dependencies/index.md

2
fastapi/__init__.py

@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" """FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.81.0" __version__ = "0.85.1"
from starlette import status as status from starlette import status as status

3
fastapi/applications.py

@ -33,9 +33,10 @@ from fastapi.types import DecoratedCallable
from fastapi.utils import generate_unique_id from fastapi.utils import generate_unique_id
from starlette.applications import Starlette from starlette.applications import Starlette
from starlette.datastructures import State from starlette.datastructures import State
from starlette.exceptions import ExceptionMiddleware, HTTPException from starlette.exceptions import HTTPException
from starlette.middleware import Middleware from starlette.middleware import Middleware
from starlette.middleware.errors import ServerErrorMiddleware from starlette.middleware.errors import ServerErrorMiddleware
from starlette.middleware.exceptions import ExceptionMiddleware
from starlette.requests import Request from starlette.requests import Request
from starlette.responses import HTMLResponse, JSONResponse, Response from starlette.responses import HTMLResponse, JSONResponse, Response
from starlette.routing import BaseRoute from starlette.routing import BaseRoute

30
fastapi/concurrency.py

@ -1,20 +1,15 @@
import sys from contextlib import AsyncExitStack as AsyncExitStack # noqa
from contextlib import asynccontextmanager as asynccontextmanager
from typing import AsyncGenerator, ContextManager, TypeVar from typing import AsyncGenerator, ContextManager, TypeVar
import anyio
from anyio import CapacityLimiter
from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa
from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa
from starlette.concurrency import ( # noqa from starlette.concurrency import ( # noqa
run_until_first_complete as run_until_first_complete, run_until_first_complete as run_until_first_complete,
) )
if sys.version_info >= (3, 7):
from contextlib import AsyncExitStack as AsyncExitStack
from contextlib import asynccontextmanager as asynccontextmanager
else:
from contextlib2 import AsyncExitStack as AsyncExitStack # noqa
from contextlib2 import asynccontextmanager as asynccontextmanager # noqa
_T = TypeVar("_T") _T = TypeVar("_T")
@ -22,11 +17,24 @@ _T = TypeVar("_T")
async def contextmanager_in_threadpool( async def contextmanager_in_threadpool(
cm: ContextManager[_T], cm: ContextManager[_T],
) -> AsyncGenerator[_T, None]: ) -> AsyncGenerator[_T, None]:
# blocking __exit__ from running waiting on a free thread
# can create race conditions/deadlocks if the context manager itself
# has it's own internal pool (e.g. a database connection pool)
# to avoid this we let __exit__ run without a capacity limit
# since we're creating a new limiter for each call, any non-zero limit
# works (1 is arbitrary)
exit_limiter = CapacityLimiter(1)
try: try:
yield await run_in_threadpool(cm.__enter__) yield await run_in_threadpool(cm.__enter__)
except Exception as e: except Exception as e:
ok: bool = await run_in_threadpool(cm.__exit__, type(e), e, None) ok = bool(
await anyio.to_thread.run_sync(
cm.__exit__, type(e), e, None, limiter=exit_limiter
)
)
if not ok: if not ok:
raise e raise e
else: else:
await run_in_threadpool(cm.__exit__, None, None, None) await anyio.to_thread.run_sync(
cm.__exit__, None, None, None, limiter=exit_limiter
)

15
fastapi/dependencies/utils.py

@ -7,6 +7,7 @@ from typing import (
Callable, Callable,
Coroutine, Coroutine,
Dict, Dict,
ForwardRef,
List, List,
Mapping, Mapping,
Optional, Optional,
@ -47,7 +48,7 @@ from pydantic.fields import (
Undefined, Undefined,
) )
from pydantic.schema import get_annotation_from_field_info from pydantic.schema import get_annotation_from_field_info
from pydantic.typing import ForwardRef, evaluate_forwardref from pydantic.typing import evaluate_forwardref
from pydantic.utils import lenient_issubclass from pydantic.utils import lenient_issubclass
from starlette.background import BackgroundTasks from starlette.background import BackgroundTasks
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
@ -449,22 +450,22 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool:
return inspect.iscoroutinefunction(call) return inspect.iscoroutinefunction(call)
if inspect.isclass(call): if inspect.isclass(call):
return False return False
call = getattr(call, "__call__", None) dunder_call = getattr(call, "__call__", None)
return inspect.iscoroutinefunction(call) return inspect.iscoroutinefunction(dunder_call)
def is_async_gen_callable(call: Callable[..., Any]) -> bool: def is_async_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isasyncgenfunction(call): if inspect.isasyncgenfunction(call):
return True return True
call = getattr(call, "__call__", None) dunder_call = getattr(call, "__call__", None)
return inspect.isasyncgenfunction(call) return inspect.isasyncgenfunction(dunder_call)
def is_gen_callable(call: Callable[..., Any]) -> bool: def is_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isgeneratorfunction(call): if inspect.isgeneratorfunction(call):
return True return True
call = getattr(call, "__call__", None) dunder_call = getattr(call, "__call__", None)
return inspect.isgeneratorfunction(call) return inspect.isgeneratorfunction(dunder_call)
async def solve_generator( async def solve_generator(

10
fastapi/encoders.py

@ -54,8 +54,8 @@ def jsonable_encoder(
if custom_encoder: if custom_encoder:
encoder.update(custom_encoder) encoder.update(custom_encoder)
obj_dict = obj.dict( obj_dict = obj.dict(
include=include, # type: ignore # in Pydantic include=include,
exclude=exclude, # type: ignore # in Pydantic exclude=exclude,
by_alias=by_alias, by_alias=by_alias,
exclude_unset=exclude_unset, exclude_unset=exclude_unset,
exclude_none=exclude_none, exclude_none=exclude_none,
@ -74,8 +74,12 @@ def jsonable_encoder(
obj_dict = dataclasses.asdict(obj) obj_dict = dataclasses.asdict(obj)
return jsonable_encoder( return jsonable_encoder(
obj_dict, obj_dict,
exclude_none=exclude_none, include=include,
exclude=exclude,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults, exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
custom_encoder=custom_encoder, custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe, sqlalchemy_safe=sqlalchemy_safe,
) )

16
fastapi/exception_handlers.py

@ -1,19 +1,19 @@
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError from fastapi.exceptions import RequestValidationError
from fastapi.utils import is_body_allowed_for_status_code
from starlette.exceptions import HTTPException from starlette.exceptions import HTTPException
from starlette.requests import Request from starlette.requests import Request
from starlette.responses import JSONResponse from starlette.responses import JSONResponse, Response
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse: async def http_exception_handler(request: Request, exc: HTTPException) -> Response:
headers = getattr(exc, "headers", None) headers = getattr(exc, "headers", None)
if headers: if not is_body_allowed_for_status_code(exc.status_code):
return JSONResponse( return Response(status_code=exc.status_code, headers=headers)
{"detail": exc.detail}, status_code=exc.status_code, headers=headers return JSONResponse(
) {"detail": exc.detail}, status_code=exc.status_code, headers=headers
else: )
return JSONResponse({"detail": exc.detail}, status_code=exc.status_code)
async def request_validation_exception_handler( async def request_validation_exception_handler(

4
fastapi/routing.py

@ -127,7 +127,7 @@ async def serialize_response(
if is_coroutine: if is_coroutine:
value, errors_ = field.validate(response_content, {}, loc=("response",)) value, errors_ = field.validate(response_content, {}, loc=("response",))
else: else:
value, errors_ = await run_in_threadpool( # type: ignore[misc] value, errors_ = await run_in_threadpool(
field.validate, response_content, {}, loc=("response",) field.validate, response_content, {}, loc=("response",)
) )
if isinstance(errors_, ErrorWrapper): if isinstance(errors_, ErrorWrapper):
@ -258,7 +258,7 @@ def get_request_handler(
is_coroutine=is_coroutine, is_coroutine=is_coroutine,
) )
response = actual_response_class(content, **response_args) response = actual_response_class(content, **response_args)
if not is_body_allowed_for_status_code(status_code): if not is_body_allowed_for_status_code(response.status_code):
response.body = b"" response.body = b""
response.headers.raw.extend(sub_response.headers.raw) response.headers.raw.extend(sub_response.headers.raw)
return response return response

2
fastapi/security/api_key.py

@ -27,7 +27,7 @@ class APIKeyQuery(APIKeyBase):
self.auto_error = auto_error self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]: async def __call__(self, request: Request) -> Optional[str]:
api_key: str = request.query_params.get(self.model.name) api_key = request.query_params.get(self.model.name)
if not api_key: if not api_key:
if self.auto_error: if self.auto_error:
raise HTTPException( raise HTTPException(

10
fastapi/utils.py

@ -21,6 +21,16 @@ if TYPE_CHECKING: # pragma: nocover
def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
if status_code is None: if status_code is None:
return True return True
# Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1
if status_code in {
"default",
"1XX",
"2XX",
"3XX",
"4XX",
"5XX",
}:
return True
current_status_code = int(status_code) current_status_code = int(status_code)
return not (current_status_code < 200 or current_status_code in {204, 304}) return not (current_status_code < 200 or current_status_code in {204, 304})

1
fastapi/websockets.py

@ -1,2 +1,3 @@
from starlette.websockets import WebSocket as WebSocket # noqa from starlette.websockets import WebSocket as WebSocket # noqa
from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa
from starlette.websockets import WebSocketState as WebSocketState # noqa

66
pyproject.toml

@ -1,12 +1,16 @@
[build-system] [build-system]
requires = ["flit"] requires = ["hatchling"]
build-backend = "flit.buildapi" build-backend = "hatchling.build"
[tool.flit.metadata] [project]
module = "fastapi" name = "fastapi"
author = "Sebastián Ramírez" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
author-email = "[email protected]" readme = "README.md"
home-page = "https://github.com/tiangolo/fastapi" requires-python = ">=3.7"
license = "MIT"
authors = [
{ name = "Sebastián Ramírez", email = "[email protected]" },
]
classifiers = [ classifiers = [
"Intended Audience :: Information Technology", "Intended Audience :: Information Technology",
"Intended Audience :: System Administrators", "Intended Audience :: System Administrators",
@ -26,7 +30,6 @@ classifiers = [
"Intended Audience :: Developers", "Intended Audience :: Developers",
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
@ -34,40 +37,44 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
"Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP",
] ]
requires = [ dependencies = [
"starlette==0.19.1", "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", "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" dynamic = ["version"]
requires-python = ">=3.6.1"
[tool.flit.metadata.urls] [project.urls]
Homepage = "https://github.com/tiangolo/fastapi"
Documentation = "https://fastapi.tiangolo.com/" Documentation = "https://fastapi.tiangolo.com/"
[tool.flit.metadata.requires-extra] [project.optional-dependencies]
test = [ test = [
"pytest >=6.2.4,<7.0.0", "pytest >=7.1.3,<8.0.0",
"pytest-cov >=2.12.0,<4.0.0", "pytest-cov >=2.12.0,<4.0.0",
"mypy ==0.910", "mypy ==0.971",
"flake8 >=3.8.3,<6.0.0", "flake8 >=3.8.3,<6.0.0",
"black == 22.3.0", "black == 22.8.0",
"isort >=5.0.6,<6.0.0", "isort >=5.0.6,<6.0.0",
"requests >=2.24.0,<3.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", "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", "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", "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", "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", "python-multipart >=0.0.5,<0.0.6",
"flask >=1.1.2,<3.0.0", "flask >=1.1.2,<3.0.0",
"anyio[trio] >=3.2.1,<4.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
"types-ujson ==4.2.1", "types-ujson ==5.4.0",
"types-orjson ==3.6.2", "types-orjson ==3.6.2",
"types-dataclasses ==0.6.5; python_version<'3.7'",
] ]
doc = [ doc = [
"mkdocs >=1.1.2,<2.0.0", "mkdocs >=1.1.2,<2.0.0",
@ -76,15 +83,13 @@ doc = [
"mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0", "mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0",
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x # TODO: upgrade and enable typer-cli once it supports Click 8.x.x
# "typer-cli >=0.0.12,<0.0.13", # "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", "pyyaml >=5.3.1,<7.0.0",
] ]
dev = [ 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", "autoflake >=1.4.0,<2.0.0",
"flake8 >=3.8.3,<6.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", "pre-commit >=2.17.0,<3.0.0",
] ]
all = [ 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", "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", "orjson >=3.2.1,<4.0.0",
"email_validator >=1.1.1,<2.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] [tool.isort]
profile = "black" profile = "black"
known_third_party = ["fastapi", "pydantic", "starlette"] 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 # 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: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', '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 # see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28
'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', 'ignore::trio.TrioDeprecationWarning',
] ]

5
scripts/docs.py

@ -1,6 +1,7 @@
import os import os
import re import re
import shutil import shutil
import subprocess
from http.server import HTTPServer, SimpleHTTPRequestHandler from http.server import HTTPServer, SimpleHTTPRequestHandler
from multiprocessing import Pool from multiprocessing import Pool
from pathlib import Path from pathlib import Path
@ -200,7 +201,7 @@ def build_lang(
) )
current_dir = os.getcwd() current_dir = os.getcwd()
os.chdir(build_lang_path) os.chdir(build_lang_path)
mkdocs.commands.build.build(mkdocs.config.load_config(site_dir=str(dist_path))) subprocess.run(["mkdocs", "build", "--site-dir", dist_path], check=True)
os.chdir(current_dir) os.chdir(current_dir)
typer.secho(f"Successfully built docs for: {lang}", color=typer.colors.GREEN) typer.secho(f"Successfully built docs for: {lang}", color=typer.colors.GREEN)
@ -275,7 +276,7 @@ def build_all():
current_dir = os.getcwd() current_dir = os.getcwd()
os.chdir(en_docs_path) os.chdir(en_docs_path)
typer.echo("Building docs for: en") typer.echo("Building docs for: en")
mkdocs.commands.build.build(mkdocs.config.load_config(site_dir=str(site_path))) subprocess.run(["mkdocs", "build", "--site-dir", site_path], check=True)
os.chdir(current_dir) os.chdir(current_dir)
langs = [] langs = []
for lang in get_lang_paths(): for lang in get_lang_paths():

63
tests/test_additional_responses_router.py

@ -1,5 +1,11 @@
from fastapi import APIRouter, FastAPI from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel
class ResponseModel(BaseModel):
message: str
app = FastAPI() app = FastAPI()
router = APIRouter() router = APIRouter()
@ -33,6 +39,18 @@ async def c():
return "c" return "c"
@router.get(
"/d",
responses={
"400": {"description": "Error with str"},
"5XX": {"model": ResponseModel},
"default": {"model": ResponseModel},
},
)
async def d():
return "d"
app.include_router(router) app.include_router(router)
openapi_schema = { openapi_schema = {
@ -81,6 +99,45 @@ openapi_schema = {
"operationId": "c_c_get", "operationId": "c_c_get",
} }
}, },
"/d": {
"get": {
"responses": {
"400": {"description": "Error with str"},
"5XX": {
"description": "Server Error",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ResponseModel"}
}
},
},
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"default": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ResponseModel"}
}
},
},
},
"summary": "D",
"operationId": "d_d_get",
}
},
},
"components": {
"schemas": {
"ResponseModel": {
"title": "ResponseModel",
"required": ["message"],
"type": "object",
"properties": {"message": {"title": "Message", "type": "string"}},
}
}
}, },
} }
@ -109,3 +166,9 @@ def test_c():
response = client.get("/c") response = client.get("/c")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == "c" assert response.json() == "c"
def test_d():
response = client.get("/d")
assert response.status_code == 200, response.text
assert response.json() == "d"

16
tests/test_jsonable_encoder.py

@ -1,3 +1,4 @@
from dataclasses import dataclass
from datetime import datetime, timezone from datetime import datetime, timezone
from enum import Enum from enum import Enum
from pathlib import PurePath, PurePosixPath, PureWindowsPath from pathlib import PurePath, PurePosixPath, PureWindowsPath
@ -19,6 +20,12 @@ class Pet:
self.name = name self.name = name
@dataclass
class Item:
name: str
count: int
class DictablePerson(Person): class DictablePerson(Person):
def __iter__(self): def __iter__(self):
return ((k, v) for k, v in self.__dict__.items()) return ((k, v) for k, v in self.__dict__.items())
@ -131,6 +138,15 @@ def test_encode_dictable():
} }
def test_encode_dataclass():
item = Item(name="foo", count=100)
assert jsonable_encoder(item) == {"name": "foo", "count": 100}
assert jsonable_encoder(item, include={"name"}) == {"name": "foo"}
assert jsonable_encoder(item, exclude={"count"}) == {"name": "foo"}
assert jsonable_encoder(item, include={}) == {}
assert jsonable_encoder(item, exclude={}) == {"name": "foo", "count": 100}
def test_encode_unsupported(): def test_encode_unsupported():
unserializable = Unserializable() unserializable = Unserializable()
with pytest.raises(ValueError): with pytest.raises(ValueError):

97
tests/test_reponse_set_reponse_code_empty.py

@ -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}

46
tests/test_starlette_exception.py

@ -18,6 +18,16 @@ async def read_item(item_id: str):
return {"item": items[item_id]} return {"item": items[item_id]}
@app.get("/http-no-body-statuscode-exception")
async def no_body_status_code_exception():
raise HTTPException(status_code=204)
@app.get("/http-no-body-statuscode-with-detail-exception")
async def no_body_status_code_with_detail_exception():
raise HTTPException(status_code=204, detail="I should just disappear!")
@app.get("/starlette-items/{item_id}") @app.get("/starlette-items/{item_id}")
async def read_starlette_item(item_id: str): async def read_starlette_item(item_id: str):
if item_id not in items: if item_id not in items:
@ -31,6 +41,30 @@ openapi_schema = {
"openapi": "3.0.2", "openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"}, "info": {"title": "FastAPI", "version": "0.1.0"},
"paths": { "paths": {
"/http-no-body-statuscode-exception": {
"get": {
"operationId": "no_body_status_code_exception_http_no_body_statuscode_exception_get",
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
}
},
"summary": "No Body " "Status " "Code " "Exception",
}
},
"/http-no-body-statuscode-with-detail-exception": {
"get": {
"operationId": "no_body_status_code_with_detail_exception_http_no_body_statuscode_with_detail_exception_get",
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
}
},
"summary": "No Body Status Code With Detail Exception",
}
},
"/items/{item_id}": { "/items/{item_id}": {
"get": { "get": {
"responses": { "responses": {
@ -154,3 +188,15 @@ def test_get_starlette_item_not_found():
assert response.status_code == 404, response.text assert response.status_code == 404, response.text
assert response.headers.get("x-error") is None assert response.headers.get("x-error") is None
assert response.json() == {"detail": "Item not found"} assert response.json() == {"detail": "Item not found"}
def test_no_body_status_code_exception_handlers():
response = client.get("/http-no-body-statuscode-exception")
assert response.status_code == 204
assert not response.content
def test_no_body_status_code_with_detail_exception_handlers():
response = client.get("/http-no-body-statuscode-with-detail-exception")
assert response.status_code == 204
assert not response.content

10
tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py

@ -5,8 +5,6 @@ from unittest.mock import MagicMock
import pytest import pytest
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py37
openapi_schema = { openapi_schema = {
"openapi": "3.0.2", "openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"}, "info": {"title": "FastAPI", "version": "0.1.0"},
@ -340,14 +338,12 @@ def client():
test_db.unlink() test_db.unlink()
@needs_py37
def test_openapi_schema(client): def test_openapi_schema(client):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == openapi_schema assert response.json() == openapi_schema
@needs_py37
def test_create_user(client): def test_create_user(client):
test_user = {"email": "[email protected]", "password": "secret"} test_user = {"email": "[email protected]", "password": "secret"}
response = client.post("/users/", json=test_user) response = client.post("/users/", json=test_user)
@ -359,7 +355,6 @@ def test_create_user(client):
assert response.status_code == 400, response.text assert response.status_code == 400, response.text
@needs_py37
def test_get_user(client): def test_get_user(client):
response = client.get("/users/1") response = client.get("/users/1")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
@ -368,13 +363,11 @@ def test_get_user(client):
assert "id" in data assert "id" in data
@needs_py37
def test_inexistent_user(client): def test_inexistent_user(client):
response = client.get("/users/999") response = client.get("/users/999")
assert response.status_code == 404, response.text assert response.status_code == 404, response.text
@needs_py37
def test_get_users(client): def test_get_users(client):
response = client.get("/users/") response = client.get("/users/")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
@ -386,7 +379,6 @@ def test_get_users(client):
time.sleep = MagicMock() time.sleep = MagicMock()
@needs_py37
def test_get_slowusers(client): def test_get_slowusers(client):
response = client.get("/slowusers/") response = client.get("/slowusers/")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
@ -395,7 +387,6 @@ def test_get_slowusers(client):
assert "id" in data[0] assert "id" in data[0]
@needs_py37
def test_create_item(client): def test_create_item(client):
item = {"title": "Foo", "description": "Something that fights"} item = {"title": "Foo", "description": "Something that fights"}
response = client.post("/users/1/items/", json=item) response = client.post("/users/1/items/", json=item)
@ -419,7 +410,6 @@ def test_create_item(client):
assert item_to_check["description"] == item["description"] assert item_to_check["description"] == item["description"]
@needs_py37
def test_read_items(client): def test_read_items(client):
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text

11
tests/test_union_inherited_body.py

@ -4,14 +4,6 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
from .utils import needs_py37
# In Python 3.6:
# u = Union[ExtendedItem, Item] == __main__.Item
# But in Python 3.7:
# u = Union[ExtendedItem, Item] == typing.Union[__main__.ExtendedItem, __main__.Item]
app = FastAPI() app = FastAPI()
@ -118,21 +110,18 @@ inherited_item_openapi_schema = {
} }
@needs_py37
def test_inherited_item_openapi_schema(): def test_inherited_item_openapi_schema():
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == inherited_item_openapi_schema assert response.json() == inherited_item_openapi_schema
@needs_py37
def test_post_extended_item(): def test_post_extended_item():
response = client.post("/items/", json={"name": "Foo", "age": 5}) response = client.post("/items/", json={"name": "Foo", "age": 5})
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == {"item": {"name": "Foo", "age": 5}} assert response.json() == {"item": {"name": "Foo", "age": 5}}
@needs_py37
def test_post_item(): def test_post_item():
response = client.post("/items/", json={"name": "Foo"}) response = client.post("/items/", json={"name": "Foo"})
assert response.status_code == 200, response.text assert response.status_code == 200, response.text

1
tests/utils.py

@ -2,7 +2,6 @@ import sys
import pytest import pytest
needs_py37 = pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7+")
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+") needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
needs_py310 = pytest.mark.skipif( needs_py310 = pytest.mark.skipif(
sys.version_info < (3, 10), reason="requires python3.10+" sys.version_info < (3, 10), reason="requires python3.10+"

Loading…
Cancel
Save