diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 8176602a75f40..322b6536a760c 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -8,9 +8,9 @@ body: Thanks for your interest in FastAPI! 🚀 Please follow these instructions, fill every question, and do every step. 🙏 - + I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time. - + I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues. All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others. @@ -18,7 +18,7 @@ body: That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅). By asking questions in a structured way (following this) it will be much easier to help you. - + And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎 As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓 @@ -50,7 +50,7 @@ body: label: Commit to Help description: | After submitting this, I commit to one of: - + * Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there. * I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future. * Implement a Pull Request for a confirmed bug. diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 5c76fd17eff15..3b16b4ad0c156 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -8,9 +8,9 @@ body: Thanks for your interest in FastAPI! 🚀 Please follow these instructions, fill every question, and do every step. 🙏 - + I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time. - + I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues. All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others. @@ -18,7 +18,7 @@ body: That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅). By asking questions in a structured way (following this) it will be much easier to help you. - + And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎 As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓 @@ -50,7 +50,7 @@ body: label: Commit to Help description: | After submitting this, I commit to one of: - + * Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there. * I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future. * Implement a Pull Request for a confirmed bug. diff --git a/.github/actions/comment-docs-preview-in-pr/app/main.py b/.github/actions/comment-docs-preview-in-pr/app/main.py index 3b10e0ee089e1..c9fb7cbbefac6 100644 --- a/.github/actions/comment-docs-preview-in-pr/app/main.py +++ b/.github/actions/comment-docs-preview-in-pr/app/main.py @@ -48,9 +48,7 @@ class PartialGithubEvent(BaseModel): use_pr = pr break if not use_pr: - logging.error( - f"No PR found for hash: {event.workflow_run.head_commit.id}" - ) + logging.error(f"No PR found for hash: {event.workflow_run.head_commit.id}") sys.exit(0) github_headers = { "Authorization": f"token {settings.input_token.get_secret_value()}" diff --git a/.github/actions/notify-translations/app/main.py b/.github/actions/notify-translations/app/main.py index 7d6c1a4d20a7f..823685e00b122 100644 --- a/.github/actions/notify-translations/app/main.py +++ b/.github/actions/notify-translations/app/main.py @@ -1,7 +1,7 @@ import logging +import random import time from pathlib import Path -import random from typing import Dict, Optional import yaml @@ -54,7 +54,7 @@ class PartialGitHubEvent(BaseModel): ) if pr.state == "open": logging.debug(f"PR is open: {pr.number}") - label_strs = set([label.name for label in pr.get_labels()]) + label_strs = {label.name for label in pr.get_labels()} if lang_all_label in label_strs and awaiting_label in label_strs: logging.info( f"This PR seems to be a language translation and awaiting reviews: {pr.number}" diff --git a/.github/actions/notify-translations/app/translations.yml b/.github/actions/notify-translations/app/translations.yml index decd63498b70a..0e5093f3acd0b 100644 --- a/.github/actions/notify-translations/app/translations.yml +++ b/.github/actions/notify-translations/app/translations.yml @@ -13,3 +13,5 @@ pl: 3169 de: 3716 id: 3717 az: 3994 +nl: 4701 +uz: 4883 diff --git a/.github/actions/people/app/main.py b/.github/actions/people/app/main.py index dc0bbc4c0a0d0..9de6fc2505856 100644 --- a/.github/actions/people/app/main.py +++ b/.github/actions/people/app/main.py @@ -14,7 +14,7 @@ github_graphql_url = "https://api.github.com/graphql" issues_query = """ -query Q($after: String) { +query Q($after: String) { repository(name: "fastapi", owner: "tiangolo") { issues(first: 100, after: $after) { edges { @@ -47,7 +47,7 @@ """ prs_query = """ -query Q($after: String) { +query Q($after: String) { repository(name: "fastapi", owner: "tiangolo") { pullRequests(first: 100, after: $after) { edges { @@ -501,9 +501,16 @@ def get_top_users( github_sponsors_path = Path("./docs/en/data/github_sponsors.yml") people_old_content = people_path.read_text(encoding="utf-8") github_sponsors_old_content = github_sponsors_path.read_text(encoding="utf-8") - new_people_content = yaml.dump(people, sort_keys=False, width=200, allow_unicode=True) - new_github_sponsors_content = yaml.dump(github_sponsors, sort_keys=False, width=200, allow_unicode=True) - if people_old_content == new_people_content and github_sponsors_old_content == new_github_sponsors_content: + new_people_content = yaml.dump( + people, sort_keys=False, width=200, allow_unicode=True + ) + new_github_sponsors_content = yaml.dump( + github_sponsors, sort_keys=False, width=200, allow_unicode=True + ) + if ( + people_old_content == new_people_content + and github_sponsors_old_content == new_github_sponsors_content + ): logging.info("The FastAPI People data hasn't changed, finishing.") sys.exit(0) people_path.write_text(new_people_content, encoding="utf-8") @@ -517,7 +524,9 @@ def get_top_users( logging.info(f"Creating a new branch {branch_name}") subprocess.run(["git", "checkout", "-b", branch_name], check=True) logging.info("Adding updated file") - subprocess.run(["git", "add", str(people_path)], check=True) + subprocess.run( + ["git", "add", str(people_path), str(github_sponsors_path)], check=True + ) logging.info("Committing updated file") message = "👥 Update FastAPI People" result = subprocess.run(["git", "commit", "-m", message], check=True) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 2482660f3bdca..505d66f9f1589 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -22,7 +22,7 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs-v2 + 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 @@ -30,7 +30,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: python3.7 -m flit install --deps production --extras doc - name: Install Material for MkDocs Insiders - if: 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 - name: Build Docs run: python3.7 ./scripts/docs.py build-all diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 42236bebaa585..5783c993a0175 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -12,7 +12,7 @@ on: description: PR number required: true debug_enabled: - description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false default: false diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 970813da7b107..2004ee7b3ad5c 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: inputs: debug_enabled: - description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false default: false diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index 0c0d2ac59a9e6..104c2677f4d35 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -3,7 +3,7 @@ on: workflow_run: workflows: - Build Docs - types: + types: - completed jobs: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 21ea7c1a8d0bd..f0a82344e43ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test + 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 @@ -38,4 +38,4 @@ jobs: - name: Test run: bash scripts/test.sh - name: Upload coverage - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000..5c278571e63f1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,51 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.0 + hooks: + - id: check-added-large-files + - id: check-toml + - id: check-yaml + args: + - --unsafe + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/asottile/pyupgrade + rev: v2.32.1 + hooks: + - id: pyupgrade + args: + - --py3-plus + - --keep-runtime-typing +- repo: https://github.com/myint/autoflake + rev: v1.4 + hooks: + - id: autoflake + args: + - --recursive + - --in-place + - --remove-all-unused-imports + - --remove-unused-variables + - --expand-star-imports + - --exclude + - __init__.py + - --remove-duplicate-keys +- repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: isort (python) + - id: isort + name: isort (cython) + types: [cython] + - id: isort + name: isort (pyi) + types: [pyi] +- repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black +ci: + autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks + autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate diff --git a/README.md b/README.md index 0fb25cc7ee895..5e9e97a2a2b70 100644 --- a/README.md +++ b/README.md @@ -49,15 +49,15 @@ The key features are: - - + - - + + + @@ -151,7 +151,7 @@ $ pip install "uvicorn[standard]" * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -164,7 +164,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -174,7 +174,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -187,7 +187,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -266,7 +266,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -277,7 +277,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -286,7 +286,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} diff --git a/docs/az/mkdocs.yml b/docs/az/mkdocs.yml index 66220f63eea08..60bd8eaad6578 100644 --- a/docs/az/mkdocs.yml +++ b/docs/az/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -97,6 +101,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +113,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index f56257e7e2d30..d99ade4024bd0 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -13,7 +13,7 @@ ### Automatische Dokumentation -Mit einer interaktiven API-Dokumentation und explorativen webbasierten Benutzerschnittstellen. Da FastAPI auf OpenAPI basiert, gibt es hierzu mehrere Optionen, wobei zwei standartmäßig vorhanden sind. +Mit einer interaktiven API-Dokumentation und explorativen webbasierten Benutzerschnittstellen. Da FastAPI auf OpenAPI basiert, gibt es hierzu mehrere Optionen, wobei zwei standardmäßig vorhanden sind. * Swagger UI, bietet interaktive Exploration: testen und rufen Sie ihre API direkt vom Webbrowser auf. @@ -27,7 +27,7 @@ Mit einer interaktiven API-Dokumentation und explorativen webbasierten Benutzers Alles basiert auf **Python 3.6 Typ**-Deklarationen (dank Pydantic). Es muss keine neue Syntax gelernt werden, nur standardisiertes modernes Python. - + Wenn Sie eine kurze, zweiminütige, Auffrischung in der Benutzung von Python Typ-Deklarationen benötigen (auch wenn Sie FastAPI nicht nutzen), schauen Sie sich diese kurze Einführung an (Englisch): Python Types{.internal-link target=_blank}. @@ -97,9 +97,9 @@ Hierdurch werden Sie nie wieder einen falschen Schlüsselnamen benutzen und spar ### Kompakt -FastAPI nutzt für alles sensible **Standard-Einstellungen**, welche optional überall konfiguriert werden können. Alle Parameter können ganz genau an Ihre Bedürfnisse angepasst werden, sodass sie genau die API definieren können, die sie brachen. +FastAPI nutzt für alles sinnvolle **Standard-Einstellungen**, welche optional überall konfiguriert werden können. Alle Parameter können ganz genau an Ihre Bedürfnisse angepasst werden, sodass sie genau die API definieren können, die sie brauchen. -Aber standartmäßig, **"funktioniert einfach"** alles. +Aber standardmäßig, **"funktioniert einfach"** alles. ### Validierung @@ -109,7 +109,7 @@ Aber standartmäßig, **"funktioniert einfach"** alles. * Zeichenketten (`str`), mit definierter minimaler und maximaler Länge. * Zahlen (`int`, `float`) mit minimaler und maximaler Größe, usw. -* Validierung für ungewögnliche Typen, wie: +* Validierung für ungewöhnliche Typen, wie: * URL. * Email. * UUID. @@ -142,8 +142,8 @@ FastAPI enthält ein extrem einfaches, aber extrem mächtiges Starlette. Das bedeutet, auch ihr eigner Starlett Quellcode funktioniert. +**FastAPI** ist vollkommen kompatibel (und basiert auf) Starlette. Das bedeutet, auch ihr eigener Starlette Quellcode funktioniert. -`FastAPI` ist eigentlich eine Unterklasse von `Starlette`. Wenn sie also bereits Starlette kennen oder benutzen, können Sie das meiste Ihres Wissen direkt anwenden. +`FastAPI` ist eigentlich eine Unterklasse von `Starlette`. Wenn Sie also bereits Starlette kennen oder benutzen, können Sie das meiste Ihres Wissens direkt anwenden. Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nur Starlette auf Steroiden ist): @@ -193,11 +193,11 @@ Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für d * Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/linter/Gehirn**: * Weil Datenstrukturen von Pydantic einfach nur Instanzen ihrer definierten Klassen sind, sollten Autovervollständigung, Linting, mypy und ihre Intuition einwandfrei funktionieren. * **Schnell**: - * In Vergleichen ist Pydantic schneller als jede andere getestete Bibliothek. + * In Vergleichen ist Pydantic schneller als jede andere getestete Bibliothek. * Validierung von **komplexen Strukturen**: * Benutzung von hierachischen Pydantic Schemata, Python `typing`’s `List` und `Dict`, etc. * Validierungen erlauben klare und einfache Datenschemadefinition, überprüft und dokumentiert als JSON Schema. * Sie können stark **verschachtelte JSON** Objekte haben und diese sind trotzdem validiert und annotiert. * **Erweiterbar**: - * Pydantic erlaubt die Definition von eigenen Datentypen oder sie können die Validierung mit einer `validator` dekorierten Methode erweitern.. + * Pydantic erlaubt die Definition von eigenen Datentypen oder Sie können die Validierung mit einer `validator` dekorierten Methode erweitern.. * 100% Testabdeckung. diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index d09ce70a097d6..9297544622de2 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -149,7 +149,7 @@ $ pip install uvicorn[standard] * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -162,7 +162,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -185,7 +185,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -264,7 +264,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -275,7 +275,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -284,7 +284,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/de/mkdocs.yml b/docs/de/mkdocs.yml index 360fa8c4a4c22..c72f325f6266a 100644 --- a/docs/de/mkdocs.yml +++ b/docs/de/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -98,6 +102,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -108,6 +114,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/en/data/external_links.yml b/docs/en/data/external_links.yml index 0850d9788507d..4a5791a43c16a 100644 --- a/docs/en/data/external_links.yml +++ b/docs/en/data/external_links.yml @@ -1,5 +1,17 @@ articles: english: + - author: Jean-Baptiste Rocher + author_link: https://hashnode.com/@jibrocher + link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app + title: Building the Poll App From Django Tutorial With FastAPI And React + - author: Silvan Melchior + author_link: https://github.com/silvanmelchior + link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12 + title: Seamless FastAPI Configuration with ConfZ + - author: Kaustubh Gupta + author_link: https://medium.com/@kaustubhgupta1828/ + link: https://levelup.gitconnected.com/5-advance-features-of-fastapi-you-should-try-7c0ac7eebb3e + title: 5 Advanced Features of FastAPI You Should Try - author: Kaustubh Gupta author_link: https://medium.com/@kaustubhgupta1828/ link: https://www.analyticsvidhya.com/blog/2021/06/deploying-ml-models-as-api-using-fastapi-and-heroku/ @@ -12,6 +24,10 @@ articles: author_link: https://pystar.substack.com/ link: https://pystar.substack.com/p/how-to-create-a-fake-certificate title: How to Create A Fake Certificate Authority And Generate TLS Certs for FastAPI + - author: Ben Gamble + author_link: https://uk.linkedin.com/in/bengamble7 + link: https://ably.com/blog/realtime-ticket-booking-solution-kafka-fastapi-ably + title: Building a realtime ticket booking solution with Kafka, FastAPI, and Ably - author: Shahriyar(Shako) Rzayev author_link: https://www.linkedin.com/in/shahriyar-rzayev/ link: https://www.azepug.az/posts/fastapi/#building-simple-e-commerce-with-nuxtjs-and-fastapi-series @@ -20,6 +36,10 @@ articles: author_link: https://rodrigo-arenas.medium.com/ link: https://medium.com/analytics-vidhya/serve-a-machine-learning-model-using-sklearn-fastapi-and-docker-85aabf96729b title: "Serve a machine learning model using Sklearn, FastAPI and Docker" + - author: Yashasvi Singh + author_link: https://hashnode.com/@aUnicornDev + link: https://aunicorndev.hashnode.dev/series/supafast-api + title: "Building an API with FastAPI and Supabase and Deploying on Deta" - author: Navule Pavan Kumar Rao author_link: https://www.linkedin.com/in/navule/ link: https://www.tutlinks.com/deploy-fastapi-on-ubuntu-gunicorn-caddy-2/ @@ -27,7 +47,7 @@ articles: - author: Patrick Ladon author_link: https://dev.to/factorlive link: https://dev.to/factorlive/python-facebook-messenger-webhook-with-fastapi-on-glitch-4n90 - title: Python Facebook messenger webhook with FastAPI on Glitch + title: Python Facebook messenger webhook with FastAPI on Glitch - author: Dom Patmore author_link: https://twitter.com/dompatmore link: https://dompatmore.com/blog/authenticate-your-fastapi-app-with-auth0 @@ -188,11 +208,19 @@ articles: author_link: https://medium.com/@williamhayes link: https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59 title: FastAPI/Starlette debug vs prod + - author: Mukul Mantosh + author_link: https://twitter.com/MantoshMukul + link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/ + title: Developing FastAPI Application using K8s & AWS german: - author: Nico Axtmann author_link: https://twitter.com/_nicoax link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/ title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI + - author: Felix Schürmeyer + author_link: https://hellocoding.de/autor/felix-schuermeyer/ + link: https://hellocoding.de/blog/coding-language/python/fastapi + title: REST-API Programmieren mittels Python und dem FastAPI Modul japanese: - author: '@bee2' author_link: https://qiita.com/bee2 diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 162a8dbe28d38..db4a9acc6ad78 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,42 +1,75 @@ sponsors: -- - login: jina-ai +- - login: cryptapi + avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 + url: https://github.com/cryptapi + - 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: sushi2all + avatarUrl: https://avatars.githubusercontent.com/u/1043732?v=4 + url: https://github.com/sushi2all + - login: chaserowbotham + avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4 + url: https://github.com/chaserowbotham - - login: mikeckennedy - avatarUrl: https://avatars.githubusercontent.com/u/2035561?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4 url: https://github.com/mikeckennedy - - login: RodneyU215 - avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4 - url: https://github.com/RodneyU215 - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie - login: deta avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4 url: https://github.com/deta + - login: deepset-ai + avatarUrl: https://avatars.githubusercontent.com/u/51827949?v=4 + url: https://github.com/deepset-ai - login: investsuite avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4 url: https://github.com/investsuite - - login: vimsoHQ - avatarUrl: https://avatars.githubusercontent.com/u/77627231?v=4 - url: https://github.com/vimsoHQ -- - login: newrelic - avatarUrl: https://avatars.githubusercontent.com/u/31739?v=4 - url: https://github.com/newrelic + - login: VincentParedes + avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4 + url: https://github.com/VincentParedes +- - login: plocher + avatarUrl: https://avatars.githubusercontent.com/u/1082871?v=4 + url: https://github.com/plocher +- - login: InesIvanova + avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 + url: https://github.com/InesIvanova +- - login: SendCloud + avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4 + url: https://github.com/SendCloud - login: qaas avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4 url: https://github.com/qaas + - login: xoflare + avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 + url: https://github.com/xoflare + - login: Striveworks + avatarUrl: https://avatars.githubusercontent.com/u/45523576?v=4 + url: https://github.com/Striveworks + - login: BoostryJP + avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 + url: https://github.com/BoostryJP - - login: johnadjei avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4 url: https://github.com/johnadjei + - login: HiredScore + avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 + url: https://github.com/HiredScore - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 url: https://github.com/wdwinslow -- - login: kamalgill - avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 - url: https://github.com/kamalgill +- - login: moellenbeck + avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4 + url: https://github.com/moellenbeck + - login: RodneyU215 + avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4 + url: https://github.com/RodneyU215 - login: grillazz - avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4 url: https://github.com/grillazz - login: tizz98 avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4 @@ -44,45 +77,57 @@ sponsors: - login: jmaralc avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 url: https://github.com/jmaralc - - login: AlexandruSimion - avatarUrl: https://avatars.githubusercontent.com/u/71321732?v=4 - url: https://github.com/AlexandruSimion -- - login: samuelcolvin + - login: marutoraman + avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 + url: https://github.com/marutoraman + - login: mainframeindustries + avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 + url: https://github.com/mainframeindustries + - login: A-Edge + avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 + url: https://github.com/A-Edge +- - login: Kludex + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 + url: https://github.com/Kludex + - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4 url: https://github.com/samuelcolvin - login: jokull avatarUrl: https://avatars.githubusercontent.com/u/701?u=0532b62166893d5160ef795c4c8b7512d971af05&v=4 url: https://github.com/jokull + - login: jefftriplett + avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4 + url: https://github.com/jefftriplett + - login: kamalgill + avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 + url: https://github.com/kamalgill + - login: jsutton + avatarUrl: https://avatars.githubusercontent.com/u/280777?v=4 + url: https://github.com/jsutton + - login: deserat + avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4 + url: https://github.com/deserat + - login: ericof + avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4 + url: https://github.com/ericof - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes - login: koxudaxi avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 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 avatarUrl: https://avatars.githubusercontent.com/u/690878?u=e4835b2a985a0f2d52018e4926cb5a58c26a62e8&v=4 url: https://github.com/jqueguiner - - login: Mazyod - avatarUrl: https://avatars.githubusercontent.com/u/860511?v=4 - url: https://github.com/Mazyod - login: ltieman avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4 url: https://github.com/ltieman - - login: mrmattwright - avatarUrl: https://avatars.githubusercontent.com/u/1277725?v=4 - url: https://github.com/mrmattwright - login: westonsteimel avatarUrl: https://avatars.githubusercontent.com/u/1593939?u=0f2c0e3647f916fe295d62fa70da7a4c177115e3&v=4 url: https://github.com/westonsteimel - - login: timdrijvers - avatarUrl: https://avatars.githubusercontent.com/u/1694939?v=4 - url: https://github.com/timdrijvers - - login: mrgnw - avatarUrl: https://avatars.githubusercontent.com/u/2504532?u=7ec43837a6d0afa80f96f0788744ea6341b89f97&v=4 - url: https://github.com/mrgnw + - login: corleyma + avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4 + url: https://github.com/corleyma - login: madisonmay avatarUrl: https://avatars.githubusercontent.com/u/2645393?u=f22b93c6ea345a4d26a90a3834dfc7f0789fcb63&v=4 url: https://github.com/madisonmay @@ -93,149 +138,194 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4 url: https://github.com/andre1sk - login: Shark009 - avatarUrl: https://avatars.githubusercontent.com/u/3163309?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4 url: https://github.com/Shark009 + - login: dblackrun + avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 + url: https://github.com/dblackrun + - login: zsinx6 + avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 + url: https://github.com/zsinx6 + - login: anomaly + avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 + url: https://github.com/anomaly - login: peterHoburg avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4 url: https://github.com/peterHoburg - login: jaredtrog avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 url: https://github.com/jaredtrog + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: CINOAdam - avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=34c3d58cb900fed475d0172b436c66a94ad739ed&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4 url: https://github.com/CINOAdam - - login: dudil - avatarUrl: https://avatars.githubusercontent.com/u/4785835?u=58b7ea39123e0507f3b2996448a27256b16fd697&v=4 - url: https://github.com/dudil + - login: ScrimForever + avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4 + url: https://github.com/ScrimForever - login: ennui93 avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4 url: https://github.com/ennui93 - login: MacroPower avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=e13991efd1e03c44c911f919872e750530ded633&v=4 url: https://github.com/MacroPower - - login: ginomempin - avatarUrl: https://avatars.githubusercontent.com/u/6091865?v=4 - url: https://github.com/ginomempin + - login: Yaleesa + avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4 + url: https://github.com/Yaleesa - login: iwpnd avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4 url: https://github.com/iwpnd + - login: simw + avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 + url: https://github.com/simw + - login: pkucmus + avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4 + url: https://github.com/pkucmus - login: s3ich4n avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4 url: https://github.com/s3ich4n - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 url: https://github.com/Rehket - - login: christippett - avatarUrl: https://avatars.githubusercontent.com/u/7218120?u=434b9d29287d7de25772d94ddc74a9bd6d969284&v=4 - url: https://github.com/christippett - - login: Kludex - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4 - url: https://github.com/Kludex + - login: hiancdtrsnm + avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 + url: https://github.com/hiancdtrsnm - login: Shackelford-Arden avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4 url: https://github.com/Shackelford-Arden - - login: cristeaadrian - avatarUrl: https://avatars.githubusercontent.com/u/9112724?v=4 - url: https://github.com/cristeaadrian - - login: otivvormes - avatarUrl: https://avatars.githubusercontent.com/u/11317418?u=6de1edefb6afd0108c0ad2816bd6efc4464a9c44&v=4 - url: https://github.com/otivvormes - - login: iambobmae - avatarUrl: https://avatars.githubusercontent.com/u/12390270?u=c9a35c2ee5092a9b4135ebb1f91b7f521c467031&v=4 - url: https://github.com/iambobmae - - login: ronaldnwilliams - avatarUrl: https://avatars.githubusercontent.com/u/13632749?u=ac41a086d0728bf66a9d2bee9e5e377041ff44a4&v=4 - url: https://github.com/ronaldnwilliams + - login: Vikka + avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4 + url: https://github.com/Vikka + - login: Ge0f3 + avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4 + url: https://github.com/Ge0f3 + - login: gokulyc + avatarUrl: https://avatars.githubusercontent.com/u/13468848?u=269f269d3e70407b5fb80138c52daba7af783997&v=4 + url: https://github.com/gokulyc + - login: dannywade + avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4 + url: https://github.com/dannywade - login: pablonnaoji avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4 url: https://github.com/pablonnaoji - - login: natenka - avatarUrl: https://avatars.githubusercontent.com/u/15850513?u=00d1083c980d0b4ce32835dc07eee7f43f34fd2f&v=4 - url: https://github.com/natenka - - login: la-mar - avatarUrl: https://avatars.githubusercontent.com/u/16618300?u=7755c0521d2bb0d704f35a51464b15c1e2e6c4da&v=4 - url: https://github.com/la-mar - login: robintully avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4 url: https://github.com/robintully - - login: ShaulAb - avatarUrl: https://avatars.githubusercontent.com/u/18129076?u=2c8d48e47f2dbee15c3f89c3d17d4c356504386c&v=4 - url: https://github.com/ShaulAb - login: wedwardbeck avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4 url: https://github.com/wedwardbeck - login: linusg avatarUrl: https://avatars.githubusercontent.com/u/19366641?u=125e390abef8fff3b3b0d370c369cba5d7fd4c67&v=4 url: https://github.com/linusg + - login: stradivari96 + avatarUrl: https://avatars.githubusercontent.com/u/19752586?u=255f5f06a768f518b20cebd6963e840ac49294fd&v=4 + url: https://github.com/stradivari96 - login: RedCarpetUp avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4 url: https://github.com/RedCarpetUp - login: Filimoa avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4 url: https://github.com/Filimoa - - login: raminsj13 - avatarUrl: https://avatars.githubusercontent.com/u/24259406?u=d51f2a526312ebba150a06936ed187ca0727d329&v=4 - url: https://github.com/raminsj13 - - login: comoelcometa - avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=c6751efa038561b9bc5fa56d1033d5174e10cd65&v=4 - url: https://github.com/comoelcometa + - login: shuheng-liu + avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4 + url: https://github.com/shuheng-liu + - login: cometa-haley + avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 + url: https://github.com/cometa-haley + - login: LarryGF + avatarUrl: https://avatars.githubusercontent.com/u/26148349?u=431bb34d36d41c172466252242175281ae132152&v=4 + url: https://github.com/LarryGF - login: veprimk avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4 url: https://github.com/veprimk - - login: orihomie - avatarUrl: https://avatars.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4 - url: https://github.com/orihomie - - login: SaltyCoco - avatarUrl: https://avatars.githubusercontent.com/u/31451104?u=6ee4e17c07d21b7054f54a12fa9cc377a1b24ff9&v=4 - url: https://github.com/SaltyCoco + - login: meysam81 + avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4 + url: https://github.com/meysam81 - login: mauroalejandrojm avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4 url: https://github.com/mauroalejandrojm - - login: bulkw4r3 - avatarUrl: https://avatars.githubusercontent.com/u/35562532?u=0b812a14a02de14bf73d05fb2b2760a67bacffc2&v=4 - url: https://github.com/bulkw4r3 + - login: Leay15 + avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 + url: https://github.com/Leay15 + - login: AlrasheedA + avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4 + url: https://github.com/AlrasheedA + - login: ProteinQure + avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 + 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 avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4 url: https://github.com/ybressler + - login: iamkarshe + avatarUrl: https://avatars.githubusercontent.com/u/43641892?u=d08c901b359c931784501740610d416558ff3e24&v=4 + url: https://github.com/iamkarshe - login: dbanty - avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4 url: https://github.com/dbanty + - login: rafsaf + avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4 + url: https://github.com/rafsaf - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4 url: https://github.com/dudikbender + - login: daisuke8000 + avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=5025e379cd3655ae1a96039efc85223a873d2e38&v=4 + url: https://github.com/daisuke8000 + - login: yakkonaut + avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4 + url: https://github.com/yakkonaut - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io - - login: tkrestiankova - avatarUrl: https://avatars.githubusercontent.com/u/67013045?v=4 - url: https://github.com/tkrestiankova + - login: around + avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4 + url: https://github.com/around + - login: predictionmachine + avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4 + url: https://github.com/predictionmachine - login: daverin avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4 url: https://github.com/daverin - login: anthonycepeda avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4 url: https://github.com/anthonycepeda - - login: an-tho-ny - avatarUrl: https://avatars.githubusercontent.com/u/74874159?v=4 - url: https://github.com/an-tho-ny + - login: NinaHwang + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 + url: https://github.com/NinaHwang + - login: dotlas + avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4 + url: https://github.com/dotlas + - login: pyt3h + avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4 + url: https://github.com/pyt3h - - login: linux-china avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4 url: https://github.com/linux-china + - login: ddanier + avatarUrl: https://avatars.githubusercontent.com/u/113563?v=4 + url: https://github.com/ddanier - login: jhb avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4 url: https://github.com/jhb + - login: justinrmiller + avatarUrl: https://avatars.githubusercontent.com/u/143998?u=b507a940394d4fc2bc1c27cea2ca9c22538874bd&v=4 + url: https://github.com/justinrmiller + - login: bryanculbertson + avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4 + url: https://github.com/bryanculbertson - login: yourkin - avatarUrl: https://avatars.githubusercontent.com/u/178984?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/178984?u=fa7c3503b47bf16405b96d21554bc59f07a65523&v=4 url: https://github.com/yourkin - - login: jmagnusson - avatarUrl: https://avatars.githubusercontent.com/u/190835?v=4 - url: https://github.com/jmagnusson - - login: sakti - avatarUrl: https://avatars.githubusercontent.com/u/196178?u=0110be74c4270244546f1b610334042cd16bb8ad&v=4 - url: https://github.com/sakti - login: slafs avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs + - login: assem-ch + avatarUrl: https://avatars.githubusercontent.com/u/315228?u=e0c5ab30726d3243a40974bb9bae327866e42d9b&v=4 + url: https://github.com/assem-ch - login: adamghill avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4 url: https://github.com/adamghill @@ -245,21 +335,33 @@ sponsors: - login: dmig avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4 url: https://github.com/dmig - - login: hongqn - avatarUrl: https://avatars.githubusercontent.com/u/405587?u=470b4c04832e45141fd5264d3354845cc9fc6466&v=4 - url: https://github.com/hongqn - login: rinckd avatarUrl: https://avatars.githubusercontent.com/u/546002?u=1fcc7e664dc86524a0af6837a0c222829c3fd4e5&v=4 url: https://github.com/rinckd + - login: securancy + avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4 + 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 avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4 url: https://github.com/hardbyte + - login: janfilips + avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4 + url: https://github.com/janfilips + - login: scari + avatarUrl: https://avatars.githubusercontent.com/u/964251?v=4 + url: https://github.com/scari - login: Pytlicek avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4 url: https://github.com/Pytlicek - - login: okken - avatarUrl: https://avatars.githubusercontent.com/u/1568356?u=0a991a21bdc62e2bea9ad311652f2c45f453dc84&v=4 - url: https://github.com/okken + - login: Celeborn2BeAlive + avatarUrl: https://avatars.githubusercontent.com/u/1659465?u=944517e4db0f6df65070074e81cabdad9c8a434b&v=4 + url: https://github.com/Celeborn2BeAlive + - login: WillHogan + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 + url: https://github.com/WillHogan - login: cbonoz avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4 url: https://github.com/cbonoz @@ -269,47 +371,47 @@ sponsors: - login: rglsk avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4 url: https://github.com/rglsk - - login: Atem18 - avatarUrl: https://avatars.githubusercontent.com/u/2875254?v=4 - url: https://github.com/Atem18 - login: paul121 avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4 url: https://github.com/paul121 - login: igorcorrea avatarUrl: https://avatars.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4 url: https://github.com/igorcorrea - - login: anthcor + - login: anthonycorletti avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4 - url: https://github.com/anthcor - - login: zsinx6 - avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 - url: https://github.com/zsinx6 + url: https://github.com/anthonycorletti - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - - login: spyker77 - avatarUrl: https://avatars.githubusercontent.com/u/4953435?u=03c724c6f8fbab5cd6575b810c0c91c652fa4f79&v=4 - url: https://github.com/spyker77 - - login: JonasKs - avatarUrl: https://avatars.githubusercontent.com/u/5310116?u=98a049f3e1491bffb91e1feb7e93def6881a9389&v=4 - url: https://github.com/JonasKs + - login: Alisa-lisa + avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 + url: https://github.com/Alisa-lisa + - login: unredundant + avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4 + url: https://github.com/unredundant - login: holec avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4 url: https://github.com/holec - - login: BartlomiejRasztabiga - avatarUrl: https://avatars.githubusercontent.com/u/8852711?u=ed213d60f7a423df31ceb1004aa3ec60e612cb98&v=4 - url: https://github.com/BartlomiejRasztabiga + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 - login: davanstrien avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4 url: https://github.com/davanstrien - - login: and-semakin - avatarUrl: https://avatars.githubusercontent.com/u/9129071?u=ea77ddf7de4bc375d546bf2825ed420eaddb7666&v=4 - url: https://github.com/and-semakin + - login: yenchenLiu + avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4 + url: https://github.com/yenchenLiu - login: VivianSolide - avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=ffb2e2ec522a15dcd3f0af1f9fd1df4afe418afa&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=4a38ef72dd39e8b262bd5ab819992128b55c52b4&v=4 url: https://github.com/VivianSolide + - login: xncbf + avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4 + url: https://github.com/xncbf + - login: DMantis + avatarUrl: https://avatars.githubusercontent.com/u/9536869?v=4 + url: https://github.com/DMantis - login: hard-coders - avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders - login: satwikkansal avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4 @@ -317,63 +419,78 @@ sponsors: - login: pheanex avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4 url: https://github.com/pheanex - - login: wotori - avatarUrl: https://avatars.githubusercontent.com/u/10486621?u=0044c295b91694b8c9bccc0a805681f794250f7b&v=4 - url: https://github.com/wotori - login: JimFawkes avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4 url: https://github.com/JimFawkes - login: logan-connolly avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4 url: https://github.com/logan-connolly - - login: iPr0ger - avatarUrl: https://avatars.githubusercontent.com/u/19322290?v=4 - url: https://github.com/iPr0ger + - login: cdsre + avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4 + url: https://github.com/cdsre + - login: jangia + avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4 + url: https://github.com/jangia - login: ghandic avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 url: https://github.com/ghandic - - login: MoronVV - avatarUrl: https://avatars.githubusercontent.com/u/24293616?v=4 - url: https://github.com/MoronVV - login: fstau avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4 url: https://github.com/fstau - login: mertguvencli avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4 url: https://github.com/mertguvencli - - login: rgreen32 - avatarUrl: https://avatars.githubusercontent.com/u/35779241?u=c9d64ad1ab364b6a1ec8e3d859da9ca802d681d8&v=4 - url: https://github.com/rgreen32 - - login: askurihin - avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4 - url: https://github.com/askurihin - - login: JitPackJoyride - avatarUrl: https://avatars.githubusercontent.com/u/40203625?u=9638bfeacfa5940358188f8205ce662bba022b53&v=4 - url: https://github.com/JitPackJoyride - - login: es3n1n - avatarUrl: https://avatars.githubusercontent.com/u/40367813?u=e881a3880f1e342d19a1ea7c8e1b6d76c52dc294&v=4 - url: https://github.com/es3n1n + - login: dwreeves + avatarUrl: https://avatars.githubusercontent.com/u/31971762?u=69732aba05aa5cf0780866349ebe109cf632b047&v=4 + url: https://github.com/dwreeves + - login: kitaramu0401 + avatarUrl: https://avatars.githubusercontent.com/u/33246506?u=929e6efa2c518033b8097ba524eb5347a069bb3b&v=4 + url: https://github.com/kitaramu0401 + - login: engineerjoe440 + avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 + url: https://github.com/engineerjoe440 + - login: declon + avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4 + url: https://github.com/declon + - login: d-e-h-i-o + avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4 + url: https://github.com/d-e-h-i-o - login: ilias-ant avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4 url: https://github.com/ilias-ant - login: arrrrrmin - avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=05600727f1cfe75f440bb3fddd49bfea84b1e894&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=fee5739394fea074cb0b66929d070114a5067aae&v=4 url: https://github.com/arrrrrmin + - login: Nephilim-Jack + avatarUrl: https://avatars.githubusercontent.com/u/48372168?u=6f2bb405238d7efc467536fe01f58df6779c58a9&v=4 + url: https://github.com/Nephilim-Jack - login: akanz1 avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4 url: https://github.com/akanz1 -- - login: leogregianin - avatarUrl: https://avatars.githubusercontent.com/u/1684053?u=94ddd387601bd1805034dbe83e6eba0491c15323&v=4 - url: https://github.com/leogregianin + - login: rooflexx + avatarUrl: https://avatars.githubusercontent.com/u/58993673?u=f8ba450460f1aea18430ed1e4a3889049a3b4dfa&v=4 + url: https://github.com/rooflexx + - login: denisyao1 + avatarUrl: https://avatars.githubusercontent.com/u/60019356?v=4 + url: https://github.com/denisyao1 + - login: apar-tiwari + avatarUrl: https://avatars.githubusercontent.com/u/61064197?v=4 + url: https://github.com/apar-tiwari + - login: 0417taehyun + avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 + url: https://github.com/0417taehyun + - login: alessio-proietti + avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4 + url: https://github.com/alessio-proietti +- - login: backbord + avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4 + url: https://github.com/backbord - login: sadikkuzu avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4 url: https://github.com/sadikkuzu - login: gabrielmbmb - avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=92084ed7242160dee4d20aece923a10c59758ee5&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4 url: https://github.com/gabrielmbmb - - login: starhype - avatarUrl: https://avatars.githubusercontent.com/u/36908028?u=6df41f7b62f0f673f1ecbc87e9cbadaa4fcb0767&v=4 - url: https://github.com/starhype - - login: pixel365 - avatarUrl: https://avatars.githubusercontent.com/u/53819609?u=9e0309c5420ec4624aececd3ca2d7105f7f68133&v=4 - url: https://github.com/pixel365 + - login: danburonline + avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4 + url: https://github.com/danburonline diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index ebbe446eed4a9..92aab109ff495 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,13 +1,13 @@ maintainers: - login: tiangolo - answers: 1237 - prs: 280 + answers: 1243 + prs: 300 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=5cad72c846b7aba2e960546af490edc7375dafc4&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 319 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=3682d9b9b93bef272f379ab623dc031c8d71432e&v=4 + count: 335 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu count: 262 @@ -29,14 +29,14 @@ experts: count: 130 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 -- login: ArcLightSlavik - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4 - url: https://github.com/ArcLightSlavik - login: raphaelauv - count: 68 + count: 71 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv +- login: ArcLightSlavik + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 + url: https://github.com/ArcLightSlavik - login: falkben count: 58 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 @@ -50,41 +50,49 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes - login: Dustyposa - count: 42 + count: 43 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa - login: includeamin - count: 38 + count: 39 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 url: https://github.com/includeamin +- login: jgould22 + count: 38 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: STeveShary count: 37 avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 url: https://github.com/STeveShary +- login: adriangb + count: 36 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4 + url: https://github.com/adriangb - login: prostomarkeloff count: 33 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4 url: https://github.com/prostomarkeloff +- login: frankie567 + count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 + url: https://github.com/frankie567 - login: krishnardt count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 url: https://github.com/krishnardt -- login: adriangb - count: 30 - avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4 - url: https://github.com/adriangb - login: wshayes count: 29 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes -- login: frankie567 - count: 29 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 - url: https://github.com/frankie567 - login: chbndrhnns - count: 25 + count: 28 avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 url: https://github.com/chbndrhnns +- login: panla + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 + url: https://github.com/panla - login: ghandic count: 25 avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 @@ -93,10 +101,6 @@ experts: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4 url: https://github.com/dbanty -- login: panla - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 - url: https://github.com/panla - login: SirTelemak count: 24 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 @@ -117,6 +121,10 @@ experts: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 url: https://github.com/retnikt +- login: acidjunk + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: Hultner count: 18 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -129,10 +137,14 @@ experts: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4 url: https://github.com/nkhitrov -- login: acidjunk - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk +- login: harunyasar + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 + url: https://github.com/harunyasar +- login: rafsaf + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4 + url: https://github.com/rafsaf - login: waynerv count: 16 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 @@ -141,18 +153,14 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny -- login: jgould22 - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: harunyasar - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 - url: https://github.com/harunyasar - login: haizaar count: 13 avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4 url: https://github.com/haizaar +- login: valentin994 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4 + url: https://github.com/valentin994 - login: hellocoldworld count: 12 avatarUrl: https://avatars.githubusercontent.com/u/47581948?v=4 @@ -161,6 +169,14 @@ experts: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4 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: jonatasoli + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 + url: https://github.com/jonatasoli - login: lowercase00 count: 11 avatarUrl: https://avatars.githubusercontent.com/u/21188280?v=4 @@ -173,59 +189,35 @@ experts: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4 url: https://github.com/juntatalor -- login: valentin994 +- login: n8sty count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4 - url: https://github.com/valentin994 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: aalifadv count: 11 avatarUrl: https://avatars.githubusercontent.com/u/78442260?v=4 url: https://github.com/aalifadv -- login: stefanondisponibile - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/20441825?u=ee1e59446b98f8ec2363caeda4c17164d0d9cc7d&v=4 - url: https://github.com/stefanondisponibile -- login: oligond - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/2858306?u=1bb1182a5944e93624b7fb26585f22c8f7a9d76e&v=4 - url: https://github.com/oligond last_month_active: -- login: harunyasar - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 - url: https://github.com/harunyasar - login: jgould22 - count: 10 + count: 15 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: rafsaf - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4 - url: https://github.com/rafsaf -- login: STeveShary +- login: accelleon count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 - url: https://github.com/STeveShary -- login: ahnaf-zamil - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/57180217?u=849128b146771ace47beca5b5ff68eb82905dd6d&v=4 - url: https://github.com/ahnaf-zamil -- login: lucastosetto - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/89307132?u=56326696423df7126c9e7c702ee58f294db69a2a&v=4 - url: https://github.com/lucastosetto -- login: blokje - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/851418?v=4 - url: https://github.com/blokje -- login: MatthijsKok - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7658129?u=1243e32d57e13abc45e3f5235ed5b9197e0d2b41&v=4 - url: https://github.com/MatthijsKok + avatarUrl: https://avatars.githubusercontent.com/u/5001614?v=4 + url: https://github.com/accelleon +- login: jonatasoli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 + url: https://github.com/jonatasoli - login: Kludex - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=3682d9b9b93bef272f379ab623dc031c8d71432e&v=4 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex +- login: yinziyan1206 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 + url: https://github.com/yinziyan1206 top_contributors: - login: waynerv count: 25 @@ -259,14 +251,14 @@ top_contributors: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 url: https://github.com/Serrones +- login: Kludex + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 + url: https://github.com/Kludex - login: RunningIkkyu count: 7 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4 url: https://github.com/RunningIkkyu -- login: Kludex - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=3682d9b9b93bef272f379ab623dc031c8d71432e&v=4 - url: https://github.com/Kludex - login: hard-coders count: 7 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 @@ -306,7 +298,7 @@ top_contributors: top_reviewers: - login: Kludex count: 93 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=3682d9b9b93bef272f379ab623dc031c8d71432e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: waynerv count: 47 @@ -324,30 +316,38 @@ top_reviewers: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4 url: https://github.com/ycd +- login: cikay + count: 41 + avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 + url: https://github.com/cikay +- login: BilalAlpaslan + count: 40 + avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 + url: https://github.com/BilalAlpaslan - login: AdrianDeAnda count: 33 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4 url: https://github.com/AdrianDeAnda - login: ArcLightSlavik count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik -- login: cikay - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 - url: https://github.com/cikay +- login: cassiobotaro + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4 + url: https://github.com/cassiobotaro - login: dmontagu count: 23 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 url: https://github.com/dmontagu -- login: cassiobotaro - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4 - url: https://github.com/cassiobotaro - login: komtaki count: 21 avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 url: https://github.com/komtaki +- login: yezz123 + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 + url: https://github.com/yezz123 - login: hard-coders count: 19 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 @@ -356,6 +356,10 @@ top_reviewers: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 url: https://github.com/0417taehyun +- login: zy7y + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4 + url: https://github.com/zy7y - login: yanever count: 16 avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4 @@ -392,10 +396,6 @@ top_reviewers: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4 url: https://github.com/RunningIkkyu -- login: yezz123 - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 - url: https://github.com/yezz123 - login: sh0nk count: 12 avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 @@ -412,6 +412,10 @@ top_reviewers: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4 url: https://github.com/maoyibo +- login: solomein-sv + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4 + url: https://github.com/solomein-sv - login: graingert count: 9 avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4 @@ -424,26 +428,30 @@ top_reviewers: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/49435654?v=4 url: https://github.com/kty4119 -- login: zy7y - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4 - url: https://github.com/zy7y - login: bezaca count: 9 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 url: https://github.com/bezaca -- login: solomein-sv - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4 - url: https://github.com/solomein-sv - login: blt232018 count: 8 avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4 url: https://github.com/blt232018 +- login: rogerbrinkmann + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4 + 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 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 + url: https://github.com/NinaHwang +- login: dimaqq + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 + url: https://github.com/dimaqq - login: Serrones count: 7 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 @@ -456,10 +464,6 @@ top_reviewers: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: BilalAlpaslan - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 - url: https://github.com/BilalAlpaslan - login: NastasiaSaby count: 7 avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4 @@ -468,35 +472,23 @@ top_reviewers: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 url: https://github.com/Mause +- 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 -- login: dimaqq - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 - url: https://github.com/dimaqq - login: jovicon count: 6 avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4 url: https://github.com/jovicon -- login: NinaHwang +- login: LorhanSohaky count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 - url: https://github.com/NinaHwang -- login: diogoduartec - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/31852339?u=b50fc11c531e9b77922e19edfc9e7233d4d7b92e&v=4 - url: https://github.com/diogoduartec -- login: n25a - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/49960770?u=eb3c95338741c78fff7d9d5d7ace9617e53eee4a&v=4 - url: https://github.com/n25a -- login: izaguerreiro - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 - url: https://github.com/izaguerreiro -- login: israteneda - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/20668624?u=d7b2961d330aca65fbce5bdb26a0800a3d23ed2d&v=4 - url: https://github.com/israteneda + avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 + url: https://github.com/LorhanSohaky +- login: peidrao + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4 + url: https://github.com/peidrao diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 65a114584ad45..ac825193b7312 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -5,15 +5,12 @@ gold: - url: https://cryptapi.io/ title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway." img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg - - url: https://www.dropbase.io/careers - title: Dropbase - seamlessly collect, clean, and centralize data. - img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg - - url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings - title: https://striveworks.us/careers - img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png - url: https://classiq.link/n4s title: Join the team building a new SaaS platform that will change the computing world img: https://fastapi.tiangolo.com/img/sponsors/classiq.png + - url: https://www.dropbase.io/careers + title: Dropbase - seamlessly collect, clean, and centralize data. + img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg silver: - url: https://www.deta.sh/?ref=fastapi title: The launchpad for all your (team's) ideas @@ -21,10 +18,7 @@ silver: - url: https://www.investsuite.com/jobs title: Wealthtech jobs with FastAPI img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg - - url: https://www.vim.so/?utm_source=FastAPI - title: We help you master vim with interactive exercises - img: https://fastapi.tiangolo.com/img/sponsors/vimso.png - - url: https://talkpython.fm/fastapi-sponsor + - url: https://training.talkpython.fm/fastapi-courses title: FastAPI video courses on demand from people you trust img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png - url: https://testdriven.io/courses/tdd-fastapi/ @@ -33,7 +27,16 @@ silver: - url: https://github.com/deepset-ai/haystack/ title: Build powerful search from composable, open source building blocks img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg + - url: https://www.udemy.com/course/fastapi-rest/ + title: Learn FastAPI by building a complete project. Extend your knowledge on advanced web development-AWS, Payments, Emails. + img: https://fastapi.tiangolo.com/img/sponsors/ines-course.jpg + - url: https://careers.budget-insight.com/ + title: Budget Insight is hiring! + img: https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg bronze: - - url: https://calmcode.io - title: Code. Simply. Clearly. Calmly. - img: https://fastapi.tiangolo.com/img/sponsors/calmcode.jpg + - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source + title: Biosecurity risk assessments made easy. + img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png + - url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings + title: https://striveworks.us/careers + img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index dbf69c1b3551c..1c8b0cde71558 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -2,10 +2,11 @@ logins: - jina-ai - deta - investsuite - - vimsoHQ - mikeckennedy - - koaning - deepset-ai - cryptapi - - DropbaseHQ - Striveworks + - xoflare + - InesIvanova + - DropbaseHQ + - VincentParedes diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md index becc8fd49446e..dca5f6a985cc1 100644 --- a/docs/en/docs/advanced/additional-responses.md +++ b/docs/en/docs/advanced/additional-responses.md @@ -36,7 +36,7 @@ For example, to declare another response with a status code `404` and a Pydantic **FastAPI** will take the Pydantic model from there, generate the `JSON Schema`, and put it in the correct place. The correct place is: - + * In the key `content`, that has as value another JSON object (`dict`) that contains: * A key with the media type, e.g. `application/json`, that contains as value another JSON object, that contains: * A key `schema`, that has as the value the JSON Schema from the model, here's the correct place. diff --git a/docs/en/docs/advanced/additional-status-codes.md b/docs/en/docs/advanced/additional-status-codes.md index eb6031953abd5..b61f88b93d19f 100644 --- a/docs/en/docs/advanced/additional-status-codes.md +++ b/docs/en/docs/advanced/additional-status-codes.md @@ -14,7 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want: -```Python hl_lines="4 23" +```Python hl_lines="4 25" {!../../../docs_src/additional_status_codes/tutorial001.py!} ``` @@ -22,7 +22,7 @@ To achieve that, import `JSONResponse`, and return your content there directly, When you return a `Response` directly, like in the example above, it will be returned directly. It won't be serialized with a model, etc. - + Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`). !!! note "Technical Details" diff --git a/docs/en/docs/advanced/extending-openapi.md b/docs/en/docs/advanced/extending-openapi.md index d1b14bc003fde..36619696b59df 100644 --- a/docs/en/docs/advanced/extending-openapi.md +++ b/docs/en/docs/advanced/extending-openapi.md @@ -132,8 +132,8 @@ You can probably right-click each link and select an option similar to `Save lin **Swagger UI** uses the files: -* `swagger-ui-bundle.js` -* `swagger-ui.css` +* `swagger-ui-bundle.js` +* `swagger-ui.css` And **ReDoc** uses the file: diff --git a/docs/en/docs/advanced/security/oauth2-scopes.md b/docs/en/docs/advanced/security/oauth2-scopes.md index 4bd9cfd0470cc..be51325cdbdbd 100644 --- a/docs/en/docs/advanced/security/oauth2-scopes.md +++ b/docs/en/docs/advanced/security/oauth2-scopes.md @@ -16,11 +16,11 @@ In this section you will see how to manage authentication and authorization with You don't necessarily need OAuth2 scopes, and you can handle authentication and authorization however you want. But OAuth2 with scopes can be nicely integrated into your API (with OpenAPI) and your API docs. - + Nevertheless, you still enforce those scopes, or any other security/authorization requirement, however you need, in your code. In many cases, OAuth2 with scopes can be an overkill. - + But if you know you need it, or you are curious, keep reading. ## OAuth2 scopes and OpenAPI @@ -47,7 +47,7 @@ They are normally used to declare specific security permissions, for example: In OAuth2 a "scope" is just a string that declares a specific permission required. It doesn't matter if it has other characters like `:` or if it is a URL. - + Those details are implementation specific. For OAuth2 they are just strings. @@ -115,7 +115,7 @@ In this case, it requires the scope `me` (it could require more than one scope). !!! note You don't necessarily need to add different scopes in different places. - + We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels. ```Python hl_lines="4 139 166" diff --git a/docs/en/docs/advanced/sql-databases-peewee.md b/docs/en/docs/advanced/sql-databases-peewee.md index 48514d1e29c1e..b4ea61367e820 100644 --- a/docs/en/docs/advanced/sql-databases-peewee.md +++ b/docs/en/docs/advanced/sql-databases-peewee.md @@ -182,7 +182,7 @@ Now let's check the file `sql_app/schemas.py`. To avoid confusion between the Peewee *models* and the Pydantic *models*, we will have the file `models.py` with the Peewee models, and the file `schemas.py` with the Pydantic models. These Pydantic models define more or less a "schema" (a valid data shape). - + So this will help us avoiding confusion while using both. ### Create the Pydantic *models* / schemas diff --git a/docs/en/docs/advanced/testing-dependencies.md b/docs/en/docs/advanced/testing-dependencies.md index 79208e8dc8625..7bba82fb7fe50 100644 --- a/docs/en/docs/advanced/testing-dependencies.md +++ b/docs/en/docs/advanced/testing-dependencies.md @@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency ( And then **FastAPI** will call that override instead of the original dependency. -```Python hl_lines="26-27 30" +```Python hl_lines="28-29 32" {!../../../docs_src/dependency_testing/tutorial001.py!} ``` diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index 28d0be8cc0802..68aa3150d7194 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -235,7 +235,7 @@ It was one of the first extremely fast Python frameworks based on `asyncio`. It !!! check "Inspired **FastAPI** to" Find a way to have a crazy performance. - + That's why **FastAPI** is based on Starlette, as it is the fastest framework available (tested by third-party benchmarks). ### Falcon @@ -333,7 +333,7 @@ Now APIStar is a set of tools to validate OpenAPI specifications, not a web fram Exist. The idea of declaring multiple things (data validation, serialization and documentation) with the same Python types, that at the same time provided great editor support, was something I considered a brilliant idea. - + And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available. Then APIStar stopped to exist as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**. @@ -391,7 +391,7 @@ That's one of the main things that **FastAPI** adds on top, all based on Python Handle all the core web parts. Adding features on top. The class `FastAPI` itself inherits directly from the class `Starlette`. - + So, anything that you can do with Starlette, you can do it directly with **FastAPI**, as it is basically Starlette on steroids. ### Uvicorn diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 8194650fd9748..71f2e75025f2c 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -116,7 +116,7 @@ The cashier 💁 gives you the number of your turn. While you are waiting, you go with your crush 😍 and pick a table, you sit and talk with your crush 😍 for a long time (as your burgers are very fancy and take some time to prepare ✨🍔✨). -As you are sitting on the table with your crush 😍, while you wait for the burgers 🍔, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨. +As you are sitting at the table with your crush 😍, while you wait for the burgers 🍔, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨. While waiting and talking to your crush 😍, from time to time, you check the number displayed on the counter to see if it's your turn already. @@ -134,7 +134,7 @@ Then, when it's your turn, you do actual "productive" work 🤓, you process the But then, even though you still don't have your burgers 🍔, your work with the cashier 💁 is "on pause" ⏸, because you have to wait 🕙 for your burgers to be ready. -But as you go away from the counter and sit on the table with a number for your turn, you can switch 🔀 your attention to your crush 😍, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" 🤓, as is flirting with your crush 😍. +But as you go away from the counter and sit at the table with a number for your turn, you can switch 🔀 your attention to your crush 😍, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" 🤓, as is flirting with your crush 😍. Then the cashier 💁 says "I'm finished with doing the burgers" 🍔 by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers 🍔 because you have the number of your turn, and they have theirs. diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index 3f86efcced275..8a542622e408a 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -142,7 +142,7 @@ Successfully installed fastapi pydantic uvicorn * Create a `main.py` file with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -155,7 +155,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -350,7 +350,7 @@ If your FastAPI is a single file, for example, `main.py` without an `./app` dire Then you would just have to change the corresponding paths to copy the file inside the `Dockerfile`: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.9 WORKDIR /code diff --git a/docs/en/docs/deployment/manually.md b/docs/en/docs/deployment/manually.md index 7fd1f4d4f2f96..d6892b2c14ad6 100644 --- a/docs/en/docs/deployment/manually.md +++ b/docs/en/docs/deployment/manually.md @@ -38,7 +38,7 @@ You can install an ASGI compatible server with: !!! tip By adding the `standard`, Uvicorn will install and use some recommended extra dependencies. - + That including `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost. === "Hypercorn" @@ -59,7 +59,7 @@ You can install an ASGI compatible server with: ## Run the Server Program -You can then your application the same way you have done in the tutorials, but without the `--reload` option, e.g.: +You can then run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.: === "Uvicorn" @@ -89,7 +89,7 @@ You can then your application the same way you have done in the tutorials, but w Remember to remove the `--reload` option if you were using it. The `--reload` option consumes much more resources, is more unstable, etc. - + It helps a lot during **development**, but you **shouldn't** use it in **production**. ## Hypercorn with Trio diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 36f80783a6104..e4672d5329347 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on * Plays nicely with your **IDE/linter/brain**: * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. * **Fast**: - * in benchmarks Pydantic is faster than all other tested libraries. + * in benchmarks Pydantic is faster than all other tested libraries. * Validate **complex structures**: * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc. * And validators allow complex data schemas to be clearly and easily defined, checked and documented as JSON Schema. diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio b/docs/en/docs/img/deployment/concepts/process-ram.drawio index 51fc30ed32f68..b29c8a3424519 100644 --- a/docs/en/docs/img/deployment/concepts/process-ram.drawio +++ b/docs/en/docs/img/deployment/concepts/process-ram.drawio @@ -103,4 +103,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/concepts/process-ram.svg b/docs/en/docs/img/deployment/concepts/process-ram.svg index cd086c36b87a5..c1bf0d5890034 100644 --- a/docs/en/docs/img/deployment/concepts/process-ram.svg +++ b/docs/en/docs/img/deployment/concepts/process-ram.svg @@ -56,4 +56,4 @@ }
Server
Server
RAM
RAM
CPU
CPU -
Process Manager
Process Manager
Worker Process
Worker Process
Worker Process
Worker Process
Another Process
Another Process
1 GB
1 GB
1 GB
1 GB
Viewer does not support full SVG 1.1 \ No newline at end of file +
Process Manager
Process Manager
Worker Process
Worker Process
Worker Process
Worker Process
Another Process
Another Process
1 GB
1 GB
1 GB
1 GB
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https.drawio b/docs/en/docs/img/deployment/https/https.drawio index 31cfab96bce3a..c4c8a362816ce 100644 --- a/docs/en/docs/img/deployment/https/https.drawio +++ b/docs/en/docs/img/deployment/https/https.drawio @@ -274,4 +274,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https.svg b/docs/en/docs/img/deployment/https/https.svg index e63345eba3204..69497518a5517 100644 --- a/docs/en/docs/img/deployment/https/https.svg +++ b/docs/en/docs/img/deployment/https/https.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https01.drawio b/docs/en/docs/img/deployment/https/https01.drawio index 9bc5340ce5858..181582f9bd913 100644 --- a/docs/en/docs/img/deployment/https/https01.drawio +++ b/docs/en/docs/img/deployment/https/https01.drawio @@ -75,4 +75,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https01.svg b/docs/en/docs/img/deployment/https/https01.svg index 4fee0adfc0161..2edbd062399ec 100644 --- a/docs/en/docs/img/deployment/https/https01.svg +++ b/docs/en/docs/img/deployment/https/https01.svg @@ -54,4 +54,4 @@ src: url("https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4mxK.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https02.drawio b/docs/en/docs/img/deployment/https/https02.drawio index 0f7578d3e4dc4..650c06d1e1c4d 100644 --- a/docs/en/docs/img/deployment/https/https02.drawio +++ b/docs/en/docs/img/deployment/https/https02.drawio @@ -107,4 +107,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https02.svg b/docs/en/docs/img/deployment/https/https02.svg index 1f37a7098b373..e16b7e94a1142 100644 --- a/docs/en/docs/img/deployment/https/https02.svg +++ b/docs/en/docs/img/deployment/https/https02.svg @@ -54,4 +54,4 @@ src: url("https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4mxK.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Port 443 (HTTPS)
Port 443 (HTTPS)
IP:
123.124.125.126
IP:...
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Viewer does not support full SVG 1.1 \ No newline at end of file +
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Port 443 (HTTPS)
Port 443 (HTTPS)
IP:
123.124.125.126
IP:...
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https03.drawio b/docs/en/docs/img/deployment/https/https03.drawio index c5766086c082d..c178fd36314e5 100644 --- a/docs/en/docs/img/deployment/https/https03.drawio +++ b/docs/en/docs/img/deployment/https/https03.drawio @@ -128,4 +128,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https03.svg b/docs/en/docs/img/deployment/https/https03.svg index e68e1c45964ac..2badd1c7d27ac 100644 --- a/docs/en/docs/img/deployment/https/https03.svg +++ b/docs/en/docs/img/deployment/https/https03.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https04.drawio b/docs/en/docs/img/deployment/https/https04.drawio index ea357a6c1b475..78a6e919a04bd 100644 --- a/docs/en/docs/img/deployment/https/https04.drawio +++ b/docs/en/docs/img/deployment/https/https04.drawio @@ -149,4 +149,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https04.svg b/docs/en/docs/img/deployment/https/https04.svg index 4c9b7999bc0dd..4513ac76b555c 100644 --- a/docs/en/docs/img/deployment/https/https04.svg +++ b/docs/en/docs/img/deployment/https/https04.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https05.drawio b/docs/en/docs/img/deployment/https/https05.drawio index 9b8b7c6f710df..236ecd841f471 100644 --- a/docs/en/docs/img/deployment/https/https05.drawio +++ b/docs/en/docs/img/deployment/https/https05.drawio @@ -163,4 +163,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https05.svg b/docs/en/docs/img/deployment/https/https05.svg index d11647b9b3174..ddcd2760a8068 100644 --- a/docs/en/docs/img/deployment/https/https05.svg +++ b/docs/en/docs/img/deployment/https/https05.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https06.drawio b/docs/en/docs/img/deployment/https/https06.drawio index 5bb85813fd5ed..9dec131846f01 100644 --- a/docs/en/docs/img/deployment/https/https06.drawio +++ b/docs/en/docs/img/deployment/https/https06.drawio @@ -180,4 +180,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https06.svg b/docs/en/docs/img/deployment/https/https06.svg index 10e03b7c5642e..3695de40c725e 100644 --- a/docs/en/docs/img/deployment/https/https06.svg +++ b/docs/en/docs/img/deployment/https/https06.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https07.drawio b/docs/en/docs/img/deployment/https/https07.drawio index 1ca994b2236ae..aa8f4d6bedb9c 100644 --- a/docs/en/docs/img/deployment/https/https07.drawio +++ b/docs/en/docs/img/deployment/https/https07.drawio @@ -200,4 +200,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https07.svg b/docs/en/docs/img/deployment/https/https07.svg index e409d8871332e..551354cef81f7 100644 --- a/docs/en/docs/img/deployment/https/https07.svg +++ b/docs/en/docs/img/deployment/https/https07.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/deployment/https/https08.drawio b/docs/en/docs/img/deployment/https/https08.drawio index 8a4f41056ca69..794b192dfe10b 100644 --- a/docs/en/docs/img/deployment/https/https08.drawio +++ b/docs/en/docs/img/deployment/https/https08.drawio @@ -214,4 +214,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/deployment/https/https08.svg b/docs/en/docs/img/deployment/https/https08.svg index 3047dd821759b..2d4680dcc23e1 100644 --- a/docs/en/docs/img/deployment/https/https08.svg +++ b/docs/en/docs/img/deployment/https/https08.svg @@ -59,4 +59,4 @@
someapp.example.com
someapp.example.com
another.example.net
another.example.net
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 \ No newline at end of file +
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1 diff --git a/docs/en/docs/img/sponsors/budget-insight.svg b/docs/en/docs/img/sponsors/budget-insight.svg new file mode 100644 index 0000000000000..d753727a1f8a5 --- /dev/null +++ b/docs/en/docs/img/sponsors/budget-insight.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/exoflare.png b/docs/en/docs/img/sponsors/exoflare.png new file mode 100644 index 0000000000000..b5977d80bedb2 Binary files /dev/null and b/docs/en/docs/img/sponsors/exoflare.png differ diff --git a/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png new file mode 100644 index 0000000000000..220d0863882d1 Binary files /dev/null and b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png differ diff --git a/docs/en/docs/img/sponsors/ines-course.jpg b/docs/en/docs/img/sponsors/ines-course.jpg new file mode 100644 index 0000000000000..05158b3872caa Binary files /dev/null and b/docs/en/docs/img/sponsors/ines-course.jpg differ diff --git a/docs/en/docs/img/sponsors/testdriven.svg b/docs/en/docs/img/sponsors/testdriven.svg index 97741b9e03d7a..6ba2daa3b9d4d 100644 --- a/docs/en/docs/img/sponsors/testdriven.svg +++ b/docs/en/docs/img/sponsors/testdriven.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio b/docs/en/docs/img/tutorial/bigger-applications/package.drawio index 48f6e76fe035a..cab3de2ca8376 100644 --- a/docs/en/docs/img/tutorial/bigger-applications/package.drawio +++ b/docs/en/docs/img/tutorial/bigger-applications/package.drawio @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.svg b/docs/en/docs/img/tutorial/bigger-applications/package.svg index a9cec926a84aa..44da1dc30dd41 100644 --- a/docs/en/docs/img/tutorial/bigger-applications/package.svg +++ b/docs/en/docs/img/tutorial/bigger-applications/package.svg @@ -1 +1 @@ -
Package app
app/__init__.py
Package app...
Module app.main
app/main.py
Module app.main...
Module app.dependencies
app/dependencies.py
Module app.dependencies...
Subpackage app.internal
app/internal/__init__.py
Subpackage app.internal...
Module app.internal.admin
app/internal/admin.py
Module app.internal.admin...
Subpackage app.routers
app/routers/__init__.py
Subpackage app.routers...
Module app.routers.items
app/routers/items.py
Module app.routers.items...
Module app.routers.users
app/routers/users.py
Module app.routers.users...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Package app
app/__init__.py
Package app...
Module app.main
app/main.py
Module app.main...
Module app.dependencies
app/dependencies.py
Module app.dependencies...
Subpackage app.internal
app/internal/__init__.py
Subpackage app.internal...
Module app.internal.admin
app/internal/admin.py
Module app.internal.admin...
Subpackage app.routers
app/routers/__init__.py
Subpackage app.routers...
Module app.routers.items
app/routers/items.py
Module app.routers.items...
Module app.routers.users
app/routers/users.py
Module app.routers.users...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 7de1e50df5627..17163ba014673 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -148,7 +148,7 @@ $ pip install "uvicorn[standard]" * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -161,7 +161,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -171,7 +171,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -184,7 +184,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -263,7 +263,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -274,7 +274,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -283,7 +283,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} diff --git a/docs/en/docs/js/termynal.js b/docs/en/docs/js/termynal.js index 8b0e9339e8772..4ac32708a31a0 100644 --- a/docs/en/docs/js/termynal.js +++ b/docs/en/docs/js/termynal.js @@ -72,14 +72,14 @@ class Termynal { * Initialise the widget, get lines, clear container and start animation. */ init() { - /** + /** * Calculates width and height of Termynal container. * If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS. - */ + */ const containerStyle = getComputedStyle(this.container); - this.container.style.width = containerStyle.width !== '0px' ? + this.container.style.width = containerStyle.width !== '0px' ? containerStyle.width : undefined; - this.container.style.minHeight = containerStyle.height !== '0px' ? + this.container.style.minHeight = containerStyle.height !== '0px' ? containerStyle.height : undefined; this.container.setAttribute('data-termynal', ''); @@ -138,7 +138,7 @@ class Termynal { restart.innerHTML = "restart ↻" return restart } - + generateFinish() { const finish = document.createElement('a') finish.onclick = (e) => { @@ -215,7 +215,7 @@ class Termynal { /** * Converts line data objects into line elements. - * + * * @param {Object[]} lineData - Dynamically loaded lines. * @param {Object} line - Line data object. * @returns {Element[]} - Array of line elements. @@ -231,7 +231,7 @@ class Termynal { /** * Helper function for generating attributes string. - * + * * @param {Object} line - Line data object. * @returns {string} - String of attributes. */ diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index fe56dadec0801..963fcaf1cd580 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -29,7 +29,7 @@ Calling this program outputs: John Doe ``` -The function does the following: +The function does the following: * Takes a `first_name` and `last_name`. * Converts the first letter of each one to upper case with `title()`. @@ -317,6 +317,45 @@ This also means that in Python 3.10, you can use `Something | None`: {!> ../../../docs_src/python_types/tutorial009_py310.py!} ``` +#### Using `Union` or `Optional` + +If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view: + +* 🚨 Avoid using `Optional[SomeType]` +* Instead ✨ **use `Union[SomeType, None]`** ✨. + +Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required. + +I think `Union[str, SomeType]` is more explicit about what it means. + +It's just about the words and names. But those words can affect how you and your teammates think about the code. + +As an example, let's take this function: + +```Python hl_lines="1 4" +{!../../../docs_src/python_types/tutorial009c.py!} +``` + +The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter: + +```Python +say_hi() # Oh, no, this throws an error! 😱 +``` + +The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value: + +```Python +say_hi(name=None) # This works, None is valid 🎉 +``` + +The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types: + +```Python hl_lines="1 4" +{!../../../docs_src/python_types/tutorial009c_py310.py!} +``` + +And then you won't have to worry about names like `Optional` and `Union`. 😎 + #### Generic types These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example: @@ -334,14 +373,14 @@ These types that take type parameters in square brackets are called **Generic ty === "Python 3.9 and above" You can use the same builtin types as generics (with square brakets and types inside): - + * `list` * `tuple` * `set` * `dict` And the same as with Python 3.6, from the `typing` module: - + * `Union` * `Optional` * ...and others. @@ -354,7 +393,7 @@ These types that take type parameters in square brackets are called **Generic ty * `tuple` * `set` * `dict` - + And the same as with Python 3.6, from the `typing` module: * `Union` @@ -422,6 +461,9 @@ An example from the official Pydantic docs: You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}. +!!! tip + Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required Optional fields. + ## Type hints in **FastAPI** **FastAPI** takes advantage of these type hints to do several things. diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b7ccd67f6b9e4..edc58171bfff7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,218 @@ ## Latest Changes + +## 0.78.0 + +### Features + +* ✨ Add support for omitting `...` as default value when declaring required parameters with: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +New docs at [Tutorial - Query Parameters and String Validations - Make it required](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#make-it-required). PR [#4906](https://github.com/tiangolo/fastapi/pull/4906) by [@tiangolo](https://github.com/tiangolo). + +Up to now, declaring a required parameter while adding additional validation or metadata needed using `...` (Ellipsis). + +For example: + +```Python +from fastapi import Cookie, FastAPI, Header, Path, Query + +app = FastAPI() + + +@app.get("/items/{item_id}") +def main( + item_id: int = Path(default=..., gt=0), + query: str = Query(default=..., max_length=10), + session: str = Cookie(default=..., min_length=3), + x_trace: str = Header(default=..., title="Tracing header"), +): + return {"message": "Hello World"} +``` + +...all these parameters are required because the default value is `...` (Ellipsis). + +But now it's possible and supported to just omit the default value, as would be done with Pydantic fields, and the parameters would still be required. + +✨ For example, this is now supported: + +```Python +from fastapi import Cookie, FastAPI, Header, Path, Query + +app = FastAPI() + + +@app.get("/items/{item_id}") +def main( + item_id: int = Path(gt=0), + query: str = Query(max_length=10), + session: str = Cookie(min_length=3), + x_trace: str = Header(title="Tracing header"), +): + return {"message": "Hello World"} +``` + +To declare parameters as optional (not required), you can set a default value as always, for example using `None`: + +```Python +from typing import Union +from fastapi import Cookie, FastAPI, Header, Path, Query + +app = FastAPI() + + +@app.get("/items/{item_id}") +def main( + item_id: int = Path(gt=0), + query: Union[str, None] = Query(default=None, max_length=10), + session: Union[str, None] = Cookie(default=None, min_length=3), + x_trace: Union[str, None] = Header(default=None, title="Tracing header"), +): + return {"message": "Hello World"} +``` + +### Docs + +* 📝 Add docs recommending `Union` over `Optional` and migrate source examples. New docs at [Python Types Intro - Using `Union` or `Optional`](https://fastapi.tiangolo.com/python-types/#using-union-or-optional). PR [#4908](https://github.com/tiangolo/fastapi/pull/4908) by [@tiangolo](https://github.com/tiangolo). +* 🎨 Fix default value as set in tutorial for Path Operations Advanced Configurations. PR [#4899](https://github.com/tiangolo/fastapi/pull/4899) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add documentation for redefined path operations. PR [#4864](https://github.com/tiangolo/fastapi/pull/4864) by [@madkinsz](https://github.com/madkinsz). +* 📝 Updates links for Celery documentation. PR [#4736](https://github.com/tiangolo/fastapi/pull/4736) by [@sammyzord](https://github.com/sammyzord). +* ✏ Fix example code with sets in tutorial for body nested models. PR [#3030](https://github.com/tiangolo/fastapi/pull/3030) by [@hitrust](https://github.com/hitrust). +* ✏ Fix links to Pydantic docs. PR [#4670](https://github.com/tiangolo/fastapi/pull/4670) by [@kinuax](https://github.com/kinuax). +* 📝 Update docs about Swagger UI self-hosting with newer source links. PR [#4813](https://github.com/tiangolo/fastapi/pull/4813) by [@Kastakin](https://github.com/Kastakin). +* 📝 Add link to external article: Building the Poll App From Django Tutorial With FastAPI And React. PR [#4778](https://github.com/tiangolo/fastapi/pull/4778) by [@jbrocher](https://github.com/jbrocher). +* 📝 Add OpenAPI warning to "Body - Fields" docs with extra schema extensions. PR [#4846](https://github.com/tiangolo/fastapi/pull/4846) by [@ml-evs](https://github.com/ml-evs). + +### Translations + +* 🌐 Fix code examples in Japanese translation for `docs/ja/docs/tutorial/testing.md`. PR [#4623](https://github.com/tiangolo/fastapi/pull/4623) by [@hirotoKirimaru](https://github.com/hirotoKirimaru). + +### Internal + +* ♻ Refactor dict value extraction to minimize key lookups `fastapi/utils.py`. PR [#3139](https://github.com/tiangolo/fastapi/pull/3139) by [@ShahriyarR](https://github.com/ShahriyarR). +* ✅ Add tests for required nonable parameters and body fields. PR [#4907](https://github.com/tiangolo/fastapi/pull/4907) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix installing Material for MkDocs Insiders in CI. PR [#4897](https://github.com/tiangolo/fastapi/pull/4897) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add pre-commit CI instead of custom GitHub Action. PR [#4896](https://github.com/tiangolo/fastapi/pull/4896) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add pre-commit GitHub Action workflow. PR [#4895](https://github.com/tiangolo/fastapi/pull/4895) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add dark mode auto switch to docs based on OS preference. PR [#4869](https://github.com/tiangolo/fastapi/pull/4869) by [@ComicShrimp](https://github.com/ComicShrimp). +* 🔥 Remove un-used old pending tests, already covered in other places. PR [#4891](https://github.com/tiangolo/fastapi/pull/4891) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add Python formatting hooks to pre-commit. PR [#4890](https://github.com/tiangolo/fastapi/pull/4890) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add pre-commit with first config and first formatting pass. PR [#4888](https://github.com/tiangolo/fastapi/pull/4888) by [@tiangolo](https://github.com/tiangolo). +* 👷 Disable CI installing Material for MkDocs in forks. PR [#4410](https://github.com/tiangolo/fastapi/pull/4410) by [@dolfinus](https://github.com/dolfinus). + +## 0.77.1 + +### Upgrades + +* ⬆ Upgrade Starlette from 0.19.0 to 0.19.1. PR [#4819](https://github.com/tiangolo/fastapi/pull/4819) by [@Kludex](https://github.com/Kludex). + +### Docs + +* 📝 Add link to german article: REST-API Programmieren mittels Python und dem FastAPI Modul. PR [#4624](https://github.com/tiangolo/fastapi/pull/4624) by [@fschuermeyer](https://github.com/fschuermeyer). +* 📝 Add external link: PyCharm Guide to FastAPI. PR [#4512](https://github.com/tiangolo/fastapi/pull/4512) by [@mukulmantosh](https://github.com/mukulmantosh). +* 📝 Add external link to article: Building an API with FastAPI and Supabase and Deploying on Deta. PR [#4440](https://github.com/tiangolo/fastapi/pull/4440) by [@aUnicornDev](https://github.com/aUnicornDev). +* ✏ Fix small typo in `docs/en/docs/tutorial/security/first-steps.md`. PR [#4515](https://github.com/tiangolo/fastapi/pull/4515) by [@KikoIlievski](https://github.com/KikoIlievski). + +### Translations + +* 🌐 Add Polish translation for `docs/pl/docs/tutorial/index.md`. PR [#4516](https://github.com/tiangolo/fastapi/pull/4516) by [@MKaczkow](https://github.com/MKaczkow). +* ✏ Fix typo in deployment. PR [#4629](https://github.com/tiangolo/fastapi/pull/4629) by [@raisulislam541](https://github.com/raisulislam541). +* 🌐 Add Portuguese translation for `docs/pt/docs/help-fastapi.md`. PR [#4583](https://github.com/tiangolo/fastapi/pull/4583) by [@mateusjs](https://github.com/mateusjs). + +### Internal + +* 🔧 Add notifications in issue for Uzbek translations. PR [#4884](https://github.com/tiangolo/fastapi/pull/4884) by [@tiangolo](https://github.com/tiangolo). + +## 0.77.0 + +### Upgrades + +* ⬆ Upgrade Starlette from 0.18.0 to 0.19.0. PR [#4488](https://github.com/tiangolo/fastapi/pull/4488) by [@Kludex](https://github.com/Kludex). + * When creating an explicit `JSONResponse` the `content` argument is now required. + +### Docs + +* 📝 Add external link to article: Seamless FastAPI Configuration with ConfZ. PR [#4414](https://github.com/tiangolo/fastapi/pull/4414) by [@silvanmelchior](https://github.com/silvanmelchior). +* 📝 Add external link to article: 5 Advanced Features of FastAPI You Should Try. PR [#4436](https://github.com/tiangolo/fastapi/pull/4436) by [@kaustubhgupta](https://github.com/kaustubhgupta). +* ✏ Reword to improve legibility of docs about `TestClient`. PR [#4389](https://github.com/tiangolo/fastapi/pull/4389) by [@rgilton](https://github.com/rgilton). +* 📝 Add external link to blog post about Kafka, FastAPI, and Ably. PR [#4044](https://github.com/tiangolo/fastapi/pull/4044) by [@Ugbot](https://github.com/Ugbot). +* ✏ Fix typo in `docs/en/docs/tutorial/sql-databases.md`. PR [#4875](https://github.com/tiangolo/fastapi/pull/4875) by [@wpyoga](https://github.com/wpyoga). +* ✏ Fix typo in `docs/en/docs/async.md`. PR [#4726](https://github.com/tiangolo/fastapi/pull/4726) by [@Prezu](https://github.com/Prezu). + +### Translations + +* 🌐 Update source example highlights for `docs/zh/docs/tutorial/query-params-str-validations.md`. PR [#4237](https://github.com/tiangolo/fastapi/pull/4237) by [@caimaoy](https://github.com/caimaoy). +* 🌐 Remove translation docs references to aiofiles as it's no longer needed since AnyIO. PR [#3594](https://github.com/tiangolo/fastapi/pull/3594) by [@alonme](https://github.com/alonme). +* ✏ 🌐 Fix typo in Portuguese translation for `docs/pt/docs/tutorial/path-params.md`. PR [#4722](https://github.com/tiangolo/fastapi/pull/4722) by [@CleoMenezesJr](https://github.com/CleoMenezesJr). +* 🌐 Fix live docs server for translations for some languages. PR [#4729](https://github.com/tiangolo/fastapi/pull/4729) by [@wakabame](https://github.com/wakabame). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/cookie-params.md`. PR [#4112](https://github.com/tiangolo/fastapi/pull/4112) by [@lbmendes](https://github.com/lbmendes). +* 🌐 Fix French translation for `docs/tutorial/body.md`. PR [#4332](https://github.com/tiangolo/fastapi/pull/4332) by [@Smlep](https://github.com/Smlep). +* 🌐 Add Japanese translation for `docs/ja/docs/advanced/conditional-openapi.md`. PR [#2631](https://github.com/tiangolo/fastapi/pull/2631) by [@sh0nk](https://github.com/sh0nk). +* 🌐 Fix Japanese translation of `docs/ja/docs/tutorial/body.md`. PR [#3062](https://github.com/tiangolo/fastapi/pull/3062) by [@a-takahashi223](https://github.com/a-takahashi223). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/background-tasks.md`. PR [#2170](https://github.com/tiangolo/fastapi/pull/2170) by [@izaguerreiro](https://github.com/izaguerreiro). +* 🌐 Add Portuguese translation for `docs/deployment/deta.md`. PR [#4442](https://github.com/tiangolo/fastapi/pull/4442) by [@lsglucas](https://github.com/lsglucas). +* 🌐 Add Russian translation for `docs/async.md`. PR [#4036](https://github.com/tiangolo/fastapi/pull/4036) by [@Winand](https://github.com/Winand). +* 🌐 Add Portuguese translation for `docs/tutorial/body.md`. PR [#3960](https://github.com/tiangolo/fastapi/pull/3960) by [@leandrodesouzadev](https://github.com/leandrodesouzadev). +* 🌐 Add Portuguese translation of `tutorial/extra-data-types.md`. PR [#4077](https://github.com/tiangolo/fastapi/pull/4077) by [@luccasmmg](https://github.com/luccasmmg). +* 🌐 Update German translation for `docs/features.md`. PR [#3905](https://github.com/tiangolo/fastapi/pull/3905) by [@jomue](https://github.com/jomue). + +## 0.76.0 + +### Upgrades + +* ⬆ Upgrade Starlette from 0.17.1 to 0.18.0. PR [#4483](https://github.com/tiangolo/fastapi/pull/4483) by [@Kludex](https://github.com/Kludex). + +### Internal + +* 👥 Update FastAPI People. PR [#4847](https://github.com/tiangolo/fastapi/pull/4847) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔧 Add Budget Insight sponsor. PR [#4824](https://github.com/tiangolo/fastapi/pull/4824) by [@tiangolo](https://github.com/tiangolo). +* 🍱 Update sponsor, ExoFlare badge. PR [#4822](https://github.com/tiangolo/fastapi/pull/4822) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, enable Dropbase again, update TalkPython link. PR [#4821](https://github.com/tiangolo/fastapi/pull/4821) by [@tiangolo](https://github.com/tiangolo). + +## 0.75.2 + +This release includes upgrades to third-party packages that handle security issues. Although there's a chance these issues don't affect you in particular, please upgrade as soon as possible. + +### Fixes + +* ✅ Fix new/recent tests with new fixed `ValidationError` JSON Schema. PR [#4806](https://github.com/tiangolo/fastapi/pull/4806) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix JSON Schema for `ValidationError` at field `loc`. PR [#3810](https://github.com/tiangolo/fastapi/pull/3810) by [@dconathan](https://github.com/dconathan). +* 🐛 Fix support for prefix on APIRouter WebSockets. PR [#2640](https://github.com/tiangolo/fastapi/pull/2640) by [@Kludex](https://github.com/Kludex). + +### Upgrades + +* ⬆️ Update ujson ranges for CVE-2021-45958. PR [#4804](https://github.com/tiangolo/fastapi/pull/4804) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade dependencies upper range for extras "all". PR [#4803](https://github.com/tiangolo/fastapi/pull/4803) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Upgrade Swagger UI - swagger-ui-dist@4. This handles a security issue in Swagger UI itself where it could be possible to inject HTML into Swagger UI. Please upgrade as soon as you can, in particular if you expose your Swagger UI (`/docs`) publicly to non-expert users. PR [#4347](https://github.com/tiangolo/fastapi/pull/4347) by [@RAlanWright](https://github.com/RAlanWright). + +### Internal + +* 🔧 Update sponsors, add: ExoFlare, Ines Course; remove: Dropbase, Vim.so, Calmcode; update: Striveworks, TalkPython and TestDriven.io. PR [#4805](https://github.com/tiangolo/fastapi/pull/4805) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade Codecov GitHub Action. PR [#4801](https://github.com/tiangolo/fastapi/pull/4801) by [@tiangolo](https://github.com/tiangolo). + +## 0.75.1 + +### Translations + +* 🌐 Start Dutch translations. PR [#4703](https://github.com/tiangolo/fastapi/pull/4703) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Start Persian/Farsi translations. PR [#4243](https://github.com/tiangolo/fastapi/pull/4243) by [@aminalaee](https://github.com/aminalaee). +* ✏ Reword sentence about handling errors. PR [#1993](https://github.com/tiangolo/fastapi/pull/1993) by [@khuhroproeza](https://github.com/khuhroproeza). + +### Internal + +* 👥 Update FastAPI People. PR [#4752](https://github.com/tiangolo/fastapi/pull/4752) by [@github-actions[bot]](https://github.com/apps/github-actions). +* ➖ Temporarily remove typer-cli from dependencies and upgrade Black to unblock Pydantic CI. PR [#4754](https://github.com/tiangolo/fastapi/pull/4754) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add configuration to notify Dutch translations. PR [#4702](https://github.com/tiangolo/fastapi/pull/4702) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#4699](https://github.com/tiangolo/fastapi/pull/4699) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🐛 Fix FastAPI People generation to include missing file in commit. PR [#4695](https://github.com/tiangolo/fastapi/pull/4695) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update Classiq sponsor links. PR [#4688](https://github.com/tiangolo/fastapi/pull/4688) by [@tiangolo](https://github.com/tiangolo). * 🔧 Add Classiq sponsor. PR [#4671](https://github.com/tiangolo/fastapi/pull/4671) by [@tiangolo](https://github.com/tiangolo). * 📝 Add Jina's QA Bot to the docs to help people that want to ask quick questions. PR [#4655](https://github.com/tiangolo/fastapi/pull/4655) by [@tiangolo](https://github.com/tiangolo) based on original PR [#4626](https://github.com/tiangolo/fastapi/pull/4626) by [@hanxiao](https://github.com/hanxiao). diff --git a/docs/en/docs/tutorial/background-tasks.md b/docs/en/docs/tutorial/background-tasks.md index 69aeb6712c70a..191a4ca0fbce0 100644 --- a/docs/en/docs/tutorial/background-tasks.md +++ b/docs/en/docs/tutorial/background-tasks.md @@ -89,7 +89,7 @@ You can see more details in Celery. +If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like Celery. They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers. diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index 2a2e764b5988d..d201953df4eb1 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -334,7 +334,7 @@ from app.routers import items, users ```Python from .routers import items, users ``` - + The second version is an "absolute import": ```Python diff --git a/docs/en/docs/tutorial/body-fields.md b/docs/en/docs/tutorial/body-fields.md index 1f38a0c5c566f..0cfe576d68d72 100644 --- a/docs/en/docs/tutorial/body-fields.md +++ b/docs/en/docs/tutorial/body-fields.md @@ -57,6 +57,10 @@ You can declare extra information in `Field`, `Query`, `Body`, etc. And it will You will learn more about adding extra information later in the docs, when learning to declare examples. +!!! warning + Extra keys passed to `Field` will also be present in the resulting OpenAPI schema for your application. + As these keys may not necessarily be part of the OpenAPI specification, some OpenAPI tools, for example [the OpenAPI validator](https://validator.swagger.io/), may not work with your generated schema. + ## Recap You can use Pydantic's `Field` to declare extra validations and metadata for model attributes. diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index 13de4c8eab531..31dd27fed45a4 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -89,13 +89,13 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`: === "Python 3.6 and above" - ```Python hl_lines="23" + ```Python hl_lines="22" {!> ../../../docs_src/body_multiple_params/tutorial003.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="21" + ```Python hl_lines="20" {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!} ``` @@ -126,7 +126,7 @@ Of course, you can also declare additional query parameters whenever you need, a As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` Or in Python 3.10 and above: @@ -139,7 +139,7 @@ For example: === "Python 3.6 and above" - ```Python hl_lines="28" + ```Python hl_lines="27" {!> ../../../docs_src/body_multiple_params/tutorial004.py!} ``` @@ -152,7 +152,6 @@ For example: !!! info `Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later. - ## Embed a single body parameter Let's say you only have a single `item` body parameter from a Pydantic model `Item`. @@ -162,7 +161,7 @@ By default, **FastAPI** will then expect its body directly. But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`: ```Python -item: Item = Body(..., embed=True) +item: Item = Body(embed=True) ``` as in: diff --git a/docs/en/docs/tutorial/body-nested-models.md b/docs/en/docs/tutorial/body-nested-models.md index fa38cfc4883f5..bfc948f4fadc2 100644 --- a/docs/en/docs/tutorial/body-nested-models.md +++ b/docs/en/docs/tutorial/body-nested-models.md @@ -366,7 +366,7 @@ In this case, you would accept any `dict` as long as it has `int` keys with `flo But Pydantic has automatic data conversion. This means that, even though your API clients can only send strings as keys, as long as those strings contain pure integers, Pydantic will convert them and validate them. - + And the `dict` you receive as `weights` will actually have `int` keys and `float` values. ## Recap diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md index 81441b41eb2aa..5090059360ba7 100644 --- a/docs/en/docs/tutorial/body.md +++ b/docs/en/docs/tutorial/body.md @@ -138,7 +138,7 @@ But you would get the same editor support with PyCharm as your editor, you can use the Pydantic PyCharm Plugin. It improves editor support for Pydantic models, with: - + * auto-completion * type checks * refactoring @@ -206,7 +206,7 @@ The function parameters will be recognized as follows: !!! note FastAPI will know that the value of `q` is not required because of the default value `= None`. - The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors. + The `Union` in `Union[str, None]` is not used by FastAPI, but will allow your editor to give you better support and detect errors. ## Without Pydantic diff --git a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md index 663fff15bf3f5..fb41ba1f67e2f 100644 --- a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md @@ -109,7 +109,7 @@ Pay attention to the `__init__` method used to create the instance of the class: === "Python 3.6 and above" - ```Python hl_lines="8" + ```Python hl_lines="9" {!> ../../../docs_src/dependencies/tutorial001.py!} ``` diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index ac2e9cb8cb4c4..a7300f0b7a68d 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -10,7 +10,7 @@ To do this, use `yield` instead of `return`, and write the extra steps after. !!! note "Technical Details" Any function that is valid to use with: - * `@contextlib.contextmanager` or + * `@contextlib.contextmanager` or * `@contextlib.asynccontextmanager` would be valid to use as a **FastAPI** dependency. @@ -207,7 +207,7 @@ You can also use them inside of **FastAPI** dependencies with `yield` by using !!! tip Another way to create a context manager is with: - * `@contextlib.contextmanager` or + * `@contextlib.contextmanager` or * `@contextlib.asynccontextmanager` using them to decorate a function with a single `yield`. diff --git a/docs/en/docs/tutorial/dependencies/index.md b/docs/en/docs/tutorial/dependencies/index.md index fe10facfbc365..5078c00968362 100644 --- a/docs/en/docs/tutorial/dependencies/index.md +++ b/docs/en/docs/tutorial/dependencies/index.md @@ -33,7 +33,7 @@ It is just a function that can take all the same parameters that a *path operati === "Python 3.6 and above" - ```Python hl_lines="8-9" + ```Python hl_lines="8-11" {!> ../../../docs_src/dependencies/tutorial001.py!} ``` @@ -81,7 +81,7 @@ The same way you use `Body`, `Query`, etc. with your *path operation function* p === "Python 3.6 and above" - ```Python hl_lines="13 18" + ```Python hl_lines="15 20" {!> ../../../docs_src/dependencies/tutorial001.py!} ``` diff --git a/docs/en/docs/tutorial/dependencies/sub-dependencies.md b/docs/en/docs/tutorial/dependencies/sub-dependencies.md index 51531228da54d..a5b40c9ad743b 100644 --- a/docs/en/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/sub-dependencies.md @@ -55,7 +55,7 @@ Then we can use the dependency with: === "Python 3.6 and above" - ```Python hl_lines="21" + ```Python hl_lines="22" {!> ../../../docs_src/dependencies/tutorial005.py!} ``` diff --git a/docs/en/docs/tutorial/extra-data-types.md b/docs/en/docs/tutorial/extra-data-types.md index a00bd32122509..fb3efd318438c 100644 --- a/docs/en/docs/tutorial/extra-data-types.md +++ b/docs/en/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ Here are some of the additional data types you can use: * `datetime.timedelta`: * A Python `datetime.timedelta`. * In requests and responses will be represented as a `float` of total seconds. - * Pydantic also allows representing it as a "ISO 8601 time diff encoding", see the docs for more info. + * Pydantic also allows representing it as a "ISO 8601 time diff encoding", see the docs for more info. * `frozenset`: * In requests and responses, treated the same as a `set`: * In requests, a list will be read, eliminating duplicates and converting it to a `set`. diff --git a/docs/en/docs/tutorial/handling-errors.md b/docs/en/docs/tutorial/handling-errors.md index 89f96176d6997..8c30326cede92 100644 --- a/docs/en/docs/tutorial/handling-errors.md +++ b/docs/en/docs/tutorial/handling-errors.md @@ -163,7 +163,7 @@ path -> item_id !!! warning These are technical details that you might skip if it's not important for you now. -`RequestValidationError` is a sub-class of Pydantic's `ValidationError`. +`RequestValidationError` is a sub-class of Pydantic's `ValidationError`. **FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log. @@ -252,9 +252,7 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ### Re-use **FastAPI**'s exception handlers -You could also just want to use the exception somehow, but then use the same default exception handlers from **FastAPI**. - -You can import and re-use the default exception handlers from `fastapi.exception_handlers`: +If you want to use the exception along with the same default exception handlers from **FastAPI**, You can import and re-use the default exception handlers from `fastapi.exception_handlers`: ```Python hl_lines="2-5 15 21" {!../../../docs_src/handling_errors/tutorial006.py!} diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index 31bf91a0ea6e6..29235c6e2863b 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -59,7 +59,7 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names, So, you can declare your function as: -```Python hl_lines="8" +```Python hl_lines="7" {!../../../docs_src/path_params_numeric_validations/tutorial002.py!} ``` @@ -71,7 +71,7 @@ Pass `*`, as the first parameter of the function. Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as kwargs. Even if they don't have a default value. -```Python hl_lines="8" +```Python hl_lines="7" {!../../../docs_src/path_params_numeric_validations/tutorial003.py!} ``` diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md index 9c458844d37cb..a0d70692e556b 100644 --- a/docs/en/docs/tutorial/path-params.md +++ b/docs/en/docs/tutorial/path-params.md @@ -115,6 +115,14 @@ Because *path operations* are evaluated in order, you need to make sure that the Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`. +Similarly, you cannot redefine a path operation: + +```Python hl_lines="6 11" +{!../../../docs_src/path_params/tutorial003b.py!} +``` + +The first one will always be used since the path matches first. + ## Predefined values If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python `Enum`. diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index ee62b97181028..c5fc35b88aeff 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -16,12 +16,12 @@ Let's take this application as example: {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!} ``` -The query parameter `q` is of type `Optional[str]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required. +The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required. !!! note FastAPI will know that the value of `q` is not required because of the default value `= None`. - The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors. + The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors. ## Additional validation @@ -59,24 +59,24 @@ And now use it as the default value of your parameter, setting the parameter `ma {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!} ``` -As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value. +As we have to replace the default value `None` in the function with `Query()`, we can now set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value. So: ```Python -q: Optional[str] = Query(None) +q: Union[str, None] = Query(default=None) ``` ...makes the parameter optional, the same as: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` And in Python 3.10 and above: ```Python -q: str | None = Query(None) +q: str | None = Query(default=None) ``` ...makes the parameter optional, the same as: @@ -97,17 +97,17 @@ But it declares it explicitly as being a query parameter. or the: ```Python - = Query(None) + = Query(default=None) ``` as it will use that `None` as the default value, and that way make the parameter **not required**. - The `Optional` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required. + The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required. Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings: ```Python -q: str = Query(None, max_length=50) +q: Union[str, None] = Query(default=None, max_length=50) ``` This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*. @@ -118,7 +118,7 @@ You can also add a parameter `min_length`: === "Python 3.6 and above" - ```Python hl_lines="9" + ```Python hl_lines="10" {!> ../../../docs_src/query_params_str_validations/tutorial003.py!} ``` @@ -134,13 +134,13 @@ You can define a ../../../docs_src/query_params_str_validations/tutorial004.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="8" + ```Python hl_lines="9" {!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!} ``` @@ -156,7 +156,7 @@ But whenever you need them and go and learn them, know that you can already use ## Default values -The same way that you can pass `None` as the first argument to be used as the default value, you can pass other values. +The same way that you can pass `None` as the value for the `default` parameter, you can pass other values. Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`: @@ -178,26 +178,68 @@ q: str instead of: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` But we are now declaring it with `Query`, for example like: ```Python -q: Optional[str] = Query(None, min_length=3) +q: Union[str, None] = Query(default=None, min_length=3) ``` -So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument: +So, when you need to declare a value as required while using `Query`, you can simply not declare a default value: ```Python hl_lines="7" {!../../../docs_src/query_params_str_validations/tutorial006.py!} ``` +### Required with Ellipsis (`...`) + +There's an alternative way to explicitly declare that a value is required. You can set the `default` parameter to the literal value `...`: + +```Python hl_lines="7" +{!../../../docs_src/query_params_str_validations/tutorial006b.py!} +``` + !!! info If you hadn't seen that `...` before: it is a special single value, it is part of Python and is called "Ellipsis". + It is used by Pydantic and FastAPI to explicitly declare that a value is required. + This will let **FastAPI** know that this parameter is required. +### Required with `None` + +You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`. + +To do that, you can declare that `None` is a valid type but still use `default=...`: + +=== "Python 3.6 and above" + + ```Python hl_lines="8" + {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!} + ``` + +=== "Python 3.10 and above" + + ```Python hl_lines="7" + {!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!} + ``` + +!!! tip + Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required Optional fields. + +### Use Pydantic's `Required` instead of Ellipsis (`...`) + +If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic: + +```Python hl_lines="2 8" +{!../../../docs_src/query_params_str_validations/tutorial006d.py!} +``` + +!!! tip + Remember that in most of the cases, when something is required, you can simply omit the `default` parameter, so you normally don't have to use `...` nor `Required`. + ## Query parameter list / multiple values When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values. @@ -315,7 +357,7 @@ You can add a `title`: === "Python 3.10 and above" - ```Python hl_lines="7" + ```Python hl_lines="8" {!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!} ``` @@ -399,7 +441,7 @@ To exclude a query parameter from the generated OpenAPI schema (and thus, from t === "Python 3.10 and above" - ```Python hl_lines="7" + ```Python hl_lines="8" {!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!} ``` diff --git a/docs/en/docs/tutorial/request-files.md b/docs/en/docs/tutorial/request-files.md index 3ca471a91b866..664a1102f161f 100644 --- a/docs/en/docs/tutorial/request-files.md +++ b/docs/en/docs/tutorial/request-files.md @@ -106,7 +106,7 @@ The way HTML forms (`
`) sends the data to the server normally uses Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded` when it doesn't include files. But when the form includes files, it is encoded as `multipart/form-data`. If you use `File`, **FastAPI** will know it has to get the files from the correct part of the body. - + If you want to read more about these encodings and form fields, head to the MDN web docs for POST. !!! warning diff --git a/docs/en/docs/tutorial/request-forms.md b/docs/en/docs/tutorial/request-forms.md index b5495a4005610..2021a098f928a 100644 --- a/docs/en/docs/tutorial/request-forms.md +++ b/docs/en/docs/tutorial/request-forms.md @@ -45,7 +45,7 @@ The way HTML forms (`
`) sends the data to the server normally uses Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded`. But when the form includes files, it is encoded as `multipart/form-data`. You'll read about handling files in the next chapter. - + If you want to read more about these encodings and form fields, head to the MDN web docs for POST. !!! warning diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md index c751a9256be90..e371e86e4abbb 100644 --- a/docs/en/docs/tutorial/response-model.md +++ b/docs/en/docs/tutorial/response-model.md @@ -162,7 +162,7 @@ Your response model could have default values, like: {!> ../../../docs_src/response_model/tutorial004_py310.py!} ``` -* `description: Optional[str] = None` has a default of `None`. +* `description: Union[str, None] = None` has a default of `None`. * `tax: float = 10.5` has a default of `10.5`. * `tags: List[str] = []` as a default of an empty list: `[]`. diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index c69df51dc9e0e..94347018d08dd 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -68,13 +68,13 @@ Here we pass an `example` of the data expected in `Body()`: === "Python 3.6 and above" - ```Python hl_lines="21-26" + ```Python hl_lines="20-25" {!> ../../../docs_src/schema_extra_example/tutorial003.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="19-24" + ```Python hl_lines="18-23" {!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!} ``` @@ -99,13 +99,13 @@ Each specific example `dict` in the `examples` can contain: === "Python 3.6 and above" - ```Python hl_lines="22-48" + ```Python hl_lines="21-47" {!> ../../../docs_src/schema_extra_example/tutorial004.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="20-46" + ```Python hl_lines="19-45" {!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!} ``` diff --git a/docs/en/docs/tutorial/security/first-steps.md b/docs/en/docs/tutorial/security/first-steps.md index 360d85ae4d923..45ffaab90c10b 100644 --- a/docs/en/docs/tutorial/security/first-steps.md +++ b/docs/en/docs/tutorial/security/first-steps.md @@ -121,7 +121,7 @@ When we create an instance of the `OAuth2PasswordBearer` class we pass in the `t ``` !!! tip - here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`. + Here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`. Because we are using a relative URL, if your API was located at `https://example.com/`, then it would refer to `https://example.com/token`. But if your API was located at `https://example.com/api/v1/`, then it would refer to `https://example.com/api/v1/token`. diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md index 9dc2f64c6e67f..3436543a5e4f7 100644 --- a/docs/en/docs/tutorial/sql-databases.md +++ b/docs/en/docs/tutorial/sql-databases.md @@ -317,7 +317,7 @@ Not only the IDs of those items, but all the data that we defined in the Pydanti Now, in the Pydantic *models* for reading, `Item` and `User`, add an internal `Config` class. -This `Config` class is used to provide configurations to Pydantic. +This `Config` class is used to provide configurations to Pydantic. In the `Config` class, set the attribute `orm_mode = True`. @@ -491,7 +491,7 @@ You can find an example of Alembic in a FastAPI project in the templates from [P ### Create a dependency -Now use the `SessionLocal` class we created in the `sql_app/databases.py` file to create a dependency. +Now use the `SessionLocal` class we created in the `sql_app/database.py` file to create a dependency. We need to have an independent database session/connection (`SessionLocal`) per request, use the same session through all the request and then close it after the request is finished. @@ -616,7 +616,7 @@ And as the code related to SQLAlchemy and the SQLAlchemy models lives in separat The same way, you would be able to use the same SQLAlchemy models and utilities in other parts of your code that are not related to **FastAPI**. -For example, in a background task worker with Celery, RQ, or ARQ. +For example, in a background task worker with Celery, RQ, or ARQ. ## Review all the files diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md index 7e2ae84d006a9..fea5a54f5c2de 100644 --- a/docs/en/docs/tutorial/testing.md +++ b/docs/en/docs/tutorial/testing.md @@ -10,7 +10,7 @@ With it, you can use @@ -81,9 +69,9 @@ }); }); -IDE
/linter/cerebro**: * Porque las estructuras de datos de Pydantic son solo instances de clases que tu defines, el auto-completado, el linting, mypy y tu intuición deberían funcionar bien con tus datos validados. * **Rápido**: - * En benchmarks Pydantic es más rápido que todas las otras libraries probadas. + * En benchmarks Pydantic es más rápido que todas las otras libraries probadas. * Valida **estructuras complejas**: * Usa modelos jerárquicos de modelos de Pydantic, `typing` de Python, `List` y `Dict`, etc. * Los validadores también permiten que se definan fácil y claramente schemas complejos de datos. Estos son chequeados y documentados como JSON Schema. diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 65eaf75d0c833..ef4850b56518c 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -145,7 +145,7 @@ $ pip install uvicorn[standard] ```Python from fastapi import FastAPI -from typing import Optional +from typing import Union app = FastAPI() @@ -156,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -167,7 +167,7 @@ Si tu código usa `async` / `await`, usa `async def`: ```Python hl_lines="7 12" from fastapi import FastAPI -from typing import Optional +from typing import Union app = FastAPI() @@ -178,7 +178,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -259,7 +259,7 @@ Declara el body usando las declaraciones de tipo estándares de Python gracias a ```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel -from typing import Optional +from typing import Union app = FastAPI() @@ -267,7 +267,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -276,7 +276,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -439,7 +439,6 @@ Usadas por Pydantic: Usados por Starlette: * requests - Requerido si quieres usar el `TestClient`. -* aiofiles - Requerido si quieres usar `FileResponse` o `StaticFiles`. * jinja2 - Requerido si quieres usar la configuración por defecto de templates. * python-multipart - Requerido si quieres dar soporte a "parsing" de formularios, con `request.form()`. * itsdangerous - Requerido para dar soporte a `SessionMiddleware`. diff --git a/docs/es/docs/tutorial/first-steps.md b/docs/es/docs/tutorial/first-steps.md index 79f0a51c0a720..110036e8caadd 100644 --- a/docs/es/docs/tutorial/first-steps.md +++ b/docs/es/docs/tutorial/first-steps.md @@ -254,7 +254,7 @@ El `@app.get("/")` le dice a **FastAPI** que la función que tiene justo debajo Esa sintaxis `@algo` se llama un "decorador" en Python. Lo pones encima de una función. Es como un lindo sombrero decorado (creo que de ahí salió el concepto). - + Un "decorador" toma la función que tiene debajo y hace algo con ella. En nuestro caso, este decorador le dice a **FastAPI** que la función que está debajo corresponde al **path** `/` con una **operación** `get`. diff --git a/docs/es/docs/tutorial/query-params.md b/docs/es/docs/tutorial/query-params.md index 69caee6e8b10a..482af8dc06f74 100644 --- a/docs/es/docs/tutorial/query-params.md +++ b/docs/es/docs/tutorial/query-params.md @@ -75,7 +75,7 @@ En este caso el parámetro de la función `q` será opcional y será `None` por !!! note "Nota" FastAPI sabrá que `q` es opcional por el `= None`. - El `Optional` en `Optional[str]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Optional[str]` le permitirá a tu editor ayudarte a encontrar errores en tu código. + El `Union` en `Union[str, None]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Union[str, None]` le permitirá a tu editor ayudarte a encontrar errores en tu código. ## Conversión de tipos de parámetros de query diff --git a/docs/es/mkdocs.yml b/docs/es/mkdocs.yml index a4bc41154f6de..b544f9b387ad8 100644 --- a/docs/es/mkdocs.yml +++ b/docs/es/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -107,6 +111,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -117,6 +123,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md new file mode 100644 index 0000000000000..fd52f994c83a9 --- /dev/null +++ b/docs/fa/docs/index.md @@ -0,0 +1,468 @@ + +{!../../../docs/missing-translation.md!} + + +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +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. Completion 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: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + +{% if sponsors %} +{% for sponsor in sponsors.gold -%} + +{% endfor -%} +{%- for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + + + +Other sponsors + +## 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._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
Brian Okken - Python Bytes podcast host (ref)
+ +--- + +"_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._" + +
Timothy Crosley - Hug creator (ref)
+ +--- + +"_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 [...]_" + +
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+ +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +Python 3.6+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
+ +```console +$ pip install fastapi + +---> 100% +``` + +
+ +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +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: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +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: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
+ +### Run it + +Run the server with: + +
+ +```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. +``` + +
+ +
+About the command uvicorn main:app --reload... + +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. + +
+ +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +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` operations (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 http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![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 Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = 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 http://127.0.0.1:8000/docs. + +* 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 http://127.0.0.1:8000/redoc. + +* 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. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion 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 Tutorial - User Guide. + +**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 **Dependency Injection** 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). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on `requests` and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) + +To understand more about it, see the section Benchmarks. + +## Optional Dependencies + +Used by Pydantic: + +* ujson - for faster JSON "parsing". +* email_validator - for email validation. + +Used by Starlette: + +* requests - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - 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. diff --git a/docs/fa/mkdocs.yml b/docs/fa/mkdocs.yml new file mode 100644 index 0000000000000..3966a60261e02 --- /dev/null +++ b/docs/fa/mkdocs.yml @@ -0,0 +1,137 @@ +site_name: FastAPI +site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production +site_url: https://fastapi.tiangolo.com/fa/ +theme: + name: material + custom_dir: overrides + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: teal + accent: amber + toggle: + icon: material/lightbulb + name: Switch to light mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: teal + accent: amber + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + features: + - search.suggest + - search.highlight + - content.tabs.link + icon: + repo: fontawesome/brands/github-alt + logo: https://fastapi.tiangolo.com/img/icon-white.svg + favicon: https://fastapi.tiangolo.com/img/favicon.png + language: fa +repo_name: tiangolo/fastapi +repo_url: https://github.com/tiangolo/fastapi +edit_uri: '' +plugins: +- search +- markdownextradata: + data: data +nav: +- FastAPI: index.md +- Languages: + - en: / + - az: /az/ + - de: /de/ + - es: /es/ + - fa: /fa/ + - fr: /fr/ + - id: /id/ + - it: /it/ + - ja: /ja/ + - ko: /ko/ + - nl: /nl/ + - pl: /pl/ + - pt: /pt/ + - ru: /ru/ + - sq: /sq/ + - tr: /tr/ + - uk: /uk/ + - zh: /zh/ +markdown_extensions: +- toc: + permalink: true +- markdown.extensions.codehilite: + guess_lang: false +- mdx_include: + base_path: docs +- admonition +- codehilite +- extra +- pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format '' +- pymdownx.tabbed: + alternate_style: true +extra: + analytics: + provider: google + property: UA-133183413-1 + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/tiangolo/fastapi + - icon: fontawesome/brands/discord + link: https://discord.gg/VQjSZaeJmf + - icon: fontawesome/brands/twitter + link: https://twitter.com/fastapi + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/tiangolo + - icon: fontawesome/brands/dev + link: https://dev.to/tiangolo + - icon: fontawesome/brands/medium + link: https://medium.com/@tiangolo + - icon: fontawesome/solid/globe + link: https://tiangolo.com + alternate: + - link: / + name: en - English + - link: /az/ + name: az + - link: /de/ + name: de + - link: /es/ + name: es - español + - link: /fa/ + name: fa + - link: /fr/ + name: fr - français + - link: /id/ + name: id + - link: /it/ + name: it - italiano + - link: /ja/ + name: ja - 日本語 + - link: /ko/ + name: ko - 한국어 + - link: /nl/ + name: nl + - link: /pl/ + name: pl + - link: /pt/ + name: pt - português + - link: /ru/ + name: ru - русский язык + - link: /sq/ + name: sq - shqip + - link: /tr/ + name: tr - Türkçe + - link: /uk/ + name: uk - українська мова + - link: /zh/ + name: zh - 汉语 +extra_css: +- https://fastapi.tiangolo.com/css/termynal.css +- https://fastapi.tiangolo.com/css/custom.css +extra_javascript: +- https://fastapi.tiangolo.com/js/termynal.js +- https://fastapi.tiangolo.com/js/custom.js diff --git a/docs/fa/overrides/.gitignore b/docs/fa/overrides/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/docs/fr/docs/alternatives.md b/docs/fr/docs/alternatives.md index bf3e7bc3c3cea..ee20438c3db2f 100644 --- a/docs/fr/docs/alternatives.md +++ b/docs/fr/docs/alternatives.md @@ -133,7 +133,7 @@ permanents qui les rendent inadaptés. ### Marshmallow -L'une des principales fonctionnalités nécessaires aux systèmes API est la "sérialisation" des données, qui consiste à prendre les données du code (Python) et à les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc. @@ -147,7 +147,7 @@ Sans un système de validation des données, vous devriez effectuer toutes les v Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée. -Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque schéma, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow. !!! check "A inspiré **FastAPI** à" @@ -155,7 +155,7 @@ Utilisez du code pour définir des "schémas" qui fournissent automatiquement le ### Webargs -Une autre grande fonctionnalité requise par les API est le parsing des données provenant des requêtes entrantes. Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask. diff --git a/docs/fr/docs/async.md b/docs/fr/docs/async.md index 20f4ee1011b61..71c28b7039068 100644 --- a/docs/fr/docs/async.md +++ b/docs/fr/docs/async.md @@ -220,7 +220,7 @@ Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps, Nope ! C'est ça la morale de l'histoire. La concurrence est différente du parallélisme. C'est mieux sur des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout. - + Donc pour équilibrer tout ça, imaginez l'histoire suivante : > Vous devez nettoyer une grande et sale maison. @@ -293,7 +293,7 @@ def get_sequential_burgers(number: int): Avec `async def`, Python sait que dans cette fonction il doit prendre en compte les expressions `await`, et qu'il peut mettre en pause ⏸ l'exécution de la fonction pour aller faire autre chose 🔀 avant de revenir. -Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas : +Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas : ```Python # Ceci ne fonctionne pas, car get_burgers a été défini avec async def @@ -375,7 +375,7 @@ Au final, dans les deux situations, il est fort probable que **FastAPI** soit to La même chose s'applique aux dépendances. Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe. -### Sous-dépendances +### Sous-dépendances Vous pouvez avoir de multiples dépendances et sous-dépendances dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être "attendues". diff --git a/docs/fr/docs/deployment/docker.md b/docs/fr/docs/deployment/docker.md index e4b59afbfd53d..d2dcae7223fdf 100644 --- a/docs/fr/docs/deployment/docker.md +++ b/docs/fr/docs/deployment/docker.md @@ -118,7 +118,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage -Vous disposez maintenant d'un serveur FastAPI optimisé dans un conteneur Docker. Configuré automatiquement pour votre +Vous disposez maintenant d'un serveur FastAPI optimisé dans un conteneur Docker. Configuré automatiquement pour votre serveur actuel (et le nombre de cœurs du CPU). ## Vérifier @@ -139,7 +139,7 @@ Vous verrez la documentation interactive automatique de l'API (fournie par http://192.168.99.100/redoc ou http://127.0.0.1/redoc (ou équivalent, en utilisant votre hôte Docker). @@ -149,7 +149,7 @@ Vous verrez la documentation automatique alternative (fournie par Traefik est un reverse proxy/load balancer +Traefik est un reverse proxy/load balancer haute performance. Il peut faire office de "Proxy de terminaison TLS" (entre autres fonctionnalités). Il est intégré à Let's Encrypt. Ainsi, il peut gérer toutes les parties HTTPS, y compris l'acquisition et le renouvellement des certificats. @@ -164,7 +164,7 @@ Avec ces informations et ces outils, passez à la section suivante pour tout com Vous pouvez avoir un cluster en mode Docker Swarm configuré en quelques minutes (environ 20 min) avec un processus Traefik principal gérant HTTPS (y compris l'acquisition et le renouvellement des certificats). -En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut même s'agir +En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut même s'agir d'un serveur à 5 USD/mois) et ensuite vous pouvez vous développer autant que vous le souhaitez en ajoutant d'autres serveurs. Pour configurer un cluster en mode Docker Swarm avec Traefik et la gestion de HTTPS, suivez ce guide : diff --git a/docs/fr/docs/fastapi-people.md b/docs/fr/docs/fastapi-people.md index 9ec2718c47390..945f0794e918f 100644 --- a/docs/fr/docs/fastapi-people.md +++ b/docs/fr/docs/fastapi-people.md @@ -114,6 +114,8 @@ Ce sont les **Sponsors**. 😎 Ils soutiennent mon travail avec **FastAPI** (et d'autres) avec GitHub Sponsors. +{% if sponsors %} + {% if sponsors.gold %} ### Gold Sponsors @@ -141,6 +143,7 @@ Ils soutiennent mon travail avec **FastAPI** (et d'autres) avec IDE
/linter/cerveau**: * Parce que les structures de données de pydantic consistent seulement en une instance de classe que vous définissez; l'auto-complétion, le linting, mypy et votre intuition devrait être largement suffisante pour valider vos données. * **Rapide**: - * Dans les benchmarks Pydantic est plus rapide que toutes les autres librairies testées. + * Dans les benchmarks Pydantic est plus rapide que toutes les autres librairies testées. * Valide les **structures complexes**: * Utilise les modèles hiérarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc. * Et les validateurs permettent aux schémas de données complexes d'être clairement et facilement définis, validés et documentés sous forme d'un schéma JSON. diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 40e6dfdff49c1..f713ee96b386f 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -149,7 +149,7 @@ $ pip install uvicorn[standard] * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -162,7 +162,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -185,7 +185,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -264,7 +264,7 @@ 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 10 11 12 25 26 27" -from typing import Optional +from typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -275,7 +275,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -284,7 +284,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. @@ -464,4 +463,4 @@ You can install all of these with `pip install fastapi[all]`. ## License -This project is licensed under the terms of the MIT license. \ No newline at end of file +This project is licensed under the terms of the MIT license. diff --git a/docs/fr/docs/tutorial/background-tasks.md b/docs/fr/docs/tutorial/background-tasks.md index 06ef93cd72f13..f7cf1a6ccc17e 100644 --- a/docs/fr/docs/tutorial/background-tasks.md +++ b/docs/fr/docs/tutorial/background-tasks.md @@ -9,7 +9,7 @@ Cela comprend, par exemple : * Les notifications par email envoyées après l'exécution d'une action : * Étant donné que se connecter à un serveur et envoyer un email a tendance à être «lent» (plusieurs secondes), vous pouvez retourner la réponse directement et envoyer la notification en arrière-plan. * Traiter des données : - * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan. + * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan. ## Utiliser `BackgroundTasks` @@ -73,7 +73,7 @@ La classe `BackgroundTasks` provient directement de Celery. +Si vous avez besoin de réaliser des traitements lourds en tâche d'arrière-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le même process (par exemple, pas besoin de partager la mémoire, les variables, etc.), il peut s'avérer profitable d'utiliser des outils plus importants tels que Celery. Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tâches d'arrière-plan dans différents process, et potentiellement, sur plusieurs serveurs. diff --git a/docs/fr/docs/tutorial/body.md b/docs/fr/docs/tutorial/body.md index c0953f49f8e3e..1e732d3364f9d 100644 --- a/docs/fr/docs/tutorial/body.md +++ b/docs/fr/docs/tutorial/body.md @@ -111,7 +111,7 @@ Mais vous auriez le même support de l'éditeur avec !!! tip "Astuce" - Si vous utilisez PyCharm comme éditeur, vous pouvez utiliser le Plugin PyCharm. + Si vous utilisez PyCharm comme éditeur, vous pouvez utiliser le Plugin Pydantic PyCharm Plugin. Ce qui améliore le support pour les modèles Pydantic avec : @@ -162,4 +162,4 @@ Les paramètres de la fonction seront reconnus comme tel : ## Sans Pydantic -Si vous ne voulez pas utiliser des modèles Pydantic, vous pouvez aussi utiliser des paramètres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requête - Paramètres multiples](body-multiple-params.md){.internal-link target=_blank}. \ No newline at end of file +Si vous ne voulez pas utiliser des modèles Pydantic, vous pouvez aussi utiliser des paramètres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requête - Paramètres multiples](body-multiple-params.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index 3a81362f608a7..224c340c66e93 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -280,7 +280,7 @@ Tout comme celles les plus exotiques : **FastAPI** n'impose pas de sens spécifique à chacune d'elle. - Les informations qui sont présentées ici forment une directive générale, pas des obligations. + Les informations qui sont présentées ici forment une directive générale, pas des obligations. Par exemple, quand l'on utilise **GraphQL**, toutes les actions sont effectuées en utilisant uniquement des opérations `POST`. diff --git a/docs/fr/docs/tutorial/path-params.md b/docs/fr/docs/tutorial/path-params.md index 58f53e008ea78..894d62dd46108 100644 --- a/docs/fr/docs/tutorial/path-params.md +++ b/docs/fr/docs/tutorial/path-params.md @@ -8,7 +8,7 @@ Vous pouvez déclarer des "paramètres" ou "variables" de chemin avec la même s {!../../../docs_src/path_params/tutorial001.py!} ``` -La valeur du paramètre `item_id` sera transmise à la fonction dans l'argument `item_id`. +La valeur du paramètre `item_id` sera transmise à la fonction dans l'argument `item_id`. Donc, si vous exécutez cet exemple et allez sur http://127.0.0.1:8000/items/foo, vous verrez comme réponse : @@ -44,7 +44,7 @@ Si vous exécutez cet exemple et allez sur "parsing" automatique. ## Validation de données @@ -91,7 +91,7 @@ documentation générée automatiquement et interactive : On voit bien dans la documentation que `item_id` est déclaré comme entier. -## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative. +## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative. Le schéma généré suivant la norme OpenAPI, il existe de nombreux outils compatibles. @@ -102,7 +102,7 @@ sur De la même façon, il existe bien d'autres outils compatibles, y compris des outils de génération de code -pour de nombreux langages. +pour de nombreux langages. ## Pydantic diff --git a/docs/fr/docs/tutorial/query-params.md b/docs/fr/docs/tutorial/query-params.md index f1f2a605db14d..7bf3b9e7942e5 100644 --- a/docs/fr/docs/tutorial/query-params.md +++ b/docs/fr/docs/tutorial/query-params.md @@ -6,7 +6,7 @@ Quand vous déclarez des paramètres dans votre fonction de chemin qui ne font p {!../../../docs_src/query_params/tutorial001.py!} ``` -La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`. +La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`. Par exemple, dans l'URL : @@ -120,7 +120,7 @@ ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la ## Multiples paramètres de chemin et de requête -Vous pouvez déclarer plusieurs paramètres de chemin et paramètres de requête dans la même fonction, **FastAPI** saura comment les gérer. +Vous pouvez déclarer plusieurs paramètres de chemin et paramètres de requête dans la même fonction, **FastAPI** saura comment les gérer. Et vous n'avez pas besoin de les déclarer dans un ordre spécifique. diff --git a/docs/fr/mkdocs.yml b/docs/fr/mkdocs.yml index ff16e1d78fd24..bf0d2b21cc49c 100644 --- a/docs/fr/mkdocs.yml +++ b/docs/fr/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -112,6 +116,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -122,6 +128,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/id/docs/index.md b/docs/id/docs/index.md index 95fb7ae212518..0bb7b55e3b065 100644 --- a/docs/id/docs/index.md +++ b/docs/id/docs/index.md @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/id/mkdocs.yml b/docs/id/mkdocs.yml index d70d2b3c3d03d..769547d11adf4 100644 --- a/docs/id/mkdocs.yml +++ b/docs/id/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -97,6 +101,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +113,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md index c52f07e59764d..6acf925528935 100644 --- a/docs/it/docs/index.md +++ b/docs/it/docs/index.md @@ -318,7 +318,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/it/mkdocs.yml b/docs/it/mkdocs.yml index e6d01fbdecac9..ebec9a6429d90 100644 --- a/docs/it/mkdocs.yml +++ b/docs/it/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -97,6 +101,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +113,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index 6c03cd92b3a5a..d1f8e645169f3 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -14,7 +14,7 @@ これを達成するには、 `JSONResponse` をインポートし、 `status_code` を設定して直接内容を返します。 -```Python hl_lines="4 23" +```Python hl_lines="4 25" {!../../../docs_src/additional_status_codes/tutorial001.py!} ``` diff --git a/docs/ja/docs/advanced/conditional-openapi.md b/docs/ja/docs/advanced/conditional-openapi.md new file mode 100644 index 0000000000000..b892ed6c6489f --- /dev/null +++ b/docs/ja/docs/advanced/conditional-openapi.md @@ -0,0 +1,58 @@ +# 条件付き OpenAPI + +必要であれば、設定と環境変数を利用して、環境に応じて条件付きでOpenAPIを構成することが可能です。また、完全にOpenAPIを無効にすることもできます。 + +## セキュリティとAPI、およびドキュメントについて + +本番環境においてドキュメントのUIを非表示にすることによって、APIを保護しようと *すべきではありません*。 + +それは、APIのセキュリティの強化にはならず、*path operations* は依然として利用可能です。 + +もしセキュリティ上の欠陥がソースコードにあるならば、それは存在したままです。 + +ドキュメンテーションを非表示にするのは、単にあなたのAPIへのアクセス方法を難解にするだけでなく、同時にあなた自身の本番環境でのAPIのデバッグを困難にしてしまう可能性があります。単純に、 Security through obscurity の一つの形態として考えられるでしょう。 + +もしあなたのAPIのセキュリティを強化したいなら、いくつかのよりよい方法があります。例を示すと、 + +* リクエストボディとレスポンスのためのPydanticモデルの定義を見直す。 +* 依存関係に基づきすべての必要なパーミッションとロールを設定する。 +* パスワードを絶対に平文で保存しない。パスワードハッシュのみを保存する。 +* PasslibやJWTトークンに代表される、よく知られた暗号化ツールを使って実装する。 +* そして必要なところでは、もっと細かいパーミッション制御をOAuth2スコープを使って行う。 +* など + +それでも、例えば本番環境のような特定の環境のみで、あるいは環境変数の設定によってAPIドキュメントをどうしても無効にしたいという、非常に特殊なユースケースがあるかもしれません。 + +## 設定と環境変数による条件付き OpenAPI + +生成するOpenAPIとドキュメントUIの構成は、共通のPydanticの設定を使用して簡単に切り替えられます。 + +例えば、 + +```Python hl_lines="6 11" +{!../../../docs_src/conditional_openapi/tutorial001.py!} +``` + +ここでは `openapi_url` の設定を、デフォルトの `"/openapi.json"` のまま宣言しています。 + +そして、これを `FastAPI` appを作る際に使います。 + +それから、以下のように `OPENAPI_URL` という環境変数を空文字列に設定することによってOpenAPI (UIドキュメントを含む) を無効化することができます。 + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +すると、以下のように `/openapi.json`, `/docs`, `/redoc` のどのURLにアクセスしても、 `404 Not Found` エラーが返ってくるようになります。 + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index 27e3c8846dfee..ca6b29a0776db 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -193,7 +193,7 @@ Flask、Flask-apispec、Marshmallow、Webargsの組み合わせは、**FastAPI** * https://github.com/tiangolo/full-stack * https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb +* https://github.com/tiangolo/full-stack-flask-couchdb そして、これらのフルスタックジェネレーターは、[**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}の元となっていました。 @@ -295,7 +295,7 @@ OpenAPIやJSON Schemaのような標準に基づいたものではありませ HugはAPIStarに部分的なインスピレーションを与えており、私が発見した中ではAPIStarと同様に最も期待の持てるツールの一つでした。 Hugは、**FastAPI**がPythonの型ヒントを用いてパラメータを宣言し自動的にAPIを定義するスキーマを生成することを触発しました。 - + Hugは、**FastAPI**がヘッダーやクッキーを設定するために関数に `response`引数を宣言することにインスピレーションを与えました。 ### APIStar (<= 0.5) diff --git a/docs/ja/docs/async.md b/docs/ja/docs/async.md index eff4f2f4332a7..8fac2cb38632e 100644 --- a/docs/ja/docs/async.md +++ b/docs/ja/docs/async.md @@ -361,7 +361,7 @@ async def read_burgers(): この部分は**FastAPI**の仕組みに関する非常に技術的な詳細です。 かなりの技術知識 (コルーチン、スレッド、ブロッキングなど) があり、FastAPIが `async def` と通常の `def` をどのように処理するか知りたい場合は、先に進んでください。 - + ### Path operation 関数 *path operation 関数*を `async def` の代わりに通常の `def` で宣言すると、(サーバーをブロックするので) 直接呼び出す代わりに外部スレッドプール (awaitされる) で実行されます。 diff --git a/docs/ja/docs/deployment/index.md b/docs/ja/docs/deployment/index.md index 2ce81b5518149..40710a93a1ab7 100644 --- a/docs/ja/docs/deployment/index.md +++ b/docs/ja/docs/deployment/index.md @@ -4,4 +4,4 @@ ユースケースや使用しているツールによっていくつかの方法に分かれます。 -次のセクションでより詳しくそれらの方法について説明します。 \ No newline at end of file +次のセクションでより詳しくそれらの方法について説明します。 diff --git a/docs/ja/docs/deployment/manually.md b/docs/ja/docs/deployment/manually.md index 3296ba76f2def..dd4b568bdcd65 100644 --- a/docs/ja/docs/deployment/manually.md +++ b/docs/ja/docs/deployment/manually.md @@ -20,7 +20,7 @@ !!! tip "豆知識" `standard` を加えることで、Uvicornがインストールされ、いくつかの推奨される依存関係を利用するようになります。 - + これには、`asyncio` の高性能な完全互換品である `uvloop` が含まれ、並行処理のパフォーマンスが大幅に向上します。 === "Hypercorn" diff --git a/docs/ja/docs/fastapi-people.md b/docs/ja/docs/fastapi-people.md index 229d8dde5a052..11dd656eaf31b 100644 --- a/docs/ja/docs/fastapi-people.md +++ b/docs/ja/docs/fastapi-people.md @@ -115,6 +115,8 @@ FastAPIには、様々なバックグラウンドの人々を歓迎する素晴 彼らは、GitHub Sponsors を介して私の **FastAPI** などに関する活動を支援してくれています。 +{% if sponsors %} + {% if sponsors.gold %} ### Gold Sponsors @@ -142,6 +144,8 @@ FastAPIには、様々なバックグラウンドの人々を歓迎する素晴 {% endfor %} {% endif %} +{% endif %} + ### Individual Sponsors {% if github_sponsors %} diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 2c406f4819d8e..5ea68515da35b 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -193,7 +193,7 @@ FastAPIには非常に使いやすく、非常に強力なしてカスタムの独自ヘッダーを追加できます。 - ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、StarletteのCORSドキュメントに記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank}) + ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、StarletteのCORSドキュメントに記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank}) !!! note "技術詳細" `from starlette.requests import Request` を使用することもできます。 diff --git a/docs/ja/docs/tutorial/path-params.md b/docs/ja/docs/tutorial/path-params.md index 452ca0c989ea6..66de05afb1339 100644 --- a/docs/ja/docs/tutorial/path-params.md +++ b/docs/ja/docs/tutorial/path-params.md @@ -139,7 +139,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ### *パスパラメータ*の宣言 -次に、作成したenumクラスである`ModelName`を使用した型アノテーションをもつ*パスパラメータ*を作成します: +次に、作成したenumクラスである`ModelName`を使用した型アノテーションをもつ*パスパラメータ*を作成します: ```Python hl_lines="16" {!../../../docs_src/path_params/tutorial005.py!} diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index ff0af725fba9e..8d375d7ce0ec9 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -34,12 +34,12 @@ {!../../../docs_src/query_params_str_validations/tutorial002.py!} ``` -デフォルト値`None`を`Query(None)`に置き換える必要があるので、`Query`の最初の引数はデフォルト値を定義するのと同じです。 +デフォルト値`None`を`Query(default=None)`に置き換える必要があるので、`Query`の最初の引数はデフォルト値を定義するのと同じです。 なので: ```Python -q: Optional[str] = Query(None) +q: Optional[str] = Query(default=None) ``` ...を以下と同じようにパラメータをオプションにします: @@ -60,7 +60,7 @@ q: Optional[str] = None もしくは: ```Python - = Query(None) + = Query(default=None) ``` そして、 `None` を利用することでクエリパラメータが必須ではないと検知します。 @@ -70,7 +70,7 @@ q: Optional[str] = None そして、さらに多くのパラメータを`Query`に渡すことができます。この場合、文字列に適用される、`max_length`パラメータを指定します。 ```Python -q: str = Query(None, max_length=50) +q: Union[str, None] = Query(default=None, max_length=50) ``` これにより、データを検証し、データが有効でない場合は明確なエラーを表示し、OpenAPIスキーマの *path operation* にパラメータを記載します。 @@ -79,7 +79,7 @@ q: str = Query(None, max_length=50) パラメータ`min_length`も追加することができます: -```Python hl_lines="9" +```Python hl_lines="10" {!../../../docs_src/query_params_str_validations/tutorial003.py!} ``` @@ -87,7 +87,7 @@ q: str = Query(None, max_length=50) パラメータが一致するべき正規表現を定義することができます: -```Python hl_lines="10" +```Python hl_lines="11" {!../../../docs_src/query_params_str_validations/tutorial004.py!} ``` @@ -125,13 +125,13 @@ q: str 以下の代わりに: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` 現在は以下の例のように`Query`で宣言しています: ```Python -q: Optional[str] = Query(None, min_length=3) +q: Union[str, None] = Query(default=None, min_length=3) ``` そのため、`Query`を使用して必須の値を宣言する必要がある場合は、第一引数に`...`を使用することができます: diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 91783a53a190a..9f8c6ab9f2b55 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -18,7 +18,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ...クエリパラメータは: * `skip`: 値は `0` -* `limit`: 値は `10` +* `limit`: 値は `10` これらはURLの一部なので、「自然に」文字列になります。 @@ -75,7 +75,7 @@ http://127.0.0.1:8000/items/?skip=20 !!! note "備考" FastAPIは、`= None`があるおかげで、`q`がオプショナルだとわかります。 - + `Optional[str]` の`Optional` はFastAPIでは使用されていません(FastAPIは`str`の部分のみ使用します)。しかし、`Optional[str]` はエディタがコードのエラーを見つけるのを助けてくれます。 ## クエリパラメータの型変換 @@ -116,7 +116,7 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -もしくは、他の大文字小文字のバリエーション (アッパーケース、最初の文字だけアッパーケース、など)で、関数は `short` パラメータを `True` な `bool` 値として扱います。それ以外は `False` になります。 +もしくは、他の大文字小文字のバリエーション (アッパーケース、最初の文字だけアッパーケース、など)で、関数は `short` パラメータを `True` な `bool` 値として扱います。それ以外は `False` になります。 ## 複数のパスパラメータとクエリパラメータ diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index 06105c9ef6ce4..bce6e8d9a60f6 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -45,7 +45,7 @@ HTMLフォーム(`
`)がサーバにデータを送信する方 フォームからのデータは通常、`application/x-www-form-urlencoded`の「media type」を使用してエンコードされます。 しかし、フォームがファイルを含む場合は、`multipart/form-data`としてエンコードされます。ファイルの扱いについては次の章で説明します。 - + これらのエンコーディングやフォームフィールドの詳細については、MDNPOSTのウェブドキュメントを参照してください。 !!! warning "注意" diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index fcc3ba924c643..1d9c434c368a5 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -2,20 +2,6 @@ `StaticFiles` を使用して、ディレクトリから静的ファイルを自動的に提供できます。 -## `aiofiles` をインストール - -まず、`aiofiles` をインストールする必要があります: - -
- -```console -$ pip install aiofiles - ----> 100% -``` - -
- ## `StaticFiles` の使用 * `StaticFiles` をインポート。 diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index ebd2de37c467f..03b0e1deef359 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -36,7 +36,7 @@ !!! tip "豆知識" FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md){.internal-link target=_blank} を参照してください。 - + ## テストの分離 実際のアプリケーションでは、おそらくテストを別のファイルに保存します。 @@ -74,16 +74,24 @@ これらの *path operation* には `X-Token` ヘッダーが必要です。 -```Python -{!../../../docs_src/app_testing/main_b.py!} -``` +=== "Python 3.6 and above" + + ```Python + {!> ../../../docs_src/app_testing/app_b/main.py!} + ``` + +=== "Python 3.10 and above" + + ```Python + {!> ../../../docs_src/app_testing/app_b_py310/main.py!} + ``` ### 拡張版テストファイル 次に、先程のものに拡張版のテストを加えた、`test_main_b.py` を作成します。 ```Python -{!../../../docs_src/app_testing/test_main_b.py!} +{!> ../../../docs_src/app_testing/app_b/test_main.py!} ``` リクエストに情報を渡せるクライアントが必要で、その方法がわからない場合はいつでも、`requests` での実現方法を検索 (Google) できます。 @@ -104,7 +112,7 @@ `TestClient` は、Pydanticモデルではなく、JSONに変換できるデータを受け取ることに注意してください。 テストにPydanticモデルがあり、テスト中にそのデータをアプリケーションに送信したい場合は、[JSON互換エンコーダ](encoder.md){.internal-link target=_blank} で説明されている `jsonable_encoder` が利用できます。 - + ## 実行 後は、`pytest` をインストールするだけです: diff --git a/docs/ja/mkdocs.yml b/docs/ja/mkdocs.yml index 39fd8a2110a81..055404feaf9aa 100644 --- a/docs/ja/mkdocs.yml +++ b/docs/ja/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -78,6 +82,7 @@ nav: - advanced/additional-status-codes.md - advanced/response-directly.md - advanced/custom-response.md + - advanced/conditional-openapi.md - async.md - デプロイ: - deployment/index.md @@ -137,6 +142,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -147,6 +154,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/ko/docs/deployment/versions.md b/docs/ko/docs/deployment/versions.md index 4c1bcdc2e4392..074c15158be6f 100644 --- a/docs/ko/docs/deployment/versions.md +++ b/docs/ko/docs/deployment/versions.md @@ -6,7 +6,7 @@ 이것이 아직도 최신 버전이 `0.x.x`인 이유입니다. 이것은 각각의 버전들이 잠재적으로 변할 수 있다는 것을 보여줍니다. 이는 유의적 버전 관습을 따릅니다. -지금 바로 **FastAPI**로 응용 프로그램을 만들 수 있습니다. 이때 (아마 지금까지 그래 왔던 것처럼), 사용하는 버전이 코드와 잘 맞는지 확인해야합니다. +지금 바로 **FastAPI**로 응용 프로그램을 만들 수 있습니다. 이때 (아마 지금까지 그래 왔던 것처럼), 사용하는 버전이 코드와 잘 맞는지 확인해야합니다. ## `fastapi` 버전을 표시 @@ -46,7 +46,7 @@ FastAPI는 오류를 수정하고, 일반적인 변경사항을 위해 "패치" !!! tip "팁" 여기서 말하는 "패치"란 버전의 마지막 숫자로, 예를 들어 `0.2.3` 버전에서 "패치"는 `3`을 의미합니다. -따라서 다음과 같이 버전을 표시할 수 있습니다: +따라서 다음과 같이 버전을 표시할 수 있습니다: ```txt fastapi>=0.45.0,<0.46.0 @@ -71,7 +71,7 @@ fastapi>=0.45.0,<0.46.0 `starlette`의 버전은 표시할 수 없습니다. -서로다른 버전의 **FastAPI**가 구체적이고 새로운 버전의 Starlette을 사용할 것입니다. +서로다른 버전의 **FastAPI**가 구체적이고 새로운 버전의 Starlette을 사용할 것입니다. 그러므로 **FastAPI**가 알맞은 Starlette 버전을 사용하도록 하십시오. diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index d0c2369069722..ec44229947b7c 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -145,7 +145,7 @@ $ pip install uvicorn[standard] * `main.py` 파일을 만드십시오: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -158,7 +158,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -168,7 +168,7 @@ def read_item(item_id: int, q: Optional[str] = None): 여러분의 코드가 `async` / `await`을 사용한다면, `async def`를 사용하십시오. ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -181,7 +181,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -260,7 +260,7 @@ INFO: Application startup complete. Pydantic을 이용해 파이썬 표준 타입으로 본문을 선언합니다. ```Python hl_lines="4 9 10 11 12 25 26 27" -from typing import Optional +from typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -271,7 +271,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -280,7 +280,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -443,7 +443,6 @@ Pydantic이 사용하는: Starlette이 사용하는: * requests - `TestClient`를 사용하려면 필요. -* aiofiles - `FileResponse` 또는 `StaticFiles`를 사용하려면 필요. * jinja2 - 기본 템플릿 설정을 사용하려면 필요. * python-multipart - `request.form()`과 함께 "parsing"의 지원을 원하면 필요. * itsdangerous - `SessionMiddleware` 지원을 위해 필요. diff --git a/docs/ko/docs/tutorial/header-params.md b/docs/ko/docs/tutorial/header-params.md index 1c46b32ba0067..484554e973ea3 100644 --- a/docs/ko/docs/tutorial/header-params.md +++ b/docs/ko/docs/tutorial/header-params.md @@ -57,7 +57,7 @@ 타입 정의에서 리스트를 사용하여 이러한 케이스를 정의할 수 있습니다. -중복 헤더의 모든 값을 파이썬 `list`로 수신합니다. +중복 헤더의 모든 값을 파이썬 `list`로 수신합니다. 예를 들어, 두 번 이상 나타날 수 있는 `X-Token`헤더를 선언하려면, 다음과 같이 작성합니다: diff --git a/docs/ko/docs/tutorial/path-params-numeric-validations.md b/docs/ko/docs/tutorial/path-params-numeric-validations.md index abb9d03dbb50c..cadf543fc69fe 100644 --- a/docs/ko/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ko/docs/tutorial/path-params-numeric-validations.md @@ -43,7 +43,7 @@ 따라서 함수를 다음과 같이 선언 할 수 있습니다: -```Python hl_lines="8" +```Python hl_lines="7" {!../../../docs_src/path_params_numeric_validations/tutorial002.py!} ``` @@ -55,7 +55,7 @@ 파이썬은 `*`으로 아무런 행동도 하지 않지만, 따르는 매개변수들은 kwargs로도 알려진 키워드 인자(키-값 쌍)여야 함을 인지합니다. 기본값을 가지고 있지 않더라도 그렇습니다. -```Python hl_lines="8" +```Python hl_lines="7" {!../../../docs_src/path_params_numeric_validations/tutorial003.py!} ``` diff --git a/docs/ko/docs/tutorial/path-params.md b/docs/ko/docs/tutorial/path-params.md index ede63f69d5c48..5cf397e7ae0e2 100644 --- a/docs/ko/docs/tutorial/path-params.md +++ b/docs/ko/docs/tutorial/path-params.md @@ -241,4 +241,4 @@ Starlette에서 직접 옵션을 사용하면 다음과 같은 URL을 사용하 위 사항들을 그저 한번에 선언하면 됩니다. -이는 (원래 성능과는 별개로) 대체 프레임워크와 비교했을 때 **FastAPI**의 주요 가시적 장점일 것입니다. \ No newline at end of file +이는 (원래 성능과는 별개로) 대체 프레임워크와 비교했을 때 **FastAPI**의 주요 가시적 장점일 것입니다. diff --git a/docs/ko/docs/tutorial/query-params.md b/docs/ko/docs/tutorial/query-params.md index 05f2ff9c9123b..bb631e6ffc310 100644 --- a/docs/ko/docs/tutorial/query-params.md +++ b/docs/ko/docs/tutorial/query-params.md @@ -75,7 +75,7 @@ http://127.0.0.1:8000/items/?skip=20 !!! note "참고" FastAPI는 `q`가 `= None`이므로 선택적이라는 것을 인지합니다. - `Optional[str]`에 있는 `Optional`은 FastAPI(FastAPI는 `str` 부분만 사용합니다)가 사용하는게 아니지만, `Optional[str]`은 편집기에게 코드에서 오류를 찾아낼 수 있게 도와줍니다. + `Union[str, None]`에 있는 `Union`은 FastAPI(FastAPI는 `str` 부분만 사용합니다)가 사용하는게 아니지만, `Union[str, None]`은 편집기에게 코드에서 오류를 찾아낼 수 있게 도와줍니다. ## 쿼리 매개변수 형변환 diff --git a/docs/ko/docs/tutorial/request-files.md b/docs/ko/docs/tutorial/request-files.md index 769a676cd82db..decefe981fef7 100644 --- a/docs/ko/docs/tutorial/request-files.md +++ b/docs/ko/docs/tutorial/request-files.md @@ -13,7 +13,7 @@ `fastapi` 에서 `File` 과 `UploadFile` 을 임포트 합니다: -```Python hl_lines="1" +```Python hl_lines="1" {!../../../docs_src/request_files/tutorial001.py!} ``` @@ -21,7 +21,7 @@ `Body` 및 `Form` 과 동일한 방식으로 파일의 매개변수를 생성합니다: -```Python hl_lines="7" +```Python hl_lines="7" {!../../../docs_src/request_files/tutorial001.py!} ``` @@ -45,7 +45,7 @@ `File` 매개변수를 `UploadFile` 타입으로 정의합니다: -```Python hl_lines="12" +```Python hl_lines="12" {!../../../docs_src/request_files/tutorial001.py!} ``` @@ -97,7 +97,7 @@ contents = myfile.file.read() ## "폼 데이터"란 -HTML의 폼들(`
`)이 서버에 데이터를 전송하는 방식은 대개 데이터에 JSON과는 다른 "특별한" 인코딩을 사용합니다. +HTML의 폼들(`
`)이 서버에 데이터를 전송하는 방식은 대개 데이터에 JSON과는 다른 "특별한" 인코딩을 사용합니다. **FastAPI**는 JSON 대신 올바른 위치에서 데이터를 읽을 수 있도록 합니다. @@ -121,7 +121,7 @@ HTML의 폼들(`
`)이 서버에 데이터를 전송하는 방식은 이 기능을 사용하기 위해 , `bytes` 의 `List` 또는 `UploadFile` 를 선언하기 바랍니다: -```Python hl_lines="10 15" +```Python hl_lines="10 15" {!../../../docs_src/request_files/tutorial002.py!} ``` diff --git a/docs/ko/docs/tutorial/request-forms-and-files.md b/docs/ko/docs/tutorial/request-forms-and-files.md index 6750c7b238dd7..ddf232e7fedd4 100644 --- a/docs/ko/docs/tutorial/request-forms-and-files.md +++ b/docs/ko/docs/tutorial/request-forms-and-files.md @@ -9,7 +9,7 @@ ## `File` 및 `Form` 업로드 -```Python hl_lines="1" +```Python hl_lines="1" {!../../../docs_src/request_forms_and_files/tutorial001.py!} ``` @@ -17,7 +17,7 @@ `Body` 및 `Query`와 동일한 방식으로 파일과 폼의 매개변수를 생성합니다: -```Python hl_lines="8" +```Python hl_lines="8" {!../../../docs_src/request_forms_and_files/tutorial001.py!} ``` diff --git a/docs/ko/docs/tutorial/response-status-code.md b/docs/ko/docs/tutorial/response-status-code.md index d201867a186b9..f92c057be4fd9 100644 --- a/docs/ko/docs/tutorial/response-status-code.md +++ b/docs/ko/docs/tutorial/response-status-code.md @@ -8,11 +8,11 @@ * `@app.delete()` * 기타 -```Python hl_lines="6" +```Python hl_lines="6" {!../../../docs_src/response_status_code/tutorial001.py!} ``` -!!! note "참고" +!!! note "참고" `status_code` 는 "데코레이터" 메소드(`get`, `post` 등)의 매개변수입니다. 모든 매개변수들과 본문처럼 *경로 작동 함수*가 아닙니다. `status_code` 매개변수는 HTTP 상태 코드를 숫자로 입력받습니다. @@ -27,7 +27,7 @@ -!!! note "참고" +!!! note "참고" 어떤 응답 코드들은 해당 응답에 본문이 없다는 것을 의미하기도 합니다 (다음 항목 참고). 이에 따라 FastAPI는 응답 본문이 없음을 명시하는 OpenAPI를 생성합니다. @@ -61,7 +61,7 @@ HTTP는 세자리의 숫자 상태 코드를 응답의 일부로 전송합니다 상기 예시 참고: -```Python hl_lines="6" +```Python hl_lines="6" {!../../../docs_src/response_status_code/tutorial001.py!} ``` @@ -71,7 +71,7 @@ HTTP는 세자리의 숫자 상태 코드를 응답의 일부로 전송합니다 `fastapi.status` 의 편의 변수를 사용할 수 있습니다. -```Python hl_lines="1 6" +```Python hl_lines="1 6" {!../../../docs_src/response_status_code/tutorial002.py!} ``` diff --git a/docs/ko/mkdocs.yml b/docs/ko/mkdocs.yml index 1d4d30913c365..60cf7d30ae754 100644 --- a/docs/ko/mkdocs.yml +++ b/docs/ko/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -107,6 +111,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -117,6 +123,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/nl/docs/index.md b/docs/nl/docs/index.md new file mode 100644 index 0000000000000..fd52f994c83a9 --- /dev/null +++ b/docs/nl/docs/index.md @@ -0,0 +1,468 @@ + +{!../../../docs/missing-translation.md!} + + +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +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. Completion 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: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + +{% if sponsors %} +{% for sponsor in sponsors.gold -%} + +{% endfor -%} +{%- for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + + + +Other sponsors + +## 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._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
Brian Okken - Python Bytes podcast host (ref)
+ +--- + +"_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._" + +
Timothy Crosley - Hug creator (ref)
+ +--- + +"_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 [...]_" + +
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+ +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +Python 3.6+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
+ +```console +$ pip install fastapi + +---> 100% +``` + +
+ +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +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: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +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: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
+ +### Run it + +Run the server with: + +
+ +```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. +``` + +
+ +
+About the command uvicorn main:app --reload... + +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. + +
+ +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +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` operations (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 http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![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 Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = 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 http://127.0.0.1:8000/docs. + +* 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 http://127.0.0.1:8000/redoc. + +* 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. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion 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 Tutorial - User Guide. + +**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 **Dependency Injection** 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). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on `requests` and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) + +To understand more about it, see the section Benchmarks. + +## Optional Dependencies + +Used by Pydantic: + +* ujson - for faster JSON "parsing". +* email_validator - for email validation. + +Used by Starlette: + +* requests - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - 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. diff --git a/docs/nl/mkdocs.yml b/docs/nl/mkdocs.yml new file mode 100644 index 0000000000000..9cd1e04010fde --- /dev/null +++ b/docs/nl/mkdocs.yml @@ -0,0 +1,137 @@ +site_name: FastAPI +site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production +site_url: https://fastapi.tiangolo.com/nl/ +theme: + name: material + custom_dir: overrides + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: teal + accent: amber + toggle: + icon: material/lightbulb + name: Switch to light mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: teal + accent: amber + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + features: + - search.suggest + - search.highlight + - content.tabs.link + icon: + repo: fontawesome/brands/github-alt + logo: https://fastapi.tiangolo.com/img/icon-white.svg + favicon: https://fastapi.tiangolo.com/img/favicon.png + language: nl +repo_name: tiangolo/fastapi +repo_url: https://github.com/tiangolo/fastapi +edit_uri: '' +plugins: +- search +- markdownextradata: + data: data +nav: +- FastAPI: index.md +- Languages: + - en: / + - az: /az/ + - de: /de/ + - es: /es/ + - fa: /fa/ + - fr: /fr/ + - id: /id/ + - it: /it/ + - ja: /ja/ + - ko: /ko/ + - nl: /nl/ + - pl: /pl/ + - pt: /pt/ + - ru: /ru/ + - sq: /sq/ + - tr: /tr/ + - uk: /uk/ + - zh: /zh/ +markdown_extensions: +- toc: + permalink: true +- markdown.extensions.codehilite: + guess_lang: false +- mdx_include: + base_path: docs +- admonition +- codehilite +- extra +- pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format '' +- pymdownx.tabbed: + alternate_style: true +extra: + analytics: + provider: google + property: UA-133183413-1 + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/tiangolo/fastapi + - icon: fontawesome/brands/discord + link: https://discord.gg/VQjSZaeJmf + - icon: fontawesome/brands/twitter + link: https://twitter.com/fastapi + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/tiangolo + - icon: fontawesome/brands/dev + link: https://dev.to/tiangolo + - icon: fontawesome/brands/medium + link: https://medium.com/@tiangolo + - icon: fontawesome/solid/globe + link: https://tiangolo.com + alternate: + - link: / + name: en - English + - link: /az/ + name: az + - link: /de/ + name: de + - link: /es/ + name: es - español + - link: /fa/ + name: fa + - link: /fr/ + name: fr - français + - link: /id/ + name: id + - link: /it/ + name: it - italiano + - link: /ja/ + name: ja - 日本語 + - link: /ko/ + name: ko - 한국어 + - link: /nl/ + name: nl + - link: /pl/ + name: pl + - link: /pt/ + name: pt - português + - link: /ru/ + name: ru - русский язык + - link: /sq/ + name: sq - shqip + - link: /tr/ + name: tr - Türkçe + - link: /uk/ + name: uk - українська мова + - link: /zh/ + name: zh - 汉语 +extra_css: +- https://fastapi.tiangolo.com/css/termynal.css +- https://fastapi.tiangolo.com/css/custom.css +extra_javascript: +- https://fastapi.tiangolo.com/js/termynal.js +- https://fastapi.tiangolo.com/js/custom.js diff --git a/docs/nl/overrides/.gitignore b/docs/nl/overrides/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/docs/pl/docs/index.md b/docs/pl/docs/index.md index 4a300ae632dbc..bbe1b1ad15e0d 100644 --- a/docs/pl/docs/index.md +++ b/docs/pl/docs/index.md @@ -144,7 +144,7 @@ $ pip install uvicorn[standard] * Utwórz plik o nazwie `main.py` z: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -157,7 +157,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -167,7 +167,7 @@ def read_item(item_id: int, q: Optional[str] = None): Jeżeli twój kod korzysta z `async` / `await`, użyj `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -180,7 +180,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -258,7 +258,7 @@ Zmodyfikuj teraz plik `main.py`, aby otrzmywał treść (body) żądania `PUT`. Zadeklaruj treść żądania, używając standardowych typów w Pythonie dzięki Pydantic. ```Python hl_lines="4 9-12 25-27" -from typing import Optional +from typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -269,7 +269,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -278,7 +278,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} diff --git a/docs/pl/docs/tutorial/index.md b/docs/pl/docs/tutorial/index.md new file mode 100644 index 0000000000000..ed8752a95a671 --- /dev/null +++ b/docs/pl/docs/tutorial/index.md @@ -0,0 +1,80 @@ +# Samouczek - Wprowadzenie + +Ten samouczek pokaże Ci, krok po kroku, jak używać większości funkcji **FastAPI**. + +Każda część korzysta z poprzednich, ale jest jednocześnie osobnym tematem. Możesz przejść bezpośrednio do każdego rozdziału, jeśli szukasz rozwiązania konkretnego problemu. + +Samouczek jest tak zbudowany, żeby służył jako punkt odniesienia w przyszłości. + +Możesz wracać i sprawdzać dokładnie to czego potrzebujesz. + +## Wykonywanie kodu + +Wszystkie fragmenty kodu mogą być skopiowane bezpośrednio i użyte (są poprawnymi i przetestowanymi plikami). + +Żeby wykonać każdy przykład skopiuj kod to pliku `main.py` i uruchom `uvicorn` za pomocą: + +
+ +```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. +``` + +
+ +**BARDZO zalecamy** pisanie bądź kopiowanie kodu, edycję, a następnie wykonywanie go lokalnie. + +Użycie w Twoim edytorze jest tym, co pokazuje prawdziwe korzyści z FastAPI, pozwala zobaczyć jak mało kodu musisz napisać, wszystkie funkcje, takie jak kontrola typów, automatyczne uzupełnianie, itd. + +--- + +## Instalacja FastAPI + +Jako pierwszy krok zainstaluj FastAPI. + +Na potrzeby samouczka możesz zainstalować również wszystkie opcjonalne biblioteki: + +
+ +```console +$ pip install "fastapi[all]" + +---> 100% +``` + +
+ +...wliczając w to `uvicorn`, który będzie służył jako serwer wykonujacy Twój kod. + +!!! note + Możesz również wykonać instalację "krok po kroku". + + Prawdopodobnie zechcesz to zrobić, kiedy będziesz wdrażać swoją aplikację w środowisku produkcyjnym: + + ``` + pip install fastapi + ``` + + Zainstaluj też `uvicorn`, który będzie służył jako serwer: + + ``` + pip install "uvicorn[standard]" + ``` + + Tak samo możesz zainstalować wszystkie dodatkowe biblioteki, których chcesz użyć. + +## Zaawansowany poradnik + +Jest też **Zaawansowany poradnik**, który możesz przeczytać po lekturze tego **Samouczka**. + +**Zaawansowany poradnik** opiera się na tym samouczku, używa tych samych pojęć, żeby pokazać Ci kilka dodatkowych funkcji. + +Najpierw jednak powinieneś przeczytać **Samouczek** (czytasz go teraz). + +Ten rozdział jest zaprojektowany tak, że możesz stworzyć kompletną aplikację używając tylko informacji tutaj zawartych, a następnie rozszerzać ją na różne sposoby, w zależności od potrzeb, używając kilku dodatkowych pomysłów z **Zaawansowanego poradnika**. diff --git a/docs/pl/mkdocs.yml b/docs/pl/mkdocs.yml index 3c1351a127ae2..0c3d100e7791f 100644 --- a/docs/pl/mkdocs.yml +++ b/docs/pl/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -52,6 +56,8 @@ nav: - tr: /tr/ - uk: /uk/ - zh: /zh/ +- Samouczek: + - tutorial/index.md markdown_extensions: - toc: permalink: true @@ -97,6 +103,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +115,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/pt/docs/alternatives.md b/docs/pt/docs/alternatives.md index 6559b7398cfcb..61ee4f9000e10 100644 --- a/docs/pt/docs/alternatives.md +++ b/docs/pt/docs/alternatives.md @@ -331,7 +331,7 @@ Agora APIStar é um conjunto de ferramentas para validar especificações OpenAP Existir. A idéia de declarar múltiplas coisas (validação de dados, serialização e documentação) com os mesmos tipos Python, que ao mesmo tempo fornecesse grande suporte ao editor, era algo que eu considerava uma brilhante idéia. - + E após procurar por um logo tempo por um framework similar e testar muitas alternativas diferentes, APIStar foi a melhor opção disponível. Então APIStar parou de existir como um servidor e Starlette foi criado, e foi uma nova melhor fundação para tal sistema. Essa foi a inspiração final para construir **FastAPI**. @@ -390,7 +390,7 @@ Essa é uma das principais coisas que **FastAPI** adiciona no topo, tudo baseado Controlar todas as partes web centrais. Adiciona recursos no topo. A classe `FastAPI` em si herda `Starlette`. - + Então, qualquer coisa que você faz com Starlette, você pode fazer diretamente com **FastAPI**, pois ele é basicamente um Starlette com esteróides. ### Uvicorn diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 44f4b5148ecaa..be1278a1b3098 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -94,7 +94,7 @@ Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "seq Essa idéia de código **assíncrono** descrito acima é algo às vezes chamado de **"concorrência"**. E é diferente de **"paralelismo"**. -**Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". +**Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". Mas os detalhes entre *concorrência* e *paralelismo* são bem diferentes. @@ -134,7 +134,7 @@ Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caix Mas enquanto você se afasta do balcão e senta na mesa com o número da sua chamada, você pode trocar sua atenção para seu _crush_ :heart_eyes:, e "trabalhar" nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_ :heart_eyes:. -Então o caixa diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porquê você tem o número de chamada, e os outros tem os números deles. +Então o caixa diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porquê você tem o número de chamada, e os outros tem os números deles. Então você espera que seu _crush_ :heart_eyes: termine a história que estava contando (terminar o trabalho atual / tarefa sendo processada), sorri gentilmente e diz que você está indo buscar os hambúrgueres. @@ -358,9 +358,9 @@ Tudo isso é o que deixa o FastAPI poderoso (através do Starlette) e que o faz !!! warning Você pode provavelmente pular isso. - + Esses são detalhes muito técnicos de como **FastAPI** funciona por baixo do capô. - + Se você tem algum conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente. ### Funções de operação de rota diff --git a/docs/pt/docs/benchmarks.md b/docs/pt/docs/benchmarks.md index 7f7c95ba1c65e..07461ce46387c 100644 --- a/docs/pt/docs/benchmarks.md +++ b/docs/pt/docs/benchmarks.md @@ -2,7 +2,7 @@ As comparações independentes da TechEmpower mostram as aplicações **FastAPI** rodando com Uvicorn como um dos _frameworks_ Python mais rápidos disponíveis, somente atrás dos próprios Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) -Mas quando se checa _benchmarks_ e comparações você deveria ter o seguinte em mente. +Mas quando se checa _benchmarks_ e comparações você deveria ter o seguinte em mente. ## Comparações e velocidade diff --git a/docs/pt/docs/deployment/deta.md b/docs/pt/docs/deployment/deta.md new file mode 100644 index 0000000000000..9271bba42ea85 --- /dev/null +++ b/docs/pt/docs/deployment/deta.md @@ -0,0 +1,258 @@ +# Implantação FastAPI na Deta + +Nessa seção você aprenderá sobre como realizar a implantação de uma aplicação **FastAPI** na Deta utilizando o plano gratuito. 🎁 + +Isso tudo levará aproximadamente **10 minutos**. + +!!! info "Informação" + Deta é uma patrocinadora do **FastAPI**. 🎉 + +## Uma aplicação **FastAPI** simples + +* Crie e entre em um diretório para a sua aplicação, por exemplo, `./fastapideta/`. + +### Código FastAPI + +* Crie o arquivo `main.py` com: + +```Python +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): + return {"item_id": item_id} +``` + +### Requisitos + +Agora, no mesmo diretório crie o arquivo `requirements.txt` com: + +```text +fastapi +``` + +!!! tip "Dica" + Você não precisa instalar Uvicorn para realizar a implantação na Deta, embora provavelmente queira instalá-lo para testar seu aplicativo localmente. + +### Estrutura de diretório + +Agora você terá o diretório `./fastapideta/` com dois arquivos: + +``` +. +└── main.py +└── requirements.txt +``` + +## Crie uma conta gratuita na Deta + +Agora crie uma conta gratuita na Deta, você precisará apenas de um email e senha. + +Você nem precisa de um cartão de crédito. + +## Instale a CLI + +Depois de ter sua conta criada, instale Deta CLI: + +=== "Linux, macOS" + +
+ + ```console + $ curl -fsSL https://get.deta.dev/cli.sh | sh + ``` + +
+ +=== "Windows PowerShell" + +
+ + ```console + $ iwr https://get.deta.dev/cli.ps1 -useb | iex + ``` + +
+ +Após a instalação, abra um novo terminal para que a CLI seja detectada. + +Em um novo terminal, confirme se foi instalado corretamente com: + +
+ +```console +$ deta --help + +Deta command line interface for managing deta micros. +Complete documentation available at https://docs.deta.sh + +Usage: + deta [flags] + deta [command] + +Available Commands: + auth Change auth settings for a deta micro + +... +``` + +
+ +!!! tip "Dica" + Se você tiver problemas ao instalar a CLI, verifique a documentação oficial da Deta. + +## Login pela CLI + +Agora faça login na Deta pela CLI com: + +
+ +```console +$ deta login + +Please, log in from the web page. Waiting.. +Logged in successfully. +``` + +
+ +Isso abrirá um navegador da Web e autenticará automaticamente. + +## Implantação com Deta + +Em seguida, implante seu aplicativo com a Deta CLI: + +
+ +```console +$ deta new + +Successfully created a new micro + +// Notice the "endpoint" 🔍 + +{ + "name": "fastapideta", + "runtime": "python3.7", + "endpoint": "https://qltnci.deta.dev", + "visor": "enabled", + "http_auth": "enabled" +} + +Adding dependencies... + + +---> 100% + + +Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6 +``` + +
+ +Você verá uma mensagem JSON semelhante a: + +```JSON hl_lines="4" +{ + "name": "fastapideta", + "runtime": "python3.7", + "endpoint": "https://qltnci.deta.dev", + "visor": "enabled", + "http_auth": "enabled" +} +``` + +!!! tip "Dica" + Sua implantação terá um URL `"endpoint"` diferente. + +## Confira + +Agora, abra seu navegador na URL do `endpoint`. No exemplo acima foi `https://qltnci.deta.dev`, mas o seu será diferente. + +Você verá a resposta JSON do seu aplicativo FastAPI: + +```JSON +{ + "Hello": "World" +} +``` + +Agora vá para o `/docs` da sua API, no exemplo acima seria `https://qltnci.deta.dev/docs`. + +Ele mostrará sua documentação como: + + + +## Permitir acesso público + +Por padrão, a Deta lidará com a autenticação usando cookies para sua conta. + +Mas quando estiver pronto, você pode torná-lo público com: + +
+ +```console +$ deta auth disable + +Successfully disabled http auth +``` + +
+ +Agora você pode compartilhar essa URL com qualquer pessoa e elas conseguirão acessar sua API. 🚀 + +## HTTPS + +Parabéns! Você realizou a implantação do seu app FastAPI na Deta! 🎉 🍰 + +Além disso, observe que a Deta lida corretamente com HTTPS para você, para que você não precise cuidar disso e tenha a certeza de que seus clientes terão uma conexão criptografada segura. ✅ 🔒 + +## Verifique o Visor + +Na UI da sua documentação (você estará em um URL como `https://qltnci.deta.dev/docs`) envie um request para *operação de rota* `/items/{item_id}`. + +Por exemplo com ID `5`. + +Agora vá para https://web.deta.sh. + +Você verá que há uma seção à esquerda chamada "Micros" com cada um dos seus apps. + +Você verá uma aba com "Detalhes", e também a aba "Visor", vá para "Visor". + +Lá você pode inspecionar as solicitações recentes enviadas ao seu aplicativo. + +Você também pode editá-los e reproduzi-los novamente. + + + +## Saiba mais + +Em algum momento, você provavelmente desejará armazenar alguns dados para seu aplicativo de uma forma que persista ao longo do tempo. Para isso você pode usar Deta Base, que também tem um generoso **nível gratuito**. + +Você também pode ler mais na documentação da Deta. + +## Conceitos de implantação + +Voltando aos conceitos que discutimos em [Deployments Concepts](./concepts.md){.internal-link target=_blank}, veja como cada um deles seria tratado com a Deta: + +* **HTTPS**: Realizado pela Deta, eles fornecerão um subdomínio e lidarão com HTTPS automaticamente. +* **Executando na inicialização**: Realizado pela Deta, como parte de seu serviço. +* **Reinicialização**: Realizado pela Deta, como parte de seu serviço. +* **Replicação**: Realizado pela Deta, como parte de seu serviço. +* **Memória**: Limite predefinido pela Deta, você pode contatá-los para aumentá-lo. +* **Etapas anteriores a inicialização**: Não suportado diretamente, você pode fazê-lo funcionar com o sistema Cron ou scripts adicionais. + +!!! note "Nota" + O Deta foi projetado para facilitar (e gratuitamente) a implantação rápida de aplicativos simples. + + Ele pode simplificar vários casos de uso, mas, ao mesmo tempo, não suporta outros, como o uso de bancos de dados externos (além do próprio sistema de banco de dados NoSQL da Deta), máquinas virtuais personalizadas, etc. + + Você pode ler mais detalhes na documentação da Deta para ver se é a escolha certa para você. diff --git a/docs/pt/docs/features.md b/docs/pt/docs/features.md index 20014fe2df2b9..2b7836a6f2c2f 100644 --- a/docs/pt/docs/features.md +++ b/docs/pt/docs/features.md @@ -191,7 +191,7 @@ Com **FastAPI** você terá todos os recursos do **Pydantic** (já que FastAPI u * Vai bem com o/a seu/sua **IDE/linter/cérebro**: * Como as estruturas de dados do Pydantic são apenas instâncias de classes que você define, a auto completação, _linting_, _mypy_ e a sua intuição devem funcionar corretamente com seus dados validados. * **Rápido**: - * em _benchmarks_, o Pydantic é mais rápido que todas as outras bibliotecas testadas. + * em _benchmarks_, o Pydantic é mais rápido que todas as outras bibliotecas testadas. * Valida **estruturas complexas**: * Use modelos hierárquicos do Pydantic, `List` e `Dict` do `typing` do Python, etc. * Validadores permitem que esquemas de dados complexos sejam limpos e facilmente definidos, conferidos e documentados como JSON Schema. diff --git a/docs/pt/docs/help-fastapi.md b/docs/pt/docs/help-fastapi.md new file mode 100644 index 0000000000000..d82ce3414a7a0 --- /dev/null +++ b/docs/pt/docs/help-fastapi.md @@ -0,0 +1,148 @@ +# Ajuda FastAPI - Obter Ajuda + +Você gosta do **FastAPI**? + +Você gostaria de ajudar o FastAPI, outros usários, e o autor? + +Ou você gostaria de obter ajuda relacionada ao **FastAPI**?? + +Existem métodos muito simples de ajudar (A maioria das ajudas podem ser feitas com um ou dois cliques). + +E também existem vários modos de se conseguir ajuda. + +## Inscreva-se na newsletter + +Você pode se inscrever (pouco frequente) [**FastAPI e amigos** newsletter](/newsletter/){.internal-link target=_blank} para receber atualizações: + +* Notícias sobre FastAPI e amigos 🚀 +* Tutoriais 📝 +* Recursos ✨ +* Mudanças de última hora 🚨 +* Truques e dicas ✅ + +## Siga o FastAPI no twitter + +Siga @fastapi no **Twitter** para receber as últimas notícias sobre o **FastAPI**. 🐦 + +## Favorite o **FastAPI** no GitHub + +Você pode "favoritar" o FastAPI no GitHub (clicando na estrela no canto superior direito): https://github.com/tiangolo/fastapi. ⭐️ + +Favoritando, outros usuários poderão encontrar mais facilmente e verão que já foi útil para muita gente. + +## Acompanhe novos updates no repositorio do GitHub + +Você pode "acompanhar" (watch) o FastAPI no GitHub (clicando no botão com um "olho" no canto superior direito): https://github.com/tiangolo/fastapi. 👀 + +Podendo selecionar apenas "Novos Updates". + +Fazendo isto, serão enviadas notificações (em seu email) sempre que tiver novos updates (uma nova versão) com correções de bugs e novos recursos no **FastAPI** + +## Conect-se com o autor + +Você pode se conectar comigo (Sebastián Ramírez / `tiangolo`), o autor. + +Você pode: + +* Me siga no **GitHub**. + * Ver também outros projetos Open Source criados por mim que podem te ajudar. + * Me seguir para saber quando um novo projeto Open Source for criado. +* Me siga no **Twitter**. + * Me dizer o motivo pelo o qual você está usando o FastAPI(Adoro ouvir esse tipo de comentário). + * Saber quando eu soltar novos anúncios ou novas ferramentas. + * Também é possivel seguir o @fastapi no Twitter (uma conta aparte). +* Conect-se comigo no **Linkedin**. + * Saber quando eu fizer novos anúncios ou novas ferramentas (apesar de que uso o twitter com mais frequência 🤷‍♂). +* Ler meus artigos (ou me seguir) no **Dev.to** ou no **Medium**. + * Ficar por dentro de novas ideias, artigos, e ferramentas criadas por mim. + * Me siga para saber quando eu publicar algo novo. + +## Tweete sobre **FastAPI** + +Tweete sobre o **FastAPI** e compartilhe comigo e com os outros o porque de gostar do FastAPI. 🎉 + +Adoro ouvir sobre como o **FastAPI** é usado, o que você gosta nele, em qual projeto/empresa está sendo usado, etc. + +## Vote no FastAPI + +* Vote no **FastAPI** no Slant. +* Vote no **FastAPI** no AlternativeTo. + +## Responda perguntas no GitHub + +Você pode acompanhar as perguntas existentes e tentar ajudar outros, . 🤓 + +Ajudando a responder as questões de varias pessoas, você pode se tornar um [Expert em FastAPI](fastapi-people.md#experts){.internal-link target=_blank} oficial. 🎉 + +## Acompanhe o repositório do GitHub + +Você pode "acompanhar" (watch) o FastAPI no GitHub (clicando no "olho" no canto superior direito): https://github.com/tiangolo/fastapi. 👀 + +Se você selecionar "Acompanhando" (Watching) em vez de "Apenas Lançamentos" (Releases only) você receberá notificações quando alguém tiver uma nova pergunta. + +Assim podendo tentar ajudar a resolver essas questões. + +## Faça perguntas + +É possível criar uma nova pergunta no repositório do GitHub, por exemplo: + +* Faça uma **pergunta** ou pergunte sobre um **problema**. +* Sugira novos **recursos**. + +**Nota**: Se você fizer uma pergunta, então eu gostaria de pedir que você também ajude os outros com suas respectivas perguntas. 😉 + +## Crie um Pull Request + +É possível [contribuir](contributing.md){.internal-link target=_blank} no código fonte fazendo Pull Requests, por exemplo: + +* Para corrigir um erro de digitação que você encontrou na documentação. +* Para compartilhar um artigo, video, ou podcast criados por você sobre o FastAPI editando este arquivo. + * Não se esqueça de adicionar o link no começo da seção correspondente. +* Para ajudar [traduzir a documentação](contributing.md#translations){.internal-link target=_blank} para sua lingua. + * Também é possivel revisar as traduções já existentes. +* Para propor novas seções na documentação. +* Para corrigir um bug/questão. +* Para adicionar um novo recurso. + +## Entre no chat + +Entre no 👥 server de conversa do Discord 👥 e conheça novas pessoas da comunidade +do FastAPI. + +!!! dica + Para perguntas, pergunte nas questões do GitHub, lá tem um chance maior de você ser ajudado sobre o FastAPI [FastAPI Experts](fastapi-people.md#experts){.internal-link target=_blank}. + + Use o chat apenas para outro tipo de assunto. + +Também existe o chat do Gitter, porém ele não possuí canais e recursos avançados, conversas são mais engessadas, por isso o Discord é mais recomendado. + +### Não faça perguntas no chat + +Tenha em mente que os chats permitem uma "conversa mais livre", dessa forma é muito fácil fazer perguntas que são muito genéricas e dificeís de responder, assim você pode acabar não sendo respondido. + +Nas questões do GitHub o template irá te guiar para que você faça a sua pergunta de um jeito mais correto, fazendo com que você receba respostas mais completas, e até mesmo que você mesmo resolva o problema antes de perguntar. E no GitHub eu garanto que sempre irei responder todas as perguntas, mesmo que leve um tempo. Eu pessoalmente não consigo fazer isso via chat. 😅 + +Conversas no chat não são tão fáceis de serem encontrados quanto no GitHub, então questões e respostas podem se perder dentro da conversa. E apenas as que estão nas questões do GitHub contam para você se tornar um [Expert em FastAPI](fastapi-people.md#experts){.internal-link target=_blank}, então você receberá mais atenção nas questões do GitHub. + +Por outro lado, existem milhares de usuários no chat, então tem uma grande chance de você encontrar alguém para trocar uma idéia por lá em qualquer horário. 😄 + +## Patrocine o autor + +Você também pode ajudar o autor financeiramente (eu) através do GitHub sponsors. + +Lá você pode me pagar um cafézinho ☕️ como agradecimento. 😄 + +E você também pode se tornar um patrocinador Prata ou Ouro do FastAPI. 🏅🎉 + +## Patrocine as ferramente que potencializam o FastAPI + +Como você viu na documentação, o FastAPI se apoia em nos gigantes, Starlette e Pydantic. + +Patrocine também: + +* Samuel Colvin (Pydantic) +* Encode (Starlette, Uvicorn) + +--- + +Muito Obrigado! 🚀 diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index 848fff08aa2e8..b1d0c89f2a813 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -138,7 +138,7 @@ $ pip install uvicorn[standard] * Crie um arquivo `main.py` com: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -151,7 +151,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -161,7 +161,7 @@ def read_item(item_id: int, q: Optional[str] = None): Se seu código utiliza `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -174,7 +174,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -253,6 +253,8 @@ Agora modifique o arquivo `main.py` para receber um corpo para uma requisição Declare o corpo utilizando tipos padrão Python, graças ao Pydantic. ```Python hl_lines="4 9-12 25-27" +from typing import Union + from fastapi import FastAPI from pydantic import BaseModel @@ -262,7 +264,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool] = None @app.get("/") @@ -271,7 +273,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -365,7 +367,7 @@ Voltando ao código do exemplo anterior, **FastAPI** irá: * Como o parâmetro `q` é declarado com `= None`, ele é opcional. * Sem o `None` ele poderia ser obrigatório (como o corpo no caso de `PUT`). * Para requisições `PUT` para `/items/{item_id}`, lerá o corpo como JSON e: - * Verifica que tem um atributo obrigatório `name` que deve ser `str`. + * Verifica que tem um atributo obrigatório `name` que deve ser `str`. * Verifica que tem um atributo obrigatório `price` que deve ser `float`. * Verifica que tem an atributo opcional `is_offer`, que deve ser `bool`, se presente. * Tudo isso também funciona para objetos JSON profundamente aninhados. @@ -434,7 +436,6 @@ Usados por Pydantic: Usados por Starlette: * requests - Necessário se você quiser utilizar o `TestClient`. -* aiofiles - Necessário se você quiser utilizar o `FileResponse` ou `StaticFiles`. * jinja2 - Necessário se você quiser utilizar a configuração padrão de templates. * python-multipart - Necessário se você quiser suporte com "parsing" de formulário, com `request.form()`. * itsdangerous - Necessário para suporte a `SessionMiddleware`. diff --git a/docs/pt/docs/python-types.md b/docs/pt/docs/python-types.md index df70afd4080bd..9f12211c74010 100644 --- a/docs/pt/docs/python-types.md +++ b/docs/pt/docs/python-types.md @@ -313,4 +313,3 @@ O importante é que, usando tipos padrão de Python, em um único local (em vez !!! info "Informação" Se você já passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso é a "cheat sheet" do `mypy` . - diff --git a/docs/pt/docs/tutorial/background-tasks.md b/docs/pt/docs/tutorial/background-tasks.md new file mode 100644 index 0000000000000..625fa2b111d23 --- /dev/null +++ b/docs/pt/docs/tutorial/background-tasks.md @@ -0,0 +1,94 @@ +# Tarefas em segundo plano + +Você pode definir tarefas em segundo plano a serem executadas _ após _ retornar uma resposta. + +Isso é útil para operações que precisam acontecer após uma solicitação, mas que o cliente realmente não precisa esperar a operação ser concluída para receber a resposta. + +Isso inclui, por exemplo: + +- Envio de notificações por email após a realização de uma ação: + - Como conectar-se a um servidor de e-mail e enviar um e-mail tende a ser "lento" (vários segundos), você pode retornar a resposta imediatamente e enviar a notificação por e-mail em segundo plano. +- Processando dados: + - Por exemplo, digamos que você receba um arquivo que deve passar por um processo lento, você pode retornar uma resposta de "Aceito" (HTTP 202) e processá-lo em segundo plano. + +## Usando `BackgroundTasks` + +Primeiro, importe `BackgroundTasks` e defina um parâmetro em sua _função de operação de caminho_ com uma declaração de tipo de `BackgroundTasks`: + +```Python hl_lines="1 13" +{!../../../docs_src/background_tasks/tutorial001.py!} +``` + +O **FastAPI** criará o objeto do tipo `BackgroundTasks` para você e o passará como esse parâmetro. + +## Criar uma função de tarefa + +Crie uma função a ser executada como tarefa em segundo plano. + +É apenas uma função padrão que pode receber parâmetros. + +Pode ser uma função `async def` ou `def` normal, o **FastAPI** saberá como lidar com isso corretamente. + +Nesse caso, a função de tarefa gravará em um arquivo (simulando o envio de um e-mail). + +E como a operação de gravação não usa `async` e `await`, definimos a função com `def` normal: + +```Python hl_lines="6-9" +{!../../../docs_src/background_tasks/tutorial001.py!} +``` + +## Adicionar a tarefa em segundo plano + +Dentro de sua _função de operação de caminho_, passe sua função de tarefa para o objeto _tarefas em segundo plano_ com o método `.add_task()`: + +```Python hl_lines="14" +{!../../../docs_src/background_tasks/tutorial001.py!} +``` + +`.add_task()` recebe como argumentos: + +- Uma função de tarefa a ser executada em segundo plano (`write_notification`). +- Qualquer sequência de argumentos que deve ser passada para a função de tarefa na ordem (`email`). +- Quaisquer argumentos nomeados que devem ser passados ​​para a função de tarefa (`mensagem = "alguma notificação"`). + +## Injeção de dependência + +Usar `BackgroundTasks` também funciona com o sistema de injeção de dependência, você pode declarar um parâmetro do tipo `BackgroundTasks` em vários níveis: em uma _função de operação de caminho_, em uma dependência (confiável), em uma subdependência, etc. + +O **FastAPI** sabe o que fazer em cada caso e como reutilizar o mesmo objeto, de forma que todas as tarefas em segundo plano sejam mescladas e executadas em segundo plano posteriormente: + +```Python hl_lines="13 15 22 25" +{!../../../docs_src/background_tasks/tutorial002.py!} +``` + +Neste exemplo, as mensagens serão gravadas no arquivo `log.txt` _após_ o envio da resposta. + +Se houver uma consulta na solicitação, ela será gravada no log em uma tarefa em segundo plano. + +E então outra tarefa em segundo plano gerada na _função de operação de caminho_ escreverá uma mensagem usando o parâmetro de caminho `email`. + +## Detalhes técnicos + +A classe `BackgroundTasks` vem diretamente de `starlette.background`. + +Ela é importada/incluída diretamente no FastAPI para que você possa importá-la do `fastapi` e evitar a importação acidental da alternativa `BackgroundTask` (sem o `s` no final) de `starlette.background`. + +Usando apenas `BackgroundTasks` (e não `BackgroundTask`), é então possível usá-la como um parâmetro de _função de operação de caminho_ e deixar o **FastAPI** cuidar do resto para você, assim como ao usar o objeto `Request` diretamente. + +Ainda é possível usar `BackgroundTask` sozinho no FastAPI, mas você deve criar o objeto em seu código e retornar uma Starlette `Response` incluindo-o. + +Você pode ver mais detalhes na documentação oficiais da Starlette para tarefas em segundo plano . + +## Ressalva + +Se você precisa realizar cálculos pesados ​​em segundo plano e não necessariamente precisa que seja executado pelo mesmo processo (por exemplo, você não precisa compartilhar memória, variáveis, etc), você pode se beneficiar do uso de outras ferramentas maiores, como Celery . + +Eles tendem a exigir configurações mais complexas, um gerenciador de fila de mensagens/tarefas, como RabbitMQ ou Redis, mas permitem que você execute tarefas em segundo plano em vários processos e, especialmente, em vários servidores. + +Para ver um exemplo, verifique os [Geradores de projeto](../project-generation.md){.internal-link target=\_blank}, todos incluem celery já configurado. + +Mas se você precisa acessar variáveis ​​e objetos do mesmo aplicativo **FastAPI**, ou precisa realizar pequenas tarefas em segundo plano (como enviar uma notificação por e-mail), você pode simplesmente usar `BackgroundTasks`. + +## Recapitulando + +Importe e use `BackgroundTasks` com parâmetros em _funções de operação de caminho_ e dependências para adicionar tarefas em segundo plano. diff --git a/docs/pt/docs/tutorial/body.md b/docs/pt/docs/tutorial/body.md new file mode 100644 index 0000000000000..99e05ab77e95f --- /dev/null +++ b/docs/pt/docs/tutorial/body.md @@ -0,0 +1,165 @@ +# Corpo da Requisição + +Quando você precisa enviar dados de um cliente (como de um navegador web) para sua API, você o envia como um **corpo da requisição**. + +O corpo da **requisição** é a informação enviada pelo cliente para sua API. O corpo da **resposta** é a informação que sua API envia para o cliente. + +Sua API quase sempre irá enviar um corpo na **resposta**. Mas os clientes não necessariamente precisam enviar um corpo em toda **requisição**. + +Para declarar um corpo da **requisição**, você utiliza os modelos do Pydantic com todos os seus poderes e benefícios. + +!!! info "Informação" + Para enviar dados, você deve usar utilizar um dos métodos: `POST` (Mais comum), `PUT`, `DELETE` ou `PATCH`. + + Enviar um corpo em uma requisição `GET` não tem um comportamento definido nas especificações, porém é suportado pelo FastAPI, apenas para casos de uso bem complexos/extremos. + + Como é desencorajado, a documentação interativa com Swagger UI não irá mostrar a documentação para o corpo da requisição para um `GET`, e proxies que intermediarem podem não suportar o corpo da requisição. + +## Importe o `BaseModel` do Pydantic + +Primeiro, você precisa importar `BaseModel` do `pydantic`: + +```Python hl_lines="4" +{!../../../docs_src/body/tutorial001.py!} +``` + +## Crie seu modelo de dados + +Então você declara seu modelo de dados como uma classe que herda `BaseModel`. + +Utilize os tipos Python padrão para todos os atributos: + +```Python hl_lines="7-11" +{!../../../docs_src/body/tutorial001.py!} +``` + +Assim como quando declaramos parâmetros de consulta, quando um atributo do modelo possui um valor padrão, ele se torna opcional. Caso contrário, se torna obrigatório. Use `None` para torná-lo opcional. + +Por exemplo, o modelo acima declara um JSON "`object`" (ou `dict` no Python) como esse: + +```JSON +{ + "name": "Foo", + "description": "Uma descrição opcional", + "price": 45.2, + "tax": 3.5 +} +``` + +...como `description` e `tax` são opcionais (Com um valor padrão de `None`), esse JSON "`object`" também é válido: + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## Declare como um parâmetro + +Para adicionar o corpo na *função de operação de rota*, declare-o da mesma maneira que você declarou parâmetros de rota e consulta: + +```Python hl_lines="18" +{!../../../docs_src/body/tutorial001.py!} +``` + +...E declare o tipo como o modelo que você criou, `Item`. + +## Resultados + +Apenas com esse declaração de tipos do Python, o **FastAPI** irá: + +* Ler o corpo da requisição como um JSON. +* Converter os tipos correspondentes (se necessário). +* Validar os dados. + * Se algum dados for inválido, irá retornar um erro bem claro, indicando exatamente onde e o que está incorreto. +* Entregar a você a informação recebida no parâmetro `item`. + * Como você o declarou na função como do tipo `Item`, você também terá o suporte do editor (completação, etc) para todos os atributos e seus tipos. +* Gerar um Esquema JSON com as definições do seu modelo, você também pode utilizá-lo em qualquer lugar que quiser, se fizer sentido para seu projeto. +* Esses esquemas farão parte do esquema OpenAPI, e utilizados nas UIs de documentação automática. + +## Documentação automática + +Os esquemas JSON dos seus modelos farão parte do esquema OpenAPI gerado para sua aplicação, e aparecerão na documentação interativa da API: + + + +E também serão utilizados em cada *função de operação de rota* que utilizá-los: + + + +## Suporte do editor de texto: + +No seu editor de texto, dentro da função você receberá dicas de tipos e completação em todo lugar (isso não aconteceria se você recebesse um `dict` em vez de um modelo Pydantic): + + + +Você também poderá receber verificações de erros para operações de tipos incorretas: + + + +Isso não é por acaso, todo o framework foi construído em volta deste design. + +E foi imensamente testado na fase de design, antes de qualquer implementação, para garantir que funcionaria para todos os editores de texto. + +Houveram mudanças no próprio Pydantic para que isso fosse possível. + +As capturas de tela anteriores foram capturas no Visual Studio Code. + +Mas você terá o mesmo suporte do editor no PyCharm e na maioria dos editores Python: + + + +!!! tip "Dica" + Se você utiliza o PyCharm como editor, você pode utilizar o Plugin do Pydantic para o PyCharm . + + Melhora o suporte do editor para seus modelos Pydantic com:: + + * completação automática + * verificação de tipos + * refatoração + * buscas + * inspeções + +## Use o modelo + +Dentro da função, você pode acessar todos os atributos do objeto do modelo diretamente: + +```Python hl_lines="21" +{!../../../docs_src/body/tutorial002.py!} +``` + +## Corpo da requisição + parâmetros de rota + +Você pode declarar parâmetros de rota e corpo da requisição ao mesmo tempo. + +O **FastAPI** irá reconhecer que os parâmetros da função que combinam com parâmetros de rota devem ser **retirados da rota**, e parâmetros da função que são declarados como modelos Pydantic sejam **retirados do corpo da requisição**. + +```Python hl_lines="17-18" +{!../../../docs_src/body/tutorial003.py!} +``` + +## Corpo da requisição + parâmetros de rota + parâmetros de consulta + +Você também pode declarar parâmetros de **corpo**, **rota** e **consulta**, ao mesmo tempo. + +O **FastAPI** irá reconhecer cada um deles e retirar a informação do local correto. + +```Python hl_lines="18" +{!../../../docs_src/body/tutorial004.py!} +``` + +Os parâmetros da função serão reconhecidos conforme abaixo: + +* Se o parâmetro também é declarado na **rota**, será utilizado como um parâmetro de rota. +* Se o parâmetro é de um **tipo único** (como `int`, `float`, `str`, `bool`, etc) será interpretado como um parâmetro de **consulta**. +* Se o parâmetro é declarado como um **modelo Pydantic**, será interpretado como o **corpo** da requisição. + +!!! note "Observação" + O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`. + + O `Union` em `Union[str, None]` não é utilizado pelo FastAPI, mas permite ao seu editor de texto lhe dar um suporte melhor e detectar erros. + +## Sem o Pydantic + +Se você não quer utilizar os modelos Pydantic, você também pode utilizar o parâmetro **Body**. Veja a documentação para [Body - Parâmetros múltiplos: Valores singulares no body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/pt/docs/tutorial/cookie-params.md b/docs/pt/docs/tutorial/cookie-params.md new file mode 100644 index 0000000000000..1a60e35713e97 --- /dev/null +++ b/docs/pt/docs/tutorial/cookie-params.md @@ -0,0 +1,33 @@ +# Parâmetros de Cookie + +Você pode definir parâmetros de Cookie da mesma maneira que define paramêtros com `Query` e `Path`. + +## Importe `Cookie` + +Primeiro importe `Cookie`: + +```Python hl_lines="3" +{!../../../docs_src/cookie_params/tutorial001.py!} +``` + +## Declare parâmetros de `Cookie` + +Então declare os paramêtros de cookie usando a mesma estrutura que em `Path` e `Query`. + +O primeiro valor é o valor padrão, você pode passar todas as validações adicionais ou parâmetros de anotação: + +```Python hl_lines="9" +{!../../../docs_src/cookie_params/tutorial001.py!} +``` + +!!! note "Detalhes Técnicos" + `Cookie` é uma classe "irmã" de `Path` e `Query`. Ela também herda da mesma classe em comum `Param`. + + Mas lembre-se que quando você importa `Query`, `Path`, `Cookie` e outras de `fastapi`, elas são na verdade funções que retornam classes especiais. + +!!! info "Informação" + Para declarar cookies, você precisa usar `Cookie`, caso contrário, os parâmetros seriam interpretados como parâmetros de consulta. + +## Recapitulando + +Declare cookies com `Cookie`, usando o mesmo padrão comum que utiliza-se em `Query` e `Path`. diff --git a/docs/pt/docs/tutorial/extra-data-types.md b/docs/pt/docs/tutorial/extra-data-types.md new file mode 100644 index 0000000000000..e4b9913dc3387 --- /dev/null +++ b/docs/pt/docs/tutorial/extra-data-types.md @@ -0,0 +1,66 @@ +# Tipos de dados extras + +Até agora, você tem usado tipos de dados comuns, tais como: + +* `int` +* `float` +* `str` +* `bool` + +Mas você também pode usar tipos de dados mais complexos. + +E você ainda terá os mesmos recursos que viu até agora: + +* Ótimo suporte do editor. +* Conversão de dados das requisições recebidas. +* Conversão de dados para os dados da resposta. +* Validação de dados. +* Anotação e documentação automáticas. + +## Outros tipos de dados + +Aqui estão alguns dos tipos de dados adicionais que você pode usar: + +* `UUID`: + * Um "Identificador Universalmente Único" padrão, comumente usado como ID em muitos bancos de dados e sistemas. + * Em requisições e respostas será representado como uma `str`. +* `datetime.datetime`: + * O `datetime.datetime` do Python. + * Em requisições e respostas será representado como uma `str` no formato ISO 8601, exemplo: `2008-09-15T15:53:00+05:00`. +* `datetime.date`: + * O `datetime.date` do Python. + * Em requisições e respostas será representado como uma `str` no formato ISO 8601, exemplo: `2008-09-15`. +* `datetime.time`: + * O `datetime.time` do Python. + * Em requisições e respostas será representado como uma `str` no formato ISO 8601, exemplo: `14:23:55.003`. +* `datetime.timedelta`: + * O `datetime.timedelta` do Python. + * Em requisições e respostas será representado como um `float` de segundos totais. + * O Pydantic também permite representá-lo como uma "codificação ISO 8601 diferença de tempo", cheque a documentação para mais informações. +* `frozenset`: + * Em requisições e respostas, será tratado da mesma forma que um `set`: + * Nas requisições, uma lista será lida, eliminando duplicadas e convertendo-a em um `set`. + * Nas respostas, o `set` será convertido para uma `list`. + * O esquema gerado vai especificar que os valores do `set` são unicos (usando o `uniqueItems` do JSON Schema). +* `bytes`: + * O `bytes` padrão do Python. + * Em requisições e respostas será representado como uma `str`. + * O esquema gerado vai especificar que é uma `str` com o "formato" `binary`. +* `Decimal`: + * O `Decimal` padrão do Python. + * Em requisições e respostas será representado como um `float`. +* Você pode checar todos os tipos de dados válidos do Pydantic aqui: Tipos de dados do Pydantic. + +## Exemplo + +Aqui está um exemplo de *operação de rota* com parâmetros utilizando-se de alguns dos tipos acima. + +```Python hl_lines="1 3 12-16" +{!../../../docs_src/extra_data_types/tutorial001.py!} +``` + +Note que os parâmetros dentro da função tem seu tipo de dados natural, e você pode, por exemplo, realizar manipulações normais de data, como: + +```Python hl_lines="18-19" +{!../../../docs_src/extra_data_types/tutorial001.py!} +``` diff --git a/docs/pt/docs/tutorial/path-params.md b/docs/pt/docs/tutorial/path-params.md index 20913a564918a..5de3756ed6cb6 100644 --- a/docs/pt/docs/tutorial/path-params.md +++ b/docs/pt/docs/tutorial/path-params.md @@ -72,7 +72,7 @@ O mesmo erro apareceria se você tivesse fornecido um `float` ao invés de um `i ## Documentação -Quando você abrir o seu navegador em http://127.0.0.1:8000/docs, você verá de forma automática e interativa a documtação da API como: +Quando você abrir o seu navegador em http://127.0.0.1:8000/docs, você verá de forma automática e interativa a documentação da API como: diff --git a/docs/pt/docs/tutorial/query-params-str-validations.md b/docs/pt/docs/tutorial/query-params-str-validations.md index baac5f4931549..9a9e071db9b3c 100644 --- a/docs/pt/docs/tutorial/query-params-str-validations.md +++ b/docs/pt/docs/tutorial/query-params-str-validations.md @@ -8,12 +8,12 @@ Vamos utilizar essa aplicação como exemplo: {!../../../docs_src/query_params_str_validations/tutorial001.py!} ``` -O parâmetro de consulta `q` é do tipo `Optional[str]`, o que significa que é do tipo `str` mas que também pode ser `None`, e de fato, o valor padrão é `None`, então o FastAPI saberá que não é obrigatório. +O parâmetro de consulta `q` é do tipo `Union[str, None]`, o que significa que é do tipo `str` mas que também pode ser `None`, e de fato, o valor padrão é `None`, então o FastAPI saberá que não é obrigatório. !!! note "Observação" O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`. - O `Optional` em `Optional[str]` não é usado pelo FastAPI, mas permitirá que seu editor lhe dê um melhor suporte e detecte erros. + O `Union` em `Union[str, None]` não é usado pelo FastAPI, mas permitirá que seu editor lhe dê um melhor suporte e detecte erros. ## Validação adicional @@ -35,18 +35,18 @@ Agora utilize-o como valor padrão do seu parâmetro, definindo o parâmetro `ma {!../../../docs_src/query_params_str_validations/tutorial002.py!} ``` -Note que substituímos o valor padrão de `None` para `Query(None)`, o primeiro parâmetro de `Query` serve para o mesmo propósito: definir o valor padrão do parâmetro. +Note que substituímos o valor padrão de `None` para `Query(default=None)`, o primeiro parâmetro de `Query` serve para o mesmo propósito: definir o valor padrão do parâmetro. Então: ```Python -q: Optional[str] = Query(None) +q: Union[str, None] = Query(default=None) ``` ...Torna o parâmetro opcional, da mesma maneira que: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` Mas o declara explicitamente como um parâmetro de consulta. @@ -61,17 +61,17 @@ Mas o declara explicitamente como um parâmetro de consulta. Ou com: ```Python - = Query(None) + = Query(default=None) ``` E irá utilizar o `None` para detectar que o parâmetro de consulta não é obrigatório. - O `Optional` é apenas para permitir que seu editor de texto lhe dê um melhor suporte. + O `Union` é apenas para permitir que seu editor de texto lhe dê um melhor suporte. Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro `max_length` que se aplica a textos: ```Python -q: str = Query(None, max_length=50) +q: str = Query(default=None, max_length=50) ``` Isso irá validar os dados, mostrar um erro claro quando os dados forem inválidos, e documentar o parâmetro na *operação de rota* do esquema OpenAPI.. @@ -80,7 +80,7 @@ Isso irá validar os dados, mostrar um erro claro quando os dados forem inválid Você também pode incluir um parâmetro `min_length`: -```Python hl_lines="9" +```Python hl_lines="10" {!../../../docs_src/query_params_str_validations/tutorial003.py!} ``` @@ -88,7 +88,7 @@ Você também pode incluir um parâmetro `min_length`: Você pode definir uma expressão regular que combine com um padrão esperado pelo parâmetro: -```Python hl_lines="10" +```Python hl_lines="11" {!../../../docs_src/query_params_str_validations/tutorial004.py!} ``` @@ -126,13 +126,13 @@ q: str em vez desta: ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` Mas agora nós o estamos declarando como `Query`, conforme abaixo: ```Python -q: Optional[str] = Query(None, min_length=3) +q: Union[str, None] = Query(default=None, min_length=3) ``` Então, quando você precisa declarar um parâmetro obrigatório utilizando o `Query`, você pode utilizar `...` como o primeiro argumento: diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml index f202f306d62b2..2bb0b568d45dd 100644 --- a/docs/pt/mkdocs.yml +++ b/docs/pt/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -58,8 +62,11 @@ nav: - tutorial/index.md - tutorial/first-steps.md - tutorial/path-params.md + - tutorial/body.md - tutorial/body-fields.md + - tutorial/extra-data-types.md - tutorial/query-params-str-validations.md + - tutorial/cookie-params.md - Segurança: - tutorial/security/index.md - Guia de Usuário Avançado: @@ -68,10 +75,12 @@ nav: - deployment/index.md - deployment/versions.md - deployment/https.md + - deployment/deta.md - alternatives.md - history-design-future.md - external-links.md - benchmarks.md +- help-fastapi.md markdown_extensions: - toc: permalink: true @@ -117,6 +126,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -127,6 +138,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/ru/docs/async.md b/docs/ru/docs/async.md new file mode 100644 index 0000000000000..4c44fc22d37f4 --- /dev/null +++ b/docs/ru/docs/async.md @@ -0,0 +1,505 @@ +# Конкурентность и async / await + +Здесь приведена подробная информация об использовании синтаксиса `async def` при написании *функций обработки пути*, а также рассмотрены основы асинхронного программирования, конкурентности и параллелизма. + +## Нет времени? + +TL;DR: + +Допустим, вы используете сторонюю библиотеку, которая требует вызова с ключевым словом `await`: + +```Python +results = await some_library() +``` + +В этом случае *функции обработки пути* необходимо объявлять с использованием синтаксиса `async def`: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +!!! note + `await` можно использовать только внутри функций, объявленных с использованием `async def`. + +--- + +Если вы обращаетесь к сторонней библиотеке, которая с чем-то взаимодействует +(с базой данных, API, файловой системой и т. д.), и не имеет поддержки синтаксиса `await` +(что относится сейчас к большинству библиотек для работы с базами данных), то +объявляйте *функции обработки пути* обычным образом с помощью `def`, например: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +Если вашему приложению (странным образом) не нужно ни с чем взаимодействовать и, соответственно, +ожидать ответа, используйте `async def`. + +--- + +Если вы не уверены, используйте обычный синтаксис `def`. + +--- + +**Примечание**: при необходимости можно смешивать `def` и `async def` в *функциях обработки пути* +и использовать в каждом случае наиболее подходящий синтаксис. А FastAPI сделает с этим всё, что нужно. + +В любом из описанных случаев FastAPI работает асинхронно и очень быстро. + +Однако придерживаясь указанных советов, можно получить дополнительную оптимизацию производительности. + +## Технические подробности + +Современные версии Python поддерживают разработку так называемого **"асинхронного кода"** посредством написания **"сопрограмм"** с использованием синтаксиса **`async` и `await`**. + +Ниже разберём эту фразу по частям: + +* **Асинхронный код** +* **`async` и `await`** +* **Сопрограммы** + +## Асинхронный код + +Асинхронный код означает, что в языке 💬 есть возможность сообщить машине / программе 🤖, +что в определённой точке кода ей 🤖 нужно будет ожидать завершения выполнения *чего-то ещё* в другом месте. Допустим это *что-то ещё* называется "медленный файл" 📝. + +И пока мы ждём завершения работы с "медленным файлом" 📝, компьютер может переключиться для выполнения других задач. + +Но при каждой возможности компьютер / программа 🤖 будет возвращаться обратно. Например, если он 🤖 опять окажется в режиме ожидания, или когда закончит всю работу. В этом случае компьютер 🤖 проверяет, не завершена ли какая-нибудь из текущих задач. + +Потом он 🤖 берёт первую выполненную задачу (допустим, наш "медленный файл" 📝) и продолжает работу, производя с ней необходимые действия. + +Вышеупомянутое "что-то ещё", завершения которого приходится ожидать, обычно относится к достаточно "медленным" операциям I/O (по сравнению со скоростью работы процессора и оперативной памяти), например: + +* отправка данных от клиента по сети +* получение клиентом данных, отправленных вашей программой по сети +* чтение системой содержимого файла с диска и передача этих данных программе +* запись на диск данных, которые программа передала системе +* обращение к удалённому API +* ожидание завершения операции с базой данных +* получение результатов запроса к базе данных +* и т. д. + +Поскольку в основном время тратится на ожидание выполнения операций I/O, +их обычно называют операциями, ограниченными скоростью ввода-вывода. + +Код называют "асинхронным", потому что компьютеру / программе не требуется "синхронизироваться" с медленной задачей и, +будучи в простое, ожидать момента её завершения, с тем чтобы забрать результат и продолжить работу. + +Вместо этого в "асинхронной" системе завершённая задача может немного подождать (буквально несколько микросекунд), +пока компьютер / программа занимается другими важными вещами, с тем чтобы потом вернуться, +забрать результаты выполнения и начать их обрабатывать. + +"Синхронное" исполнение (в противовес "асинхронному") также называют "последовательным", +потому что компьютер / программа последовательно выполняет все требуемые шаги перед тем, как перейти к следующей задаче, +даже если в процессе приходится ждать. + +### Конкурентность и бургеры + +Тот **асинхронный** код, о котором идёт речь выше, иногда называют **"конкурентностью"**. Она отличается от **"параллелизма"**. + +Да, **конкурентность** и **параллелизм** подразумевают, что разные вещи происходят примерно в одно время. + +Но внутреннее устройство **конкурентности** и **параллелизма** довольно разное. + +Чтобы это понять, представьте такую картину: + +### Конкурентные бургеры + + + +Вы идёте со своей возлюбленной 😍 в фастфуд 🍔 и становитесь в очередь, в это время кассир 💁 принимает заказы у посетителей перед вами. + +Когда наконец подходит очередь, вы заказываете парочку самых вкусных и навороченных бургеров 🍔, один для своей возлюбленной 😍, а другой себе. + +Отдаёте деньги 💸. + +Кассир 💁 что-то говорит поварам на кухне 👨‍🍳, теперь они знают, какие бургеры нужно будет приготовить 🍔 +(но пока они заняты бургерами предыдущих клиентов). + +Кассир 💁 отдаёт вам чек с номером заказа. + +В ожидании еды вы идёте со своей возлюбленной 😍 выбрать столик, садитесь и довольно продолжительное время общаетесь 😍 +(поскольку ваши бургеры самые навороченные, готовятся они не так быстро ✨🍔✨). + +Сидя за столиком с возлюбленной 😍 в ожидании бургеров 🍔, вы отлично проводите время, +восхищаясь её великолепием, красотой и умом ✨😍✨. + +Всё ещё ожидая заказ и болтая со своей возлюбленной 😍, время от времени вы проверяете, +какой номер горит над прилавком, и не подошла ли уже ваша очередь. + +И вот наконец настаёт этот момент, и вы идёте к стойке, чтобы забрать бургеры 🍔 и вернуться за столик. + +Вы со своей возлюбленной 😍 едите бургеры 🍔 и отлично проводите время ✨. + +--- + +А теперь представьте, что в этой небольшой истории вы компьютер / программа 🤖. + +В очереди вы просто глазеете по сторонам 😴, ждёте и ничего особо "продуктивного" не делаете. +Но очередь движется довольно быстро, поскольку кассир 💁 только принимает заказы (а не занимается приготовлением еды), так что ничего страшного. + +Когда подходит очередь вы наконец предпринимаете "продуктивные" действия 🤓: просматриваете меню, выбираете в нём что-то, узнаёте, что хочет ваша возлюбленная 😍, собираетесь оплатить 💸, смотрите, какую достали карту, проверяете, чтобы с вас списали верную сумму, и что в заказе всё верно и т. д. + +И хотя вы всё ещё не получили бургеры 🍔, ваша работа с кассиром 💁 ставится "на паузу" ⏸, +поскольку теперь нужно ждать 🕙, когда заказ приготовят. + +Но отойдя с номерком от прилавка, вы садитесь за столик и можете переключить 🔀 внимание +на свою возлюбленную 😍 и "работать" ⏯ 🤓 уже над этим. И вот вы снова очень +"продуктивны" 🤓, мило болтаете вдвоём и всё такое 😍. + +В какой-то момент кассир 💁 поместит на табло ваш номер, подразумевая, что бургеры готовы 🍔, но вы не станете подскакивать как умалишённый, лишь только увидев на экране свою очередь. Вы уверены, что ваши бургеры 🍔 никто не утащит, ведь у вас свой номерок, а у других свой. + +Поэтому вы подождёте, пока возлюбленная 😍 закончит рассказывать историю (закончите текущую работу ⏯ / задачу в обработке 🤓), +и мило улыбнувшись, скажете, что идёте забирать заказ ⏸. + +И вот вы подходите к стойке 🔀, к первоначальной задаче, которая уже завершена ⏯, берёте бургеры 🍔, говорите спасибо и относите заказ за столик. На этом заканчивается этап / задача взаимодействия с кассой ⏹. +В свою очередь порождается задача "поедание бургеров" 🔀 ⏯, но предыдущая ("получение бургеров") завершена ⏹. + +### Параллельные бургеры + +Теперь представим, что вместо бургерной "Конкурентные бургеры" вы решили сходить в "Параллельные бургеры". + +И вот вы идёте со своей возлюбленной 😍 отведать параллельного фастфуда 🍔. + +Вы становитесь в очередь пока несколько (пусть будет 8) кассиров, которые по совместительству ещё и повары 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳, принимают заказы у посетителей перед вами. + +При этом клиенты не отходят от стойки и ждут 🕙 получения еды, поскольку каждый +из 8 кассиров идёт на кухню готовить бургеры 🍔, а только потом принимает следующий заказ. + +Наконец настаёт ваша очередь, и вы просите два самых навороченных бургера 🍔, один для дамы сердца 😍, а другой себе. + +Ни о чём не жалея, расплачиваетесь 💸. + +И кассир уходит на кухню 👨‍🍳. + +Вам приходится ждать перед стойкой 🕙, чтобы никто по случайности не забрал ваши бургеры 🍔, ведь никаких номерков у вас нет. + +Поскольку вы с возлюбленной 😍 хотите получить заказ вовремя 🕙, и следите за тем, чтобы никто не вклинился в очередь, +у вас не получается уделять должного внимание своей даме сердца 😞. + +Это "синхронная" работа, вы "синхронизированы" с кассиром/поваром 👨‍🍳. Приходится ждать 🕙 у стойки, +когда кассир/повар 👨‍🍳 закончит делать бургеры 🍔 и вручит вам заказ, иначе его случайно может забрать кто-то другой. + +Наконец кассир/повар 👨‍🍳 возвращается с бургерами 🍔 после невыносимо долгого ожидания 🕙 за стойкой. + +Вы скорее забираете заказ 🍔 и идёте с возлюбленной 😍 за столик. + +Там вы просто едите эти бургеры, и на этом всё 🍔 ⏹. + +Вам не особо удалось пообщаться, потому что большую часть времени 🕙 пришлось провести у кассы 😞. + +--- + +В описанном сценарии вы компьютер / программа 🤖 с двумя исполнителями (вы и ваша возлюбленная 😍), +на протяжении долгого времени 🕙 вы оба уделяете всё внимание ⏯ задаче "ждать на кассе". + +В этом ресторане быстрого питания 8 исполнителей (кассиров/поваров) 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳. +Хотя в бургерной конкурентного типа было всего два (один кассир и один повар) 💁 👨‍🍳. + +Несмотря на обилие работников, опыт в итоге получился не из лучших 😞. + +--- + +Так бы выглядел аналог истории про бургерную 🍔 в "параллельном" мире. + +Вот более реалистичный пример. Представьте себе банк. + +До недавних пор в большинстве банков было несколько кассиров 👨‍💼👨‍💼👨‍💼👨‍💼 и длинные очереди 🕙🕙🕙🕙🕙🕙🕙🕙. + +Каждый кассир обслуживал одного клиента, потом следующего 👨‍💼⏯. + +Нужно было долгое время 🕙 стоять перед окошком вместе со всеми, иначе пропустишь свою очередь. + +Сомневаюсь, что у вас бы возникло желание прийти с возлюбленной 😍 в банк 🏦 оплачивать налоги. + +### Выводы о бургерах + +В нашей истории про поход в фастфуд за бургерами приходится много ждать 🕙, +поэтому имеет смысл организовать конкурентную систему ⏸🔀⏯. + +И то же самое с большинством веб-приложений. + +Пользователей очень много, но ваш сервер всё равно вынужден ждать 🕙 запросы по их слабому интернет-соединению. + +Потом снова ждать 🕙, пока вернётся ответ. + + +Это ожидание 🕙 измеряется микросекундами, но если всё сложить, то набегает довольно много времени. + +Вот почему есть смысл использовать асинхронное ⏸🔀⏯ программирование при построении веб-API. + +Большинство популярных фреймворков (включая Flask и Django) создавались +до появления в Python новых возможностей асинхронного программирования. Поэтому +их можно разворачивать с поддержкой параллельного исполнения или асинхронного +программирования старого типа, которое не настолько эффективно. + +При том, что основная спецификация асинхронного взаимодействия Python с веб-сервером +(ASGI) +была разработана командой Django для внедрения поддержки веб-сокетов. + +Именно асинхронность сделала NodeJS таким популярным (несмотря на то, что он не параллельный), +и в этом преимущество Go как языка программирования. + +И тот же уровень производительности даёт **FastAPI**. + +Поскольку можно использовать преимущества параллелизма и асинхронности вместе, +вы получаете производительность лучше, чем у большинства протестированных NodeJS фреймворков +и на уровне с Go, который является компилируемым языком близким к C (всё благодаря Starlette). + +### Получается, конкурентность лучше параллелизма? + +Нет! Мораль истории совсем не в этом. + +Конкурентность отличается от параллелизма. Она лучше в **конкретных** случаях, где много времени приходится на ожидание. +Вот почему она зачастую лучше параллелизма при разработке веб-приложений. Но это не значит, что конкурентность лучше в любых сценариях. + +Давайте посмотрим с другой стороны, представьте такую картину: + +> Вам нужно убраться в большом грязном доме. + +*Да, это вся история*. + +--- + +Тут не нужно нигде ждать 🕙, просто есть куча работы в разных частях дома. + +Можно организовать очередь как в примере с бургерами, сначала гостиная, потом кухня, +но это ни на что не повлияет, поскольку вы нигде не ждёте 🕙, а просто трёте да моете. + +И понадобится одинаковое количество времени с очередью (конкурентностью) и без неё, +и работы будет сделано тоже одинаковое количество. + +Однако в случае, если бы вы могли привести 8 бывших кассиров/поваров, а ныне уборщиков 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳, +и каждый из них (вместе с вами) взялся бы за свой участок дома, +с такой помощью вы бы закончили намного быстрее, делая всю работу **параллельно**. + +В описанном сценарии каждый уборщик (включая вас) был бы исполнителем, занятым на своём участке работы. + +И поскольку большую часть времени выполнения занимает реальная работа (а не ожидание), +а работу в компьютере делает ЦП, +такие задачи называют ограниченными производительностью процессора. + +--- + +Ограничение по процессору проявляется в операциях, где требуется выполнять сложные математические вычисления. + +Например: + +* Обработка **звука** или **изображений**. +* **Компьютерное зрение**: изображение состоит из миллионов пикселей, в каждом пикселе 3 составляющих цвета, +обработка обычно требует проведения расчётов по всем пикселям сразу. +* **Машинное обучение**: здесь обычно требуется умножение "матриц" и "векторов". +Представьте гигантскую таблицу с числами в Экселе, и все их надо одновременно перемножить. +* **Глубокое обучение**: это область *машинного обучения*, поэтому сюда подходит то же описание. +Просто у вас будет не одна таблица в Экселе, а множество. В ряде случаев используется +специальный процессор для создания и / или использования построенных таким образом моделей. + +### Конкурентность + параллелизм: Веб + машинное обучение + +**FastAPI** предоставляет возможности конкуретного программирования, +которое очень распространено в веб-разработке (именно этим славится NodeJS). + +Кроме того вы сможете использовать все преимущества параллелизма и +многопроцессорности (когда несколько процессов работают параллельно), +если рабочая нагрузка предполагает **ограничение по процессору**, +как, например, в системах машинного обучения. + +Необходимо также отметить, что Python является главным языком в области +**дата-сайенс**, +машинного обучения и, особенно, глубокого обучения. Всё это делает FastAPI +отличным вариантом (среди многих других) для разработки веб-API и приложений +в области дата-сайенс / машинного обучения. + +Как добиться такого параллелизма в эксплуатации описано в разделе [Развёртывание](deployment/index.md){.internal-link target=_blank}. + +## `async` и `await` + +В современных версиях Python разработка асинхронного кода реализована очень интуитивно. +Он выглядит как обычный "последовательный" код и самостоятельно выполняет "ожидание", когда это необходимо. + +Если некая операция требует ожидания перед тем, как вернуть результат, и +поддерживает современные возможности Python, код можно написать следующим образом: + +```Python +burgers = await get_burgers(2) +``` + +Главное здесь слово `await`. Оно сообщает интерпретатору, что необходимо дождаться ⏸ +пока `get_burgers(2)` закончит свои дела 🕙, и только после этого сохранить результат в `burgers`. +Зная это, Python может пока переключиться на выполнение других задач 🔀 ⏯ +(например получение следующего запроса). + +Чтобы ключевое слово `await` сработало, оно должно находиться внутри функции, +которая поддерживает асинхронность. Для этого вам просто нужно объявить её как `async def`: + +```Python hl_lines="1" +async def get_burgers(number: int): + # Готовим бургеры по специальному асинхронному рецепту + return burgers +``` + +...вместо `def`: + +```Python hl_lines="2" +# Это не асинхронный код +def get_sequential_burgers(number: int): + # Готовим бургеры последовательно по шагам + return burgers +``` + +Объявление `async def` указывает интерпретатору, что внутри этой функции +следует ожидать выражений `await`, и что можно поставить выполнение такой функции на "паузу" ⏸ и +переключиться на другие задачи 🔀, с тем чтобы вернуться сюда позже. + +Если вы хотите вызвать функцию с `async def`, вам нужно "ожидать" её. +Поэтому такое не сработает: + +```Python +# Это не заработает, поскольку get_burgers объявлена с использованием async def +burgers = get_burgers(2) +``` + +--- + +Если сторонняя библиотека требует вызывать её с ключевым словом `await`, +необходимо писать *функции обработки пути* с использованием `async def`, например: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### Технические подробности + +Как вы могли заметить, `await` может применяться только в функциях, объявленных с использованием `async def`. + + +Но выполнение такой функции необходимо "ожидать" с помощью `await`. +Это означает, что её можно вызвать только из другой функции, которая тоже объявлена с `async def`. + +Но как же тогда появилась первая курица? В смысле... как нам вызвать первую асинхронную функцию? + +При работе с **FastAPI** просто не думайте об этом, потому что "первой" функцией является ваша *функция обработки пути*, +и дальше с этим разберётся FastAPI. + +Кроме того, если хотите, вы можете использовать синтаксис `async` / `await` и без FastAPI. + +### Пишите свой асинхронный код + +Starlette (и **FastAPI**) основаны на AnyIO, что делает их совместимыми как со стандартной библиотекой asyncio в Python, так и с Trio. + +В частности, вы можете напрямую использовать AnyIO в тех проектах, где требуется более сложная логика работы с конкурентностью. + +Даже если вы не используете FastAPI, вы можете писать асинхронные приложения с помощью AnyIO, чтобы они были максимально совместимыми и получали его преимущества (например *структурную конкурентность*). + +### Другие виды асинхронного программирования + +Стиль написания кода с `async` и `await` появился в языке Python относительно недавно. + +Но он сильно облегчает работу с асинхронным кодом. + +Ровно такой же синтаксис (ну или почти такой же) недавно был включён в современные версии JavaScript (в браузере и NodeJS). + +До этого поддержка асинхронного кода была реализована намного сложнее, и его было труднее воспринимать. + +В предыдущих версиях Python для этого использовались потоки или Gevent. Но такой код намного сложнее понимать, отлаживать и мысленно представлять. + +Что касается JavaScript (в браузере и NodeJS), раньше там использовали для этой цели +"обратные вызовы". Что выливалось в +ад обратных вызовов. + +## Сопрограммы + +**Корути́на** (или же сопрограмма) — это крутое словечко для именования той сущности, +которую возвращает функция `async def`. Python знает, что её можно запустить, как и обычную функцию, +но кроме того сопрограмму можно поставить на паузу ⏸ в том месте, где встретится слово `await`. + +Всю функциональность асинхронного программирования с использованием `async` и `await` +часто обобщают словом "корутины". Они аналогичны "горутинам", ключевой особенности +языка Go. + +## Заключение + +В самом начале была такая фраза: + +> Современные версии Python поддерживают разработку так называемого +**"асинхронного кода"** посредством написания **"сопрограмм"** с использованием +синтаксиса **`async` и `await`**. + +Теперь всё должно звучать понятнее. ✨ + +На этом основана работа FastAPI (посредством Starlette), и именно это +обеспечивает его высокую производительность. + +## Очень технические подробности + +!!! warning + Этот раздел читать не обязательно. + + Здесь приводятся подробности внутреннего устройства **FastAPI**. + + Но если вы обладаете техническими знаниями (корутины, потоки, блокировка и т. д.) + и вам интересно, как FastAPI обрабатывает `async def` в отличие от обычных `def`, + читайте дальше. + +### Функции обработки пути + +Когда вы объявляете *функцию обработки пути* обычным образом с ключевым словом `def` +вместо `async def`, FastAPI ожидает её выполнения, запустив функцию во внешнем +пуле потоков, а не напрямую (это бы заблокировало сервер). + +Если ранее вы использовали другой асинхронный фреймворк, который работает иначе, +и привыкли объявлять простые вычислительные *функции* через `def` ради +незначительного прироста скорости (порядка 100 наносекунд), обратите внимание, +что с **FastAPI** вы получите противоположный эффект. В таком случае больше подходит +`async def`, если только *функция обработки пути* не использует код, приводящий +к блокировке I/O. + + + +Но в любом случае велика вероятность, что **FastAPI** [окажется быстрее](/#performance){.internal-link target=_blank} +другого фреймворка (или хотя бы на уровне с ним). + +### Зависимости + +То же относится к зависимостям. Если это обычная функция `def`, а не `async def`, +она запускается во внешнем пуле потоков. + +### Подзависимости + +Вы можете объявить множество ссылающихся друг на друга зависимостей и подзависимостей +(в виде параметров при определении функции). Какие-то будут созданы с помощью `async def`, +другие обычным образом через `def`, и такая схема вполне работоспособна. Функции, +объявленные с помощью `def` будут запускаться на внешнем потоке (из пула), +а не с помощью `await`. + +### Другие служебные функции + +Любые другие служебные функции, которые вы вызываете напрямую, можно объявлять +с использованием `def` или `async def`. FastAPI не будет влиять на то, как вы +их запускаете. + +Этим они отличаются от функций, которые FastAPI вызывает самостоятельно: +*функции обработки пути* и зависимости. + +Если служебная функция объявлена с помощью `def`, она будет вызвана напрямую +(как вы и написали в коде), а не в отдельном потоке. Если же она объявлена с +помощью `async def`, её вызов должен осуществляться с ожиданием через `await`. + +--- + + +Ещё раз повторим, что все эти технические подробности полезны, только если вы специально их искали. + +В противном случае просто ознакомьтесь с основными принципами в разделе выше: Нет времени?. diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 0c2506b872019..9a3957d5f6efa 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -149,7 +149,7 @@ $ pip install uvicorn[standard] * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -162,7 +162,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -185,7 +185,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -264,7 +264,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -275,7 +275,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -284,7 +284,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md index 99670363c8432..7523083c88319 100644 --- a/docs/ru/docs/python-types.md +++ b/docs/ru/docs/python-types.md @@ -1,6 +1,6 @@ # Введение в аннотации типов Python -Python имеет поддержку необязательных аннотаций типов. +Python имеет поддержку необязательных аннотаций типов. **Аннотации типов** являются специальным синтаксисом, который позволяет определять тип переменной. diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml index 6e17c287e6551..bb0702489da52 100644 --- a/docs/ru/mkdocs.yml +++ b/docs/ru/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -52,6 +56,7 @@ nav: - tr: /tr/ - uk: /uk/ - zh: /zh/ +- async.md markdown_extensions: - toc: permalink: true @@ -97,6 +102,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +114,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/sq/docs/index.md b/docs/sq/docs/index.md index 95fb7ae212518..29f92e020a7a8 100644 --- a/docs/sq/docs/index.md +++ b/docs/sq/docs/index.md @@ -149,7 +149,7 @@ $ pip install uvicorn[standard] * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -162,7 +162,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -185,7 +185,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -264,7 +264,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -275,7 +275,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -284,7 +284,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/sq/mkdocs.yml b/docs/sq/mkdocs.yml index d9c3dad4cce33..8914395fef8af 100644 --- a/docs/sq/mkdocs.yml +++ b/docs/sq/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -97,6 +101,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +113,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md index c06c27c16fe3e..0bcda4e9c7f85 100644 --- a/docs/tr/docs/features.md +++ b/docs/tr/docs/features.md @@ -6,7 +6,7 @@ ### Açık standartları temel alır -* API oluşturma işlemlerinde OpenAPI buna path operasyonları parametreleri, body talebi, güvenlik gibi şeyler dahil olmak üzere deklare bunların deklare edilmesi. +* API oluşturma işlemlerinde OpenAPI buna path operasyonları parametreleri, body talebi, güvenlik gibi şeyler dahil olmak üzere deklare bunların deklare edilmesi. * Otomatik olarak data modelinin JSON Schema ile beraber dokümante edilmesi (OpenAPI'n kendisi zaten JSON Schema'ya dayanıyor). * Titiz bir çalışmanın sonucunda yukarıdaki standartlara uygun bir framework oluşturduk. Standartları pastanın üzerine sonradan eklenmiş bir çilek olarak görmedik. * Ayrıca bu bir çok dilde kullanılabilecek **client code generator** kullanımına da izin veriyor. @@ -74,7 +74,7 @@ my_second_user: User = User(**second_user_data) ### Editor desteği -Bütün framework kullanılması kolay ve sezgileri güçlü olması için tasarlandı, verilen bütün kararlar geliştiricilere en iyi geliştirme deneyimini yaşatmak üzere, bir çok editör üzerinde test edildi. +Bütün framework kullanılması kolay ve sezgileri güçlü olması için tasarlandı, verilen bütün kararlar geliştiricilere en iyi geliştirme deneyimini yaşatmak üzere, bir çok editör üzerinde test edildi. Son yapılan Python geliştiricileri anketinde, açık ara en çok kullanılan özellik "oto-tamamlama" idi.. @@ -135,7 +135,7 @@ Bütün güvenlik şemaları OpenAPI'da tanımlanmış durumda, kapsadıkları: Bütün güvenlik özellikleri Starlette'den geliyor (**session cookies'de** dahil olmak üzere). -Bütün hepsi tekrardan kullanılabilir aletler ve bileşenler olarak, kolayca sistemlerinize, data depolarınıza, ilişkisel ve NoSQL databaselerinize entegre edebileceğiniz şekilde yapıldı. +Bütün hepsi tekrardan kullanılabilir aletler ve bileşenler olarak, kolayca sistemlerinize, data depolarınıza, ilişkisel ve NoSQL databaselerinize entegre edebileceğiniz şekilde yapıldı. ### Dependency injection @@ -198,7 +198,7 @@ Aynı şekilde, databaseden gelen objeyi de **direkt olarak isteğe** de tamamiy * Kullandığın geliştirme araçları ile iyi çalışır **IDE/linter/brain**: * Pydantic'in veri yapıları aslında sadece senin tanımladığın classlar; Bu yüzden doğrulanmış dataların ile otomatik tamamlama, linting ve mypy'ı kullanarak sorunsuz bir şekilde çalışabilirsin * **Hızlı**: - * Benchmarklarda, Pydantic'in diğer bütün test edilmiş bütün kütüphanelerden daha hızlı. + * Benchmarklarda, Pydantic'in diğer bütün test edilmiş bütün kütüphanelerden daha hızlı. * **En kompleks** yapıları bile doğrula: * Hiyerarşik Pydantic modellerinin kullanımı ile beraber, Python `typing`’s `List` and `Dict`, vs gibi şeyleri doğrula. * Doğrulayıcılar en kompleks data şemalarının bile temiz ve kolay bir şekilde tanımlanmasına izin veriyor, ve hepsi JSON şeması olarak dokümante ediliyor @@ -206,4 +206,3 @@ Aynı şekilde, databaseden gelen objeyi de **direkt olarak isteğe** de tamamiy * **Genişletilebilir**: * Pydantic özelleştirilmiş data tiplerinin tanımlanmasının yapılmasına izin veriyor ayrıca validator decoratorü ile senin doğrulamaları genişletip, kendi doğrulayıcılarını yazmana izin veriyor. * 100% test kapsayıcılığı. - diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index 88660f7ebc50e..5693029b528a1 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -28,7 +28,7 @@ --- -FastAPI, Python 3.6+'nın standart type hintlerine dayanan modern ve hızlı (yüksek performanslı) API'lar oluşturmak için kullanılabilecek web framework'ü. +FastAPI, Python 3.6+'nın standart type hintlerine dayanan modern ve hızlı (yüksek performanslı) API'lar oluşturmak için kullanılabilecek web framework'ü. Ana özellikleri: @@ -157,7 +157,7 @@ $ pip install uvicorn[standard] * `main.py` adında bir dosya oluştur : ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -170,7 +170,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -180,7 +180,7 @@ def read_item(item_id: int, q: Optional[str] = None): Eğer kodunda `async` / `await` var ise, `async def` kullan: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -193,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -272,7 +272,7 @@ Senin için alternatif olarak (requests - Eğer `TestClient` kullanmak istiyorsan gerekli. -* aiofiles - `FileResponse` ya da `StaticFiles` kullanmak istiyorsan gerekli. * jinja2 - Eğer kendine ait template konfigürasyonu oluşturmak istiyorsan gerekli * python-multipart - Form kullanmak istiyorsan gerekli ("dönüşümü"). * itsdangerous - `SessionMiddleware` desteği için gerekli. diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md index 7e46bd0314dee..3b9ab905079e5 100644 --- a/docs/tr/docs/python-types.md +++ b/docs/tr/docs/python-types.md @@ -29,7 +29,7 @@ Programın çıktısı: John Doe ``` -Fonksiyon sırayla şunları yapar: +Fonksiyon sırayla şunları yapar: * `first_name` ve `last_name` değerlerini alır. * `title()` ile değişkenlerin ilk karakterlerini büyütür. diff --git a/docs/tr/mkdocs.yml b/docs/tr/mkdocs.yml index f6ed7f5b9c336..74186033c6d8a 100644 --- a/docs/tr/mkdocs.yml +++ b/docs/tr/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -100,6 +104,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -110,6 +116,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 95fb7ae212518..29f92e020a7a8 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -149,7 +149,7 @@ $ pip install uvicorn[standard] * Create a file `main.py` with: ```Python -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -162,7 +162,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None): If your code uses `async` / `await`, use `async def`: ```Python hl_lines="9 14" -from typing import Optional +from typing import Union from fastapi import FastAPI @@ -185,7 +185,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Optional[str] = None): +async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` @@ -264,7 +264,7 @@ 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 typing import Union from fastapi import FastAPI from pydantic import BaseModel @@ -275,7 +275,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Optional[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -284,7 +284,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @@ -321,7 +321,7 @@ And now, go to requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/uk/mkdocs.yml b/docs/uk/mkdocs.yml index d0de8cc0ef621..ddf299d8b64f4 100644 --- a/docs/uk/mkdocs.yml +++ b/docs/uk/mkdocs.yml @@ -5,13 +5,15 @@ theme: name: material custom_dir: overrides palette: - - scheme: default + - media: "(prefers-color-scheme: light)" + scheme: default primary: teal accent: amber toggle: icon: material/lightbulb name: Switch to light mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate primary: teal accent: amber toggle: @@ -40,11 +42,13 @@ nav: - az: /az/ - de: /de/ - es: /es/ + - fa: /fa/ - fr: /fr/ - id: /id/ - it: /it/ - ja: /ja/ - ko: /ko/ + - nl: /nl/ - pl: /pl/ - pt: /pt/ - ru: /ru/ @@ -97,6 +101,8 @@ extra: name: de - link: /es/ name: es - español + - link: /fa/ + name: fa - link: /fr/ name: fr - français - link: /id/ @@ -107,6 +113,8 @@ extra: name: ja - 日本語 - link: /ko/ name: ko - 한국어 + - link: /nl/ + name: nl - link: /pl/ name: pl - link: /pt/ diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index 1cb724f1db142..54ec9775b6204 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -14,7 +14,7 @@ 要实现它,导入 `JSONResponse`,然后在其中直接返回你的内容,并将 `status_code` 设置为为你要的值。 -```Python hl_lines="2 19" +```Python hl_lines="4 25" {!../../../docs_src/additional_status_codes/tutorial001.py!} ``` @@ -22,7 +22,7 @@ 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。 FastAPI 不会用模型等对该响应进行序列化。 - + 确保其中有你想要的数据,且返回的值为合法的 JSON(如果你使用 `JSONResponse` 的话)。 !!! note "技术细节" diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md index 5f1a74e9e6bba..155ce28828b0b 100644 --- a/docs/zh/docs/advanced/custom-response.md +++ b/docs/zh/docs/advanced/custom-response.md @@ -60,7 +60,7 @@ 正如你在 [直接返回响应](response-directly.md){.internal-link target=_blank} 中了解到的,你也可以通过直接返回响应在 *路径操作* 中直接重载响应。 和上面一样的例子,返回一个 `HTMLResponse` 看起来可能是这样: - + ```Python hl_lines="2 7 19" {!../../../docs_src/custom_response/tutorial003.py!} ``` diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md index 05926a9c8310c..797a878eb923b 100644 --- a/docs/zh/docs/advanced/response-directly.md +++ b/docs/zh/docs/advanced/response-directly.md @@ -10,7 +10,7 @@ 直接返回响应可能会有用处,比如返回自定义的响应头和 cookies。 -## 返回 `Response` +## 返回 `Response` 事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。 @@ -62,4 +62,3 @@ 但是你仍可以参考 [OpenApI 中的额外响应](additional-responses.md){.internal-link target=_blank} 给响应编写文档。 在后续的章节中你可以了解到如何使用/声明这些自定义的 `Response` 的同时还保留自动化的数据转换和文档等。 - diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md index c133d51b7d90e..8991c72cd9b4b 100644 --- a/docs/zh/docs/benchmarks.md +++ b/docs/zh/docs/benchmarks.md @@ -22,7 +22,7 @@ * 具有最佳性能,因为除了服务器本身外,它没有太多额外的代码。 * 您不会直接在 Uvicorn 中编写应用程序。这意味着您的代码至少必须包含 Starlette(或 **FastAPI**)提供的代码。如果您这样做了(即直接在 Uvicorn 中编写应用程序),最终的应用程序会和使用了框架并且最小化了应用代码和 bug 的情况具有相同的性能损耗。 * 如果要对比与 Uvicorn 对标的服务器,请将其与 Daphne,Hypercorn,uWSGI等应用服务器进行比较。 -* **Starlette**: +* **Starlette**: * 在 Uvicorn 后使用 Starlette,性能会略有下降。实际上,Starlette 使用 Uvicorn运行。因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。 * 但它为您提供了构建简单的网络程序的工具,并具有基于路径的路由等功能。 * 如果想对比与 Starlette 对标的开发框架,请将其与 Sanic,Flask,Django 等网络框架(或微框架)进行比较。 diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md index 402668c47e4b6..95500d12be3a6 100644 --- a/docs/zh/docs/contributing.md +++ b/docs/zh/docs/contributing.md @@ -497,4 +497,4 @@ $ bash scripts/test-cov-html.sh -该命令生成了一个 `./htmlcov/` 目录,如果你在浏览器中打开 `./htmlcov/index.html` 文件,你可以交互式地浏览被测试所覆盖的代码区块,并注意是否缺少了任何区块。 +该命令生成了一个 `./htmlcov/` 目录,如果你在浏览器中打开 `./htmlcov/index.html` 文件,你可以交互式地浏览被测试所覆盖的代码区块,并注意是否缺少了任何区块。 diff --git a/docs/zh/docs/fastapi-people.md b/docs/zh/docs/fastapi-people.md index 75651592db2b2..5d7b0923f33c4 100644 --- a/docs/zh/docs/fastapi-people.md +++ b/docs/zh/docs/fastapi-people.md @@ -114,6 +114,8 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋 他们主要通过GitHub Sponsors支持我在 **FastAPI** (和其他项目)的工作。 +{% if sponsors %} + {% if sponsors.gold %} ### 金牌赞助商 @@ -141,6 +143,8 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋 {% endfor %} {% endif %} +{% endif %} + ### 个人赞助 {% if github_sponsors %} diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 4752947a3990a..fefe4b1973995 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -193,9 +193,9 @@ FastAPI 有一个使用非常简单,但是非常强大的 ModelField: - default_value = Required + default_value: Any = Undefined had_schema = False if not param.default == param.empty and ignore_default is False: default_value = param.default @@ -369,8 +370,13 @@ def get_param_field( if force_type: field_info.in_ = force_type # type: ignore else: - field_info = default_field_info(default_value) - required = default_value == Required + field_info = default_field_info(default=default_value) + required = True + if default_value is Required or ignore_default: + required = True + default_value = None + elif default_value is not Undefined: + required = False annotation: Any = Any if not param.annotation == param.empty: annotation = param.annotation @@ -382,12 +388,11 @@ def get_param_field( field = create_response_field( name=param.name, type_=annotation, - default=None if required else default_value, + default=default_value, alias=alias, required=required, field_info=field_info, ) - field.required = required if not had_schema and not is_scalar_field(field=field): field.field_info = params.Body(field_info.default) if not had_schema and lenient_issubclass(field.type_, UploadFile): @@ -462,13 +467,10 @@ async def solve_dependencies( ]: values: Dict[str, Any] = {} errors: List[ErrorWrapper] = [] - response = response or Response( - content=None, - status_code=None, # type: ignore - headers=None, # type: ignore # in Starlette - media_type=None, # type: ignore # in Starlette - background=None, # type: ignore # in Starlette - ) + if response is None: + response = Response() + del response.headers["content-length"] + response.status_code = None # type: ignore dependency_cache = dependency_cache or {} sub_dependant: Dependant for sub_dependant in dependant.dependencies: diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index f4a837bb4e2bf..0f50acc6c58d0 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -12,8 +12,7 @@ def __init__( detail: Any = None, headers: Optional[Dict[str, Any]] = None, ) -> None: - super().__init__(status_code=status_code, detail=detail) - self.headers = headers + super().__init__(status_code=status_code, detail=detail, headers=headers) RequestErrorModel: Type[BaseModel] = create_model("Request") diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index 1be90d188fade..d6af17a850e78 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -17,8 +17,8 @@ def get_swagger_ui_html( *, openapi_url: str, title: str, - swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js", - swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css", + swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js", + swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css", swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", oauth2_redirect_url: Optional[str] = None, init_oauth: Optional[Dict[str, Any]] = None, diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index 9c6598d2d1a7b..35aa1672b3cc0 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -73,7 +73,7 @@ class Config: class Reference(BaseModel): - ref: str = Field(..., alias="$ref") + ref: str = Field(alias="$ref") class Discriminator(BaseModel): @@ -101,28 +101,28 @@ class Config: class Schema(BaseModel): - ref: Optional[str] = Field(None, alias="$ref") + ref: Optional[str] = Field(default=None, alias="$ref") title: Optional[str] = None multipleOf: Optional[float] = None maximum: Optional[float] = None exclusiveMaximum: Optional[float] = None minimum: Optional[float] = None exclusiveMinimum: Optional[float] = None - maxLength: Optional[int] = Field(None, gte=0) - minLength: Optional[int] = Field(None, gte=0) + maxLength: Optional[int] = Field(default=None, gte=0) + minLength: Optional[int] = Field(default=None, gte=0) pattern: Optional[str] = None - maxItems: Optional[int] = Field(None, gte=0) - minItems: Optional[int] = Field(None, gte=0) + maxItems: Optional[int] = Field(default=None, gte=0) + minItems: Optional[int] = Field(default=None, gte=0) uniqueItems: Optional[bool] = None - maxProperties: Optional[int] = Field(None, gte=0) - minProperties: Optional[int] = Field(None, gte=0) + maxProperties: Optional[int] = Field(default=None, gte=0) + minProperties: Optional[int] = Field(default=None, gte=0) required: Optional[List[str]] = None enum: Optional[List[Any]] = None type: Optional[str] = None allOf: Optional[List["Schema"]] = None oneOf: Optional[List["Schema"]] = None anyOf: Optional[List["Schema"]] = None - not_: Optional["Schema"] = Field(None, alias="not") + not_: Optional["Schema"] = Field(default=None, alias="not") items: Optional[Union["Schema", List["Schema"]]] = None properties: Optional[Dict[str, "Schema"]] = None additionalProperties: Optional[Union["Schema", Reference, bool]] = None @@ -171,7 +171,7 @@ class Config: class MediaType(BaseModel): - schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema") + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") example: Optional[Any] = None examples: Optional[Dict[str, Union[Example, Reference]]] = None encoding: Optional[Dict[str, Encoding]] = None @@ -188,7 +188,7 @@ class ParameterBase(BaseModel): style: Optional[str] = None explode: Optional[bool] = None allowReserved: Optional[bool] = None - schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema") + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") example: Optional[Any] = None examples: Optional[Dict[str, Union[Example, Reference]]] = None # Serialization rules for more complex scenarios @@ -200,7 +200,7 @@ class Config: class Parameter(ParameterBase): name: str - in_: ParameterInType = Field(..., alias="in") + in_: ParameterInType = Field(alias="in") class Header(ParameterBase): @@ -258,7 +258,7 @@ class Config: class PathItem(BaseModel): - ref: Optional[str] = Field(None, alias="$ref") + ref: Optional[str] = Field(default=None, alias="$ref") summary: Optional[str] = None description: Optional[str] = None get: Optional[Operation] = None @@ -284,7 +284,7 @@ class SecuritySchemeType(Enum): class SecurityBase(BaseModel): - type_: SecuritySchemeType = Field(..., alias="type") + type_: SecuritySchemeType = Field(alias="type") description: Optional[str] = None class Config: @@ -299,7 +299,7 @@ class APIKeyIn(Enum): class APIKey(SecurityBase): type_ = Field(SecuritySchemeType.apiKey, alias="type") - in_: APIKeyIn = Field(..., alias="in") + in_: APIKeyIn = Field(alias="in") name: str diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 58a748d04919f..4eb727bd4ffc2 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -38,7 +38,11 @@ "title": "ValidationError", "type": "object", "properties": { - "loc": {"title": "Location", "type": "array", "items": {"type": "string"}}, + "loc": { + "title": "Location", + "type": "array", + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, }, diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index a553a1461f8d7..1932ef0657d66 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -5,7 +5,7 @@ def Path( # noqa: N802 - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -44,7 +44,7 @@ def Path( # noqa: N802 def Query( # noqa: N802 - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -63,7 +63,7 @@ def Query( # noqa: N802 **extra: Any, ) -> Any: return params.Query( - default, + default=default, alias=alias, title=title, description=description, @@ -83,7 +83,7 @@ def Query( # noqa: N802 def Header( # noqa: N802 - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, convert_underscores: bool = True, @@ -103,7 +103,7 @@ def Header( # noqa: N802 **extra: Any, ) -> Any: return params.Header( - default, + default=default, alias=alias, convert_underscores=convert_underscores, title=title, @@ -124,7 +124,7 @@ def Header( # noqa: N802 def Cookie( # noqa: N802 - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -143,7 +143,7 @@ def Cookie( # noqa: N802 **extra: Any, ) -> Any: return params.Cookie( - default, + default=default, alias=alias, title=title, description=description, @@ -163,7 +163,7 @@ def Cookie( # noqa: N802 def Body( # noqa: N802 - default: Any, + default: Any = Undefined, *, embed: bool = False, media_type: str = "application/json", @@ -182,7 +182,7 @@ def Body( # noqa: N802 **extra: Any, ) -> Any: return params.Body( - default, + default=default, embed=embed, media_type=media_type, alias=alias, @@ -202,7 +202,7 @@ def Body( # noqa: N802 def Form( # noqa: N802 - default: Any, + default: Any = Undefined, *, media_type: str = "application/x-www-form-urlencoded", alias: Optional[str] = None, @@ -220,7 +220,7 @@ def Form( # noqa: N802 **extra: Any, ) -> Any: return params.Form( - default, + default=default, media_type=media_type, alias=alias, title=title, @@ -239,7 +239,7 @@ def Form( # noqa: N802 def File( # noqa: N802 - default: Any, + default: Any = Undefined, *, media_type: str = "multipart/form-data", alias: Optional[str] = None, @@ -257,7 +257,7 @@ def File( # noqa: N802 **extra: Any, ) -> Any: return params.File( - default, + default=default, media_type=media_type, alias=alias, title=title, diff --git a/fastapi/params.py b/fastapi/params.py index 042bbd42ff8b0..5395b98a39ab1 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -16,7 +16,7 @@ class Param(FieldInfo): def __init__( self, - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -39,7 +39,7 @@ def __init__( self.examples = examples self.include_in_schema = include_in_schema super().__init__( - default, + default=default, alias=alias, title=title, description=description, @@ -62,7 +62,7 @@ class Path(Param): def __init__( self, - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -82,7 +82,7 @@ def __init__( ): self.in_ = self.in_ super().__init__( - ..., + default=..., alias=alias, title=title, description=description, @@ -106,7 +106,7 @@ class Query(Param): def __init__( self, - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -125,7 +125,7 @@ def __init__( **extra: Any, ): super().__init__( - default, + default=default, alias=alias, title=title, description=description, @@ -149,7 +149,7 @@ class Header(Param): def __init__( self, - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, convert_underscores: bool = True, @@ -170,7 +170,7 @@ def __init__( ): self.convert_underscores = convert_underscores super().__init__( - default, + default=default, alias=alias, title=title, description=description, @@ -194,7 +194,7 @@ class Cookie(Param): def __init__( self, - default: Any, + default: Any = Undefined, *, alias: Optional[str] = None, title: Optional[str] = None, @@ -213,7 +213,7 @@ def __init__( **extra: Any, ): super().__init__( - default, + default=default, alias=alias, title=title, description=description, @@ -235,7 +235,7 @@ def __init__( class Body(FieldInfo): def __init__( self, - default: Any, + default: Any = Undefined, *, embed: bool = False, media_type: str = "application/json", @@ -258,7 +258,7 @@ def __init__( self.example = example self.examples = examples super().__init__( - default, + default=default, alias=alias, title=title, description=description, @@ -297,7 +297,7 @@ def __init__( **extra: Any, ): super().__init__( - default, + default=default, embed=True, media_type=media_type, alias=alias, @@ -337,7 +337,7 @@ def __init__( **extra: Any, ): super().__init__( - default, + default=default, media_type=media_type, alias=alias, title=title, diff --git a/fastapi/routing.py b/fastapi/routing.py index 0f416ac42e1df..a6542c15a035e 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -127,7 +127,7 @@ async def serialize_response( if is_coroutine: value, errors_ = field.validate(response_content, {}, loc=("response",)) else: - value, errors_ = await run_in_threadpool( + value, errors_ = await run_in_threadpool( # type: ignore[misc] field.validate, response_content, {}, loc=("response",) ) if isinstance(errors_, ErrorWrapper): @@ -364,7 +364,7 @@ def __init__( self.path_regex, self.path_format, self.param_convertors = compile_path(path) if methods is None: methods = ["GET"] - self.methods: Set[str] = set([method.upper() for method in methods]) + self.methods: Set[str] = {method.upper() for method in methods} if isinstance(generate_unique_id_function, DefaultPlaceholder): current_generate_unique_id: Callable[ ["APIRoute"], str @@ -478,11 +478,11 @@ def __init__( ), ) -> None: super().__init__( - routes=routes, # type: ignore # in Starlette + routes=routes, redirect_slashes=redirect_slashes, - default=default, # type: ignore # in Starlette - on_startup=on_startup, # type: ignore # in Starlette - on_shutdown=on_shutdown, # type: ignore # in Starlette + default=default, + on_startup=on_startup, + on_shutdown=on_shutdown, ) if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" @@ -649,7 +649,7 @@ def add_api_websocket_route( self, path: str, endpoint: Callable[..., Any], name: Optional[str] = None ) -> None: route = APIWebSocketRoute( - path, + self.prefix + path, endpoint=endpoint, name=name, dependency_overrides_provider=self.dependency_overrides_provider, @@ -757,7 +757,7 @@ def include_router( generate_unique_id_function=current_generate_unique_id, ) elif isinstance(route, routing.Route): - methods = list(route.methods or []) # type: ignore # in Starlette + methods = list(route.methods or []) self.add_route( prefix + route.path, route.endpoint, diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index bdc6e2ea9beee..888208c1501fc 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -45,12 +45,12 @@ def login(form_data: OAuth2PasswordRequestForm = Depends()): def __init__( self, - grant_type: str = Form(None, regex="password"), - username: str = Form(...), - password: str = Form(...), - scope: str = Form(""), - client_id: Optional[str] = Form(None), - client_secret: Optional[str] = Form(None), + grant_type: str = Form(default=None, regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), ): self.grant_type = grant_type self.username = username @@ -95,12 +95,12 @@ def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): def __init__( self, - grant_type: str = Form(..., regex="password"), - username: str = Form(...), - password: str = Form(...), - scope: str = Form(""), - client_id: Optional[str] = Form(None), - client_secret: Optional[str] = Form(None), + grant_type: str = Form(regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), ): super().__init__( grant_type=grant_type, diff --git a/fastapi/utils.py b/fastapi/utils.py index b9301499a27a7..a7e135bcab598 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -52,7 +52,7 @@ def create_response_field( Create a new response field. Raises if type_ is invalid. """ class_validators = class_validators or {} - field_info = field_info or FieldInfo(None) + field_info = field_info or FieldInfo() response_field = functools.partial( ModelField, @@ -147,15 +147,15 @@ def generate_unique_id(route: "APIRoute") -> str: def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None: - for key in update_dict: + for key, value in update_dict.items(): if ( key in main_dict and isinstance(main_dict[key], dict) - and isinstance(update_dict[key], dict) + and isinstance(value, dict) ): - deep_dict_update(main_dict[key], update_dict[key]) + deep_dict_update(main_dict[key], value) else: - main_dict[key] = update_dict[key] + main_dict[key] = value def get_value_or_default( diff --git a/pending_tests/main.py b/pending_tests/main.py deleted file mode 100644 index 5e919f1bcf3dc..0000000000000 --- a/pending_tests/main.py +++ /dev/null @@ -1,118 +0,0 @@ -from fastapi import ( - Body, - Cookie, - Depends, - FastAPI, - File, - Form, - Header, - Path, - Query, - Security, -) -from fastapi.security import ( - HTTPBasic, - OAuth2, - OAuth2PasswordBearer, - OAuth2PasswordRequestForm, -) -from pydantic import BaseModel -from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse -from starlette.status import HTTP_202_ACCEPTED - -app = FastAPI() - - -@app.get("/security") -def get_security(sec=Security(HTTPBasic())): - return sec - - -reusable_oauth2 = OAuth2( - flows={ - "password": { - "tokenUrl": "token", - "scopes": {"read:user": "Read a User", "write:user": "Create a user"}, - } - } -) - - -@app.get("/security/oauth2") -def get_security_oauth2(sec=Security(reusable_oauth2, scopes=["read:user"])): - return sec - - -@app.post("/token") -def post_token(request_data: OAuth2PasswordRequestForm = Form(...)): - data = request_data.parse() - access_token = data.username + ":" + data.password - return {"access_token": access_token} - - -class Item(BaseModel): - name: str - price: float - is_offer: bool - - -class FakeDB: - def __init__(self): - self.data = { - "johndoe": { - "username": "johndoe", - "password": "shouldbehashed", - "first_name": "John", - "last_name": "Doe", - } - } - - -class DBConnectionManager: - def __init__(self): - self.db = FakeDB() - - def __call__(self): - return self.db - - -connection_manager = DBConnectionManager() - - -class TokenUserData(BaseModel): - username: str - password: str - - -class UserInDB(BaseModel): - username: str - password: str - first_name: str - last_name: str - - -def require_token( - token: str = Security(reusable_oauth2, scopes=["read:user", "write:user"]) -): - raw_token = token.replace("Bearer ", "") - # Never do this plaintext password usage in production - username, password = raw_token.split(":") - return TokenUserData(username=username, password=password) - - -def require_user( - db: FakeDB = Depends(connection_manager), - user_data: TokenUserData = Depends(require_token), -): - return db.data[user_data.username] - - -class UserOut(BaseModel): - username: str - first_name: str - last_name: str - - -@app.get("/dependency", response_model=UserOut) -def get_dependency(user: UserInDB = Depends(require_user)): - return user diff --git a/pyproject.toml b/pyproject.toml index 77c01322fe6b0..5ffdf93ad371c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] requires = [ - "starlette ==0.17.1", + "starlette==0.19.1", "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" @@ -50,7 +50,7 @@ test = [ "pytest-cov >=2.12.0,<4.0.0", "mypy ==0.910", "flake8 >=3.8.3,<4.0.0", - "black ==21.9b0", + "black == 22.3.0", "isort >=5.0.6,<6.0.0", "requests >=2.24.0,<3.0.0", "httpx >=0.14.0,<0.19.0", @@ -59,41 +59,44 @@ test = [ "peewee >=3.13.3,<4.0.0", "databases[sqlite] >=0.3.2,<0.6.0", "orjson >=3.2.1,<4.0.0", - "ujson >=4.0.1,<5.0.0", + "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0", "python-multipart >=0.0.5,<0.0.6", "flask >=1.1.2,<3.0.0", "anyio[trio] >=3.2.1,<4.0.0", # types - "types-ujson ==0.1.1", - "types-orjson ==3.6.0", - "types-dataclasses ==0.1.7; python_version<'3.7'", + "types-ujson ==4.2.1", + "types-orjson ==3.6.2", + "types-dataclasses ==0.6.5; python_version<'3.7'", ] doc = [ "mkdocs >=1.1.2,<2.0.0", "mkdocs-material >=8.1.4,<9.0.0", "mdx-include >=1.4.1,<2.0.0", "mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0", - "typer-cli >=0.0.12,<0.0.13", - "pyyaml >=5.3.1,<6.0.0" + # TODO: upgrade and enable typer-cli once it supports Click 8.x.x + # "typer-cli >=0.0.12,<0.0.13", + "typer >=0.4.1,<0.5.0", + "pyyaml >=5.3.1,<7.0.0", ] dev = [ "python-jose[cryptography] >=3.3.0,<4.0.0", "passlib[bcrypt] >=1.7.2,<2.0.0", "autoflake >=1.4.0,<2.0.0", "flake8 >=3.8.3,<4.0.0", - "uvicorn[standard] >=0.12.0,<0.16.0", + "uvicorn[standard] >=0.12.0,<0.18.0", + "pre-commit >=2.17.0,<3.0.0", ] all = [ "requests >=2.24.0,<3.0.0", "jinja2 >=2.11.2,<4.0.0", "python-multipart >=0.0.5,<0.0.6", "itsdangerous >=1.1.0,<3.0.0", - "pyyaml >=5.3.1,<6.0.0", - "ujson >=4.0.1,<5.0.0", + "pyyaml >=5.3.1,<7.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", "email_validator >=1.1.1,<2.0.0", - "uvicorn[standard] >=0.12.0,<0.16.0", + "uvicorn[standard] >=0.12.0,<0.18.0", ] [tool.isort] @@ -138,4 +141,7 @@ filterwarnings = [ "error", # TODO: needed by asyncio in Python 3.9.7 https://bugs.python.org/issue45097, try to remove on 3.9.8 'ignore:The loop argument is deprecated since Python 3\.8, and scheduled for removal in Python 3\.10:DeprecationWarning:asyncio', + 'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', + # TODO: remove after dropping support for Python 3.6 + 'ignore:Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.:UserWarning:jose', ] diff --git a/tests/main.py b/tests/main.py index d5603d0e617e1..f70496db8e111 100644 --- a/tests/main.py +++ b/tests/main.py @@ -49,97 +49,97 @@ def get_bool_id(item_id: bool): @app.get("/path/param/{item_id}") -def get_path_param_id(item_id: Optional[str] = Path(None)): +def get_path_param_id(item_id: str = Path()): return item_id @app.get("/path/param-required/{item_id}") -def get_path_param_required_id(item_id: str = Path(...)): +def get_path_param_required_id(item_id: str = Path()): return item_id @app.get("/path/param-minlength/{item_id}") -def get_path_param_min_length(item_id: str = Path(..., min_length=3)): +def get_path_param_min_length(item_id: str = Path(min_length=3)): return item_id @app.get("/path/param-maxlength/{item_id}") -def get_path_param_max_length(item_id: str = Path(..., max_length=3)): +def get_path_param_max_length(item_id: str = Path(max_length=3)): return item_id @app.get("/path/param-min_maxlength/{item_id}") -def get_path_param_min_max_length(item_id: str = Path(..., max_length=3, min_length=2)): +def get_path_param_min_max_length(item_id: str = Path(max_length=3, min_length=2)): return item_id @app.get("/path/param-gt/{item_id}") -def get_path_param_gt(item_id: float = Path(..., gt=3)): +def get_path_param_gt(item_id: float = Path(gt=3)): return item_id @app.get("/path/param-gt0/{item_id}") -def get_path_param_gt0(item_id: float = Path(..., gt=0)): +def get_path_param_gt0(item_id: float = Path(gt=0)): return item_id @app.get("/path/param-ge/{item_id}") -def get_path_param_ge(item_id: float = Path(..., ge=3)): +def get_path_param_ge(item_id: float = Path(ge=3)): return item_id @app.get("/path/param-lt/{item_id}") -def get_path_param_lt(item_id: float = Path(..., lt=3)): +def get_path_param_lt(item_id: float = Path(lt=3)): return item_id @app.get("/path/param-lt0/{item_id}") -def get_path_param_lt0(item_id: float = Path(..., lt=0)): +def get_path_param_lt0(item_id: float = Path(lt=0)): return item_id @app.get("/path/param-le/{item_id}") -def get_path_param_le(item_id: float = Path(..., le=3)): +def get_path_param_le(item_id: float = Path(le=3)): return item_id @app.get("/path/param-lt-gt/{item_id}") -def get_path_param_lt_gt(item_id: float = Path(..., lt=3, gt=1)): +def get_path_param_lt_gt(item_id: float = Path(lt=3, gt=1)): return item_id @app.get("/path/param-le-ge/{item_id}") -def get_path_param_le_ge(item_id: float = Path(..., le=3, ge=1)): +def get_path_param_le_ge(item_id: float = Path(le=3, ge=1)): return item_id @app.get("/path/param-lt-int/{item_id}") -def get_path_param_lt_int(item_id: int = Path(..., lt=3)): +def get_path_param_lt_int(item_id: int = Path(lt=3)): return item_id @app.get("/path/param-gt-int/{item_id}") -def get_path_param_gt_int(item_id: int = Path(..., gt=3)): +def get_path_param_gt_int(item_id: int = Path(gt=3)): return item_id @app.get("/path/param-le-int/{item_id}") -def get_path_param_le_int(item_id: int = Path(..., le=3)): +def get_path_param_le_int(item_id: int = Path(le=3)): return item_id @app.get("/path/param-ge-int/{item_id}") -def get_path_param_ge_int(item_id: int = Path(..., ge=3)): +def get_path_param_ge_int(item_id: int = Path(ge=3)): return item_id @app.get("/path/param-lt-gt-int/{item_id}") -def get_path_param_lt_gt_int(item_id: int = Path(..., lt=3, gt=1)): +def get_path_param_lt_gt_int(item_id: int = Path(lt=3, gt=1)): return item_id @app.get("/path/param-le-ge-int/{item_id}") -def get_path_param_le_ge_int(item_id: int = Path(..., le=3, ge=1)): +def get_path_param_le_ge_int(item_id: int = Path(le=3, ge=1)): return item_id @@ -173,19 +173,19 @@ def get_query_type_int_default(query: int = 10): @app.get("/query/param") -def get_query_param(query=Query(None)): +def get_query_param(query=Query(default=None)): if query is None: return "foo bar" return f"foo bar {query}" @app.get("/query/param-required") -def get_query_param_required(query=Query(...)): +def get_query_param_required(query=Query()): return f"foo bar {query}" @app.get("/query/param-required/int") -def get_query_param_required_type(query: int = Query(...)): +def get_query_param_required_type(query: int = Query()): return f"foo bar {query}" diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py index 9e15e6ed06042..016c1f734ed11 100644 --- a/tests/test_additional_properties.py +++ b/tests/test_additional_properties.py @@ -76,7 +76,7 @@ def foo(items: Items): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_additional_responses_custom_model_in_callback.py b/tests/test_additional_responses_custom_model_in_callback.py index 36dd0d6dbe39e..a1072cc5697ed 100644 --- a/tests/test_additional_responses_custom_model_in_callback.py +++ b/tests/test_additional_responses_custom_model_in_callback.py @@ -119,7 +119,7 @@ def main_route(callback_url: HttpUrl): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_additional_responses_default_validationerror.py b/tests/test_additional_responses_default_validationerror.py index 6ea372ce8d696..cabb536d714bc 100644 --- a/tests/test_additional_responses_default_validationerror.py +++ b/tests/test_additional_responses_default_validationerror.py @@ -54,7 +54,7 @@ async def a(id): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_application.py b/tests/test_application.py index 5ba7373075c06..d9194c15c7313 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1101,7 +1101,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py index 5e15812b67042..33899134e924b 100644 --- a/tests/test_dependency_duplicates.py +++ b/tests/test_dependency_duplicates.py @@ -177,7 +177,7 @@ async def no_duplicates_sub( "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_dependency_normal_exceptions.py b/tests/test_dependency_normal_exceptions.py index 49a19f460cc04..23c366d5d7a6f 100644 --- a/tests/test_dependency_normal_exceptions.py +++ b/tests/test_dependency_normal_exceptions.py @@ -26,14 +26,14 @@ async def get_database(): @app.put("/invalid-user/{user_id}") def put_invalid_user( - user_id: str, name: str = Body(...), db: dict = Depends(get_database) + user_id: str, name: str = Body(), db: dict = Depends(get_database) ): db[user_id] = name raise HTTPException(status_code=400, detail="Invalid user") @app.put("/user/{user_id}") -def put_user(user_id: str, name: str = Body(...), db: dict = Depends(get_database)): +def put_user(user_id: str, name: str = Body(), db: dict = Depends(get_database)): db[user_id] = name return {"message": "OK"} diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index 6aba3e8dda535..491ba61c68040 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -32,12 +32,12 @@ def delete_item(item_id: str, item: Item): @app.head("/items/{item_id}") def head_item(item_id: str): - return JSONResponse(headers={"x-fastapi-item-id": item_id}) + return JSONResponse(None, headers={"x-fastapi-item-id": item_id}) @app.options("/items/{item_id}") def options_item(item_id: str): - return JSONResponse(headers={"x-fastapi-item-id": item_id}) + return JSONResponse(None, headers={"x-fastapi-item-id": item_id}) @app.patch("/items/{item_id}") @@ -47,7 +47,7 @@ def patch_item(item_id: str, item: Item): @app.trace("/items/{item_id}") def trace_item(item_id: str): - return JSONResponse(media_type="message/http") + return JSONResponse(None, media_type="message/http") client = TestClient(app) @@ -292,7 +292,7 @@ def trace_item(item_id: str): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_filter_pydantic_sub_model.py b/tests/test_filter_pydantic_sub_model.py index 90a372976313e..8814356a10e79 100644 --- a/tests/test_filter_pydantic_sub_model.py +++ b/tests/test_filter_pydantic_sub_model.py @@ -116,7 +116,7 @@ async def get_model_a(name: str, model_c=Depends(get_model_c)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_forms_from_non_typing_sequences.py b/tests/test_forms_from_non_typing_sequences.py index be917eab7e2e0..52ce247533eb1 100644 --- a/tests/test_forms_from_non_typing_sequences.py +++ b/tests/test_forms_from_non_typing_sequences.py @@ -5,17 +5,17 @@ @app.post("/form/python-list") -def post_form_param_list(items: list = Form(...)): +def post_form_param_list(items: list = Form()): return items @app.post("/form/python-set") -def post_form_param_set(items: set = Form(...)): +def post_form_param_set(items: set = Form()): return items @app.post("/form/python-tuple") -def post_form_param_tuple(items: tuple = Form(...)): +def post_form_param_tuple(items: tuple = Form()): return items diff --git a/tests/test_generate_unique_id_function.py b/tests/test_generate_unique_id_function.py index ffc0e38440036..0b519f8596f5b 100644 --- a/tests/test_generate_unique_id_function.py +++ b/tests/test_generate_unique_id_function.py @@ -217,7 +217,9 @@ def post_router(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -416,7 +418,9 @@ def post_router(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -615,7 +619,9 @@ def post_router(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -887,7 +893,9 @@ def post_subrouter(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -1089,7 +1097,9 @@ def post_router(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -1295,7 +1305,9 @@ def post_router(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -1579,7 +1591,9 @@ def post_with_callback(item1: Item, item2: Item): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index b12f499ebcf6a..88b9d839f5a6b 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -85,7 +85,7 @@ async def create_item(product: Product): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_include_router_defaults_overrides.py b/tests/test_include_router_defaults_overrides.py index 5dd7e7098d6ae..ccb6c7229d37f 100644 --- a/tests/test_include_router_defaults_overrides.py +++ b/tests/test_include_router_defaults_overrides.py @@ -6612,7 +6612,7 @@ def test_paths_level5(override1, override2, override3, override4, override5): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_invalid_sequence_param.py b/tests/test_invalid_sequence_param.py index f00dd7b9343c1..475786adbf80d 100644 --- a/tests/test_invalid_sequence_param.py +++ b/tests/test_invalid_sequence_param.py @@ -13,7 +13,7 @@ class Item(BaseModel): title: str @app.get("/items/") - def read_items(q: List[Item] = Query(None)): + def read_items(q: List[Item] = Query(default=None)): pass # pragma: no cover @@ -25,7 +25,7 @@ class Item(BaseModel): title: str @app.get("/items/") - def read_items(q: Tuple[Item, Item] = Query(None)): + def read_items(q: Tuple[Item, Item] = Query(default=None)): pass # pragma: no cover @@ -37,7 +37,7 @@ class Item(BaseModel): title: str @app.get("/items/") - def read_items(q: Dict[str, Item] = Query(None)): + def read_items(q: Dict[str, Item] = Query(default=None)): pass # pragma: no cover @@ -49,5 +49,5 @@ class Item(BaseModel): title: str @app.get("/items/") - def read_items(q: Optional[dict] = Query(None)): + def read_items(q: Optional[dict] = Query(default=None)): pass # pragma: no cover diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index fa82b5ea83585..ed35fd32e43f0 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -67,7 +67,7 @@ class Config: class ModelWithAlias(BaseModel): - foo: str = Field(..., alias="Foo") + foo: str = Field(alias="Foo") class ModelWithDefault(BaseModel): diff --git a/tests/test_modules_same_name_body/app/a.py b/tests/test_modules_same_name_body/app/a.py index 3c86c1865e74f..37723689062cf 100644 --- a/tests/test_modules_same_name_body/app/a.py +++ b/tests/test_modules_same_name_body/app/a.py @@ -4,5 +4,5 @@ @router.post("/compute") -def compute(a: int = Body(...), b: str = Body(...)): +def compute(a: int = Body(), b: str = Body()): return {"a": a, "b": b} diff --git a/tests/test_modules_same_name_body/app/b.py b/tests/test_modules_same_name_body/app/b.py index f7c7fdfc690d1..b62118f84142c 100644 --- a/tests/test_modules_same_name_body/app/b.py +++ b/tests/test_modules_same_name_body/app/b.py @@ -4,5 +4,5 @@ @router.post("/compute/") -def compute(a: int = Body(...), b: str = Body(...)): +def compute(a: int = Body(), b: str = Body()): return {"a": a, "b": b} diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index b0d3330c72b2c..8b1aea0316493 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -101,7 +101,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index c1be82806ebd1..31308ea85cdbc 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -79,7 +79,7 @@ def save_item_no_body(item: List[Item]): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py index 69ea87a9b65cc..3da461af5a532 100644 --- a/tests/test_multi_query_errors.py +++ b/tests/test_multi_query_errors.py @@ -7,7 +7,7 @@ @app.get("/items/") -def read_items(q: List[int] = Query(None)): +def read_items(q: List[int] = Query(default=None)): return {"q": q} @@ -63,7 +63,7 @@ def read_items(q: List[int] = Query(None)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_multipart_installation.py b/tests/test_multipart_installation.py index c8a6fd942fa1a..788d9ef5afd30 100644 --- a/tests/test_multipart_installation.py +++ b/tests/test_multipart_installation.py @@ -12,7 +12,7 @@ def test_incorrect_multipart_installed_form(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...)): + async def root(username: str = Form()): return username # pragma: nocover @@ -22,7 +22,7 @@ def test_incorrect_multipart_installed_file_upload(monkeypatch): app = FastAPI() @app.post("/") - async def root(f: UploadFile = File(...)): + async def root(f: UploadFile = File()): return f # pragma: nocover @@ -32,7 +32,7 @@ def test_incorrect_multipart_installed_file_bytes(monkeypatch): app = FastAPI() @app.post("/") - async def root(f: bytes = File(...)): + async def root(f: bytes = File()): return f # pragma: nocover @@ -42,7 +42,7 @@ def test_incorrect_multipart_installed_multi_form(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...), password: str = Form(...)): + async def root(username: str = Form(), password: str = Form()): return username # pragma: nocover @@ -52,7 +52,7 @@ def test_incorrect_multipart_installed_form_file(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...), f: UploadFile = File(...)): + async def root(username: str = Form(), f: UploadFile = File()): return username # pragma: nocover @@ -62,7 +62,7 @@ def test_no_multipart_installed(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...)): + async def root(username: str = Form()): return username # pragma: nocover @@ -72,7 +72,7 @@ def test_no_multipart_installed_file(monkeypatch): app = FastAPI() @app.post("/") - async def root(f: UploadFile = File(...)): + async def root(f: UploadFile = File()): return f # pragma: nocover @@ -82,7 +82,7 @@ def test_no_multipart_installed_file_bytes(monkeypatch): app = FastAPI() @app.post("/") - async def root(f: bytes = File(...)): + async def root(f: bytes = File()): return f # pragma: nocover @@ -92,7 +92,7 @@ def test_no_multipart_installed_multi_form(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...), password: str = Form(...)): + async def root(username: str = Form(), password: str = Form()): return username # pragma: nocover @@ -102,5 +102,5 @@ def test_no_multipart_installed_form_file(monkeypatch): app = FastAPI() @app.post("/") - async def root(username: str = Form(...), f: UploadFile = File(...)): + async def root(username: str = Form(), f: UploadFile = File()): return username # pragma: nocover diff --git a/tests/test_param_class.py b/tests/test_param_class.py index f5767ec96cab8..1fd40dcd218b9 100644 --- a/tests/test_param_class.py +++ b/tests/test_param_class.py @@ -8,7 +8,7 @@ @app.get("/items/") -def read_items(q: Optional[str] = Param(None)): # type: ignore +def read_items(q: Optional[str] = Param(default=None)): # type: ignore return {"q": q} diff --git a/tests/test_param_in_path_and_dependency.py b/tests/test_param_in_path_and_dependency.py index 0a94c2151316d..4d85afbceef2a 100644 --- a/tests/test_param_in_path_and_dependency.py +++ b/tests/test_param_in_path_and_dependency.py @@ -71,7 +71,7 @@ async def read_users(user_id: int): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index 4eaac72d87e50..214f039b67d3e 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -9,26 +9,26 @@ @app.get("/hidden_cookie") async def hidden_cookie( - hidden_cookie: Optional[str] = Cookie(None, include_in_schema=False) + hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False) ): return {"hidden_cookie": hidden_cookie} @app.get("/hidden_header") async def hidden_header( - hidden_header: Optional[str] = Header(None, include_in_schema=False) + hidden_header: Optional[str] = Header(default=None, include_in_schema=False) ): return {"hidden_header": hidden_header} @app.get("/hidden_path/{hidden_path}") -async def hidden_path(hidden_path: str = Path(..., include_in_schema=False)): +async def hidden_path(hidden_path: str = Path(include_in_schema=False)): return {"hidden_path": hidden_path} @app.get("/hidden_query") async def hidden_query( - hidden_query: Optional[str] = Query(None, include_in_schema=False) + hidden_query: Optional[str] = Query(default=None, include_in_schema=False) ): return {"hidden_query": hidden_query} @@ -149,7 +149,7 @@ async def hidden_query( "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_put_no_body.py b/tests/test_put_no_body.py index 1c2cfac891f52..3da294ccf735f 100644 --- a/tests/test_put_no_body.py +++ b/tests/test_put_no_body.py @@ -57,7 +57,7 @@ def save_item_no_body(item_id: str): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index fd616e12ad167..ca0305184aaff 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -4,7 +4,7 @@ app = FastAPI() -def get_header(*, someheader: str = Header(...)): +def get_header(*, someheader: str = Header()): return someheader @@ -36,7 +36,7 @@ def get_deps(dep1: str = Depends(get_header), dep2: str = Depends(get_something_ "ValidationError": { "properties": { "loc": { - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "title": "Location", "type": "array", }, diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index ace6bdef76ee6..e9cf4006d9eff 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -21,14 +21,14 @@ class Shop(BaseModel): @app.post("/products") -async def create_product(data: Product = Body(..., media_type=media_type, embed=True)): +async def create_product(data: Product = Body(media_type=media_type, embed=True)): pass # pragma: no cover @app.post("/shops") async def create_shop( - data: Shop = Body(..., media_type=media_type), - included: typing.List[Product] = Body([], media_type=media_type), + data: Shop = Body(media_type=media_type), + included: typing.List[Product] = Body(default=[], media_type=media_type), ): pass # pragma: no cover diff --git a/tests/test_required_noneable.py b/tests/test_required_noneable.py new file mode 100644 index 0000000000000..5da8cd4d09095 --- /dev/null +++ b/tests/test_required_noneable.py @@ -0,0 +1,62 @@ +from typing import Union + +from fastapi import Body, FastAPI, Query +from fastapi.testclient import TestClient + +app = FastAPI() + + +@app.get("/query") +def read_query(q: Union[str, None]): + return q + + +@app.get("/explicit-query") +def read_explicit_query(q: Union[str, None] = Query()): + return q + + +@app.post("/body-embed") +def send_body_embed(b: Union[str, None] = Body(embed=True)): + return b + + +client = TestClient(app) + + +def test_required_nonable_query_invalid(): + response = client.get("/query") + assert response.status_code == 422 + + +def test_required_noneable_query_value(): + response = client.get("/query", params={"q": "foo"}) + assert response.status_code == 200 + assert response.json() == "foo" + + +def test_required_nonable_explicit_query_invalid(): + response = client.get("/explicit-query") + assert response.status_code == 422 + + +def test_required_nonable_explicit_query_value(): + response = client.get("/explicit-query", params={"q": "foo"}) + assert response.status_code == 200 + assert response.json() == "foo" + + +def test_required_nonable_body_embed_no_content(): + response = client.post("/body-embed") + assert response.status_code == 422 + + +def test_required_nonable_body_embed_invalid(): + response = client.post("/body-embed", json={"invalid": "invalid"}) + assert response.status_code == 422 + + +def test_required_noneable_body_embed_value(): + response = client.post("/body-embed", json={"b": "foo"}) + assert response.status_code == 200 + assert response.json() == "foo" diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index 3e0d846cd30b6..5047aeaa4b02a 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -1,3 +1,5 @@ +from typing import Union + from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient from pydantic import BaseModel @@ -18,14 +20,13 @@ def schema_extra(item: Item): @app.post("/example/") -def example(item: Item = Body(..., example={"data": "Data in Body example"})): +def example(item: Item = Body(example={"data": "Data in Body example"})): return item @app.post("/examples/") def examples( item: Item = Body( - ..., examples={ "example1": { "summary": "example1 summary", @@ -41,7 +42,6 @@ def examples( @app.post("/example_examples/") def example_examples( item: Item = Body( - ..., example={"data": "Overriden example"}, examples={ "example1": {"value": {"data": "examples example_examples 1"}}, @@ -55,7 +55,7 @@ def example_examples( # TODO: enable these tests once/if Form(embed=False) is supported # TODO: In that case, define if File() should support example/examples too # @app.post("/form_example") -# def form_example(firstname: str = Form(..., example="John")): +# def form_example(firstname: str = Form(example="John")): # return firstname @@ -89,7 +89,6 @@ def example_examples( @app.get("/path_example/{item_id}") def path_example( item_id: str = Path( - ..., example="item_1", ), ): @@ -99,7 +98,6 @@ def path_example( @app.get("/path_examples/{item_id}") def path_examples( item_id: str = Path( - ..., examples={ "example1": {"summary": "item ID summary", "value": "item_1"}, "example2": {"value": "item_2"}, @@ -112,7 +110,6 @@ def path_examples( @app.get("/path_example_examples/{item_id}") def path_example_examples( item_id: str = Path( - ..., example="item_overriden", examples={ "example1": {"summary": "item ID summary", "value": "item_1"}, @@ -125,8 +122,8 @@ def path_example_examples( @app.get("/query_example/") def query_example( - data: str = Query( - None, + data: Union[str, None] = Query( + default=None, example="query1", ), ): @@ -135,8 +132,8 @@ def query_example( @app.get("/query_examples/") def query_examples( - data: str = Query( - None, + data: Union[str, None] = Query( + default=None, examples={ "example1": {"summary": "Query example 1", "value": "query1"}, "example2": {"value": "query2"}, @@ -148,8 +145,8 @@ def query_examples( @app.get("/query_example_examples/") def query_example_examples( - data: str = Query( - None, + data: Union[str, None] = Query( + default=None, example="query_overriden", examples={ "example1": {"summary": "Qeury example 1", "value": "query1"}, @@ -162,8 +159,8 @@ def query_example_examples( @app.get("/header_example/") def header_example( - data: str = Header( - None, + data: Union[str, None] = Header( + default=None, example="header1", ), ): @@ -172,8 +169,8 @@ def header_example( @app.get("/header_examples/") def header_examples( - data: str = Header( - None, + data: Union[str, None] = Header( + default=None, examples={ "example1": {"summary": "header example 1", "value": "header1"}, "example2": {"value": "header2"}, @@ -185,8 +182,8 @@ def header_examples( @app.get("/header_example_examples/") def header_example_examples( - data: str = Header( - None, + data: Union[str, None] = Header( + default=None, example="header_overriden", examples={ "example1": {"summary": "Qeury example 1", "value": "header1"}, @@ -199,8 +196,8 @@ def header_example_examples( @app.get("/cookie_example/") def cookie_example( - data: str = Cookie( - None, + data: Union[str, None] = Cookie( + default=None, example="cookie1", ), ): @@ -209,8 +206,8 @@ def cookie_example( @app.get("/cookie_examples/") def cookie_examples( - data: str = Cookie( - None, + data: Union[str, None] = Cookie( + default=None, examples={ "example1": {"summary": "cookie example 1", "value": "cookie1"}, "example2": {"value": "cookie2"}, @@ -222,8 +219,8 @@ def cookie_examples( @app.get("/cookie_example_examples/") def cookie_example_examples( - data: str = Cookie( - None, + data: Union[str, None] = Cookie( + default=None, example="cookie_overriden", examples={ "example1": {"summary": "Qeury example 1", "value": "cookie1"}, @@ -830,7 +827,7 @@ def cookie_example_examples( "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index b7ada7caf2edc..b9ac488eea545 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -117,7 +117,7 @@ def read_current_user(current_user: "User" = Depends(get_current_user)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index ecc7665113fe9..a5fd49b8c7a7a 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -121,7 +121,7 @@ def read_users_me(current_user: Optional[User] = Depends(get_current_user)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index 011db65ecb3d2..171f96b762e7f 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -122,7 +122,7 @@ def read_users_me(current_user: Optional[User] = Depends(get_current_user)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_serialize_response_model.py b/tests/test_serialize_response_model.py index 2956674376a58..3bb46b2e9bcd6 100644 --- a/tests/test_serialize_response_model.py +++ b/tests/test_serialize_response_model.py @@ -8,7 +8,7 @@ class Item(BaseModel): - name: str = Field(..., alias="aliased_name") + name: str = Field(alias="aliased_name") price: Optional[float] = None owner_ids: Optional[List[int]] = None diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 5759a93f4ea6e..859169d3cdad8 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -102,7 +102,7 @@ async def read_starlette_item(item_id: str): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_starlette_urlconvertors.py b/tests/test_starlette_urlconvertors.py index 2320c7005f2cb..5a980cbf6dad7 100644 --- a/tests/test_starlette_urlconvertors.py +++ b/tests/test_starlette_urlconvertors.py @@ -5,17 +5,17 @@ @app.get("/int/{param:int}") -def int_convertor(param: int = Path(...)): +def int_convertor(param: int = Path()): return {"int": param} @app.get("/float/{param:float}") -def float_convertor(param: float = Path(...)): +def float_convertor(param: float = Path()): return {"float": param} @app.get("/path/{param:path}") -def path_convertor(param: str = Path(...)): +def path_convertor(param: str = Path()): return {"path": param} diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index 16644b5569d13..7574d6fbc5fb2 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -256,7 +256,7 @@ def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tuples.py b/tests/test_tuples.py index 4cd5ee3afbe05..18ec2d0489912 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -27,7 +27,7 @@ def post_tuple_of_models(square: Tuple[Coordinate, Coordinate]): @app.post("/tuple-form/") -def hello(values: Tuple[int, int] = Form(...)): +def hello(values: Tuple[int, int] = Form()): return values @@ -200,7 +200,7 @@ def hello(values: Tuple[int, int] = Form(...)): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index 8342dd787d54e..1a8acb523154f 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -76,7 +76,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index 57f8779789b86..2adcf15d07f51 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -72,7 +72,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index 37190b36a7ec9..8b2167de0513c 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -77,7 +77,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index c44a18f689742..990d5235aa104 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -75,7 +75,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py index 90feb0172aac6..1ad625db6a7a6 100644 --- a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py @@ -88,7 +88,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index 7eb675179eb00..cd6d7b5c8b0d9 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -323,7 +323,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 7bf62c907db79..8dbaf15dbef06 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -63,7 +63,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body/test_tutorial001_py310.py b/tests/test_tutorial/test_body/test_tutorial001_py310.py index e292b53460a1a..dd9d9911e402c 100644 --- a/tests/test_tutorial/test_body/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body/test_tutorial001_py310.py @@ -61,7 +61,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index 9de4907c24783..fe5a270f3611d 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -87,7 +87,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py index d7a525ea790b1..993e2a91d2836 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py @@ -84,7 +84,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index b11ecddabe2fe..8dc710d755183 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -79,7 +79,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py index 85ba41ce61b4d..5114ccea29ff0 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py @@ -77,7 +77,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index d98e3e4199d09..64aa9c43bf3f3 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -90,7 +90,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py index f896f7bf55458..fc019d8bb4b16 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py @@ -88,7 +88,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index 8eb0ad1308aae..c56d41b5bf795 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -53,7 +53,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py index 17ca29ce5002d..5b8d8286120a0 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py @@ -52,7 +52,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index 5e92ef7eaeccf..efd0e46765369 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -109,7 +109,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py index ca1d8c585eb02..49279b3206f8f 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py @@ -108,7 +108,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py index f2b184c4f8c78..872530bcf9286 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py @@ -108,7 +108,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index 3451dc19ec080..edccffec1e87e 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -50,7 +50,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py index 587a328da68cf..5caa5c440039e 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py @@ -48,7 +48,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index 3e3fc9acf65d1..bf15641949245 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -71,7 +71,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index dd0f1f2c0da59..2d86f7b9abe89 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -118,7 +118,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001.py b/tests/test_tutorial/test_dependencies/test_tutorial001.py index 8b53157cd6482..c3bca5d5b3b0c 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001.py @@ -104,7 +104,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py index a7991170e8383..32a61c8219f8e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py @@ -102,7 +102,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial004.py index eb21f65241ab1..f2b1878d5413f 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004.py @@ -62,7 +62,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py index f66a36a997a2c..e3ae0c7418166 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py @@ -60,7 +60,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index c08992ec8df24..2916577a2acb2 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -55,7 +55,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index ada83c6260246..e4e07395dff4b 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -102,7 +102,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index e3587a0e88ffc..d52dd1a047123 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -47,7 +47,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py index 68b7d61dc698e..8522d7b9d7d5a 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py @@ -89,7 +89,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py index 3d4c1d07d6008..4efdecc53ad2e 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py @@ -87,7 +87,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index a2a325c77082a..f1433470c1ad9 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -78,7 +78,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py index 185bc3a374010..56fd83ad3a24d 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py @@ -77,7 +77,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index d79123163656d..128fcea3094dd 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -147,7 +147,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index 6b62293d8ffd3..ffd79ccff3a6c 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index d2ce0bf9dd4c1..e678499c63a2b 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index ca9d94e3cedde..a01726dc2d399 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index d95debf378a84..0b5f747986cf7 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index cedcaae704969..253f3d006a7c5 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -69,7 +69,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index 8b6c1e7eda9c8..21233d7bbf415 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 0f05b9e8c887b..273cf3249ee44 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -51,7 +51,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py index f5ee17428d4f1..77a60eb9db976 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py @@ -48,7 +48,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index b30427d08eddf..e773e7f8f550f 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -143,7 +143,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index f2ec2c7e5eaa0..456e509d5b76a 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -72,7 +72,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index d2164094603d6..e587519a00534 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -72,7 +72,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py index 1f617da70c70f..43a7a610de844 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py @@ -71,7 +71,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py index ffdf050812cc4..62aa73ac528c7 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py @@ -71,7 +71,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index 131bf773be567..7f0227ecfb547 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -49,7 +49,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index ed9d2032b3a83..eae3637bed587 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -54,7 +54,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -138,7 +138,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index aabc0af4f9e37..07178f8a6e814 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -56,7 +56,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index 042a0e1f8360e..73c5302e7c7e5 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -68,7 +68,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py index 1986d27d03356..141525f15ff79 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py @@ -66,7 +66,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py index 709bf69569eb1..f8d7f85c8e6cb 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py @@ -59,7 +59,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001_py310.py index 66b24017edef5..298b5d616ccec 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001_py310.py @@ -57,7 +57,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index 6ae10296f4573..ad3645f314ead 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -53,7 +53,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py index 8894ee1b5d242..9330037eddf07 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py @@ -52,7 +52,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py index b10e70af76d53..11f23be27c80f 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py @@ -52,7 +52,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index 724c975f8aad9..d69139dda5203 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -54,7 +54,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py index a9cbce02a4f91..b25bb2847fabf 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py @@ -53,7 +53,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index ad559791316ec..1b2e363540a12 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -54,7 +54,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 98ae5a6842d4d..57b8b9d946abc 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -53,7 +53,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py index 33f3d5f773c4c..fe54fc080bb67 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py @@ -51,7 +51,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index c1537f445da17..166014c71fc78 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -99,7 +99,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, @@ -162,7 +162,7 @@ def test_post_file(tmp_path): def test_post_large_file(tmp_path): - default_pydantic_max_size = 2 ** 16 + default_pydantic_max_size = 2**16 path = tmp_path / "test.txt" path.write_bytes(b"x" * (default_pydantic_max_size + 1)) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index e852a1b31336b..a254bf3e8fcd9 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -106,7 +106,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py index 62e9f98d0bf35..15b6a8d53833a 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py @@ -107,7 +107,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index ec7509ea29624..c34165f18e76d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -120,7 +120,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 4e33ef464dd7d..73d1179a1c2cf 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -119,7 +119,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial002_py39.py b/tests/test_tutorial/test_request_files/test_tutorial002_py39.py index bbdf25cd962fb..de4127057d1a7 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002_py39.py @@ -119,7 +119,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index 943b235ab88ab..83aea66cddb63 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -132,7 +132,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_files/test_tutorial003_py39.py b/tests/test_tutorial/test_request_files/test_tutorial003_py39.py index d5fbd78899c5e..56aeb54cd10c6 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003_py39.py @@ -132,7 +132,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py index 3d271b5319763..215260ffa9894 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py @@ -61,7 +61,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index 10cce5e61284a..09e232b8e5cba 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -61,7 +61,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index 44f2fb7ca42b3..e1bde5d1335f3 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -74,7 +74,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py index ffba11662757d..9827dab8a31b6 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py @@ -73,7 +73,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py index 19303982b9efa..8c98c6de3088c 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004.py @@ -71,7 +71,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py index f1508a05d47e1..7fc86fafab8b0 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py @@ -69,7 +69,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py index e5d9c8b5fce00..405fe79f50aa5 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py @@ -69,7 +69,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py index 9ca5463e64fe1..476b172d3d69c 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005.py @@ -98,7 +98,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py index 6d7366f1260de..389a302e08d62 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py @@ -97,7 +97,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py index 25eb6e333f88a..38eb31e54f7b4 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006.py @@ -98,7 +98,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py index a3d8d204ef2e2..f870f39261e59 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py @@ -97,7 +97,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py index 89f5b66fd6862..badf66b3d132d 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -103,7 +103,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py index 4f9a2ff576393..d326a5a092e3f 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py @@ -102,7 +102,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index 3fc7f5f40f49f..5951078343c67 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -81,7 +81,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial003_py310.py b/tests/test_tutorial/test_security/test_tutorial003_py310.py index e621bcd450d39..26f5c097ffcb9 100644 --- a/tests/test_tutorial/test_security/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial003_py310.py @@ -80,7 +80,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index a37f2d60acd5c..e8697339ff159 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -141,7 +141,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_py310.py b/tests/test_tutorial/test_security/test_tutorial005_py310.py index 0c9372e2a70e9..3144a23657191 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py310.py @@ -134,7 +134,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_py39.py b/tests/test_tutorial/test_security/test_tutorial005_py39.py index 099ab2526a13b..290136e179ace 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py39.py @@ -134,7 +134,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases.py b/tests/test_tutorial/test_sql_databases/test_sql_databases.py index c88fd0bcdc30a..09304ff8780a7 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases.py @@ -261,7 +261,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py index b02e1c89ed922..fbaa8938a46d1 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py @@ -260,7 +260,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py index 1d0442eb54977..d131b4b6a9495 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py @@ -263,7 +263,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py index 8764d07a685f6..470fb52fd5d90 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py @@ -263,7 +263,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py index f7e73dea4814a..dc6a1db157ebc 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py @@ -263,7 +263,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py index c194c85aa170f..ebf55ed0152e0 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py @@ -263,7 +263,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py b/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py index 2ebc31b953197..d28ea5e7670d3 100644 --- a/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py +++ b/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py @@ -318,7 +318,7 @@ "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_union_body.py b/tests/test_union_body.py index d1dfd5efbad2c..3e424de07d1c8 100644 --- a/tests/test_union_body.py +++ b/tests/test_union_body.py @@ -84,7 +84,7 @@ def save_union_body(item: Union[OtherItem, Item]): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_union_inherited_body.py b/tests/test_union_inherited_body.py index e3d0acc99d49c..60b327ebcc037 100644 --- a/tests/test_union_inherited_body.py +++ b/tests/test_union_inherited_body.py @@ -96,7 +96,7 @@ def save_union_different_body(item: Union[ExtendedItem, Item]): "loc": { "title": "Location", "type": "array", - "items": {"type": "string"}, + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, diff --git a/tests/test_ws_router.py b/tests/test_ws_router.py index bd7c3c53d6e3b..fbca104a231a1 100644 --- a/tests/test_ws_router.py +++ b/tests/test_ws_router.py @@ -3,6 +3,7 @@ router = APIRouter() prefix_router = APIRouter() +native_prefix_route = APIRouter(prefix="/native") app = FastAPI() @@ -47,8 +48,16 @@ async def router_ws_decorator_depends( await websocket.close() +@native_prefix_route.websocket("/") +async def router_native_prefix_ws(websocket: WebSocket): + await websocket.accept() + await websocket.send_text("Hello, router with native prefix!") + await websocket.close() + + app.include_router(router) app.include_router(prefix_router, prefix="/prefix") +app.include_router(native_prefix_route) def test_app(): @@ -72,6 +81,13 @@ def test_prefix_router(): assert data == "Hello, router with prefix!" +def test_native_prefix_router(): + client = TestClient(app) + with client.websocket_connect("/native/") as websocket: + data = websocket.receive_text() + assert data == "Hello, router with native prefix!" + + def test_router2(): client = TestClient(app) with client.websocket_connect("/router2") as websocket: