mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-24 14:48:35 -05:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef176c6631 | ||
|
|
7b7e86a307 | ||
|
|
25aabe05ce | ||
|
|
392ffaae43 | ||
|
|
202ee0497a | ||
|
|
321e873c95 | ||
|
|
4860631468 | ||
|
|
8e4c96c703 | ||
|
|
39813aa9b0 | ||
|
|
3e3278ed3f | ||
|
|
c8a07078cf | ||
|
|
59f91db1d2 | ||
|
|
f04b61bd16 | ||
|
|
253d58bc5c | ||
|
|
78b8a9b6ec | ||
|
|
c26db94a90 | ||
|
|
d1f3753e5e | ||
|
|
d5b0cc9f58 | ||
|
|
42daed222e | ||
|
|
fd3bfe9f50 | ||
|
|
1fea9c5626 | ||
|
|
d783463ebd | ||
|
|
8a4cfa52af | ||
|
|
25382d2d19 | ||
|
|
b9bb441b23 | ||
|
|
e33f30a607 | ||
|
|
cc9a73c3f8 | ||
|
|
66e03c816b | ||
|
|
639cf3440a | ||
|
|
2f1b856fe6 | ||
|
|
31e148ba8e | ||
|
|
40c2c44ff9 | ||
|
|
c5f72f02cd | ||
|
|
9b83a00c40 | ||
|
|
83012a9cf6 | ||
|
|
8625189351 | ||
|
|
e570371003 | ||
|
|
4d099250f6 | ||
|
|
9ef46a2299 | ||
|
|
30a9d68232 | ||
|
|
03bb7c166c | ||
|
|
c5f343a4fd | ||
|
|
83050bead6 | ||
|
|
bd219c2bbf | ||
|
|
4b95025d44 | ||
|
|
ff64772dd1 | ||
|
|
e8fd74e737 | ||
|
|
87842ac0db | ||
|
|
7674da89d3 | ||
|
|
e9326de161 | ||
|
|
97effae92d | ||
|
|
a8bde44029 | ||
|
|
be54d44b0c | ||
|
|
35d93d59d8 | ||
|
|
7b3727e03e | ||
|
|
a270ab0c3f | ||
|
|
f6f39d8714 | ||
|
|
4f4035262c | ||
|
|
6879082b36 | ||
|
|
52ca6cb95b | ||
|
|
9e283ef66b | ||
|
|
75e7e9e0a2 | ||
|
|
2ca77f9a4d | ||
|
|
3c05189b06 | ||
|
|
a04acf6900 | ||
|
|
d566c6cbca | ||
|
|
6e94ec2bf0 | ||
|
|
e85c109bcd | ||
|
|
445e611a29 | ||
|
|
392766bcfa | ||
|
|
5ed70f285b | ||
|
|
d6fb9429d2 | ||
|
|
9a5147382e | ||
|
|
99deead7fc | ||
|
|
18e6c3ff6a | ||
|
|
3c5536a780 | ||
|
|
79eed9d7d9 | ||
|
|
e37d504e27 | ||
|
|
70688eb7b2 | ||
|
|
16599b7356 |
2
.github/DISCUSSION_TEMPLATE/questions.yml
vendored
2
.github/DISCUSSION_TEMPLATE/questions.yml
vendored
@@ -36,7 +36,7 @@ body:
|
||||
required: true
|
||||
- label: I already read and followed all the tutorial in the docs and didn't find an answer.
|
||||
required: true
|
||||
- label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic).
|
||||
- label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/pydantic/pydantic).
|
||||
required: true
|
||||
- label: I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
|
||||
required: true
|
||||
|
||||
421
.github/actions/notify-translations/app/main.py
vendored
421
.github/actions/notify-translations/app/main.py
vendored
@@ -1,10 +1,11 @@
|
||||
import logging
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, Union
|
||||
from typing import Any, Dict, List, Union, cast
|
||||
|
||||
import yaml
|
||||
import httpx
|
||||
from github import Github
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr
|
||||
|
||||
@@ -13,12 +14,172 @@ lang_all_label = "lang-all"
|
||||
approved_label = "approved-2"
|
||||
translations_path = Path(__file__).parent / "translations.yml"
|
||||
|
||||
github_graphql_url = "https://api.github.com/graphql"
|
||||
questions_translations_category_id = "DIC_kwDOCZduT84CT5P9"
|
||||
|
||||
all_discussions_query = """
|
||||
query Q($category_id: ID) {
|
||||
repository(name: "fastapi", owner: "tiangolo") {
|
||||
discussions(categoryId: $category_id, first: 100) {
|
||||
nodes {
|
||||
title
|
||||
id
|
||||
number
|
||||
labels(first: 10) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
translation_discussion_query = """
|
||||
query Q($after: String, $discussion_number: Int!) {
|
||||
repository(name: "fastapi", owner: "tiangolo") {
|
||||
discussion(number: $discussion_number) {
|
||||
comments(first: 100, after: $after) {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
url
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
add_comment_mutation = """
|
||||
mutation Q($discussion_id: ID!, $body: String!) {
|
||||
addDiscussionComment(input: {discussionId: $discussion_id, body: $body}) {
|
||||
comment {
|
||||
id
|
||||
url
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
update_comment_mutation = """
|
||||
mutation Q($comment_id: ID!, $body: String!) {
|
||||
updateDiscussionComment(input: {commentId: $comment_id, body: $body}) {
|
||||
comment {
|
||||
id
|
||||
url
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class Comment(BaseModel):
|
||||
id: str
|
||||
url: str
|
||||
body: str
|
||||
|
||||
|
||||
class UpdateDiscussionComment(BaseModel):
|
||||
comment: Comment
|
||||
|
||||
|
||||
class UpdateCommentData(BaseModel):
|
||||
updateDiscussionComment: UpdateDiscussionComment
|
||||
|
||||
|
||||
class UpdateCommentResponse(BaseModel):
|
||||
data: UpdateCommentData
|
||||
|
||||
|
||||
class AddDiscussionComment(BaseModel):
|
||||
comment: Comment
|
||||
|
||||
|
||||
class AddCommentData(BaseModel):
|
||||
addDiscussionComment: AddDiscussionComment
|
||||
|
||||
|
||||
class AddCommentResponse(BaseModel):
|
||||
data: AddCommentData
|
||||
|
||||
|
||||
class CommentsEdge(BaseModel):
|
||||
node: Comment
|
||||
cursor: str
|
||||
|
||||
|
||||
class Comments(BaseModel):
|
||||
edges: List[CommentsEdge]
|
||||
|
||||
|
||||
class CommentsDiscussion(BaseModel):
|
||||
comments: Comments
|
||||
|
||||
|
||||
class CommentsRepository(BaseModel):
|
||||
discussion: CommentsDiscussion
|
||||
|
||||
|
||||
class CommentsData(BaseModel):
|
||||
repository: CommentsRepository
|
||||
|
||||
|
||||
class CommentsResponse(BaseModel):
|
||||
data: CommentsData
|
||||
|
||||
|
||||
class AllDiscussionsLabelNode(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
|
||||
|
||||
class AllDiscussionsLabelsEdge(BaseModel):
|
||||
node: AllDiscussionsLabelNode
|
||||
|
||||
|
||||
class AllDiscussionsDiscussionLabels(BaseModel):
|
||||
edges: List[AllDiscussionsLabelsEdge]
|
||||
|
||||
|
||||
class AllDiscussionsDiscussionNode(BaseModel):
|
||||
title: str
|
||||
id: str
|
||||
number: int
|
||||
labels: AllDiscussionsDiscussionLabels
|
||||
|
||||
|
||||
class AllDiscussionsDiscussions(BaseModel):
|
||||
nodes: List[AllDiscussionsDiscussionNode]
|
||||
|
||||
|
||||
class AllDiscussionsRepository(BaseModel):
|
||||
discussions: AllDiscussionsDiscussions
|
||||
|
||||
|
||||
class AllDiscussionsData(BaseModel):
|
||||
repository: AllDiscussionsRepository
|
||||
|
||||
|
||||
class AllDiscussionsResponse(BaseModel):
|
||||
data: AllDiscussionsData
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
github_repository: str
|
||||
input_token: SecretStr
|
||||
github_event_path: Path
|
||||
github_event_name: Union[str, None] = None
|
||||
httpx_timeout: int = 30
|
||||
input_debug: Union[bool, None] = False
|
||||
|
||||
|
||||
@@ -30,6 +191,113 @@ class PartialGitHubEvent(BaseModel):
|
||||
pull_request: PartialGitHubEventIssue
|
||||
|
||||
|
||||
def get_graphql_response(
|
||||
*,
|
||||
settings: Settings,
|
||||
query: str,
|
||||
after: Union[str, None] = None,
|
||||
category_id: Union[str, None] = None,
|
||||
discussion_number: Union[int, None] = None,
|
||||
discussion_id: Union[str, None] = None,
|
||||
comment_id: Union[str, None] = None,
|
||||
body: Union[str, None] = None,
|
||||
) -> Dict[str, Any]:
|
||||
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
|
||||
# some fields are only used by one query, but GraphQL allows unused variables, so
|
||||
# keep them here for simplicity
|
||||
variables = {
|
||||
"after": after,
|
||||
"category_id": category_id,
|
||||
"discussion_number": discussion_number,
|
||||
"discussion_id": discussion_id,
|
||||
"comment_id": comment_id,
|
||||
"body": body,
|
||||
}
|
||||
response = httpx.post(
|
||||
github_graphql_url,
|
||||
headers=headers,
|
||||
timeout=settings.httpx_timeout,
|
||||
json={"query": query, "variables": variables, "operationName": "Q"},
|
||||
)
|
||||
if response.status_code != 200:
|
||||
logging.error(
|
||||
f"Response was not 200, after: {after}, category_id: {category_id}"
|
||||
)
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
data = response.json()
|
||||
if "errors" in data:
|
||||
logging.error(f"Errors in response, after: {after}, category_id: {category_id}")
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
return cast(Dict[str, Any], data)
|
||||
|
||||
|
||||
def get_graphql_translation_discussions(*, settings: Settings):
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=all_discussions_query,
|
||||
category_id=questions_translations_category_id,
|
||||
)
|
||||
graphql_response = AllDiscussionsResponse.parse_obj(data)
|
||||
return graphql_response.data.repository.discussions.nodes
|
||||
|
||||
|
||||
def get_graphql_translation_discussion_comments_edges(
|
||||
*, settings: Settings, discussion_number: int, after: Union[str, None] = None
|
||||
):
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=translation_discussion_query,
|
||||
discussion_number=discussion_number,
|
||||
after=after,
|
||||
)
|
||||
graphql_response = CommentsResponse.parse_obj(data)
|
||||
return graphql_response.data.repository.discussion.comments.edges
|
||||
|
||||
|
||||
def get_graphql_translation_discussion_comments(
|
||||
*, settings: Settings, discussion_number: int
|
||||
):
|
||||
comment_nodes: List[Comment] = []
|
||||
discussion_edges = get_graphql_translation_discussion_comments_edges(
|
||||
settings=settings, discussion_number=discussion_number
|
||||
)
|
||||
|
||||
while discussion_edges:
|
||||
for discussion_edge in discussion_edges:
|
||||
comment_nodes.append(discussion_edge.node)
|
||||
last_edge = discussion_edges[-1]
|
||||
discussion_edges = get_graphql_translation_discussion_comments_edges(
|
||||
settings=settings,
|
||||
discussion_number=discussion_number,
|
||||
after=last_edge.cursor,
|
||||
)
|
||||
return comment_nodes
|
||||
|
||||
|
||||
def create_comment(*, settings: Settings, discussion_id: str, body: str):
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=add_comment_mutation,
|
||||
discussion_id=discussion_id,
|
||||
body=body,
|
||||
)
|
||||
response = AddCommentResponse.parse_obj(data)
|
||||
return response.data.addDiscussionComment.comment
|
||||
|
||||
|
||||
def update_comment(*, settings: Settings, comment_id: str, body: str):
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=update_comment_mutation,
|
||||
comment_id=comment_id,
|
||||
body=body,
|
||||
)
|
||||
response = UpdateCommentResponse.parse_obj(data)
|
||||
return response.data.updateDiscussionComment.comment
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
settings = Settings()
|
||||
if settings.input_debug:
|
||||
@@ -45,60 +313,105 @@ if __name__ == "__main__":
|
||||
)
|
||||
contents = settings.github_event_path.read_text()
|
||||
github_event = PartialGitHubEvent.parse_raw(contents)
|
||||
translations_map: Dict[str, int] = yaml.safe_load(translations_path.read_text())
|
||||
logging.debug(f"Using translations map: {translations_map}")
|
||||
|
||||
# Avoid race conditions with multiple labels
|
||||
sleep_time = random.random() * 10 # random number between 0 and 10 seconds
|
||||
pr = repo.get_pull(github_event.pull_request.number)
|
||||
logging.debug(
|
||||
f"Processing PR: {pr.number}, with anti-race condition sleep time: {sleep_time}"
|
||||
logging.info(
|
||||
f"Sleeping for {sleep_time} seconds to avoid "
|
||||
"race conditions and multiple comments"
|
||||
)
|
||||
if pr.state == "open":
|
||||
logging.debug(f"PR is open: {pr.number}")
|
||||
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}"
|
||||
)
|
||||
if approved_label in label_strs:
|
||||
message = (
|
||||
f"It seems this PR already has the approved label: {pr.number}"
|
||||
)
|
||||
logging.error(message)
|
||||
raise RuntimeError(message)
|
||||
langs = []
|
||||
for label in label_strs:
|
||||
if label.startswith("lang-") and not label == lang_all_label:
|
||||
langs.append(label[5:])
|
||||
for lang in langs:
|
||||
if lang in translations_map:
|
||||
num = translations_map[lang]
|
||||
logging.info(
|
||||
f"Found a translation issue for language: {lang} in issue: {num}"
|
||||
)
|
||||
issue = repo.get_issue(num)
|
||||
message = f"Good news everyone! 😉 There's a new translation PR to be reviewed: #{pr.number} 🎉"
|
||||
already_notified = False
|
||||
time.sleep(sleep_time)
|
||||
logging.info(
|
||||
f"Sleeping for {sleep_time} seconds to avoid race conditions and multiple comments"
|
||||
)
|
||||
logging.info(
|
||||
f"Checking current comments in issue: {num} to see if already notified about this PR: {pr.number}"
|
||||
)
|
||||
for comment in issue.get_comments():
|
||||
if message in comment.body:
|
||||
already_notified = True
|
||||
if not already_notified:
|
||||
logging.info(
|
||||
f"Writing comment in issue: {num} about PR: {pr.number}"
|
||||
)
|
||||
issue.create_comment(message)
|
||||
else:
|
||||
logging.info(
|
||||
f"Issue: {num} was already notified of PR: {pr.number}"
|
||||
)
|
||||
else:
|
||||
time.sleep(sleep_time)
|
||||
|
||||
# Get PR
|
||||
logging.debug(f"Processing PR: #{github_event.pull_request.number}")
|
||||
pr = repo.get_pull(github_event.pull_request.number)
|
||||
label_strs = {label.name for label in pr.get_labels()}
|
||||
langs = []
|
||||
for label in label_strs:
|
||||
if label.startswith("lang-") and not label == lang_all_label:
|
||||
langs.append(label[5:])
|
||||
logging.info(f"PR #{pr.number} has labels: {label_strs}")
|
||||
if not langs or lang_all_label not in label_strs:
|
||||
logging.info(f"PR #{pr.number} doesn't seem to be a translation PR, skipping")
|
||||
sys.exit(0)
|
||||
|
||||
# Generate translation map, lang ID to discussion
|
||||
discussions = get_graphql_translation_discussions(settings=settings)
|
||||
lang_to_discussion_map: Dict[str, AllDiscussionsDiscussionNode] = {}
|
||||
for discussion in discussions:
|
||||
for edge in discussion.labels.edges:
|
||||
label = edge.node.name
|
||||
if label.startswith("lang-") and not label == lang_all_label:
|
||||
lang = label[5:]
|
||||
lang_to_discussion_map[lang] = discussion
|
||||
logging.debug(f"Using translations map: {lang_to_discussion_map}")
|
||||
|
||||
# Messages to create or check
|
||||
new_translation_message = f"Good news everyone! 😉 There's a new translation PR to be reviewed: #{pr.number} by @{pr.user.login}. 🎉 This requires 2 approvals from native speakers to be merged. 🤓"
|
||||
done_translation_message = f"~There's a new translation PR to be reviewed: #{pr.number} by @{pr.user.login}~ Good job! This is done. 🍰☕"
|
||||
|
||||
# Normally only one language, but still
|
||||
for lang in langs:
|
||||
if lang not in lang_to_discussion_map:
|
||||
log_message = f"Could not find discussion for language: {lang}"
|
||||
logging.error(log_message)
|
||||
raise RuntimeError(log_message)
|
||||
discussion = lang_to_discussion_map[lang]
|
||||
logging.info(
|
||||
f"Changing labels in a closed PR doesn't trigger comments, PR: {pr.number}"
|
||||
f"Found a translation discussion for language: {lang} in discussion: #{discussion.number}"
|
||||
)
|
||||
|
||||
already_notified_comment: Union[Comment, None] = None
|
||||
already_done_comment: Union[Comment, None] = None
|
||||
|
||||
logging.info(
|
||||
f"Checking current comments in discussion: #{discussion.number} to see if already notified about this PR: #{pr.number}"
|
||||
)
|
||||
comments = get_graphql_translation_discussion_comments(
|
||||
settings=settings, discussion_number=discussion.number
|
||||
)
|
||||
for comment in comments:
|
||||
if new_translation_message in comment.body:
|
||||
already_notified_comment = comment
|
||||
elif done_translation_message in comment.body:
|
||||
already_done_comment = comment
|
||||
logging.info(
|
||||
f"Already notified comment: {already_notified_comment}, already done comment: {already_done_comment}"
|
||||
)
|
||||
|
||||
if pr.state == "open" and awaiting_label in label_strs:
|
||||
logging.info(
|
||||
f"This PR seems to be a language translation and awaiting reviews: #{pr.number}"
|
||||
)
|
||||
if already_notified_comment:
|
||||
logging.info(
|
||||
f"This PR #{pr.number} was already notified in comment: {already_notified_comment.url}"
|
||||
)
|
||||
else:
|
||||
logging.info(
|
||||
f"Writing notification comment about PR #{pr.number} in Discussion: #{discussion.number}"
|
||||
)
|
||||
comment = create_comment(
|
||||
settings=settings,
|
||||
discussion_id=discussion.id,
|
||||
body=new_translation_message,
|
||||
)
|
||||
logging.info(f"Notified in comment: {comment.url}")
|
||||
elif pr.state == "closed" or approved_label in label_strs:
|
||||
logging.info(f"Already approved or closed PR #{pr.number}")
|
||||
if already_done_comment:
|
||||
logging.info(
|
||||
f"This PR #{pr.number} was already marked as done in comment: {already_done_comment.url}"
|
||||
)
|
||||
elif already_notified_comment:
|
||||
updated_comment = update_comment(
|
||||
settings=settings,
|
||||
comment_id=already_notified_comment.id,
|
||||
body=done_translation_message,
|
||||
)
|
||||
logging.info(f"Marked as done in comment: {updated_comment.url}")
|
||||
else:
|
||||
logging.info(
|
||||
f"There doesn't seem to be anything to be done about PR #{pr.number}"
|
||||
)
|
||||
logging.info("Finished")
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
pt: 1211
|
||||
es: 1218
|
||||
zh: 1228
|
||||
ru: 1362
|
||||
it: 1556
|
||||
ja: 1572
|
||||
uk: 1748
|
||||
tr: 1892
|
||||
fr: 1972
|
||||
ko: 2017
|
||||
fa: 2041
|
||||
pl: 3169
|
||||
de: 3716
|
||||
id: 3717
|
||||
az: 3994
|
||||
nl: 4701
|
||||
uz: 4883
|
||||
sv: 5146
|
||||
he: 5157
|
||||
ta: 5434
|
||||
ar: 3349
|
||||
28
.github/actions/people/app/main.py
vendored
28
.github/actions/people/app/main.py
vendored
@@ -381,6 +381,10 @@ def get_graphql_response(
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
data = response.json()
|
||||
if "errors" in data:
|
||||
logging.error(f"Errors in response, after: {after}, category_id: {category_id}")
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
return data
|
||||
|
||||
|
||||
@@ -496,21 +500,25 @@ def get_discussions_experts(settings: Settings):
|
||||
|
||||
|
||||
def get_experts(settings: Settings):
|
||||
(
|
||||
issues_commentors,
|
||||
issues_last_month_commentors,
|
||||
issues_authors,
|
||||
) = get_issues_experts(settings=settings)
|
||||
# Migrated to only use GitHub Discussions
|
||||
# (
|
||||
# issues_commentors,
|
||||
# issues_last_month_commentors,
|
||||
# issues_authors,
|
||||
# ) = get_issues_experts(settings=settings)
|
||||
(
|
||||
discussions_commentors,
|
||||
discussions_last_month_commentors,
|
||||
discussions_authors,
|
||||
) = get_discussions_experts(settings=settings)
|
||||
commentors = issues_commentors + discussions_commentors
|
||||
last_month_commentors = (
|
||||
issues_last_month_commentors + discussions_last_month_commentors
|
||||
)
|
||||
authors = {**issues_authors, **discussions_authors}
|
||||
# commentors = issues_commentors + discussions_commentors
|
||||
commentors = discussions_commentors
|
||||
# last_month_commentors = (
|
||||
# issues_last_month_commentors + discussions_last_month_commentors
|
||||
# )
|
||||
last_month_commentors = discussions_last_month_commentors
|
||||
# authors = {**issues_authors, **discussions_authors}
|
||||
authors = {**discussions_authors}
|
||||
return commentors, last_month_commentors, authors
|
||||
|
||||
|
||||
|
||||
1
.github/workflows/notify-translations.yml
vendored
1
.github/workflows/notify-translations.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
notify-translations:
|
||||
|
||||
3
.github/workflows/people.yml
vendored
3
.github/workflows/people.yml
vendored
@@ -15,6 +15,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# Ref: https://github.com/actions/runner/issues/2033
|
||||
- name: Fix git safe.directory in container
|
||||
run: mkdir -p /home/runner/work/_temp/_github_home && printf "[safe]\n\tdirectory = /github/workspace" > /home/runner/work/_temp/_github_home/.gitconfig
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
|
||||
2
.github/workflows/preview-docs.yml
vendored
2
.github/workflows/preview-docs.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
rm -rf ./site
|
||||
mkdir ./site
|
||||
- name: Download Artifact Docs
|
||||
uses: dawidd6/action-download-artifact@v2.24.3
|
||||
uses: dawidd6/action-download-artifact@v2.26.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build-docs.yml
|
||||
|
||||
2
.github/workflows/smokeshow.yml
vendored
2
.github/workflows/smokeshow.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
- run: pip install smokeshow
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2.24.3
|
||||
- uses: dawidd6/action-download-artifact@v2.26.0
|
||||
with:
|
||||
workflow: test.yml
|
||||
commit: ${{ github.event.workflow_run.head_sha }}
|
||||
|
||||
@@ -4,7 +4,7 @@ default_language_version:
|
||||
python: python3.10
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-toml
|
||||
@@ -14,14 +14,14 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.2.2
|
||||
rev: v3.3.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args:
|
||||
- --py3-plus
|
||||
- --keep-runtime-typing
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.138
|
||||
rev: v0.0.254
|
||||
hooks:
|
||||
- id: ruff
|
||||
args:
|
||||
@@ -38,7 +38,7 @@ repos:
|
||||
name: isort (pyi)
|
||||
types: [pyi]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.10.0
|
||||
rev: 23.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
ci:
|
||||
|
||||
@@ -102,6 +102,12 @@ The key features are:
|
||||
|
||||
---
|
||||
|
||||
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -81,7 +83,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -112,6 +114,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -132,6 +136,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -2,6 +2,9 @@ sponsors:
|
||||
- - login: jina-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
||||
url: https://github.com/jina-ai
|
||||
- - login: armand-sauzay
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35524799?u=56e3e944bfe62770d1709c09552d2efc6d285ca6&v=4
|
||||
url: https://github.com/armand-sauzay
|
||||
- - login: cryptapi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
||||
url: https://github.com/cryptapi
|
||||
@@ -35,21 +38,18 @@ sponsors:
|
||||
- - login: getsentry
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
|
||||
url: https://github.com/getsentry
|
||||
- - login: InesIvanova
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
|
||||
url: https://github.com/InesIvanova
|
||||
- - login: vyos
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4
|
||||
url: https://github.com/vyos
|
||||
- login: takashi-yoneya
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
|
||||
url: https://github.com/takashi-yoneya
|
||||
- login: mercedes-benz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
|
||||
url: https://github.com/mercedes-benz
|
||||
- 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
|
||||
@@ -59,6 +59,9 @@ sponsors:
|
||||
- login: HiredScore
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
|
||||
url: https://github.com/HiredScore
|
||||
- login: ianshan0915
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5893101?u=a178d247d882578b1d1ef214b2494e52eb28634c&v=4
|
||||
url: https://github.com/ianshan0915
|
||||
- login: Trivie
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
||||
url: https://github.com/Trivie
|
||||
@@ -119,9 +122,6 @@ sponsors:
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- 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
|
||||
@@ -137,18 +137,15 @@ sponsors:
|
||||
- login: jqueguiner
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
|
||||
url: https://github.com/jqueguiner
|
||||
- login: iobruno
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/901651?u=460bc34ac298dca9870aafe3a1560a2ae789bc4a&v=4
|
||||
url: https://github.com/iobruno
|
||||
- login: tcsmith
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4
|
||||
url: https://github.com/tcsmith
|
||||
- login: ltieman
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
|
||||
url: https://github.com/ltieman
|
||||
- login: mrkmcknz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4
|
||||
url: https://github.com/mrkmcknz
|
||||
- login: theonlynexus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1515004?v=4
|
||||
url: https://github.com/theonlynexus
|
||||
- login: coffeewasmyidea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4
|
||||
url: https://github.com/coffeewasmyidea
|
||||
@@ -156,11 +153,8 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1906344?u=5ca0c9a1a89b6a2ba31abe35c66bdc07af60a632&v=4
|
||||
url: https://github.com/jonakoudijs
|
||||
- login: corleyma
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=c61f9a4bbc45a45f5d855f93e5f6e0fc8b32c468&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
|
||||
- login: andre1sk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4
|
||||
url: https://github.com/andre1sk
|
||||
@@ -182,15 +176,9 @@ sponsors:
|
||||
- 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: jgreys
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=c66ae617d614f6c886f1f1c1799d22100b3c848d&v=4
|
||||
url: https://github.com/jgreys
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
@@ -203,6 +191,9 @@ sponsors:
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=fabc8d75c921b3380126adb5a931c5da6e7db04f&v=4
|
||||
url: https://github.com/ternaus
|
||||
- login: eseglem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
|
||||
url: https://github.com/eseglem
|
||||
- login: Yaleesa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
|
||||
url: https://github.com/Yaleesa
|
||||
@@ -243,8 +234,14 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: pablonnaoji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=7480e0eaf959e9c5dfe3a05286f2ea4588c0a3c6&v=4
|
||||
url: https://github.com/pablonnaoji
|
||||
- login: mjohnsey
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
|
||||
url: https://github.com/mjohnsey
|
||||
- login: abdalla19977
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17257234?v=4
|
||||
url: https://github.com/abdalla19977
|
||||
- login: wedwardbeck
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
|
||||
url: https://github.com/wedwardbeck
|
||||
@@ -254,6 +251,9 @@ sponsors:
|
||||
- login: shuheng-liu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
|
||||
url: https://github.com/shuheng-liu
|
||||
- login: Pablongo24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24843427?u=78a6798469889d7a0690449fc667c39e13d5c6a9&v=4
|
||||
url: https://github.com/Pablongo24
|
||||
- login: Joeriksson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25037079?v=4
|
||||
url: https://github.com/Joeriksson
|
||||
@@ -284,9 +284,12 @@ sponsors:
|
||||
- login: ProteinQure
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
|
||||
url: https://github.com/ProteinQure
|
||||
- login: AbdulwahabDev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34792253?u=9d27cbb6e196c95d747abf002df7fe0539764265&v=4
|
||||
url: https://github.com/AbdulwahabDev
|
||||
- login: askurihin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4
|
||||
url: https://github.com/askurihin
|
||||
- login: arleybri18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39681546?u=5c028f81324b0e8c73b3c15bc4e7b0218d2ba0c3&v=4
|
||||
url: https://github.com/arleybri18
|
||||
- login: ybressler
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
|
||||
url: https://github.com/ybressler
|
||||
@@ -300,11 +303,14 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
|
||||
url: https://github.com/rafsaf
|
||||
- login: dudikbender
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4
|
||||
url: https://github.com/dudikbender
|
||||
- login: thisistheplace
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57633545?u=a3f3a7f8ace8511c6c067753f6eb6aee0db11ac6&v=4
|
||||
url: https://github.com/thisistheplace
|
||||
- login: kyjoconn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58443406?u=a3e9c2acfb7ba62edda9334aba61cf027f41f789&v=4
|
||||
url: https://github.com/kyjoconn
|
||||
- login: A-Edge
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
|
||||
url: https://github.com/A-Edge
|
||||
@@ -317,9 +323,6 @@ sponsors:
|
||||
- login: predictionmachine
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
|
||||
url: https://github.com/predictionmachine
|
||||
- login: minsau
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64386242?u=7e45f24b2958caf946fa3546ea33bacf5cd886f8&v=4
|
||||
url: https://github.com/minsau
|
||||
- login: daverin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
|
||||
url: https://github.com/daverin
|
||||
@@ -329,16 +332,19 @@ sponsors:
|
||||
- login: DelfinaCare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||
url: https://github.com/DelfinaCare
|
||||
- login: programvx
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/96057906?v=4
|
||||
url: https://github.com/programvx
|
||||
- login: osawa-koki
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/94336223?u=59c6fe6945bcbbaff87b2a794238671b060620d2&v=4
|
||||
url: https://github.com/osawa-koki
|
||||
- login: pyt3h
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
|
||||
url: https://github.com/pyt3h
|
||||
- login: Dagmaara
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4
|
||||
url: https://github.com/Dagmaara
|
||||
- - login: linux-china
|
||||
- - login: pawamoy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||
url: https://github.com/pawamoy
|
||||
- login: linux-china
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46711?u=cd77c65338b158750eb84dc7ff1acf3209ccfc4f&v=4
|
||||
url: https://github.com/linux-china
|
||||
- login: ddanier
|
||||
@@ -353,12 +359,6 @@ sponsors:
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: hhatto
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/150309?u=3e8f63c27bf996bfc68464b0ce3f7a3e40e6ea7f&v=4
|
||||
url: https://github.com/hhatto
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: adamghill
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4
|
||||
url: https://github.com/adamghill
|
||||
@@ -380,12 +380,6 @@ sponsors:
|
||||
- login: janfilips
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=50de77b93d3a0b06887e672d4e8c7b9d643085aa&v=4
|
||||
url: https://github.com/janfilips
|
||||
- login: woodrad
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4
|
||||
url: https://github.com/woodrad
|
||||
- login: Pytlicek
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=01b1f2f7671ce3131e0877d08e2e3f8bdbb0a38a&v=4
|
||||
url: https://github.com/Pytlicek
|
||||
- login: allen0125
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4
|
||||
url: https://github.com/allen0125
|
||||
@@ -398,9 +392,6 @@ sponsors:
|
||||
- login: cbonoz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
|
||||
url: https://github.com/cbonoz
|
||||
- login: Debakel
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2857237?u=07df6d11c8feef9306d071cb1c1005a2dd596585&v=4
|
||||
url: https://github.com/Debakel
|
||||
- login: paul121
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
|
||||
url: https://github.com/paul121
|
||||
@@ -410,12 +401,6 @@ sponsors:
|
||||
- login: anthonycorletti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
||||
url: https://github.com/anthonycorletti
|
||||
- login: jonathanhle
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3851599?u=76b9c5d2fecd6c3a16e7645231878c4507380d4d&v=4
|
||||
url: https://github.com/jonathanhle
|
||||
- login: pawamoy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||
url: https://github.com/pawamoy
|
||||
- login: nikeee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4
|
||||
url: https://github.com/nikeee
|
||||
@@ -431,11 +416,14 @@ sponsors:
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
- login: holec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
|
||||
url: https://github.com/holec
|
||||
- login: mattwelke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7719209?v=4
|
||||
url: https://github.com/mattwelke
|
||||
- login: hcristea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
|
||||
@@ -443,9 +431,6 @@ sponsors:
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- login: yenchenLiu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
|
||||
url: https://github.com/yenchenLiu
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
|
||||
url: https://github.com/xncbf
|
||||
@@ -470,12 +455,9 @@ sponsors:
|
||||
- login: giuliano-oliveira
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4
|
||||
url: https://github.com/giuliano-oliveira
|
||||
- login: logan-connolly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
|
||||
url: https://github.com/logan-connolly
|
||||
- login: harripj
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16853829?u=14db1ad132af9ec340f3f1da564620a73b6e4981&v=4
|
||||
url: https://github.com/harripj
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b2923ac17fe6e2a7c9ea14800351ddb92f79b100&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: cdsre
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
|
||||
url: https://github.com/cdsre
|
||||
@@ -485,15 +467,9 @@ sponsors:
|
||||
- login: paulowiz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4
|
||||
url: https://github.com/paulowiz
|
||||
- login: yannicschroeer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=91515328b5418a4e7289a83f0dcec3573f1a6500&v=4
|
||||
url: https://github.com/yannicschroeer
|
||||
- login: ghandic
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||
url: https://github.com/ghandic
|
||||
- login: fstau
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4
|
||||
url: https://github.com/fstau
|
||||
- login: pers0n4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=f211a13a7b572cbbd7779b9c8d8cb428cc7ba07e&v=4
|
||||
url: https://github.com/pers0n4
|
||||
@@ -534,26 +510,14 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38921751?u=ae14bc1e40f2dd5a9c5741fc0b0dffbd416a5fa9&v=4
|
||||
url: https://github.com/ww-daniel-mora
|
||||
- login: rwxd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=34cba2eaca6a52072498e06bccebe141694fe1d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4
|
||||
url: https://github.com/rwxd
|
||||
- login: ilias-ant
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a84d169eb6f6bbcb85434c2bed0b4a6d4d13c10e&v=4
|
||||
url: https://github.com/ilias-ant
|
||||
- login: arrrrrmin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=2a812c1a2ec58227ed01778837f255143de9df97&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=5265858add14a6822bd145f7547323cf078563e6&v=4
|
||||
url: https://github.com/arrrrrmin
|
||||
- login: MauriceKuenicke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47433175?u=37455bc95c7851db296ac42626f0cacb77ca2443&v=4
|
||||
url: https://github.com/MauriceKuenicke
|
||||
- login: hgalytoby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4
|
||||
url: https://github.com/hgalytoby
|
||||
- login: akanz1
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
|
||||
url: https://github.com/akanz1
|
||||
- login: shidenko97
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54946990?u=3fdc0caea36af9217dacf1cc7760c7ed9d67dcfe&v=4
|
||||
url: https://github.com/shidenko97
|
||||
- login: data-djinn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56449985?u=42146e140806908d49bd59ccc96f222abf587886&v=4
|
||||
url: https://github.com/data-djinn
|
||||
@@ -572,27 +536,12 @@ sponsors:
|
||||
- login: realabja
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66185192?u=001e2dd9297784f4218997981b4e6fa8357bb70b&v=4
|
||||
url: https://github.com/realabja
|
||||
- login: pondDevThai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4
|
||||
url: https://github.com/pondDevThai
|
||||
- login: lukzmu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80778518?u=f636ad03cab8e8de15183fa81e768bfad3f515d0&v=4
|
||||
url: https://github.com/lukzmu
|
||||
- - login: chrislemke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11752694?u=70ceb6ee7c51d9a52302ab9220ffbf09eaa9c2a4&v=4
|
||||
url: https://github.com/chrislemke
|
||||
- login: gabrielmbmb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
|
||||
url: https://github.com/gabrielmbmb
|
||||
- login: garydsong
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/105745865?u=03cc1aa9c978be0020e5a1ce1ecca323dd6c8d65&v=4
|
||||
url: https://github.com/garydsong
|
||||
- - login: Leon0824
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1922026?v=4
|
||||
url: https://github.com/Leon0824
|
||||
- login: danburonline
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
||||
url: https://github.com/danburonline
|
||||
- login: buabaj
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/49881677?u=a85952891036eb448f86eb847902f25badd5f9f7&v=4
|
||||
url: https://github.com/buabaj
|
||||
- login: SoulPancake
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70265851?u=9cdd82f2835da7d6a56a2e29e1369d5bf251e8f2&v=4
|
||||
url: https://github.com/SoulPancake
|
||||
- login: junah201
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/75025529?u=2451c256e888fa2a06bcfc0646d09b87ddb6a945&v=4
|
||||
url: https://github.com/junah201
|
||||
|
||||
@@ -1,162 +1,158 @@
|
||||
maintainers:
|
||||
- login: tiangolo
|
||||
answers: 1956
|
||||
prs: 372
|
||||
answers: 1827
|
||||
prs: 384
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
|
||||
url: https://github.com/tiangolo
|
||||
experts:
|
||||
- login: Kludex
|
||||
count: 400
|
||||
count: 376
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
count: 262
|
||||
count: 237
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: ycd
|
||||
count: 224
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: Mause
|
||||
count: 223
|
||||
count: 220
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: ycd
|
||||
count: 217
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: JarroVGIT
|
||||
count: 196
|
||||
count: 192
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: euri10
|
||||
count: 166
|
||||
count: 151
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: phy25
|
||||
count: 130
|
||||
count: 126
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
||||
url: https://github.com/phy25
|
||||
- login: iudeen
|
||||
count: 118
|
||||
count: 116
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: jgould22
|
||||
count: 95
|
||||
count: 101
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: raphaelauv
|
||||
count: 79
|
||||
count: 83
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
url: https://github.com/raphaelauv
|
||||
- login: ArcLightSlavik
|
||||
count: 74
|
||||
count: 71
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: ghandic
|
||||
count: 72
|
||||
count: 71
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||
url: https://github.com/ghandic
|
||||
- login: falkben
|
||||
count: 59
|
||||
count: 57
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: sm-Fifteen
|
||||
count: 52
|
||||
count: 49
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||
url: https://github.com/sm-Fifteen
|
||||
- login: insomnes
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: Dustyposa
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: acidjunk
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: adriangb
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: insomnes
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: frankie567
|
||||
count: 41
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: acidjunk
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: odiseo0
|
||||
count: 42
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: adriangb
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: includeamin
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||
url: https://github.com/includeamin
|
||||
- login: odiseo0
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: STeveShary
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
|
||||
url: https://github.com/STeveShary
|
||||
- login: chbndrhnns
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: krishnardt
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
|
||||
url: https://github.com/krishnardt
|
||||
- login: prostomarkeloff
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||
url: https://github.com/prostomarkeloff
|
||||
- login: yinziyan1206
|
||||
count: 33
|
||||
count: 34
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: chbndrhnns
|
||||
count: 34
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: panla
|
||||
count: 32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
||||
url: https://github.com/panla
|
||||
- login: wshayes
|
||||
count: 29
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: prostomarkeloff
|
||||
count: 28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||
url: https://github.com/prostomarkeloff
|
||||
- login: dbanty
|
||||
count: 26
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
|
||||
url: https://github.com/dbanty
|
||||
- login: wshayes
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: SirTelemak
|
||||
count: 24
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: acnebs
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: nsidnev
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
|
||||
url: https://github.com/nsidnev
|
||||
- login: chris-allnutt
|
||||
- login: caeser1996
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
||||
url: https://github.com/chris-allnutt
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4
|
||||
url: https://github.com/caeser1996
|
||||
- login: rafsaf
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
|
||||
url: https://github.com/rafsaf
|
||||
- login: Hultner
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||
url: https://github.com/Hultner
|
||||
- login: nsidnev
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
|
||||
url: https://github.com/nsidnev
|
||||
- login: acnebs
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: chris-allnutt
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
||||
url: https://github.com/chris-allnutt
|
||||
- login: retnikt
|
||||
count: 19
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
||||
url: https://github.com/retnikt
|
||||
- login: zoliknemet
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
|
||||
url: https://github.com/zoliknemet
|
||||
- login: jorgerpo
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
||||
url: https://github.com/jorgerpo
|
||||
- login: nkhitrov
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
|
||||
@@ -165,75 +161,79 @@ experts:
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
|
||||
url: https://github.com/harunyasar
|
||||
- login: waynerv
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: dstlny
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||
url: https://github.com/dstlny
|
||||
- login: Hultner
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||
url: https://github.com/Hultner
|
||||
- login: jonatasoli
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||
url: https://github.com/jonatasoli
|
||||
- login: hellocoldworld
|
||||
- login: dstlny
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||
url: https://github.com/dstlny
|
||||
- login: jorgerpo
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4
|
||||
url: https://github.com/hellocoldworld
|
||||
- login: mbroton
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
||||
url: https://github.com/jorgerpo
|
||||
- login: ghost
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
|
||||
url: https://github.com/mbroton
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4
|
||||
url: https://github.com/ghost
|
||||
- login: simondale00
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33907262?v=4
|
||||
url: https://github.com/simondale00
|
||||
- login: haizaar
|
||||
- login: hellocoldworld
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4
|
||||
url: https://github.com/hellocoldworld
|
||||
- login: waynerv
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: mbroton
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4
|
||||
url: https://github.com/haizaar
|
||||
- login: n8sty
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
|
||||
url: https://github.com/mbroton
|
||||
last_month_active:
|
||||
- login: jgould22
|
||||
- login: mr-st0rm
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: yinziyan1206
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: Kludex
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: moadennagi
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16942283?v=4
|
||||
url: https://github.com/moadennagi
|
||||
- login: iudeen
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: anthonycorletti
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
||||
url: https://github.com/anthonycorletti
|
||||
- login: ThirVondukr
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50728601?u=56010d6430583b2096a96f0946501156cdb79c75&v=4
|
||||
url: https://github.com/ThirVondukr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/48455163?u=6b83550e4e70bea57cd2fdb41e717aeab7f64a91&v=4
|
||||
url: https://github.com/mr-st0rm
|
||||
- login: caeser1996
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4
|
||||
url: https://github.com/caeser1996
|
||||
- login: ebottos94
|
||||
count: 4
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4
|
||||
url: https://github.com/ebottos94
|
||||
- login: odiseo0
|
||||
- login: jgould22
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: Kludex
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: clemens-tolboom
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/371014?v=4
|
||||
url: https://github.com/clemens-tolboom
|
||||
- login: williamjamir
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5083518?u=b76ca8e08b906a86fa195fb817dd94e8d9d3d8f6&v=4
|
||||
url: https://github.com/williamjamir
|
||||
- login: nymous
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4
|
||||
url: https://github.com/nymous
|
||||
- login: frankie567
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
|
||||
url: https://github.com/frankie567
|
||||
top_contributors:
|
||||
- login: waynerv
|
||||
count: 25
|
||||
@@ -243,6 +243,10 @@ top_contributors:
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
- login: Kludex
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: jaystone776
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
||||
@@ -251,10 +255,6 @@ top_contributors:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: Kludex
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: euri10
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
@@ -283,6 +283,10 @@ top_contributors:
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: batlopes
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
|
||||
url: https://github.com/batlopes
|
||||
- login: wshayes
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
@@ -301,12 +305,12 @@ top_contributors:
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: NinaHwang
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4
|
||||
url: https://github.com/NinaHwang
|
||||
- login: batlopes
|
||||
- login: Xewus
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
|
||||
url: https://github.com/batlopes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: jekirl
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
|
||||
@@ -335,21 +339,17 @@ top_contributors:
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: Xewus
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=4bdd4a0300530a504987db27488ba79c37f2fb18&v=4
|
||||
url: https://github.com/Xewus
|
||||
top_reviewers:
|
||||
- login: Kludex
|
||||
count: 110
|
||||
count: 111
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: BilalAlpaslan
|
||||
count: 72
|
||||
count: 75
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
||||
url: https://github.com/BilalAlpaslan
|
||||
- login: yezz123
|
||||
count: 70
|
||||
count: 71
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
||||
url: https://github.com/yezz123
|
||||
- login: tokusumi
|
||||
@@ -404,24 +404,24 @@ top_reviewers:
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: LorhanSohaky
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
- login: rjNemo
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: hard-coders
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: LorhanSohaky
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
- login: 0417taehyun
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
||||
url: https://github.com/0417taehyun
|
||||
- login: rjNemo
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: odiseo0
|
||||
count: 18
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: Smlep
|
||||
@@ -452,26 +452,30 @@ top_reviewers:
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
|
||||
url: https://github.com/delhi09
|
||||
- login: Ryandaydev
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: Xewus
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: sh0nk
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
||||
url: https://github.com/sh0nk
|
||||
- login: peidrao
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5401640e0b961cc199dee39ec79e162c7833cd6b&v=4
|
||||
url: https://github.com/peidrao
|
||||
- login: RunningIkkyu
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4
|
||||
url: https://github.com/RunningIkkyu
|
||||
- login: Ryandaydev
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: solomein-sv
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
|
||||
url: https://github.com/solomein-sv
|
||||
- login: Xewus
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=4bdd4a0300530a504987db27488ba79c37f2fb18&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: mariacamilagl
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||
@@ -488,10 +492,10 @@ top_reviewers:
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: peidrao
|
||||
- login: r0b2g1t
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5401640e0b961cc199dee39ec79e162c7833cd6b&v=4
|
||||
url: https://github.com/peidrao
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5357541?u=6428442d875d5d71aaa1bb38bb11c4be1a526bc2&v=4
|
||||
url: https://github.com/r0b2g1t
|
||||
- login: izaguerreiro
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
|
||||
@@ -532,7 +536,3 @@ top_reviewers:
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
|
||||
url: https://github.com/rogerbrinkmann
|
||||
- login: NinaHwang
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||
url: https://github.com/NinaHwang
|
||||
|
||||
@@ -15,3 +15,4 @@ logins:
|
||||
- Doist
|
||||
- nihpo
|
||||
- svix
|
||||
- armand-sauzay
|
||||
|
||||
@@ -1,13 +1,108 @@
|
||||
# Events: startup - shutdown
|
||||
# Lifespan Events
|
||||
|
||||
You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**.
|
||||
|
||||
The same way, you can define logic (code) that should be executed when the application is **shutting down**. In this case, this code will be executed **once**, **after** having handled possibly **many requests**.
|
||||
|
||||
Because this code is executed before the application **starts** taking requests, and right after it **finishes** handling requests, it covers the whole application **lifespan** (the word "lifespan" will be important in a second 😉).
|
||||
|
||||
This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model.
|
||||
|
||||
## Use Case
|
||||
|
||||
Let's start with an example **use case** and then see how to solve it with this.
|
||||
|
||||
Let's imagine that you have some **machine learning models** that you want to use to handle requests. 🤖
|
||||
|
||||
The same models are shared among requests, so, it's not one model per request, or one per user or something similar.
|
||||
|
||||
Let's imagine that loading the model can **take quite some time**, because it has to read a lot of **data from disk**. So you don't want to do it for every request.
|
||||
|
||||
You could load it at the top level of the module/file, but that would also mean that it would **load the model** even if you are just running a simple automated test, then that test would be **slow** because it would have to wait for the model to load before being able to run an independent part of the code.
|
||||
|
||||
That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while the code is being loaded.
|
||||
|
||||
## Lifespan
|
||||
|
||||
You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second).
|
||||
|
||||
Let's start with an example and then see it in detail.
|
||||
|
||||
We create an async function `lifespan()` with `yield` like this:
|
||||
|
||||
```Python hl_lines="16 19"
|
||||
{!../../../docs_src/events/tutorial003.py!}
|
||||
```
|
||||
|
||||
Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*.
|
||||
|
||||
And then, right after the `yield`, we unload the model. This code will be executed **after** the application **finishes handling requests**, right before the *shutdown*. This could, for example, release resources like memory or a GPU.
|
||||
|
||||
!!! tip
|
||||
The `shutdown` would happen when you are **stopping** the application.
|
||||
|
||||
Maybe you need to start a new version, or you just got tired of running it. 🤷
|
||||
|
||||
### Lifespan function
|
||||
|
||||
The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`.
|
||||
|
||||
```Python hl_lines="14-19"
|
||||
{!../../../docs_src/events/tutorial003.py!}
|
||||
```
|
||||
|
||||
The first part of the function, before the `yield`, will be executed **before** the application starts.
|
||||
|
||||
And the part after the `yield` will be executed **after** the application has finished.
|
||||
|
||||
### Async Context Manager
|
||||
|
||||
If you check, the function is decorated with an `@asynccontextmanager`.
|
||||
|
||||
That converts the function into something called an "**async context manager**".
|
||||
|
||||
```Python hl_lines="1 13"
|
||||
{!../../../docs_src/events/tutorial003.py!}
|
||||
```
|
||||
|
||||
A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager:
|
||||
|
||||
```Python
|
||||
with open("file.txt") as file:
|
||||
file.read()
|
||||
```
|
||||
|
||||
In recent versions of Python, there's also an **async context manager**. You would use it with `async with`:
|
||||
|
||||
```Python
|
||||
async with lifespan(app):
|
||||
await do_stuff()
|
||||
```
|
||||
|
||||
When you create a context manager or an async context manager like above, what it does is that, before entering the `with` block, it will execute the code before the `yield`, and after exiting the `with` block, it will execute the code after the `yield`.
|
||||
|
||||
In our code example above, we don't use it directly, but we pass it to FastAPI for it to use it.
|
||||
|
||||
The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it.
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!../../../docs_src/events/tutorial003.py!}
|
||||
```
|
||||
|
||||
## Alternative Events (deprecated)
|
||||
|
||||
!!! warning
|
||||
The recommended way to handle the *startup* and *shutdown* is using the `lifespan` parameter of the `FastAPI` app as described above.
|
||||
|
||||
You can probably skip this part.
|
||||
|
||||
There's an alternative way to define this logic to be executed during *startup* and during *shutdown*.
|
||||
|
||||
You can define event handlers (functions) that need to be executed before the application starts up, or when the application is shutting down.
|
||||
|
||||
These functions can be declared with `async def` or normal `def`.
|
||||
|
||||
!!! warning
|
||||
Only event handlers for the main application will be executed, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
|
||||
|
||||
## `startup` event
|
||||
### `startup` event
|
||||
|
||||
To add a function that should be run before the application starts, declare it with the event `"startup"`:
|
||||
|
||||
@@ -21,7 +116,7 @@ You can add more than one event handler function.
|
||||
|
||||
And your application won't start receiving requests until all the `startup` event handlers have completed.
|
||||
|
||||
## `shutdown` event
|
||||
### `shutdown` event
|
||||
|
||||
To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`:
|
||||
|
||||
@@ -43,5 +138,25 @@ Here, the `shutdown` event handler function will write a text line `"Application
|
||||
|
||||
So, we declare the event handler function with standard `def` instead of `async def`.
|
||||
|
||||
### `startup` and `shutdown` together
|
||||
|
||||
There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc.
|
||||
|
||||
Doing that in separated functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks.
|
||||
|
||||
Because of that, it's now recommended to instead use the `lifespan` as explained above.
|
||||
|
||||
## Technical Details
|
||||
|
||||
Just a technical detail for the curious nerds. 🤓
|
||||
|
||||
Underneath, in the ASGI technical specification, this is part of the <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Lifespan Protocol</a>, and it defines events called `startup` and `shutdown`.
|
||||
|
||||
!!! info
|
||||
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.
|
||||
You can read more about the Starlette `lifespan` handlers in <a href="https://www.starlette.io/lifespan/" class="external-link" target="_blank">Starlette's Lifespan' docs</a>.
|
||||
|
||||
Including how to handle lifespan state that can be used in other areas of your code.
|
||||
|
||||
## Sub Applications
|
||||
|
||||
🚨 Have in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
|
||||
|
||||
@@ -92,7 +92,7 @@ There are many other ASGI middlewares.
|
||||
|
||||
For example:
|
||||
|
||||
* <a href="https://docs.sentry.io/platforms/python/asgi/" class="external-link" target="_blank">Sentry</a>
|
||||
* <a href="https://docs.sentry.io/platforms/python/guides/fastapi/" class="external-link" target="_blank">Sentry</a>
|
||||
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn's `ProxyHeadersMiddleware`</a>
|
||||
* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
|
||||
|
||||
|
||||
@@ -99,6 +99,12 @@ The key features are:
|
||||
|
||||
---
|
||||
|
||||
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Project Generation - Template
|
||||
|
||||
You can use a project generator to get started, as it includes a lot of the initial set up, security, database and first API endpoints already done for you.
|
||||
You can use a project generator to get started, as it includes a lot of the initial set up, security, database and some API endpoints already done for you.
|
||||
|
||||
A project generator will always have a very opinionated setup that you should update and adapt for your own needs, but it might be a good starting point for your project.
|
||||
|
||||
|
||||
@@ -3,6 +3,143 @@
|
||||
## Latest Changes
|
||||
|
||||
|
||||
## 0.94.1
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🎨 Fix types for lifespan, upgrade Starlette to 0.26.1. PR [#9245](https://github.com/tiangolo/fastapi/pull/9245) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.94.0
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆ Upgrade python-multipart to support 0.0.6. PR [#9212](https://github.com/tiangolo/fastapi/pull/9212) by [@musicinmybrain](https://github.com/musicinmybrain).
|
||||
* ⬆️ Upgrade Starlette version, support new `lifespan` with state. PR [#9239](https://github.com/tiangolo/fastapi/pull/9239) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Update Sentry link in docs. PR [#9218](https://github.com/tiangolo/fastapi/pull/9218) by [@smeubank](https://github.com/smeubank).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/history-design-future.md`. PR [#5986](https://github.com/tiangolo/fastapi/pull/5986) by [@Xewus](https://github.com/Xewus).
|
||||
|
||||
### Internal
|
||||
|
||||
* ➕ Add `pydantic` to PyPI classifiers. PR [#5914](https://github.com/tiangolo/fastapi/pull/5914) by [@yezz123](https://github.com/yezz123).
|
||||
* ⬆ Bump black from 22.10.0 to 23.1.0. PR [#5953](https://github.com/tiangolo/fastapi/pull/5953) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Bump types-ujson from 5.6.0.0 to 5.7.0.1. PR [#6027](https://github.com/tiangolo/fastapi/pull/6027) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Bump dawidd6/action-download-artifact from 2.24.3 to 2.26.0. PR [#6034](https://github.com/tiangolo/fastapi/pull/6034) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5709](https://github.com/tiangolo/fastapi/pull/5709) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
|
||||
## 0.93.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support for `lifespan` async context managers (superseding `startup` and `shutdown` events). Initial PR [#2944](https://github.com/tiangolo/fastapi/pull/2944) by [@uSpike](https://github.com/uSpike).
|
||||
|
||||
Now, instead of using independent `startup` and `shutdown` events, you can define that logic in a single function with `yield` decorated with `@asynccontextmanager` (an async context manager).
|
||||
|
||||
For example:
|
||||
|
||||
```Python
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
|
||||
def fake_answer_to_everything_ml_model(x: float):
|
||||
return x * 42
|
||||
|
||||
|
||||
ml_models = {}
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Load the ML model
|
||||
ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
|
||||
yield
|
||||
# Clean up the ML models and release the resources
|
||||
ml_models.clear()
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
|
||||
@app.get("/predict")
|
||||
async def predict(x: float):
|
||||
result = ml_models["answer_to_everything"](x)
|
||||
return {"result": result}
|
||||
```
|
||||
|
||||
**Note**: This is the recommended way going forward, instead of using `startup` and `shutdown` events.
|
||||
|
||||
Read more about it in the new docs: [Advanced User Guide: Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Fix formatting in `docs/en/docs/tutorial/metadata.md` for `ReDoc`. PR [#6005](https://github.com/tiangolo/fastapi/pull/6005) by [@eykamp](https://github.com/eykamp).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Tamil translations - initial setup. PR [#5564](https://github.com/tiangolo/fastapi/pull/5564) by [@gusty1g](https://github.com/gusty1g).
|
||||
* 🌐 Add French translation for `docs/fr/docs/advanced/path-operation-advanced-configuration.md`. PR [#9221](https://github.com/tiangolo/fastapi/pull/9221) by [@axel584](https://github.com/axel584).
|
||||
* 🌐 Add French translation for `docs/tutorial/debugging.md`. PR [#9175](https://github.com/tiangolo/fastapi/pull/9175) by [@frabc](https://github.com/frabc).
|
||||
* 🌐 Initiate Armenian translation setup. PR [#5844](https://github.com/tiangolo/fastapi/pull/5844) by [@har8](https://github.com/har8).
|
||||
* 🌐 Add French translation for `deployment/manually.md`. PR [#3693](https://github.com/tiangolo/fastapi/pull/3693) by [@rjNemo](https://github.com/rjNemo).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👷 Update translation bot messages. PR [#9206](https://github.com/tiangolo/fastapi/pull/9206) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Update translations bot to use Discussions, and notify when a PR is done. PR [#9183](https://github.com/tiangolo/fastapi/pull/9183) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update sponsors-badges. PR [#9182](https://github.com/tiangolo/fastapi/pull/9182) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#9181](https://github.com/tiangolo/fastapi/pull/9181) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 🔊 Log GraphQL errors in FastAPI People, because it returns 200, with a payload with an error. PR [#9171](https://github.com/tiangolo/fastapi/pull/9171) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 💚 Fix/workaround GitHub Actions in Docker with git for FastAPI People. PR [#9169](https://github.com/tiangolo/fastapi/pull/9169) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ♻️ Refactor FastAPI Experts to use only discussions now that questions are migrated. PR [#9165](https://github.com/tiangolo/fastapi/pull/9165) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade analytics. PR [#6025](https://github.com/tiangolo/fastapi/pull/6025) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade and re-enable installing Typer-CLI. PR [#6008](https://github.com/tiangolo/fastapi/pull/6008) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.92.0
|
||||
|
||||
🚨 This is a security fix. Please upgrade as soon as possible.
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette to 0.25.0. PR [#5996](https://github.com/tiangolo/fastapi/pull/5996) by [@tiangolo](https://github.com/tiangolo).
|
||||
* This solves a vulnerability that could allow denial of service attacks by using many small multipart fields/files (parts), consuming high CPU and memory.
|
||||
* Only applications using forms (e.g. file uploads) could be affected.
|
||||
* For most cases, upgrading won't have any breaking changes.
|
||||
|
||||
## 0.91.0
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette version to `0.24.0` and refactor internals for compatibility. PR [#5985](https://github.com/tiangolo/fastapi/pull/5985) by [@tiangolo](https://github.com/tiangolo).
|
||||
* This can solve nuanced errors when using middlewares. Before Starlette `0.24.0`, a new instance of each middleware class would be created when a new middleware was added. That normally was not a problem, unless the middleware class expected to be created only once, with only one instance, that happened in some cases. This upgrade would solve those cases (thanks [@adriangb](https://github.com/adriangb)! Starlette PR [#2017](https://github.com/encode/starlette/pull/2017)). Now the middleware class instances are created once, right before the first request (the first time the app is called).
|
||||
* If you depended on that previous behavior, you might need to update your code. As always, make sure your tests pass before merging the upgrade.
|
||||
|
||||
## 0.90.1
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette range to allow 0.23.1. PR [#5980](https://github.com/tiangolo/fastapi/pull/5980) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Tweak wording to clarify `docs/en/docs/project-generation.md`. PR [#5930](https://github.com/tiangolo/fastapi/pull/5930) by [@chandra-deb](https://github.com/chandra-deb).
|
||||
* ✏ Update Pydantic GitHub URLs. PR [#5952](https://github.com/tiangolo/fastapi/pull/5952) by [@yezz123](https://github.com/yezz123).
|
||||
* 📝 Add opinion from Cisco. PR [#5981](https://github.com/tiangolo/fastapi/pull/5981) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-params.md`. PR [#5890](https://github.com/tiangolo/fastapi/pull/5890) by [@bnzone](https://github.com/bnzone).
|
||||
|
||||
### Internal
|
||||
|
||||
* ✏ Update `zip-docs.sh` internal script, remove extra space. PR [#5931](https://github.com/tiangolo/fastapi/pull/5931) by [@JuanPerdomo00](https://github.com/JuanPerdomo00).
|
||||
|
||||
## 0.90.0
|
||||
|
||||
### Upgrades
|
||||
@@ -1241,7 +1378,7 @@ Thanks to [Dima Boger](https://twitter.com/b0g3r) for the security report! 🙇
|
||||
|
||||
### Security fixes
|
||||
|
||||
* 📌 Upgrade pydantic pin, to handle security vulnerability [CVE-2021-29510](https://github.com/samuelcolvin/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh). PR [#3213](https://github.com/tiangolo/fastapi/pull/3213) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📌 Upgrade pydantic pin, to handle security vulnerability [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh). PR [#3213](https://github.com/tiangolo/fastapi/pull/3213) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.65.0
|
||||
|
||||
@@ -1796,11 +1933,11 @@ Note: all the previous parameters are still there, so it's still possible to dec
|
||||
|
||||
## 0.55.1
|
||||
|
||||
* Fix handling of enums with their own schema in path parameters. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
|
||||
* Fix handling of enums with their own schema in path parameters. To support [pydantic/pydantic#1432](https://github.com/pydantic/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
|
||||
|
||||
## 0.55.0
|
||||
|
||||
* Allow enums to allow them to have their own schemas in OpenAPI. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).
|
||||
* Allow enums to allow them to have their own schemas in OpenAPI. To support [pydantic/pydantic#1432](https://github.com/pydantic/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).
|
||||
* Add links for funding through [GitHub sponsors](https://github.com/sponsors/tiangolo). PR [#1425](https://github.com/tiangolo/fastapi/pull/1425).
|
||||
* Update issue template for for questions. PR [#1344](https://github.com/tiangolo/fastapi/pull/1344) by [@retnikt](https://github.com/retnikt).
|
||||
* Update warning about storing passwords in docs. PR [#1336](https://github.com/tiangolo/fastapi/pull/1336) by [@skorokithakis](https://github.com/skorokithakis).
|
||||
|
||||
@@ -189,7 +189,7 @@ The end result is that the item paths are now:
|
||||
|
||||
### Import the dependencies
|
||||
|
||||
This codes lives in the module `app.routers.items`, the file `app/routers/items.py`.
|
||||
This code lives in the module `app.routers.items`, the file `app/routers/items.py`.
|
||||
|
||||
And we need to get the dependency function from the module `app.dependencies`, the file `app/dependencies.py`.
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ You can configure the two documentation user interfaces included:
|
||||
* **Swagger UI**: served at `/docs`.
|
||||
* You can set its URL with the parameter `docs_url`.
|
||||
* You can disable it by setting `docs_url=None`.
|
||||
* ReDoc: served at `/redoc`.
|
||||
* **ReDoc**: served at `/redoc`.
|
||||
* You can set its URL with the parameter `redoc_url`.
|
||||
* You can disable it by setting `redoc_url=None`.
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -187,7 +189,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -218,6 +220,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -238,6 +242,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -90,7 +92,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -121,6 +123,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -141,6 +145,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
168
docs/fr/docs/advanced/path-operation-advanced-configuration.md
Normal file
168
docs/fr/docs/advanced/path-operation-advanced-configuration.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Configuration avancée des paramètres de chemin
|
||||
|
||||
## ID d'opération OpenAPI
|
||||
|
||||
!!! Attention
|
||||
Si vous n'êtes pas un "expert" en OpenAPI, vous n'en avez probablement pas besoin.
|
||||
|
||||
Dans OpenAPI, les chemins sont des ressources, tels que /users/ ou /items/, exposées par votre API, et les opérations sont les méthodes HTTP utilisées pour manipuler ces chemins, telles que GET, POST ou DELETE. Les operationId sont des chaînes uniques facultatives utilisées pour identifier une opération d'un chemin. Vous pouvez définir l'OpenAPI `operationId` à utiliser dans votre *opération de chemin* avec le paramètre `operation_id`.
|
||||
|
||||
Vous devez vous assurer qu'il est unique pour chaque opération.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Utilisation du nom *path operation function* comme operationId
|
||||
|
||||
Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer chaque `operation_id` de l'*opération de chemin* en utilisant leur `APIRoute.name`.
|
||||
|
||||
Vous devriez le faire après avoir ajouté toutes vos *paramètres de chemin*.
|
||||
|
||||
```Python hl_lines="2 12-21 24"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! Astuce
|
||||
Si vous appelez manuellement `app.openapi()`, vous devez mettre à jour les `operationId` avant.
|
||||
|
||||
!!! Attention
|
||||
Pour faire cela, vous devez vous assurer que chacun de vos *chemin* ait un nom unique.
|
||||
|
||||
Même s'ils se trouvent dans des modules différents (fichiers Python).
|
||||
|
||||
## Exclusion d'OpenAPI
|
||||
|
||||
Pour exclure un *chemin* du schéma OpenAPI généré (et donc des systèmes de documentation automatiques), utilisez le paramètre `include_in_schema` et assignez-lui la valeur `False` :
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
|
||||
```
|
||||
|
||||
## Description avancée de docstring
|
||||
|
||||
Vous pouvez limiter le texte utilisé de la docstring d'une *fonction de chemin* qui sera affiché sur OpenAPI.
|
||||
|
||||
L'ajout d'un `\f` (un caractère d'échappement "form feed") va permettre à **FastAPI** de tronquer la sortie utilisée pour OpenAPI à ce stade.
|
||||
|
||||
Il n'apparaîtra pas dans la documentation, mais d'autres outils (tel que Sphinx) pourront utiliser le reste.
|
||||
|
||||
```Python hl_lines="19-29"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Réponses supplémentaires
|
||||
|
||||
Vous avez probablement vu comment déclarer le `response_model` et le `status_code` pour une *opération de chemin*.
|
||||
|
||||
Cela définit les métadonnées sur la réponse principale d'une *opération de chemin*.
|
||||
|
||||
Vous pouvez également déclarer des réponses supplémentaires avec leurs modèles, codes de statut, etc.
|
||||
|
||||
Il y a un chapitre entier ici dans la documentation à ce sujet, vous pouvez le lire sur [Réponses supplémentaires dans OpenAPI](./additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
## OpenAPI supplémentaire
|
||||
|
||||
Lorsque vous déclarez un *chemin* dans votre application, **FastAPI** génère automatiquement les métadonnées concernant ce *chemin* à inclure dans le schéma OpenAPI.
|
||||
|
||||
!!! note "Détails techniques"
|
||||
La spécification OpenAPI appelle ces métaonnées des <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objets d'opération</a>.
|
||||
|
||||
Il contient toutes les informations sur le *chemin* et est utilisé pour générer automatiquement la documentation.
|
||||
|
||||
Il inclut les `tags`, `parameters`, `requestBody`, `responses`, etc.
|
||||
|
||||
Ce schéma OpenAPI spécifique aux *operations* est normalement généré automatiquement par **FastAPI**, mais vous pouvez également l'étendre.
|
||||
|
||||
!!! Astuce
|
||||
Si vous avez seulement besoin de déclarer des réponses supplémentaires, un moyen plus pratique de le faire est d'utiliser les [réponses supplémentaires dans OpenAPI](./additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
Vous pouvez étendre le schéma OpenAPI pour une *opération de chemin* en utilisant le paramètre `openapi_extra`.
|
||||
|
||||
### Extensions OpenAPI
|
||||
|
||||
Cet `openapi_extra` peut être utile, par exemple, pour déclarer [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) :
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial005.py!}
|
||||
```
|
||||
|
||||
Si vous ouvrez la documentation automatique de l'API, votre extension apparaîtra au bas du *chemin* spécifique.
|
||||
|
||||
<img src="/img/tutorial/path-operation-advanced-configuration/image01.png">
|
||||
|
||||
Et dans le fichier openapi généré (`/openapi.json`), vous verrez également votre extension dans le cadre du *chemin* spécifique :
|
||||
|
||||
```JSON hl_lines="22"
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-aperture-labs-portal": "blue"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Personnalisation du Schéma OpenAPI pour un chemin
|
||||
|
||||
Le dictionnaire contenu dans la variable `openapi_extra` sera fusionné avec le schéma OpenAPI généré automatiquement pour l'*opération de chemin*.
|
||||
|
||||
Ainsi, vous pouvez ajouter des données supplémentaires au schéma généré automatiquement.
|
||||
|
||||
Par exemple, vous pouvez décider de lire et de valider la requête avec votre propre code, sans utiliser les fonctionnalités automatiques de validation proposée par Pydantic, mais vous pouvez toujours définir la requête dans le schéma OpenAPI.
|
||||
|
||||
Vous pouvez le faire avec `openapi_extra` :
|
||||
|
||||
```Python hl_lines="20-37 39-40"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial006.py !}
|
||||
```
|
||||
|
||||
Dans cet exemple, nous n'avons déclaré aucun modèle Pydantic. En fait, le corps de la requête n'est même pas <abbr title="converti d'un format simple, comme des octets, en objets Python">parsé</abbr> en tant que JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargé de l'analyser d'une manière ou d'une autre.
|
||||
|
||||
Néanmoins, nous pouvons déclarer le schéma attendu pour le corps de la requête.
|
||||
|
||||
### Type de contenu OpenAPI personnalisé
|
||||
|
||||
En utilisant cette même astuce, vous pouvez utiliser un modèle Pydantic pour définir le schéma JSON qui est ensuite inclus dans la section de schéma OpenAPI personnalisée pour le *chemin* concerné.
|
||||
|
||||
Et vous pouvez le faire même si le type de données dans la requête n'est pas au format JSON.
|
||||
|
||||
Dans cet exemple, nous n'utilisons pas les fonctionnalités de FastAPI pour extraire le schéma JSON des modèles Pydantic ni la validation automatique pour JSON. En fait, nous déclarons le type de contenu de la requête en tant que YAML, et non JSON :
|
||||
|
||||
```Python hl_lines="17-22 24"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
|
||||
Néanmoins, bien que nous n'utilisions pas la fonctionnalité par défaut, nous utilisons toujours un modèle Pydantic pour générer manuellement le schéma JSON pour les données que nous souhaitons recevoir en YAML.
|
||||
|
||||
Ensuite, nous utilisons directement la requête et extrayons son contenu en tant qu'octets. Cela signifie que FastAPI n'essaiera même pas d'analyser le payload de la requête en tant que JSON.
|
||||
|
||||
Et nous analysons directement ce contenu YAML, puis nous utilisons à nouveau le même modèle Pydantic pour valider le contenu YAML :
|
||||
|
||||
```Python hl_lines="26-33"
|
||||
{!../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
|
||||
!!! Astuce
|
||||
Ici, nous réutilisons le même modèle Pydantic.
|
||||
|
||||
Mais nous aurions pu tout aussi bien pu le valider d'une autre manière.
|
||||
153
docs/fr/docs/deployment/manually.md
Normal file
153
docs/fr/docs/deployment/manually.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Exécuter un serveur manuellement - Uvicorn
|
||||
|
||||
La principale chose dont vous avez besoin pour exécuter une application **FastAPI** sur une machine serveur distante est un programme serveur ASGI tel que **Uvicorn**.
|
||||
|
||||
Il existe 3 principales alternatives :
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a> : un serveur ASGI haute performance.
|
||||
* <a href="https://pgjones.gitlab.io/hypercorn/" class="external-link" target="_blank">Hypercorn</a> : un serveur
|
||||
ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalités.
|
||||
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a> : le serveur ASGI
|
||||
conçu pour Django Channels.
|
||||
|
||||
## Machine serveur et programme serveur
|
||||
|
||||
Il y a un petit détail sur les noms à garder à l'esprit. 💡
|
||||
|
||||
Le mot "**serveur**" est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn).
|
||||
|
||||
Gardez cela à l'esprit lorsque vous lisez "serveur" en général, cela pourrait faire référence à l'une de ces deux choses.
|
||||
|
||||
Lorsqu'on se réfère à la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nœud**. Tout cela fait référence à un type de machine distante, exécutant Linux, en règle générale, sur laquelle vous exécutez des programmes.
|
||||
|
||||
|
||||
## Installer le programme serveur
|
||||
|
||||
Vous pouvez installer un serveur compatible ASGI avec :
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip "Astuce"
|
||||
En ajoutant `standard`, Uvicorn va installer et utiliser quelques dépendances supplémentaires recommandées.
|
||||
|
||||
Cela inclut `uvloop`, le remplaçant performant de `asyncio`, qui fournit le gros gain de performance en matière de concurrence.
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, un serveur ASGI également compatible avec HTTP/2.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...ou tout autre serveur ASGI.
|
||||
|
||||
## Exécutez le programme serveur
|
||||
|
||||
Vous pouvez ensuite exécuter votre application de la même manière que vous l'avez fait dans les tutoriels, mais sans l'option `--reload`, par exemple :
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! warning
|
||||
N'oubliez pas de supprimer l'option `--reload` si vous l'utilisiez.
|
||||
|
||||
L'option `--reload` consomme beaucoup plus de ressources, est plus instable, etc.
|
||||
|
||||
Cela aide beaucoup pendant le **développement**, mais vous **ne devriez pas** l'utiliser en **production**.
|
||||
|
||||
## Hypercorn avec Trio
|
||||
|
||||
Starlette et **FastAPI** sont basés sur
|
||||
<a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, qui les rend
|
||||
compatibles avec <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a>, de la bibliothèque standard Python et
|
||||
<a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
|
||||
|
||||
Néanmoins, Uvicorn n'est actuellement compatible qu'avec asyncio, et il utilise normalement <a href="https://github.
|
||||
com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a >, le remplaçant hautes performances de `asyncio`.
|
||||
|
||||
Mais si vous souhaitez utiliser directement **Trio**, vous pouvez utiliser **Hypercorn** car il le prend en charge. ✨
|
||||
|
||||
### Installer Hypercorn avec Trio
|
||||
|
||||
Vous devez d'abord installer Hypercorn avec le support Trio :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "hypercorn[trio]"
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Exécuter avec Trio
|
||||
|
||||
Ensuite, vous pouvez passer l'option de ligne de commande `--worker-class` avec la valeur `trio` :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --worker-class trio
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Et cela démarrera Hypercorn avec votre application en utilisant Trio comme backend.
|
||||
|
||||
Vous pouvez désormais utiliser Trio en interne dans votre application. Ou mieux encore, vous pouvez utiliser AnyIO pour que votre code reste compatible avec Trio et asyncio. 🎉
|
||||
|
||||
## Concepts de déploiement
|
||||
|
||||
Ces exemples lancent le programme serveur (e.g. Uvicorn), démarrant **un seul processus**, sur toutes les IPs (`0.0.
|
||||
0.0`) sur un port prédéfini (par example, `80`).
|
||||
|
||||
C'est l'idée de base. Mais vous vous préoccuperez probablement de certains concepts supplémentaires, tels que ... :
|
||||
|
||||
* la sécurité - HTTPS
|
||||
* l'exécution au démarrage
|
||||
* les redémarrages
|
||||
* la réplication (le nombre de processus en cours d'exécution)
|
||||
* la mémoire
|
||||
* les étapes précédant le démarrage
|
||||
|
||||
Je vous en dirai plus sur chacun de ces concepts, sur la façon de les aborder, et donnerai quelques exemples concrets avec des stratégies pour les traiter dans les prochains chapitres. 🚀
|
||||
112
docs/fr/docs/tutorial/debugging.md
Normal file
112
docs/fr/docs/tutorial/debugging.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# <abbr title="En anglais: Debugging">Débogage</abbr>
|
||||
|
||||
Vous pouvez connecter le <abbr title="En anglais: debugger">débogueur</abbr> dans votre éditeur, par exemple avec Visual Studio Code ou PyCharm.
|
||||
|
||||
## Faites appel à `uvicorn`
|
||||
|
||||
Dans votre application FastAPI, importez et exécutez directement `uvicorn` :
|
||||
|
||||
```Python hl_lines="1 15"
|
||||
{!../../../docs_src/debugging/tutorial001.py!}
|
||||
```
|
||||
|
||||
### À propos de `__name__ == "__main__"`
|
||||
|
||||
Le but principal de `__name__ == "__main__"` est d'avoir du code qui est exécuté lorsque votre fichier est appelé avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ python myapp.py
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
mais qui n'est pas appelé lorsqu'un autre fichier l'importe, comme dans :
|
||||
|
||||
```Python
|
||||
from myapp import app
|
||||
```
|
||||
|
||||
#### Pour davantage de détails
|
||||
|
||||
Imaginons que votre fichier s'appelle `myapp.py`.
|
||||
|
||||
Si vous l'exécutez avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ python myapp.py
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
alors la variable interne `__name__` de votre fichier, créée automatiquement par Python, aura pour valeur la chaîne de caractères `"__main__"`.
|
||||
|
||||
Ainsi, la section :
|
||||
|
||||
```Python
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
va s'exécuter.
|
||||
|
||||
---
|
||||
|
||||
Cela ne se produira pas si vous importez ce module (fichier).
|
||||
|
||||
Par exemple, si vous avez un autre fichier `importer.py` qui contient :
|
||||
|
||||
```Python
|
||||
from myapp import app
|
||||
|
||||
# Code supplémentaire
|
||||
```
|
||||
|
||||
dans ce cas, la variable automatique `__name__` à l'intérieur de `myapp.py` n'aura pas la valeur `"__main__"`.
|
||||
|
||||
Ainsi, la ligne :
|
||||
|
||||
```Python
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
ne sera pas exécutée.
|
||||
|
||||
!!! info
|
||||
Pour plus d'informations, consultez <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">la documentation officielle de Python</a>.
|
||||
|
||||
## Exécutez votre code avec votre <abbr title="En anglais: debugger">débogueur</abbr>
|
||||
|
||||
Parce que vous exécutez le serveur Uvicorn directement depuis votre code, vous pouvez appeler votre programme Python (votre application FastAPI) directement depuis le <abbr title="En anglais: debugger">débogueur</abbr>.
|
||||
|
||||
---
|
||||
|
||||
Par exemple, dans Visual Studio Code, vous pouvez :
|
||||
|
||||
- Cliquer sur l'onglet "Debug" de la barre d'activités de Visual Studio Code.
|
||||
- "Add configuration...".
|
||||
- Sélectionnez "Python".
|
||||
- Lancez le <abbr title="En anglais: debugger">débogueur</abbr> avec l'option "`Python: Current File (Integrated Terminal)`".
|
||||
|
||||
Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc.
|
||||
|
||||
Voici à quoi cela pourrait ressembler :
|
||||
|
||||
<img src="/img/tutorial/debugging/image01.png">
|
||||
|
||||
---
|
||||
|
||||
Si vous utilisez Pycharm, vous pouvez :
|
||||
|
||||
- Ouvrir le menu "Run".
|
||||
- Sélectionnez l'option "Debug...".
|
||||
- Un menu contextuel s'affiche alors.
|
||||
- Sélectionnez le fichier à déboguer (dans ce cas, `main.py`).
|
||||
|
||||
Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc.
|
||||
|
||||
Voici à quoi cela pourrait ressembler :
|
||||
|
||||
<img src="/img/tutorial/debugging/image02.png">
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -67,7 +69,9 @@ nav:
|
||||
- tutorial/query-params.md
|
||||
- tutorial/body.md
|
||||
- tutorial/background-tasks.md
|
||||
- tutorial/debugging.md
|
||||
- Guide utilisateur avancé:
|
||||
- advanced/path-operation-advanced-configuration.md
|
||||
- advanced/additional-status-codes.md
|
||||
- advanced/additional-responses.md
|
||||
- async.md
|
||||
@@ -77,6 +81,7 @@ nav:
|
||||
- deployment/https.md
|
||||
- deployment/deta.md
|
||||
- deployment/docker.md
|
||||
- deployment/manually.md
|
||||
- project-generation.md
|
||||
- alternatives.md
|
||||
- history-design-future.md
|
||||
@@ -104,7 +109,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -135,6 +140,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -155,6 +162,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
467
docs/hy/docs/index.md
Normal file
467
docs/hy/docs/index.md
Normal file
@@ -0,0 +1,467 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## Opinions
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
|
||||
## Installation
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
|
||||
### Create it
|
||||
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import 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}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import 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 <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
|
||||
Run the server with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
|
||||
### Interactive API docs
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import 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 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.7+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
|
||||
Try changing the line with:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* **GraphQL** integration with <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> and other libraries.
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* **WebSockets**
|
||||
* extremely easy tests based on HTTPX and `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
|
||||
Used by Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
|
||||
Used by Starlette:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install "fastapi[all]"`.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
148
docs/hy/mkdocs.yml
Normal file
148
docs/hy/mkdocs.yml
Normal file
@@ -0,0 +1,148 @@
|
||||
site_name: FastAPI
|
||||
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
||||
site_url: https://fastapi.tiangolo.com/hy/
|
||||
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: hy
|
||||
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/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
- ko: /ko/
|
||||
- nl: /nl/
|
||||
- pl: /pl/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- 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
|
||||
- attr_list
|
||||
- md_in_html
|
||||
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: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- 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: /sv/
|
||||
name: sv - svenska
|
||||
- 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
|
||||
0
docs/hy/overrides/.gitignore
vendored
Normal file
0
docs/hy/overrides/.gitignore
vendored
Normal file
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -124,7 +126,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -155,6 +157,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -175,6 +179,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -92,7 +94,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -123,6 +125,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -143,6 +147,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -83,7 +85,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -114,6 +116,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -134,6 +138,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -117,7 +119,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -148,6 +150,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -168,6 +172,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
77
docs/ru/docs/history-design-future.md
Normal file
77
docs/ru/docs/history-design-future.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# История создания и дальнейшее развитие
|
||||
|
||||
Однажды, <a href="https://github.com/tiangolo/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">один из пользователей **FastAPI** задал вопрос</a>:
|
||||
|
||||
> Какова история этого проекта? Создаётся впечатление, что он явился из ниоткуда и завоевал мир за несколько недель [...]
|
||||
|
||||
Что ж, вот небольшая часть истории проекта.
|
||||
|
||||
## Альтернативы
|
||||
|
||||
В течение нескольких лет я, возглавляя различные команды разработчиков, создавал довольно сложные API для машинного обучения, распределённых систем, асинхронных задач, баз данных NoSQL и т.д.
|
||||
|
||||
В рамках работы над этими проектами я исследовал, проверял и использовал многие фреймворки.
|
||||
|
||||
Во многом история **FastAPI** - история его предшественников.
|
||||
|
||||
Как написано в разделе [Альтернативы](alternatives.md){.internal-link target=_blank}:
|
||||
|
||||
<blockquote markdown="1">
|
||||
|
||||
**FastAPI** не существовал бы, если б не было более ранних работ других людей.
|
||||
|
||||
Они создали большое количество инструментов, которые и вдохновили меня на создание **FastAPI**.
|
||||
|
||||
Я всячески избегал создания нового фреймворка в течение нескольких лет. Сначала я пытался собрать все нужные возможности, которые ныне есть в **FastAPI**, используя множество различных фреймворков, плагинов и инструментов.
|
||||
|
||||
Но в какой-то момент не осталось другого выбора, кроме как создать что-то, что предоставляло бы все эти возможности сразу. Взять самые лучшие идеи из предыдущих инструментов и, используя введённые в Python подсказки типов (которых не было до версии 3.6), объединить их.
|
||||
|
||||
</blockquote>
|
||||
|
||||
## Исследования
|
||||
|
||||
Благодаря опыту использования существующих альтернатив, мы с коллегами изучили их основные идеи и скомбинировали собранные знания наилучшим образом.
|
||||
|
||||
Например, стало ясно, что необходимо брать за основу стандартные подсказки типов Python, а самым лучшим подходом является использование уже существующих стандартов.
|
||||
|
||||
Итак, прежде чем приступить к написанию **FastAPI**, я потратил несколько месяцев на изучение OpenAPI, JSON Schema, OAuth2, и т.п. для понимания их взаимосвязей, совпадений и различий.
|
||||
|
||||
## Дизайн
|
||||
|
||||
Затем я потратил некоторое время на придумывание "API" разработчика, который я хотел иметь как пользователь (как разработчик, использующий FastAPI).
|
||||
|
||||
Я проверил несколько идей на самых популярных редакторах кода среди Python-разработчиков: PyCharm, VS Code, Jedi.
|
||||
|
||||
Данные по редакторам я взял из <a href="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools" class="external-link" target="_blank">опроса Python-разработчиков</a>, который охватываает около 80% пользователей.
|
||||
|
||||
Это означает, что **FastAPI** был специально проверен на редакторах, используемых 80% Python-разработчиками. И поскольку большинство других редакторов, как правило, работают аналогичным образом, все его преимущества должны работать практически для всех редакторов.
|
||||
|
||||
Таким образом, я смог найти наилучшие способы сократить дублирование кода, обеспечить повсеместное автодополнение, проверку типов и ошибок и т.д.
|
||||
|
||||
И все это, чтобы все пользователи могли получать наилучший опыт разработки.
|
||||
|
||||
## Зависимости
|
||||
|
||||
Протестировав несколько вариантов, я решил, что в качестве основы буду использовать <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">**Pydantic**</a> и его преимущества.
|
||||
|
||||
По моим предложениям был изменён код этого фреймворка, чтобы сделать его полностью совместимым с JSON Schema, поддержать различные способы определения ограничений и улучшить помощь редакторов (проверки типов, автозаполнение).
|
||||
|
||||
В то же время, я принимал участие в разработке <a href="https://www.starlette.io/" class="external-link" target="_blank">**Starlette**</a>, ещё один из основных компонентов FastAPI.
|
||||
|
||||
## Разработка
|
||||
|
||||
К тому времени, когда я начал создавать **FastAPI**, большинство необходимых деталей уже существовало, дизайн был определён, зависимости и прочие инструменты были готовы, а знания о стандартах и спецификациях были четкими и свежими.
|
||||
|
||||
## Будущее
|
||||
|
||||
Сейчас уже ясно, что **FastAPI** со своими идеями стал полезен многим людям.
|
||||
|
||||
При сравнении с альтернативами, выбор падает на него, поскольку он лучше подходит для множества вариантов использования.
|
||||
|
||||
Многие разработчики и команды уже используют **FastAPI** в своих проектах (включая меня и мою команду).
|
||||
|
||||
Но, тем не менее, грядёт добавление ещё многих улучшений и возможностей.
|
||||
|
||||
У **FastAPI** великое будущее.
|
||||
|
||||
И [ваш вклад в это](help-fastapi.md){.internal-link target=_blank} - очень ценнен.
|
||||
49
docs/ru/docs/tutorial/cookie-params.md
Normal file
49
docs/ru/docs/tutorial/cookie-params.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Параметры Cookie
|
||||
|
||||
Вы можете задать параметры Cookie таким же способом, как `Query` и `Path` параметры.
|
||||
|
||||
## Импорт `Cookie`
|
||||
|
||||
Сначала импортируйте `Cookie`:
|
||||
|
||||
=== "Python 3.6 и выше"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 и выше"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
## Объявление параметров `Cookie`
|
||||
|
||||
Затем объявляйте параметры cookie, используя ту же структуру, что и с `Path` и `Query`.
|
||||
|
||||
Первое значение - это значение по умолчанию, вы можете передать все дополнительные параметры проверки или аннотации:
|
||||
|
||||
=== "Python 3.6 и выше"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 и выше"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! note "Технические детали"
|
||||
`Cookie` - это класс, родственный `Path` и `Query`. Он также наследуется от общего класса `Param`.
|
||||
|
||||
Но помните, что когда вы импортируете `Query`, `Path`, `Cookie` и другое из `fastapi`, это фактически функции, которые возвращают специальные классы.
|
||||
|
||||
!!! info "Дополнительная информация"
|
||||
Для объявления cookies, вам нужно использовать `Cookie`, иначе параметры будут интерпретированы как параметры запроса.
|
||||
|
||||
## Резюме
|
||||
|
||||
Объявляйте cookies с помощью `Cookie`, используя тот же общий шаблон, что и `Query`, и `Path`.
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -64,10 +66,12 @@ nav:
|
||||
- Учебник - руководство пользователя:
|
||||
- tutorial/body-fields.md
|
||||
- tutorial/background-tasks.md
|
||||
- tutorial/cookie-params.md
|
||||
- async.md
|
||||
- Развёртывание:
|
||||
- deployment/index.md
|
||||
- deployment/versions.md
|
||||
- history-design-future.md
|
||||
- external-links.md
|
||||
- contributing.md
|
||||
markdown_extensions:
|
||||
@@ -92,7 +96,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -123,6 +127,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -143,6 +149,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
148
docs/ta/mkdocs.yml
Normal file
148
docs/ta/mkdocs.yml
Normal file
@@ -0,0 +1,148 @@
|
||||
site_name: FastAPI
|
||||
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
||||
site_url: https://fastapi.tiangolo.com/ta/
|
||||
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: en
|
||||
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/
|
||||
- he: /he/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
- ko: /ko/
|
||||
- nl: /nl/
|
||||
- pl: /pl/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- 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
|
||||
- attr_list
|
||||
- md_in_html
|
||||
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: /he/
|
||||
name: he
|
||||
- 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: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- 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
|
||||
0
docs/ta/overrides/.gitignore
vendored
Normal file
0
docs/ta/overrides/.gitignore
vendored
Normal file
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -85,7 +87,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -116,6 +118,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -136,6 +140,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -80,7 +82,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -111,6 +113,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -131,6 +135,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -45,6 +45,7 @@ nav:
|
||||
- fa: /fa/
|
||||
- fr: /fr/
|
||||
- he: /he/
|
||||
- hy: /hy/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
@@ -55,6 +56,7 @@ nav:
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- sv: /sv/
|
||||
- ta: /ta/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -137,7 +139,7 @@ markdown_extensions:
|
||||
extra:
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-133183413-1
|
||||
property: G-YNEVN69SC3
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
@@ -168,6 +170,8 @@ extra:
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
- link: /hy/
|
||||
name: hy
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
@@ -188,6 +192,8 @@ extra:
|
||||
name: sq - shqip
|
||||
- link: /sv/
|
||||
name: sv - svenska
|
||||
- link: /ta/
|
||||
name: ta - தமிழ்
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
|
||||
@@ -25,7 +25,7 @@ async def update_item(
|
||||
item: Item,
|
||||
user: User,
|
||||
importance: int = Body(gt=0),
|
||||
q: Union[str, None] = None
|
||||
q: Union[str, None] = None,
|
||||
):
|
||||
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
|
||||
if q:
|
||||
|
||||
@@ -23,7 +23,7 @@ async def update_item(
|
||||
item: Item,
|
||||
user: User,
|
||||
importance: int = Body(gt=0),
|
||||
q: str | None = None
|
||||
q: str | None = None,
|
||||
):
|
||||
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
|
||||
if q:
|
||||
|
||||
28
docs_src/events/tutorial003.py
Normal file
28
docs_src/events/tutorial003.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
|
||||
def fake_answer_to_everything_ml_model(x: float):
|
||||
return x * 42
|
||||
|
||||
|
||||
ml_models = {}
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Load the ML model
|
||||
ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
|
||||
yield
|
||||
# Clean up the ML models and release the resources
|
||||
ml_models.clear()
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
|
||||
@app.get("/predict")
|
||||
async def predict(x: float):
|
||||
result = ml_models["answer_to_everything"](x)
|
||||
return {"result": result}
|
||||
@@ -8,7 +8,7 @@ async def read_items(
|
||||
*,
|
||||
item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
|
||||
q: str,
|
||||
size: float = Query(gt=0, lt=10.5)
|
||||
size: float = Query(gt=0, lt=10.5),
|
||||
):
|
||||
results = {"item_id": item_id}
|
||||
if q:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.90.0"
|
||||
__version__ = "0.94.1"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from typing import (
|
||||
Optional,
|
||||
Sequence,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
|
||||
@@ -41,12 +42,14 @@ from starlette.middleware.exceptions import ExceptionMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
from starlette.types import ASGIApp, Receive, Scope, Send
|
||||
from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send
|
||||
|
||||
AppType = TypeVar("AppType", bound="FastAPI")
|
||||
|
||||
|
||||
class FastAPI(Starlette):
|
||||
def __init__(
|
||||
self,
|
||||
self: AppType,
|
||||
*,
|
||||
debug: bool = False,
|
||||
routes: Optional[List[BaseRoute]] = None,
|
||||
@@ -71,6 +74,7 @@ class FastAPI(Starlette):
|
||||
] = None,
|
||||
on_startup: Optional[Sequence[Callable[[], Any]]] = None,
|
||||
on_shutdown: Optional[Sequence[Callable[[], Any]]] = None,
|
||||
lifespan: Optional[Lifespan[AppType]] = None,
|
||||
terms_of_service: Optional[str] = None,
|
||||
contact: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
license_info: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
@@ -87,7 +91,7 @@ class FastAPI(Starlette):
|
||||
),
|
||||
**extra: Any,
|
||||
) -> None:
|
||||
self._debug: bool = debug
|
||||
self.debug = debug
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.version = version
|
||||
@@ -125,6 +129,7 @@ class FastAPI(Starlette):
|
||||
dependency_overrides_provider=self,
|
||||
on_startup=on_startup,
|
||||
on_shutdown=on_shutdown,
|
||||
lifespan=lifespan,
|
||||
default_response_class=default_response_class,
|
||||
dependencies=dependencies,
|
||||
callbacks=callbacks,
|
||||
@@ -144,7 +149,7 @@ class FastAPI(Starlette):
|
||||
self.user_middleware: List[Middleware] = (
|
||||
[] if middleware is None else list(middleware)
|
||||
)
|
||||
self.middleware_stack: ASGIApp = self.build_middleware_stack()
|
||||
self.middleware_stack: Union[ASGIApp, None] = None
|
||||
self.setup()
|
||||
|
||||
def build_middleware_stack(self) -> ASGIApp:
|
||||
|
||||
@@ -696,7 +696,7 @@ async def request_body_to_args(
|
||||
fn: Callable[[], Coroutine[Any, Any, Any]]
|
||||
) -> None:
|
||||
result = await fn()
|
||||
results.append(result)
|
||||
results.append(result) # noqa: B023
|
||||
|
||||
async with anyio.create_task_group() as tg:
|
||||
for sub_value in value:
|
||||
|
||||
@@ -57,7 +57,7 @@ from starlette.routing import (
|
||||
websocket_session,
|
||||
)
|
||||
from starlette.status import WS_1008_POLICY_VIOLATION
|
||||
from starlette.types import ASGIApp, Scope
|
||||
from starlette.types import ASGIApp, Lifespan, Scope
|
||||
from starlette.websockets import WebSocket
|
||||
|
||||
|
||||
@@ -492,6 +492,9 @@ class APIRouter(routing.Router):
|
||||
route_class: Type[APIRoute] = APIRoute,
|
||||
on_startup: Optional[Sequence[Callable[[], Any]]] = None,
|
||||
on_shutdown: Optional[Sequence[Callable[[], Any]]] = None,
|
||||
# the generic to Lifespan[AppType] is the type of the top level application
|
||||
# which the router cannot know statically, so we use typing.Any
|
||||
lifespan: Optional[Lifespan[Any]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
include_in_schema: bool = True,
|
||||
generate_unique_id_function: Callable[[APIRoute], str] = Default(
|
||||
@@ -504,6 +507,7 @@ class APIRouter(routing.Router):
|
||||
default=default,
|
||||
on_startup=on_startup,
|
||||
on_shutdown=on_shutdown,
|
||||
lifespan=lifespan,
|
||||
)
|
||||
if prefix:
|
||||
assert prefix.startswith("/"), "A path prefix must start with '/'"
|
||||
@@ -1248,7 +1252,6 @@ class APIRouter(routing.Router):
|
||||
generate_unique_id
|
||||
),
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
|
||||
return self.api_route(
|
||||
path=path,
|
||||
response_model=response_model,
|
||||
|
||||
@@ -18,7 +18,7 @@ class APIKeyQuery(APIKeyBase):
|
||||
name: str,
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: bool = True
|
||||
auto_error: bool = True,
|
||||
):
|
||||
self.model: APIKey = APIKey(
|
||||
**{"in": APIKeyIn.query}, name=name, description=description
|
||||
@@ -45,7 +45,7 @@ class APIKeyHeader(APIKeyBase):
|
||||
name: str,
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: bool = True
|
||||
auto_error: bool = True,
|
||||
):
|
||||
self.model: APIKey = APIKey(
|
||||
**{"in": APIKeyIn.header}, name=name, description=description
|
||||
@@ -72,7 +72,7 @@ class APIKeyCookie(APIKeyBase):
|
||||
name: str,
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: bool = True
|
||||
auto_error: bool = True,
|
||||
):
|
||||
self.model: APIKey = APIKey(
|
||||
**{"in": APIKeyIn.cookie}, name=name, description=description
|
||||
|
||||
@@ -119,7 +119,7 @@ class OAuth2(SecurityBase):
|
||||
flows: Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]] = OAuthFlowsModel(),
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: bool = True
|
||||
auto_error: bool = True,
|
||||
):
|
||||
self.model = OAuth2Model(flows=flows, description=description)
|
||||
self.scheme_name = scheme_name or self.__class__.__name__
|
||||
|
||||
@@ -14,7 +14,7 @@ class OpenIdConnect(SecurityBase):
|
||||
openIdConnectUrl: str,
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: bool = True
|
||||
auto_error: bool = True,
|
||||
):
|
||||
self.model = OpenIdConnectModel(
|
||||
openIdConnectUrl=openIdConnectUrl, description=description
|
||||
|
||||
@@ -27,6 +27,8 @@ classifiers = [
|
||||
"Environment :: Web Environment",
|
||||
"Framework :: AsyncIO",
|
||||
"Framework :: FastAPI",
|
||||
"Framework :: Pydantic",
|
||||
"Framework :: Pydantic :: 1",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
@@ -39,7 +41,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
"starlette>=0.22.0,<=0.23.0",
|
||||
"starlette>=0.26.1,<0.27.0",
|
||||
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0",
|
||||
]
|
||||
dynamic = ["version"]
|
||||
@@ -54,7 +56,7 @@ test = [
|
||||
"coverage[toml] >= 6.5.0,< 8.0",
|
||||
"mypy ==0.982",
|
||||
"ruff ==0.0.138",
|
||||
"black == 22.10.0",
|
||||
"black == 23.1.0",
|
||||
"isort >=5.0.6,<6.0.0",
|
||||
"httpx >=0.23.0,<0.24.0",
|
||||
"email_validator >=1.1.1,<2.0.0",
|
||||
@@ -65,7 +67,7 @@ test = [
|
||||
"databases[sqlite] >=0.3.2,<0.7.0",
|
||||
"orjson >=3.2.1,<4.0.0",
|
||||
"ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0",
|
||||
"python-multipart >=0.0.5,<0.0.6",
|
||||
"python-multipart >=0.0.5,<0.0.7",
|
||||
"flask >=1.1.2,<3.0.0",
|
||||
"anyio[trio] >=3.2.1,<4.0.0",
|
||||
"python-jose[cryptography] >=3.3.0,<4.0.0",
|
||||
@@ -73,7 +75,7 @@ test = [
|
||||
"passlib[bcrypt] >=1.7.2,<2.0.0",
|
||||
|
||||
# types
|
||||
"types-ujson ==5.6.0.0",
|
||||
"types-ujson ==5.7.0.1",
|
||||
"types-orjson ==3.6.2",
|
||||
]
|
||||
doc = [
|
||||
@@ -81,8 +83,7 @@ doc = [
|
||||
"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",
|
||||
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x
|
||||
# "typer-cli >=0.0.12,<0.0.13",
|
||||
"typer-cli >=0.0.13,<0.0.14",
|
||||
"typer[all] >=0.6.1,<0.8.0",
|
||||
"pyyaml >=5.3.1,<7.0.0",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncGenerator, Dict
|
||||
|
||||
import pytest
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
@@ -12,57 +16,49 @@ class State(BaseModel):
|
||||
sub_router_shutdown: bool = False
|
||||
|
||||
|
||||
state = State()
|
||||
|
||||
app = FastAPI()
|
||||
@pytest.fixture
|
||||
def state() -> State:
|
||||
return State()
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
def app_startup():
|
||||
state.app_startup = True
|
||||
def test_router_events(state: State) -> None:
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/")
|
||||
def main() -> Dict[str, str]:
|
||||
return {"message": "Hello World"}
|
||||
|
||||
@app.on_event("shutdown")
|
||||
def app_shutdown():
|
||||
state.app_shutdown = True
|
||||
@app.on_event("startup")
|
||||
def app_startup() -> None:
|
||||
state.app_startup = True
|
||||
|
||||
@app.on_event("shutdown")
|
||||
def app_shutdown() -> None:
|
||||
state.app_shutdown = True
|
||||
|
||||
router = APIRouter()
|
||||
router = APIRouter()
|
||||
|
||||
@router.on_event("startup")
|
||||
def router_startup() -> None:
|
||||
state.router_startup = True
|
||||
|
||||
@router.on_event("startup")
|
||||
def router_startup():
|
||||
state.router_startup = True
|
||||
@router.on_event("shutdown")
|
||||
def router_shutdown() -> None:
|
||||
state.router_shutdown = True
|
||||
|
||||
sub_router = APIRouter()
|
||||
|
||||
@router.on_event("shutdown")
|
||||
def router_shutdown():
|
||||
state.router_shutdown = True
|
||||
@sub_router.on_event("startup")
|
||||
def sub_router_startup() -> None:
|
||||
state.sub_router_startup = True
|
||||
|
||||
@sub_router.on_event("shutdown")
|
||||
def sub_router_shutdown() -> None:
|
||||
state.sub_router_shutdown = True
|
||||
|
||||
sub_router = APIRouter()
|
||||
router.include_router(sub_router)
|
||||
app.include_router(router)
|
||||
|
||||
|
||||
@sub_router.on_event("startup")
|
||||
def sub_router_startup():
|
||||
state.sub_router_startup = True
|
||||
|
||||
|
||||
@sub_router.on_event("shutdown")
|
||||
def sub_router_shutdown():
|
||||
state.sub_router_shutdown = True
|
||||
|
||||
|
||||
@sub_router.get("/")
|
||||
def main():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
|
||||
router.include_router(sub_router)
|
||||
app.include_router(router)
|
||||
|
||||
|
||||
def test_router_events():
|
||||
assert state.app_startup is False
|
||||
assert state.router_startup is False
|
||||
assert state.sub_router_startup is False
|
||||
@@ -85,3 +81,28 @@ def test_router_events():
|
||||
assert state.app_shutdown is True
|
||||
assert state.router_shutdown is True
|
||||
assert state.sub_router_shutdown is True
|
||||
|
||||
|
||||
def test_app_lifespan_state(state: State) -> None:
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
state.app_startup = True
|
||||
yield
|
||||
state.app_shutdown = True
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
@app.get("/")
|
||||
def main() -> Dict[str, str]:
|
||||
return {"message": "Hello World"}
|
||||
|
||||
assert state.app_startup is False
|
||||
assert state.app_shutdown is False
|
||||
with TestClient(app) as client:
|
||||
assert state.app_startup is True
|
||||
assert state.app_shutdown is False
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"message": "Hello World"}
|
||||
assert state.app_startup is True
|
||||
assert state.app_shutdown is True
|
||||
|
||||
@@ -54,7 +54,7 @@ def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
# TODO: remove this once Pydantic 1.9 is released
|
||||
# Ref: https://github.com/samuelcolvin/pydantic/pull/2557
|
||||
# Ref: https://github.com/pydantic/pydantic/pull/2557
|
||||
data = response.json()
|
||||
alternative_data1 = deepcopy(data)
|
||||
alternative_data2 = deepcopy(data)
|
||||
|
||||
86
tests/test_tutorial/test_events/test_tutorial003.py
Normal file
86
tests/test_tutorial/test_events/test_tutorial003.py
Normal file
@@ -0,0 +1,86 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.events.tutorial003 import (
|
||||
app,
|
||||
fake_answer_to_everything_ml_model,
|
||||
ml_models,
|
||||
)
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/predict": {
|
||||
"get": {
|
||||
"summary": "Predict",
|
||||
"operationId": "predict_predict_get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "X", "type": "number"},
|
||||
"name": "x",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_events():
|
||||
assert not ml_models, "ml_models should be empty"
|
||||
with TestClient(app) as client:
|
||||
assert ml_models["answer_to_everything"] == fake_answer_to_everything_ml_model
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
response = client.get("/predict", params={"x": 2})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"result": 84.0}
|
||||
assert not ml_models, "ml_models should be empty"
|
||||
@@ -150,7 +150,6 @@ def get_app():
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(app: FastAPI):
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
@@ -152,7 +152,6 @@ def get_app():
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(app: FastAPI):
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
Reference in New Issue
Block a user