analisado como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
diff --git a/docs/pt/docs/advanced/response-change-status-code.md b/docs/pt/docs/advanced/response-change-status-code.md
index 0f08873f67..ee81f0bfc8 100644
--- a/docs/pt/docs/advanced/response-change-status-code.md
+++ b/docs/pt/docs/advanced/response-change-status-code.md
@@ -20,7 +20,7 @@ Você pode declarar um parâmetro do tipo `Response` em sua *função de operaç
E então você pode definir o `status_code` neste objeto de retorno temporal.
-{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *}
+{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
E então você pode retornar qualquer objeto que você precise, como você faria normalmente (um `dict`, um modelo de banco de dados, etc.).
diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md
index 41fc000133..67820b433b 100644
--- a/docs/pt/docs/advanced/response-cookies.md
+++ b/docs/pt/docs/advanced/response-cookies.md
@@ -6,7 +6,7 @@ Você pode declarar um parâmetro do tipo `Response` na sua *função de operaç
E então você pode definir cookies nesse objeto de resposta *temporário*.
-{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
+{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
@@ -24,7 +24,7 @@ Para fazer isso, você pode criar uma resposta como descrito em [Retorne uma Res
Então, defina os cookies nela e a retorne:
-{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
+{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
/// tip | Dica
diff --git a/docs/pt/docs/advanced/response-directly.md b/docs/pt/docs/advanced/response-directly.md
index 0c0144e9a1..bbbef2f913 100644
--- a/docs/pt/docs/advanced/response-directly.md
+++ b/docs/pt/docs/advanced/response-directly.md
@@ -54,7 +54,7 @@ Vamos dizer que você quer retornar uma resposta FastAPI Cloud com um **único comando**; entre na lista de espera, caso ainda não tenha feito isso. 🚀
+
+## Login { #login }
+
+Certifique-se de que você já tem uma conta no **FastAPI Cloud** (nós convidamos você a partir da lista de espera 😉).
+
+Depois, faça login:
+
+
+
+```console
+$ fastapi login
+
+You are logged in to FastAPI Cloud 🚀
+```
+
+
+
+## Implantar { #deploy }
+
+Agora, implante sua aplicação, com **um único comando**:
+
+
+
+```console
+$ fastapi deploy
+
+Deploying to FastAPI Cloud...
+
+✅ Deployment successful!
+
+🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
+```
+
+
+
+É isso! Agora você pode acessar sua aplicação nesse URL. ✨
+
+## Sobre o FastAPI Cloud { #about-fastapi-cloud }
+
+O **FastAPI Cloud** é desenvolvido pelo mesmo autor e equipe por trás do **FastAPI**.
+
+Ele simplifica o processo de **criar**, **implantar** e **acessar** uma API com esforço mínimo.
+
+Traz a mesma **experiência do desenvolvedor** de criar aplicações com FastAPI para **implantá-las** na nuvem. 🎉
+
+Ele também cuidará da maioria das coisas de que você precisaria ao implantar uma aplicação, como:
+
+* HTTPS
+* Replicação, com dimensionamento automático baseado em requests
+* etc.
+
+O FastAPI Cloud é o patrocinador principal e provedor de financiamento dos projetos open source do ecossistema *FastAPI and friends*. ✨
+
+## Implantar em outros provedores de nuvem { #deploy-to-other-cloud-providers }
+
+FastAPI é open source e baseado em padrões. Você pode implantar aplicações FastAPI em qualquer provedor de nuvem que escolher.
+
+Siga os tutoriais do seu provedor de nuvem para implantar aplicações FastAPI com esse provedor. 🤓
+
+## Implantar no seu próprio servidor { #deploy-your-own-server }
+
+Também vou lhe ensinar, mais adiante neste guia de **Implantação**, todos os detalhes, para que você possa entender o que está acontecendo, o que precisa acontecer, ou como implantar aplicações FastAPI por conta própria, inclusive nos seus próprios servidores. 🤓
diff --git a/docs/pt/docs/how-to/authentication-error-status-code.md b/docs/pt/docs/how-to/authentication-error-status-code.md
new file mode 100644
index 0000000000..878a1ca1ac
--- /dev/null
+++ b/docs/pt/docs/how-to/authentication-error-status-code.md
@@ -0,0 +1,17 @@
+# Usar antigos códigos de status de erro de autenticação 403 { #use-old-403-authentication-error-status-codes }
+
+Antes da versão `0.122.0` do FastAPI, quando os utilitários de segurança integrados retornavam um erro ao cliente após uma falha na autenticação, eles usavam o código de status HTTP `403 Forbidden`.
+
+A partir da versão `0.122.0` do FastAPI, eles usam o código de status HTTP `401 Unauthorized`, mais apropriado, e retornam um cabeçalho `WWW-Authenticate` adequado na response, seguindo as especificações HTTP, RFC 7235, RFC 9110.
+
+Mas, se por algum motivo seus clientes dependem do comportamento antigo, você pode voltar a ele sobrescrevendo o método `make_not_authenticated_error` nas suas classes de segurança.
+
+Por exemplo, você pode criar uma subclasse de `HTTPBearer` que retorne um erro `403 Forbidden` em vez do erro padrão `401 Unauthorized`:
+
+{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
+
+/// tip | Dica
+
+Perceba que a função retorna a instância da exceção, ela não a lança. O lançamento é feito no restante do código interno.
+
+///
diff --git a/docs/pt/docs/how-to/conditional-openapi.md b/docs/pt/docs/how-to/conditional-openapi.md
index da4f5f7642..b475dae6d6 100644
--- a/docs/pt/docs/how-to/conditional-openapi.md
+++ b/docs/pt/docs/how-to/conditional-openapi.md
@@ -29,7 +29,7 @@ Você pode usar facilmente as mesmas configurações do Pydantic para configurar
Por exemplo:
-{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *}
+{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
Aqui declaramos a configuração `openapi_url` com o mesmo padrão de `"/openapi.json"`.
diff --git a/docs/pt/docs/how-to/configure-swagger-ui.md b/docs/pt/docs/how-to/configure-swagger-ui.md
index 163316932f..2d1863c64c 100644
--- a/docs/pt/docs/how-to/configure-swagger-ui.md
+++ b/docs/pt/docs/how-to/configure-swagger-ui.md
@@ -18,7 +18,7 @@ Sem alterar as configurações, o destaque de sintaxe é habilitado por padrão:
Mas você pode desabilitá-lo definindo `syntaxHighlight` como `False`:
-{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
...e então o Swagger UI não mostrará mais o destaque de sintaxe:
@@ -28,7 +28,7 @@ Mas você pode desabilitá-lo definindo `syntaxHighlight` como `False`:
Da mesma forma que você pode definir o tema de destaque de sintaxe com a chave `"syntaxHighlight.theme"` (observe que há um ponto no meio):
-{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
Essa configuração alteraria o tema de cores de destaque de sintaxe:
@@ -46,7 +46,7 @@ Você pode substituir qualquer um deles definindo um valor diferente no argument
Por exemplo, para desabilitar `deepLinking` você pode passar essas configurações para `swagger_ui_parameters`:
-{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
## Outros parâmetros da UI do Swagger { #other-swagger-ui-parameters }
diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md
index 30224c72bb..adda9eca50 100644
--- a/docs/pt/docs/how-to/custom-docs-ui-assets.md
+++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md
@@ -18,7 +18,7 @@ O primeiro passo é desativar a documentação automática, pois por padrão, el
Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
### Incluir a documentação personalizada { #include-the-custom-docs }
@@ -34,7 +34,7 @@ Você pode reutilizar as funções internas do FastAPI para criar as páginas HT
E de forma semelhante para o ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
/// tip | Dica
@@ -50,7 +50,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
### Teste { #test-it }
@@ -118,7 +118,7 @@ Depois disso, sua estrutura de arquivos deve se parecer com:
* Importe `StaticFiles`.
* "Monte" a instância `StaticFiles()` em um caminho específico.
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
### Teste os arquivos estáticos { #test-the-static-files }
@@ -144,7 +144,7 @@ Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a
Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
### Incluir a documentação personalizada para arquivos estáticos { #include-the-custom-docs-for-static-files }
@@ -160,7 +160,7 @@ Novamente, você pode reutilizar as funções internas do FastAPI para criar as
E de forma semelhante para o ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
/// tip | Dica
@@ -176,7 +176,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
### Teste a UI de Arquivos Estáticos { #test-static-files-ui }
diff --git a/docs/pt/docs/how-to/extending-openapi.md b/docs/pt/docs/how-to/extending-openapi.md
index 54d56b95ae..b1b50ce654 100644
--- a/docs/pt/docs/how-to/extending-openapi.md
+++ b/docs/pt/docs/how-to/extending-openapi.md
@@ -43,19 +43,19 @@ Por exemplo, vamos adicionar documentação do Strawberry.
diff --git a/docs/pt/docs/python-types.md b/docs/pt/docs/python-types.md
index 3e2d1ccb30..fc983d1df1 100644
--- a/docs/pt/docs/python-types.md
+++ b/docs/pt/docs/python-types.md
@@ -22,7 +22,7 @@ Se você é um especialista em Python e já sabe tudo sobre type hints, pule par
Vamos começar com um exemplo simples:
-{* ../../docs_src/python_types/tutorial001.py *}
+{* ../../docs_src/python_types/tutorial001_py39.py *}
A chamada deste programa gera:
@@ -36,7 +36,7 @@ A função faz o seguinte:
* Converte a primeira letra de cada uma em maiúsculas com `title()`.
* Concatena com um espaço no meio.
-{* ../../docs_src/python_types/tutorial001.py hl[2] *}
+{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
### Edite-o { #edit-it }
@@ -78,7 +78,7 @@ para:
Esses são os "type hints":
-{* ../../docs_src/python_types/tutorial002.py hl[1] *}
+{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
Isso não é o mesmo que declarar valores padrão como seria com:
@@ -106,7 +106,7 @@ Com isso, você pode rolar, vendo as opções, até encontrar o que "soa familia
Verifique esta função, ela já possui type hints:
-{* ../../docs_src/python_types/tutorial003.py hl[1] *}
+{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
Como o editor conhece os tipos de variáveis, você não obtém apenas o preenchimento automático, mas também as verificações de erro:
@@ -114,7 +114,7 @@ Como o editor conhece os tipos de variáveis, você não obtém apenas o preench
Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str(age)`:
-{* ../../docs_src/python_types/tutorial004.py hl[2] *}
+{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
## Declarando Tipos { #declaring-types }
@@ -133,7 +133,7 @@ Você pode usar, por exemplo:
* `bool`
* `bytes`
-{* ../../docs_src/python_types/tutorial005.py hl[1] *}
+{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
### Tipos genéricos com parâmetros de tipo { #generic-types-with-type-parameters }
@@ -161,56 +161,24 @@ Se você pode utilizar a **versão mais recente do Python**, utilize os exemplos
Por exemplo, vamos definir uma variável para ser uma `list` de `str`.
-//// tab | Python 3.9+
+Declare a variável, com a mesma sintaxe com dois pontos (`:`).
-Declare uma variável com a mesma sintaxe com dois pontos (`:`)
+Como o tipo, coloque `list`.
-Como tipo, coloque `list`.
+Como a lista é um tipo que contém tipos internos, você os coloca entre colchetes:
-Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial006_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-De `typing`, importe `List` (com o `L` maiúsculo):
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial006.py!}
-```
-
-Declare uma variável com a mesma sintaxe com dois pontos (`:`)
-
-Como tipo, coloque o `List` que você importou de `typing`.
-
-Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
-
-```Python hl_lines="4"
-{!> ../../docs_src/python_types/tutorial006.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
/// info | Informação
Estes tipos internos dentro dos colchetes são chamados "parâmetros de tipo" (type parameters).
-Neste caso, `str` é o parâmetro de tipo passado para `List` (ou `list` no Python 3.9 ou superior).
+Neste caso, `str` é o parâmetro de tipo passado para `list`.
///
Isso significa: "a variável `items` é uma `list`, e cada um dos itens desta lista é uma `str`".
-/// tip | Dica
-
-Se você usa o Python 3.9 ou superior, você não precisa importar `List` de `typing`. Você pode utilizar o mesmo tipo `list` no lugar.
-
-///
-
Ao fazer isso, seu editor pode fornecer suporte mesmo durante o processamento de itens da lista:
@@ -225,21 +193,7 @@ E, ainda assim, o editor sabe que é um `str` e fornece suporte para isso.
Você faria o mesmo para declarar `tuple`s e `set`s:
-//// tab | Python 3.9+
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial007_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial007.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
Isso significa que:
@@ -254,21 +208,7 @@ O primeiro parâmetro de tipo é para as chaves do `dict`.
O segundo parâmetro de tipo é para os valores do `dict`:
-//// tab | Python 3.9+
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial008_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial008.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
Isso significa que:
@@ -292,10 +232,10 @@ No Python 3.10 também existe uma **nova sintaxe** onde você pode colocar os po
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial008b.py!}
+{!> ../../docs_src/python_types/tutorial008b_py39.py!}
```
////
@@ -309,7 +249,7 @@ Você pode declarar que um valor pode ter um tipo, como `str`, mas que ele tamb
No Python 3.6 e superior (incluindo o Python 3.10) você pode declará-lo importando e utilizando `Optional` do módulo `typing`.
```Python hl_lines="1 4"
-{!../../docs_src/python_types/tutorial009.py!}
+{!../../docs_src/python_types/tutorial009_py39.py!}
```
O uso de `Optional[str]` em vez de apenas `str` permitirá que o editor o ajude a detectar erros, onde você pode estar assumindo que um valor é sempre um `str`, quando na verdade também pode ser `None`.
@@ -326,18 +266,18 @@ Isso também significa que no Python 3.10, você pode utilizar `Something | None
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial009.py!}
+{!> ../../docs_src/python_types/tutorial009_py39.py!}
```
////
-//// tab | Python 3.8+ alternativa
+//// tab | Python 3.9+ alternativa
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial009b.py!}
+{!> ../../docs_src/python_types/tutorial009b_py39.py!}
```
////
@@ -357,7 +297,7 @@ Isso é apenas sobre palavras e nomes. Mas estas palavras podem afetar como os s
Por exemplo, vamos pegar esta função:
-{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
+{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
O parâmetro `name` é definido como `Optional[str]`, mas ele **não é opcional**, você não pode chamar a função sem o parâmetro:
@@ -390,10 +330,10 @@ Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e ti
* `set`
* `dict`
-E o mesmo como no Python 3.8, do módulo `typing`:
+E o mesmo que com versões anteriores do Python, do módulo `typing`:
* `Union`
-* `Optional` (o mesmo que com o 3.8)
+* `Optional`
* ...entre outros.
No Python 3.10, como uma alternativa para a utilização dos genéricos `Union` e `Optional`, você pode usar a barra vertical (`|`) para declarar uniões de tipos. Isso é muito melhor e mais simples.
@@ -409,7 +349,7 @@ Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e ti
* `set`
* `dict`
-E o mesmo como no Python 3.8, do módulo `typing`:
+E genéricos do módulo `typing`:
* `Union`
* `Optional`
@@ -417,31 +357,19 @@ E o mesmo como no Python 3.8, do módulo `typing`:
////
-//// tab | Python 3.8+
-
-* `List`
-* `Tuple`
-* `Set`
-* `Dict`
-* `Union`
-* `Optional`
-* ...entre outros.
-
-////
-
### Classes como tipos { #classes-as-types }
Você também pode declarar uma classe como o tipo de uma variável.
Digamos que você tenha uma classe `Person`, com um nome:
-{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
+{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
Então você pode declarar que uma variável é do tipo `Person`:
-{* ../../docs_src/python_types/tutorial010.py hl[6] *}
+{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
-E então, novamente, você recebe todo o suporte do editor:
+E então, novamente, você recebe todo o apoio do editor:
@@ -461,31 +389,9 @@ Em seguida, você cria uma instância dessa classe com alguns valores e ela os v
E você recebe todo o suporte do editor com esse objeto resultante.
-Retirado dos documentos oficiais dos Pydantic:
+Um exemplo da documentação oficial do Pydantic:
-//// tab | Python 3.10+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial011_py310.py *}
/// info | Informação
@@ -507,27 +413,9 @@ O Pydantic tem um comportamento especial quando você usa `Optional` ou `Union[S
O Python possui uma funcionalidade que nos permite incluir **metadados adicionais** nos type hints utilizando `Annotated`.
-//// tab | Python 3.9+
+Desde o Python 3.9, `Annotated` faz parte da biblioteca padrão, então você pode importá-lo de `typing`.
-No Python 3.9, `Annotated` é parte da biblioteca padrão, então você pode importá-lo de `typing`.
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial013_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-Em versões abaixo do Python 3.9, você importa `Annotated` de `typing_extensions`.
-
-Ele já estará instalado com o **FastAPI**.
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial013.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
O Python em si não faz nada com este `Annotated`. E para editores e outras ferramentas, o tipo ainda é `str`.
diff --git a/docs/pt/docs/tutorial/background-tasks.md b/docs/pt/docs/tutorial/background-tasks.md
index af0c8b2acd..34805364b4 100644
--- a/docs/pt/docs/tutorial/background-tasks.md
+++ b/docs/pt/docs/tutorial/background-tasks.md
@@ -15,7 +15,7 @@ Isso inclui, por exemplo:
Primeiro, importe `BackgroundTasks` e defina um parâmetro na sua *função de operação de rota* com uma declaração de tipo `BackgroundTasks`:
-{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
O **FastAPI** criará o objeto do tipo `BackgroundTasks` para você e o passará como esse parâmetro.
@@ -31,13 +31,13 @@ Neste caso, a função da tarefa escreverá em um arquivo (simulando o envio de
E como a operação de escrita não usa `async` e `await`, definimos a função com um `def` normal:
-{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
## Adicione a tarefa em segundo plano { #add-the-background-task }
Dentro da sua *função de operação de rota*, passe sua função de tarefa para o objeto de *tarefas em segundo plano* com o método `.add_task()`:
-{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
O `.add_task()` recebe como argumentos:
diff --git a/docs/pt/docs/tutorial/body-nested-models.md b/docs/pt/docs/tutorial/body-nested-models.md
index 4f3ca661fb..f2bec19a2f 100644
--- a/docs/pt/docs/tutorial/body-nested-models.md
+++ b/docs/pt/docs/tutorial/body-nested-models.md
@@ -14,35 +14,15 @@ Isso fará com que tags seja uma lista de itens mesmo sem declarar o tipo dos el
Mas o Python tem uma maneira específica de declarar listas com tipos internos ou "parâmetros de tipo":
-### Importe `List` do typing { #import-typings-list }
-
-No Python 3.9 e superior você pode usar a `list` padrão para declarar essas anotações de tipo, como veremos abaixo. 💡
-
-Mas nas versões do Python anteriores à 3.9 (3.6 e superiores), primeiro é necessário importar `List` do módulo padrão `typing` do Python:
-
-{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
-
### Declare uma `list` com um parâmetro de tipo { #declare-a-list-with-a-type-parameter }
-Para declarar tipos que têm parâmetros de tipo (tipos internos), como `list`, `dict`, `tuple`:
-
-* Se você estiver em uma versão do Python inferior a 3.9, importe a versão equivalente do módulo `typing`
-* Passe o(s) tipo(s) interno(s) como "parâmetros de tipo" usando colchetes: `[` e `]`
-
-No Python 3.9, seria:
+Para declarar tipos que têm parâmetros de tipo (tipos internos), como `list`, `dict`, `tuple`,
+passe o(s) tipo(s) interno(s) como "parâmetros de tipo" usando colchetes: `[` e `]`
```Python
my_list: list[str]
```
-Em versões do Python anteriores à 3.9, seria:
-
-```Python
-from typing import List
-
-my_list: List[str]
-```
-
Essa é a sintaxe padrão do Python para declarações de tipo.
Use a mesma sintaxe padrão para atributos de modelo com tipos internos.
@@ -178,12 +158,6 @@ Observe como `Offer` tem uma lista de `Item`s, que por sua vez têm uma lista op
Se o valor de primeiro nível do corpo JSON que você espera for um `array` do JSON (uma` lista` do Python), você pode declarar o tipo no parâmetro da função, da mesma forma que nos modelos do Pydantic:
-```Python
-images: List[Image]
-```
-
-ou no Python 3.9 e superior:
-
```Python
images: list[Image]
```
diff --git a/docs/pt/docs/tutorial/body.md b/docs/pt/docs/tutorial/body.md
index ef00b9a7a7..1330f4458f 100644
--- a/docs/pt/docs/tutorial/body.md
+++ b/docs/pt/docs/tutorial/body.md
@@ -161,7 +161,7 @@ Os parâmetros da função serão reconhecidos conforme abaixo:
O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`.
-O `str | None` (Python 3.10+) ou o `Union` em `Union[str, None]` (Python 3.8+) não é utilizado pelo FastAPI para determinar que o valor não é obrigatório, ele saberá que não é obrigatório porque tem um valor padrão `= None`.
+O `str | None` (Python 3.10+) ou o `Union` em `Union[str, None]` (Python 3.9+) não é utilizado pelo FastAPI para determinar que o valor não é obrigatório, ele saberá que não é obrigatório porque tem um valor padrão `= None`.
Mas adicionar as anotações de tipo permitirá ao seu editor oferecer um suporte melhor e detectar erros.
diff --git a/docs/pt/docs/tutorial/cors.md b/docs/pt/docs/tutorial/cors.md
index c08191db14..0f99db888e 100644
--- a/docs/pt/docs/tutorial/cors.md
+++ b/docs/pt/docs/tutorial/cors.md
@@ -46,7 +46,7 @@ Você também pode especificar se o seu backend permite:
* Métodos HTTP específicos (`POST`, `PUT`) ou todos eles com o curinga `"*"`.
* Cabeçalhos HTTP específicos ou todos eles com o curinga `"*"`.
-{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
+{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
Os parâmetros padrão usados pela implementação `CORSMiddleware` são restritivos por padrão, então você precisará habilitar explicitamente as origens, métodos ou cabeçalhos específicos para que os navegadores tenham permissão para usá-los em um contexto cross domain.
diff --git a/docs/pt/docs/tutorial/debugging.md b/docs/pt/docs/tutorial/debugging.md
index 21d1d527bd..e39c7d1280 100644
--- a/docs/pt/docs/tutorial/debugging.md
+++ b/docs/pt/docs/tutorial/debugging.md
@@ -6,7 +6,7 @@ Você pode conectar o depurador no seu editor, por exemplo, com o Visual Studio
Em sua aplicação FastAPI, importe e execute `uvicorn` diretamente:
-{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
+{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
### Sobre `__name__ == "__main__"` { #about-name-main }
diff --git a/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md
index aa26d158f4..c30d0b5f08 100644
--- a/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -101,7 +101,7 @@ O **FastAPI** chama a classe `CommonQueryParams`. Isso cria uma "instância" des
Perceba como escrevemos `CommonQueryParams` duas vezes no código abaixo:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
@@ -137,7 +137,7 @@ O último `CommonQueryParams`, em:
Nesse caso, o primeiro `CommonQueryParams`, em:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, ...
@@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
@@ -163,7 +163,7 @@ commons: CommonQueryParams ...
Na verdade você poderia escrever apenas:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
@@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
@@ -197,7 +197,7 @@ Mas declarar o tipo é encorajado por que é a forma que o seu editor de texto s
Mas você pode ver que temos uma repetição do código neste exemplo, escrevendo `CommonQueryParams` duas vezes:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
@@ -225,7 +225,7 @@ Para esses casos específicos, você pode fazer o seguinte:
Em vez de escrever:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
@@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
...escreva:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends()]
@@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
////
-//// tab | Python 3.8 non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Dica
diff --git a/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md
index 0aedcfb31e..3678730139 100644
--- a/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md
+++ b/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -29,15 +29,15 @@ Por exemplo, você poderia utilizar isso para criar uma sessão do banco de dado
Apenas o código anterior à declaração com `yield` e o código contendo essa declaração são executados antes de criar uma resposta:
-{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
O valor gerado (yielded) é o que é injetado nas *operações de rota* e outras dependências:
-{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
O código após o `yield` é executado após a resposta:
-{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
/// tip | Dica
@@ -57,7 +57,7 @@ Então, você pode procurar por essa exceção específica dentro da dependênci
Da mesma forma, você pode utilizar `finally` para garantir que os passos de saída são executados, com ou sem exceções.
-{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
## Subdependências com `yield` { #sub-dependencies-with-yield }
@@ -269,7 +269,7 @@ Em Python, você pode criar Gerenciadores de Contexto ao descontinuada, mas sem removê-la, passe o parâmetro `deprecated`:
-{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *}
+{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
Ela será claramente marcada como descontinuada nas documentações interativas:
diff --git a/docs/pt/docs/tutorial/path-params-numeric-validations.md b/docs/pt/docs/tutorial/path-params-numeric-validations.md
index cec744fd5e..9f12ba38fe 100644
--- a/docs/pt/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/pt/docs/tutorial/path-params-numeric-validations.md
@@ -54,7 +54,7 @@ Isso não faz diferença para o **FastAPI**. Ele vai detectar os parâmetros pel
Então, você pode declarar sua função assim:
-{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
Mas tenha em mente que, se você usar `Annotated`, você não terá esse problema, não fará diferença, pois você não está usando valores padrão de parâmetros de função para `Query()` ou `Path()`.
@@ -83,7 +83,7 @@ Passe `*`, como o primeiro parâmetro da função.
O Python não fará nada com esse `*`, mas saberá que todos os parâmetros seguintes devem ser chamados como argumentos nomeados (pares chave-valor), também conhecidos como kwargs. Mesmo que eles não tenham um valor padrão.
-{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
### Melhor com `Annotated` { #better-with-annotated }
diff --git a/docs/pt/docs/tutorial/path-params.md b/docs/pt/docs/tutorial/path-params.md
index d795d5b2a0..1f47ca6e59 100644
--- a/docs/pt/docs/tutorial/path-params.md
+++ b/docs/pt/docs/tutorial/path-params.md
@@ -2,7 +2,7 @@
Você pode declarar "parâmetros" ou "variáveis" de path com a mesma sintaxe usada por strings de formatação do Python:
-{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
+{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
O valor do parâmetro de path `item_id` será passado para a sua função como o argumento `item_id`.
@@ -16,7 +16,7 @@ Então, se você executar este exemplo e acessar Enumerations (ou enums) estão disponíveis no Python desde a versão 3.4.
-///
+{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
/// tip | Dica
Se você está se perguntando, "AlexNet", "ResNet" e "LeNet" são apenas nomes de modelos de Aprendizado de Máquina.
@@ -146,7 +142,7 @@ Se você está se perguntando, "AlexNet", "ResNet" e "LeNet" são apenas nomes d
Em seguida, crie um *parâmetro de path* com anotação de tipo usando a classe enum que você criou (`ModelName`):
-{* ../../docs_src/path_params/tutorial005.py hl[16] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
### Verifique a documentação { #check-the-docs }
@@ -162,13 +158,13 @@ O valor do *parâmetro de path* será um *membro de enumeração*.
Você pode compará-lo com o *membro de enumeração* no seu enum `ModelName` criado:
-{* ../../docs_src/path_params/tutorial005.py hl[17] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
#### Obtenha o valor da enumeração { #get-the-enumeration-value }
Você pode obter o valor real (um `str` neste caso) usando `model_name.value`, ou, em geral, `your_enum_member.value`:
-{* ../../docs_src/path_params/tutorial005.py hl[20] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
/// tip | Dica
Você também pode acessar o valor `"lenet"` com `ModelName.lenet.value`.
@@ -180,7 +176,7 @@ Você pode retornar *membros de enum* da sua *operação de rota*, até mesmo an
Eles serão convertidos para seus valores correspondentes (strings neste caso) antes de serem retornados ao cliente:
-{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
No seu cliente, você receberá uma resposta JSON como:
@@ -219,7 +215,7 @@ Nesse caso, o nome do parâmetro é `file_path`, e a última parte, `:path`, diz
Então, você pode usá-lo com:
-{* ../../docs_src/path_params/tutorial004.py hl[6] *}
+{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
/// tip | Dica
Você pode precisar que o parâmetro contenha `/home/johndoe/myfile.txt`, com uma barra inicial (`/`).
diff --git a/docs/pt/docs/tutorial/query-params-str-validations.md b/docs/pt/docs/tutorial/query-params-str-validations.md
index 948f8ca8fa..5ec1b1b55e 100644
--- a/docs/pt/docs/tutorial/query-params-str-validations.md
+++ b/docs/pt/docs/tutorial/query-params-str-validations.md
@@ -55,7 +55,7 @@ q: str | None = None
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
q: Union[str, None] = None
@@ -73,7 +73,7 @@ q: Annotated[str | None] = None
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
diff --git a/docs/pt/docs/tutorial/query-params.md b/docs/pt/docs/tutorial/query-params.md
index 5a3fed0359..8826602a25 100644
--- a/docs/pt/docs/tutorial/query-params.md
+++ b/docs/pt/docs/tutorial/query-params.md
@@ -2,7 +2,7 @@
Quando você declara outros parâmetros na função que não fazem parte dos parâmetros da rota, esses parâmetros são automaticamente interpretados como parâmetros de "consulta".
-{* ../../docs_src/query_params/tutorial001.py hl[9] *}
+{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
A consulta é o conjunto de pares chave-valor que vai depois de `?` na URL, separado pelo caractere `&`.
@@ -127,7 +127,7 @@ Caso você não queira adicionar um valor específico mas queira apenas torná-l
Porém, quando você quiser fazer com que o parâmetro de consulta seja obrigatório, você pode simplesmente não declarar nenhum valor como padrão.
-{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
+{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
Aqui o parâmetro de consulta `needy` é um valor obrigatório, do tipo `str`.
diff --git a/docs/pt/docs/tutorial/response-model.md b/docs/pt/docs/tutorial/response-model.md
index 5958240e4c..dc66bb46c4 100644
--- a/docs/pt/docs/tutorial/response-model.md
+++ b/docs/pt/docs/tutorial/response-model.md
@@ -183,7 +183,7 @@ Pode haver casos em que você retorna algo que não é um campo Pydantic válido
O caso mais comum seria [retornar uma Response diretamente, conforme explicado posteriormente na documentação avançada](../advanced/response-directly.md){.internal-link target=_blank}.
-{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
+{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
Este caso simples é tratado automaticamente pelo FastAPI porque a anotação do tipo de retorno é a classe (ou uma subclasse de) `Response`.
@@ -193,7 +193,7 @@ E as ferramentas também ficarão felizes porque `RedirectResponse` e `JSO
Você também pode usar uma subclasse de `Response` na anotação de tipo:
-{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *}
+{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
Isso também funcionará porque `RedirectResponse` é uma subclasse de `Response`, e o FastAPI tratará automaticamente este caso simples.
diff --git a/docs/pt/docs/tutorial/response-status-code.md b/docs/pt/docs/tutorial/response-status-code.md
index 854bf57c9d..756c86dada 100644
--- a/docs/pt/docs/tutorial/response-status-code.md
+++ b/docs/pt/docs/tutorial/response-status-code.md
@@ -8,7 +8,7 @@ Da mesma forma que você pode especificar um modelo de resposta, você também p
* `@app.delete()`
* etc.
-{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
/// note | Nota
@@ -74,7 +74,7 @@ Para saber mais sobre cada código de status e qual código serve para quê, ver
Vamos ver o exemplo anterior novamente:
-{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
`201` é o código de status para "Criado".
@@ -82,7 +82,7 @@ Mas você não precisa memorizar o que cada um desses códigos significa.
Você pode usar as variáveis de conveniência de `fastapi.status`.
-{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
+{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o preenchimento automático do editor para encontrá-los:
diff --git a/docs/pt/docs/tutorial/static-files.md b/docs/pt/docs/tutorial/static-files.md
index 13313a909e..04a02c7f96 100644
--- a/docs/pt/docs/tutorial/static-files.md
+++ b/docs/pt/docs/tutorial/static-files.md
@@ -7,7 +7,7 @@ Você pode servir arquivos estáticos automaticamente a partir de um diretório
* Importe `StaticFiles`.
* "Monte" uma instância de `StaticFiles()` em um path específico.
-{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
/// note | Detalhes Técnicos
diff --git a/docs/pt/docs/tutorial/testing.md b/docs/pt/docs/tutorial/testing.md
index 03f1981a3c..e56edcb8c2 100644
--- a/docs/pt/docs/tutorial/testing.md
+++ b/docs/pt/docs/tutorial/testing.md
@@ -30,7 +30,7 @@ Use o objeto `TestClient` da mesma forma que você faz com `httpx`.
Escreva instruções `assert` simples com as expressões Python padrão que você precisa verificar (novamente, `pytest` padrão).
-{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
+{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
/// tip | Dica
@@ -76,7 +76,7 @@ Digamos que você tenha uma estrutura de arquivo conforme descrito em [Aplicaç
No arquivo `main.py` você tem sua aplicação **FastAPI**:
-{* ../../docs_src/app_testing/main.py *}
+{* ../../docs_src/app_testing/app_a_py39/main.py *}
### Arquivo de teste { #testing-file }
@@ -92,7 +92,7 @@ Então você poderia ter um arquivo `test_main.py` com seus testes. Ele poderia
Como esse arquivo está no mesmo pacote, você pode usar importações relativas para importar o objeto `app` do módulo `main` (`main.py`):
-{* ../../docs_src/app_testing/test_main.py hl[3] *}
+{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
...e ter o código para os testes como antes.
diff --git a/docs/pt/llm-prompt.md b/docs/pt/llm-prompt.md
index 01ce4143cb..2374070ced 100644
--- a/docs/pt/llm-prompt.md
+++ b/docs/pt/llm-prompt.md
@@ -47,7 +47,7 @@ For the next terms, use the following translations:
* list (as in Python list): list
* Machine Learning: Aprendizado de Máquina
* media type: media type (do not translate to "tipo de mídia")
-* non-Annotated: non-Annotated (do not translate non-Annotated when it comes after a Python version.e.g., “Python 3.8+ non-Annotated”)
+* non-Annotated: non-Annotated (do not translate non-Annotated when it comes after a Python version.e.g., “Python 3.10+ non-Annotated”)
* operation IDs: IDs de operação
* path (as in URL path): path
* path operation: operação de rota
diff --git a/docs/ru/docs/advanced/additional-responses.md b/docs/ru/docs/advanced/additional-responses.md
index 1fc3715e41..fca4f072da 100644
--- a/docs/ru/docs/advanced/additional-responses.md
+++ b/docs/ru/docs/advanced/additional-responses.md
@@ -26,7 +26,7 @@
Например, чтобы объявить ещё один ответ со статус-кодом `404` и Pydantic-моделью `Message`, можно написать:
-{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
+{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
/// note | Примечание
@@ -203,7 +203,7 @@
А также ответ со статус-кодом `200`, который использует ваш `response_model`, но включает пользовательский `example`:
-{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
+{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
Всё это будет объединено и включено в ваш OpenAPI и отображено в документации API:
diff --git a/docs/ru/docs/advanced/async-tests.md b/docs/ru/docs/advanced/async-tests.md
index 5062bc52e7..e689704066 100644
--- a/docs/ru/docs/advanced/async-tests.md
+++ b/docs/ru/docs/advanced/async-tests.md
@@ -32,11 +32,11 @@
Файл `main.py`:
-{* ../../docs_src/async_tests/main.py *}
+{* ../../docs_src/async_tests/app_a_py39/main.py *}
Файл `test_main.py` содержит тесты для `main.py`, теперь он может выглядеть так:
-{* ../../docs_src/async_tests/test_main.py *}
+{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
## Запуск тестов { #run-it }
@@ -56,7 +56,7 @@ $ pytest
Маркер `@pytest.mark.anyio` говорит pytest, что тестовая функция должна быть вызвана асинхронно:
-{* ../../docs_src/async_tests/test_main.py hl[7] *}
+{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
/// tip | Подсказка
@@ -66,7 +66,7 @@ $ pytest
Затем мы можем создать `AsyncClient` со ссылкой на приложение и посылать асинхронные запросы, используя `await`.
-{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
+{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
Это эквивалентно следующему:
diff --git a/docs/ru/docs/advanced/behind-a-proxy.md b/docs/ru/docs/advanced/behind-a-proxy.md
index 7119efe2dc..f78da01a09 100644
--- a/docs/ru/docs/advanced/behind-a-proxy.md
+++ b/docs/ru/docs/advanced/behind-a-proxy.md
@@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*"
Например, вы объявили операцию пути `/items/`:
-{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
Если клиент обратится к `/items`, по умолчанию произойдёт редирект на `/items/`.
@@ -115,7 +115,7 @@ sequenceDiagram
Хотя весь ваш код написан с расчётом, что путь один — `/app`.
-{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
Прокси будет «обрезать» префикс пути на лету перед передачей запроса на сервер приложения (скорее всего Uvicorn, запущенный через FastAPI CLI), поддерживая у вашего приложения иллюзию, что его обслуживают по `/app`, чтобы вам не пришлось менять весь код и добавлять префикс `/api/v1`.
@@ -193,7 +193,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
Здесь мы добавляем его в сообщение лишь для демонстрации.
-{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
+{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
Затем, если вы запустите Uvicorn так:
@@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
Если нет возможности передать опцию командной строки `--root-path` (или аналог), вы можете указать параметр `root_path` при создании приложения FastAPI:
-{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
+{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
Передача `root_path` в `FastAPI` эквивалентна опции командной строки `--root-path` для Uvicorn или Hypercorn.
@@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
Например:
-{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
+{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
Будет сгенерирована схема OpenAPI примерно такая:
@@ -455,7 +455,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
Если вы не хотите, чтобы FastAPI добавлял автоматический сервер, используя `root_path`, укажите параметр `root_path_in_servers=False`:
-{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
+{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
и тогда этот сервер не будет добавлен в схему OpenAPI.
diff --git a/docs/ru/docs/advanced/custom-response.md b/docs/ru/docs/advanced/custom-response.md
index 2c238bd95b..49550b49ff 100644
--- a/docs/ru/docs/advanced/custom-response.md
+++ b/docs/ru/docs/advanced/custom-response.md
@@ -30,7 +30,7 @@
Но если вы уверены, что содержимое, которое вы возвращаете, **сериализуемо в JSON**, вы можете передать его напрямую в класс ответа и избежать дополнительных накладных расходов, которые FastAPI понёс бы, пропуская возвращаемое содержимое через `jsonable_encoder` перед передачей в класс ответа.
-{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
/// info | Информация
@@ -55,7 +55,7 @@
- Импортируйте `HTMLResponse`.
- Передайте `HTMLResponse` в параметр `response_class` вашего декоратора операции пути.
-{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
/// info | Информация
@@ -73,7 +73,7 @@
Тот же пример сверху, возвращающий `HTMLResponse`, может выглядеть так:
-{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
+{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
/// warning | Предупреждение
@@ -97,7 +97,7 @@
Например, это может быть что-то вроде:
-{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *}
+{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
В этом примере функция `generate_html_response()` уже генерирует и возвращает `Response` вместо возврата HTML в `str`.
@@ -136,7 +136,7 @@
FastAPI (фактически Starlette) автоматически добавит заголовок Content-Length. Также будет добавлен заголовок Content-Type, основанный на `media_type` и с добавлением charset для текстовых типов.
-{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
+{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
### `HTMLResponse` { #htmlresponse }
@@ -146,7 +146,7 @@ FastAPI (фактически Starlette) автоматически добави
Принимает текст или байты и возвращает ответ в виде простого текста.
-{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
### `JSONResponse` { #jsonresponse }
@@ -180,7 +180,7 @@ FastAPI (фактически Starlette) автоматически добави
///
-{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
+{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
/// tip | Совет
@@ -194,13 +194,13 @@ FastAPI (фактически Starlette) автоматически добави
Вы можете вернуть `RedirectResponse` напрямую:
-{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
+{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
---
Или можно использовать его в параметре `response_class`:
-{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
Если вы сделаете так, то сможете возвращать URL напрямую из своей функции-обработчика пути.
@@ -210,13 +210,13 @@ FastAPI (фактически Starlette) автоматически добави
Также вы можете использовать параметр `status_code` в сочетании с параметром `response_class`:
-{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
+{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
### `StreamingResponse` { #streamingresponse }
Принимает асинхронный генератор или обычный генератор/итератор и отправляет тело ответа потоково.
-{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
+{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
#### Использование `StreamingResponse` с файлоподобными объектами { #using-streamingresponse-with-file-like-objects }
@@ -226,7 +226,7 @@ FastAPI (фактически Starlette) автоматически добави
Это включает многие библиотеки для работы с облачным хранилищем, обработки видео и т.д.
-{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
+{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
1. Это функция-генератор. Она является «функцией-генератором», потому что содержит оператор(ы) `yield` внутри.
2. Используя блок `with`, мы гарантируем, что файлоподобный объект будет закрыт после завершения работы функции-генератора. То есть после того, как она закончит отправку ответа.
@@ -255,11 +255,11 @@ FastAPI (фактически Starlette) автоматически добави
Файловые ответы будут содержать соответствующие заголовки `Content-Length`, `Last-Modified` и `ETag`.
-{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
+{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
Вы также можете использовать параметр `response_class`:
-{* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *}
+{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
В этом случае вы можете возвращать путь к файлу напрямую из своей функции-обработчика пути.
@@ -273,7 +273,7 @@ FastAPI (фактически Starlette) автоматически добави
Вы могли бы создать `CustomORJSONResponse`. Главное, что вам нужно сделать — реализовать метод `Response.render(content)`, который возвращает содержимое как `bytes`:
-{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
+{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
Теперь вместо того, чтобы возвращать:
@@ -299,7 +299,7 @@ FastAPI (фактически Starlette) автоматически добави
В примере ниже **FastAPI** будет использовать `ORJSONResponse` по умолчанию во всех операциях пути вместо `JSONResponse`.
-{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *}
+{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
/// tip | Совет
diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md
index 20d1df98a9..db73d9094e 100644
--- a/docs/ru/docs/advanced/events.md
+++ b/docs/ru/docs/advanced/events.md
@@ -30,7 +30,7 @@
Мы создаём асинхронную функцию `lifespan()` с `yield` примерно так:
-{* ../../docs_src/events/tutorial003.py hl[16,19] *}
+{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup.
@@ -48,7 +48,7 @@
Первое, на что стоит обратить внимание, — мы определяем асинхронную функцию с `yield`. Это очень похоже на Зависимости с `yield`.
-{* ../../docs_src/events/tutorial003.py hl[14:19] *}
+{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
Первая часть функции, до `yield`, будет выполнена до запуска приложения.
@@ -60,7 +60,7 @@
Это превращает функцию в «асинхронный менеджер контекста».
-{* ../../docs_src/events/tutorial003.py hl[1,13] *}
+{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
Менеджер контекста в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста:
@@ -82,7 +82,7 @@ async with lifespan(app):
Параметр `lifespan` приложения `FastAPI` принимает асинхронный менеджер контекста, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`.
-{* ../../docs_src/events/tutorial003.py hl[22] *}
+{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
## Альтернативные события (устаревшие) { #alternative-events-deprecated }
@@ -104,7 +104,7 @@ async with lifespan(app):
Чтобы добавить функцию, которую нужно запустить до старта приложения, объявите её как обработчик события `"startup"`:
-{* ../../docs_src/events/tutorial001.py hl[8] *}
+{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
В этом случае функция-обработчик события `startup` инициализирует «базу данных» items (это просто `dict`) некоторыми значениями.
@@ -116,7 +116,7 @@ async with lifespan(app):
Чтобы добавить функцию, которую нужно запустить при завершении работы приложения, объявите её как обработчик события `"shutdown"`:
-{* ../../docs_src/events/tutorial002.py hl[6] *}
+{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
Здесь функция-обработчик события `shutdown` запишет строку текста `"Application shutdown"` в файл `log.txt`.
diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md
index ee52412c6d..00bdd31fe8 100644
--- a/docs/ru/docs/advanced/generate-clients.md
+++ b/docs/ru/docs/advanced/generate-clients.md
@@ -167,7 +167,7 @@ FastAPI использует **уникальный ID** для каждой *о
Мы можем скачать OpenAPI JSON в файл `openapi.json`, а затем **убрать этот префикс‑тег** таким скриптом:
-{* ../../docs_src/generate_clients/tutorial004.py *}
+{* ../../docs_src/generate_clients/tutorial004_py39.py *}
//// tab | Node.js
diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md
index 82c86b2317..5ebe010782 100644
--- a/docs/ru/docs/advanced/middleware.md
+++ b/docs/ru/docs/advanced/middleware.md
@@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
Любой входящий запрос по `http` или `ws` будет перенаправлен на безопасную схему.
-{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
+{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
## `TrustedHostMiddleware` { #trustedhostmiddleware }
Гарантирует, что во всех входящих запросах корректно установлен `Host`‑заголовок, чтобы защититься от атак на HTTP‑заголовок Host.
-{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
+{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
Поддерживаются следующие аргументы:
@@ -78,7 +78,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
Это middleware обрабатывает как обычные, так и потоковые ответы.
-{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
+{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
Поддерживаются следующие аргументы:
diff --git a/docs/ru/docs/advanced/openapi-webhooks.md b/docs/ru/docs/advanced/openapi-webhooks.md
index d38cf315f7..3a2b9fff74 100644
--- a/docs/ru/docs/advanced/openapi-webhooks.md
+++ b/docs/ru/docs/advanced/openapi-webhooks.md
@@ -32,7 +32,7 @@
При создании приложения на **FastAPI** есть атрибут `webhooks`, с помощью которого можно объявлять вебхуки так же, как вы объявляете операции пути (обработчики пути), например с `@app.webhooks.post()`.
-{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *}
+{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
Определенные вами вебхуки попадут в схему **OpenAPI** и в автоматический **интерфейс документации**.
diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md
index 78a16a5583..eaf9ad0528 100644
--- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md
+++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md
@@ -12,7 +12,7 @@
Нужно убедиться, что он уникален для каждой операции.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
### Использование имени функции-обработчика пути как operationId { #using-the-path-operation-function-name-as-the-operationid }
@@ -20,7 +20,7 @@
Делать это следует после добавления всех *операций пути*.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
/// tip | Совет
@@ -40,7 +40,7 @@
Чтобы исключить *операцию пути* из генерируемой схемы OpenAPI (а значит, и из автоматической документации), используйте параметр `include_in_schema` и установите его в `False`:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
## Расширенное описание из docstring { #advanced-description-from-docstring }
@@ -92,7 +92,7 @@
`openapi_extra` может пригодиться, например, чтобы объявить [Расширения OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
-{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
Если вы откроете автоматическую документацию API, ваше расширение появится внизу страницы конкретной *операции пути*.
@@ -139,7 +139,7 @@
Это можно сделать с помощью `openapi_extra`:
-{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
В этом примере мы не объявляли никакую Pydantic-модель. Фактически тело запроса даже не распарсено как JSON, оно читается напрямую как `bytes`, а функция `magic_data_reader()` будет отвечать за его парсинг каким-то способом.
diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md
index e9e1c9470f..85d9050ffc 100644
--- a/docs/ru/docs/advanced/response-change-status-code.md
+++ b/docs/ru/docs/advanced/response-change-status-code.md
@@ -20,7 +20,7 @@
И затем вы можете установить `status_code` в этом *временном* объекте ответа.
-{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *}
+{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
После этого вы можете вернуть любой объект, который вам нужен, как обычно (`dict`, модель базы данных и т.д.).
diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md
index 9319aba6e2..2872d6c0ad 100644
--- a/docs/ru/docs/advanced/response-cookies.md
+++ b/docs/ru/docs/advanced/response-cookies.md
@@ -6,7 +6,7 @@
Затем установить cookies в этом временном объекте ответа.
-{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
+{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
После этого можно вернуть любой объект, как и раньше (например, `dict`, объект модели базы данных и так далее).
@@ -24,7 +24,7 @@
Затем установите cookies и верните этот объект:
-{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
+{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
/// tip | Совет
diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md
index 3c10633e91..b452810714 100644
--- a/docs/ru/docs/advanced/response-directly.md
+++ b/docs/ru/docs/advanced/response-directly.md
@@ -54,7 +54,7 @@
Вы можете поместить ваш XML-контент в строку, поместить её в `Response` и вернуть:
-{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
+{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
## Примечания { #notes }
diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md
index 1c9360b31d..8f24f05b07 100644
--- a/docs/ru/docs/advanced/response-headers.md
+++ b/docs/ru/docs/advanced/response-headers.md
@@ -6,7 +6,7 @@
А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа.
-{* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *}
+{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
После этого вы можете вернуть любой нужный объект, как обычно (например, `dict`, модель из базы данных и т.д.).
@@ -22,7 +22,7 @@
Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md){.internal-link target=_blank}, и передайте заголовки как дополнительный параметр:
-{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *}
+{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
/// note | Технические детали
diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md
index 0ef46fb13c..b96ee44a3a 100644
--- a/docs/ru/docs/advanced/settings.md
+++ b/docs/ru/docs/advanced/settings.md
@@ -62,7 +62,7 @@ $ pip install "fastapi[all]"
//// tab | Pydantic v2
-{* ../../docs_src/settings/tutorial001.py hl[2,5:8,11] *}
+{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
////
@@ -74,7 +74,7 @@ $ pip install "fastapi[all]"
///
-{* ../../docs_src/settings/tutorial001_pv1.py hl[2,5:8,11] *}
+{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *}
////
@@ -92,7 +92,7 @@ $ pip install "fastapi[all]"
Затем вы можете использовать новый объект `settings` в вашем приложении:
-{* ../../docs_src/settings/tutorial001.py hl[18:20] *}
+{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
### Запуск сервера { #run-the-server }
@@ -126,11 +126,11 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
Например, у вас может быть файл `config.py` со следующим содержимым:
-{* ../../docs_src/settings/app01/config.py *}
+{* ../../docs_src/settings/app01_py39/config.py *}
А затем использовать его в файле `main.py`:
-{* ../../docs_src/settings/app01/main.py hl[3,11:13] *}
+{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
/// tip | Совет
diff --git a/docs/ru/docs/advanced/sub-applications.md b/docs/ru/docs/advanced/sub-applications.md
index 3464f17040..fa5a683f45 100644
--- a/docs/ru/docs/advanced/sub-applications.md
+++ b/docs/ru/docs/advanced/sub-applications.md
@@ -10,7 +10,7 @@
Сначала создайте основное, верхнего уровня, приложение **FastAPI** и его *операции пути*:
-{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
+{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
### Подприложение { #sub-application }
@@ -18,7 +18,7 @@
Это подприложение — обычное стандартное приложение FastAPI, но именно оно будет «смонтировано»:
-{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
+{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
### Смонтируйте подприложение { #mount-the-sub-application }
@@ -26,7 +26,7 @@
В этом случае оно будет смонтировано по пути `/subapi`:
-{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
+{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
### Проверьте автоматическую документацию API { #check-the-automatic-api-docs }
diff --git a/docs/ru/docs/advanced/templates.md b/docs/ru/docs/advanced/templates.md
index 204e887605..460e2e4660 100644
--- a/docs/ru/docs/advanced/templates.md
+++ b/docs/ru/docs/advanced/templates.md
@@ -27,7 +27,7 @@ $ pip install jinja2
- Объявите параметр `Request` в *операции пути*, которая будет возвращать шаблон.
- Используйте созданный `templates`, чтобы отрендерить и вернуть `TemplateResponse`; передайте имя шаблона, объект `request` и словарь «context» с парами ключ-значение для использования внутри шаблона Jinja2.
-{* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *}
+{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
/// note | Примечание
diff --git a/docs/ru/docs/advanced/testing-events.md b/docs/ru/docs/advanced/testing-events.md
index e0ec774399..82caea845b 100644
--- a/docs/ru/docs/advanced/testing-events.md
+++ b/docs/ru/docs/advanced/testing-events.md
@@ -2,11 +2,11 @@
Если вам нужно, чтобы `lifespan` выполнялся в ваших тестах, вы можете использовать `TestClient` вместе с оператором `with`:
-{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *}
+{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
Вы можете узнать больше подробностей в статье [Запуск lifespan в тестах на официальном сайте документации Starlette.](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
Для устаревших событий `startup` и `shutdown` вы можете использовать `TestClient` следующим образом:
-{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}
+{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
diff --git a/docs/ru/docs/advanced/testing-websockets.md b/docs/ru/docs/advanced/testing-websockets.md
index e840a03f28..b6626679e4 100644
--- a/docs/ru/docs/advanced/testing-websockets.md
+++ b/docs/ru/docs/advanced/testing-websockets.md
@@ -4,7 +4,7 @@
Для этого используйте `TestClient` с менеджером контекста `with`, подключаясь к WebSocket:
-{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *}
+{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
/// note | Примечание
diff --git a/docs/ru/docs/advanced/using-request-directly.md b/docs/ru/docs/advanced/using-request-directly.md
index b922216105..cdf500c0e2 100644
--- a/docs/ru/docs/advanced/using-request-directly.md
+++ b/docs/ru/docs/advanced/using-request-directly.md
@@ -29,7 +29,7 @@
Для этого нужно обратиться к запросу напрямую.
-{* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *}
+{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
Если объявить параметр *функции-обработчика пути* с типом `Request`, **FastAPI** поймёт, что нужно передать объект `Request` в этот параметр.
diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md
index f26185bea5..fa5e4738eb 100644
--- a/docs/ru/docs/advanced/websockets.md
+++ b/docs/ru/docs/advanced/websockets.md
@@ -38,13 +38,13 @@ $ pip install websockets
Для примера нам нужен наиболее простой способ, который позволит сосредоточиться на серверной части веб‑сокетов и получить рабочий код:
-{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
+{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
## Создание `websocket` { #create-a-websocket }
Создайте `websocket` в своем **FastAPI** приложении:
-{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *}
+{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
/// note | Технические детали
@@ -58,7 +58,7 @@ $ pip install websockets
Через эндпоинт веб-сокета вы можете получать и отправлять сообщения.
-{* ../../docs_src/websockets/tutorial001.py hl[48:52] *}
+{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
Вы можете получать и отправлять двоичные, текстовые и JSON данные.
diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md
index 1c5bf0a626..64d7c7a289 100644
--- a/docs/ru/docs/advanced/wsgi.md
+++ b/docs/ru/docs/advanced/wsgi.md
@@ -12,7 +12,7 @@
После этого смонтируйте его на путь.
-{* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *}
+{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Проверьте { #check-it }
diff --git a/docs/ru/docs/how-to/conditional-openapi.md b/docs/ru/docs/how-to/conditional-openapi.md
index dc987ae26b..d0845b91e2 100644
--- a/docs/ru/docs/how-to/conditional-openapi.md
+++ b/docs/ru/docs/how-to/conditional-openapi.md
@@ -29,7 +29,7 @@
Например:
-{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *}
+{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
Здесь мы объявляем настройку `openapi_url` с тем же значением по умолчанию — `"/openapi.json"`.
diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md
index 9d104423d7..b3b1c1ba62 100644
--- a/docs/ru/docs/how-to/configure-swagger-ui.md
+++ b/docs/ru/docs/how-to/configure-swagger-ui.md
@@ -18,7 +18,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы
Но вы можете отключить её, установив `syntaxHighlight` в `False`:
-{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
…и после этого Swagger UI больше не будет показывать подсветку синтаксиса:
@@ -28,7 +28,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы
Аналогично вы можете задать тему подсветки синтаксиса с ключом "syntaxHighlight.theme" (обратите внимание, что посередине стоит точка):
-{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
Эта настройка изменит цветовую тему подсветки синтаксиса:
@@ -46,7 +46,7 @@ FastAPI включает некоторые параметры конфигур
Например, чтобы отключить `deepLinking`, можно передать такие настройки в `swagger_ui_parameters`:
-{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
+{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
## Другие параметры Swagger UI { #other-swagger-ui-parameters }
diff --git a/docs/ru/docs/how-to/custom-docs-ui-assets.md b/docs/ru/docs/how-to/custom-docs-ui-assets.md
index c07a9695b9..f524911e65 100644
--- a/docs/ru/docs/how-to/custom-docs-ui-assets.md
+++ b/docs/ru/docs/how-to/custom-docs-ui-assets.md
@@ -18,7 +18,7 @@
Чтобы отключить её, установите их URL в значение `None` при создании вашего приложения `FastAPI`:
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
### Подключить пользовательскую документацию { #include-the-custom-docs }
@@ -34,7 +34,7 @@
Аналогично и для ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
/// tip | Совет
@@ -50,7 +50,7 @@ Swagger UI сделает это за вас «за кулисами», но д
Чтобы убедиться, что всё работает, создайте *операцию пути*:
-{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *}
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
### Тестирование { #test-it }
@@ -118,7 +118,7 @@ Swagger UI сделает это за вас «за кулисами», но д
* Импортируйте `StaticFiles`.
* Смонтируйте экземпляр `StaticFiles()` в определённый путь.
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
### Протестируйте статические файлы { #test-the-static-files }
@@ -144,7 +144,7 @@ Swagger UI сделает это за вас «за кулисами», но д
Чтобы отключить её, установите их URL в значение `None` при создании вашего приложения `FastAPI`:
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
### Подключить пользовательскую документацию со статическими файлами { #include-the-custom-docs-for-static-files }
@@ -160,7 +160,7 @@ Swagger UI сделает это за вас «за кулисами», но д
Аналогично и для ReDoc...
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
/// tip | Совет
@@ -176,7 +176,7 @@ Swagger UI сделает это за вас «за кулисами», но д
Чтобы убедиться, что всё работает, создайте *операцию пути*:
-{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *}
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
### Тестирование UI со статическими файлами { #test-static-files-ui }
diff --git a/docs/ru/docs/how-to/extending-openapi.md b/docs/ru/docs/how-to/extending-openapi.md
index 2897fb89ba..1d69cbdb3a 100644
--- a/docs/ru/docs/how-to/extending-openapi.md
+++ b/docs/ru/docs/how-to/extending-openapi.md
@@ -43,19 +43,19 @@
Сначала напишите приложение **FastAPI** как обычно:
-{* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *}
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
### Сгенерируйте схему OpenAPI { #generate-the-openapi-schema }
Затем используйте ту же вспомогательную функцию для генерации схемы OpenAPI внутри функции `custom_openapi()`:
-{* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *}
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
### Измените схему OpenAPI { #modify-the-openapi-schema }
Теперь можно добавить расширение ReDoc, добавив кастомный `x-logo` в «объект» `info` в схеме OpenAPI:
-{* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *}
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
### Кэшируйте схему OpenAPI { #cache-the-openapi-schema }
@@ -65,13 +65,13 @@
Она будет создана один раз, а затем тот же кэшированный вариант будет использоваться для последующих запросов.
-{* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *}
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
### Переопределите метод { #override-the-method }
Теперь вы можете заменить метод `.openapi()` на вашу новую функцию.
-{* ../../docs_src/extending_openapi/tutorial001.py hl[29] *}
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
### Проверьте { #check-it }
diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md
index 9ed6d95ca1..97278069ad 100644
--- a/docs/ru/docs/how-to/graphql.md
+++ b/docs/ru/docs/how-to/graphql.md
@@ -35,7 +35,7 @@
Вот небольшой пример того, как можно интегрировать Strawberry с FastAPI:
-{* ../../docs_src/graphql/tutorial001.py hl[3,22,25] *}
+{* ../../docs_src/graphql/tutorial001_py39.py hl[3,22,25] *}
Подробнее о Strawberry можно узнать в документации Strawberry.
diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md
index 84a901f547..ae4a1e2b79 100644
--- a/docs/ru/docs/python-types.md
+++ b/docs/ru/docs/python-types.md
@@ -22,7 +22,7 @@ Python поддерживает необязательные «подсказк
Давайте начнем с простого примера:
-{* ../../docs_src/python_types/tutorial001.py *}
+{* ../../docs_src/python_types/tutorial001_py39.py *}
Вызов этой программы выводит:
@@ -36,7 +36,7 @@ John Doe
* Преобразует первую букву каждого значения в верхний регистр с помощью `title()`.
* Соединяет их пробелом посередине.
-{* ../../docs_src/python_types/tutorial001.py hl[2] *}
+{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
### Отредактируем пример { #edit-it }
@@ -78,7 +78,7 @@ John Doe
Это и есть «подсказки типов»:
-{* ../../docs_src/python_types/tutorial002.py hl[1] *}
+{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
Это не то же самое, что объявление значений по умолчанию, как, например:
@@ -106,7 +106,7 @@ John Doe
Посмотрите на эту функцию — у неё уже есть подсказки типов:
-{* ../../docs_src/python_types/tutorial003.py hl[1] *}
+{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
Так как редактор кода знает типы переменных, вы получаете не только автозавершение, но и проверки ошибок:
@@ -114,7 +114,7 @@ John Doe
Теперь вы знаете, что нужно исправить — преобразовать `age` в строку с помощью `str(age)`:
-{* ../../docs_src/python_types/tutorial004.py hl[2] *}
+{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
## Объявление типов { #declaring-types }
@@ -133,7 +133,7 @@ John Doe
* `bool`
* `bytes`
-{* ../../docs_src/python_types/tutorial005.py hl[1] *}
+{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
### Generic-типы с параметрами типов { #generic-types-with-type-parameters }
@@ -161,56 +161,24 @@ John Doe
Например, давайте определим переменную как `list` из `str`.
-//// tab | Python 3.9+
-
Объявите переменную с тем же синтаксисом двоеточия (`:`).
В качестве типа укажите `list`.
Так как список — это тип, содержащий внутренние типы, укажите их в квадратных скобках:
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial006_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-Из `typing` импортируйте `List` (с заглавной `L`):
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial006.py!}
-```
-
-Объявите переменную с тем же синтаксисом двоеточия (`:`).
-
-В качестве типа используйте `List`, который вы импортировали из `typing`.
-
-Так как список — это тип, содержащий внутренние типы, укажите их в квадратных скобках:
-
-```Python hl_lines="4"
-{!> ../../docs_src/python_types/tutorial006.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
/// info | Информация
Эти внутренние типы в квадратных скобках называются «параметрами типов».
-В данном случае `str` — это параметр типа, передаваемый в `List` (или `list` в Python 3.9 и выше).
+В данном случае `str` — это параметр типа, передаваемый в `list`.
///
Это означает: «переменная `items` — это `list`, и каждый элемент этого списка — `str`».
-/// tip | Совет
-
-Если вы используете Python 3.9 или выше, вам не нужно импортировать `List` из `typing`, можно использовать обычный встроенный тип `list`.
-
-///
-
Таким образом, ваш редактор кода сможет помогать даже при обработке элементов списка:
@@ -225,21 +193,7 @@ John Doe
Аналогично вы бы объявили `tuple` и `set`:
-//// tab | Python 3.9+
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial007_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial007.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
Это означает:
@@ -254,21 +208,7 @@ John Doe
Второй параметр типа — для значений `dict`:
-//// tab | Python 3.9+
-
-```Python hl_lines="1"
-{!> ../../docs_src/python_types/tutorial008_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial008.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
Это означает:
@@ -292,10 +232,10 @@ John Doe
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial008b.py!}
+{!> ../../docs_src/python_types/tutorial008b_py39.py!}
```
////
@@ -309,7 +249,7 @@ John Doe
В Python 3.6 и выше (включая Python 3.10) это можно объявить, импортировав и используя `Optional` из модуля `typing`.
```Python hl_lines="1 4"
-{!../../docs_src/python_types/tutorial009.py!}
+{!../../docs_src/python_types/tutorial009_py39.py!}
```
Использование `Optional[str]` вместо просто `str` позволит редактору кода помочь вам обнаружить ошибки, когда вы предполагаете, что значение всегда `str`, хотя на самом деле оно может быть и `None`.
@@ -326,18 +266,18 @@ John Doe
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial009.py!}
+{!> ../../docs_src/python_types/tutorial009_py39.py!}
```
////
-//// tab | Python 3.8+ альтернативный вариант
+//// tab | Python 3.9+ альтернативный вариант
```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial009b.py!}
+{!> ../../docs_src/python_types/tutorial009b_py39.py!}
```
////
@@ -357,7 +297,7 @@ John Doe
В качестве примера возьмём эту функцию:
-{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
+{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
Параметр `name` определён как `Optional[str]`, но он **не необязательный** — вы не можете вызвать функцию без этого параметра:
@@ -390,10 +330,10 @@ say_hi(name=None) # Это работает, None допустим 🎉
* `set`
* `dict`
-И, как и в Python 3.8, из модуля `typing`:
+И, как и в предыдущих версиях Python, из модуля `typing`:
* `Union`
-* `Optional` (так же, как в Python 3.8)
+* `Optional`
* ...и другие.
В Python 3.10, как альтернативу generics `Union` и `Optional`, можно использовать вертикальную черту (`|`) для объявления объединений типов — это гораздо лучше и проще.
@@ -409,7 +349,7 @@ say_hi(name=None) # Это работает, None допустим 🎉
* `set`
* `dict`
-И, как и в Python 3.8, из модуля `typing`:
+И generics из модуля `typing`:
* `Union`
* `Optional`
@@ -417,29 +357,17 @@ say_hi(name=None) # Это работает, None допустим 🎉
////
-//// tab | Python 3.8+
-
-* `List`
-* `Tuple`
-* `Set`
-* `Dict`
-* `Union`
-* `Optional`
-* ...и другие.
-
-////
-
### Классы как типы { #classes-as-types }
Вы также можете объявлять класс как тип переменной.
Допустим, у вас есть класс `Person` с именем:
-{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
+{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
Тогда вы можете объявить переменную типа `Person`:
-{* ../../docs_src/python_types/tutorial010.py hl[6] *}
+{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
И снова вы получите полную поддержку редактора кода:
@@ -463,29 +391,7 @@ say_hi(name=None) # Это работает, None допустим 🎉
Пример из официальной документации Pydantic:
-//// tab | Python 3.10+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-```Python
-{!> ../../docs_src/python_types/tutorial011.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial011_py310.py *}
/// info | Информация
@@ -507,27 +413,9 @@ say_hi(name=None) # Это работает, None допустим 🎉
В Python также есть возможность добавлять **дополнительные метаданные** к подсказкам типов с помощью `Annotated`.
-//// tab | Python 3.9+
+Начиная с Python 3.9, `Annotated` входит в стандартную библиотеку, поэтому вы можете импортировать его из `typing`.
-В Python 3.9 `Annotated` входит в стандартную библиотеку, поэтому вы можете импортировать его из `typing`.
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial013_py39.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-В версиях ниже Python 3.9 импортируйте `Annotated` из `typing_extensions`.
-
-Он уже будет установлен вместе с **FastAPI**.
-
-```Python hl_lines="1 4"
-{!> ../../docs_src/python_types/tutorial013.py!}
-```
-
-////
+{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
Сам Python ничего не делает с `Annotated`. А для редакторов кода и других инструментов тип по-прежнему `str`.
@@ -558,7 +446,7 @@ say_hi(name=None) # Это работает, None допустим 🎉
...и **FastAPI** использует эти же объявления для:
-* **Определения требований**: из path-параметров, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д.
+* **Определения требований**: из path-параметров пути запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д.
* **Преобразования данных**: из HTTP-запроса к требуемому типу.
* **Валидации данных**: приходящих с каждого HTTP-запроса:
* Генерации **автоматических ошибок**, возвращаемых клиенту, когда данные некорректны.
diff --git a/docs/ru/docs/tutorial/background-tasks.md b/docs/ru/docs/tutorial/background-tasks.md
index 1ed8522d69..8d7b7442f9 100644
--- a/docs/ru/docs/tutorial/background-tasks.md
+++ b/docs/ru/docs/tutorial/background-tasks.md
@@ -15,7 +15,7 @@
Сначала импортируйте `BackgroundTasks` и объявите параметр в вашей функции‑обработчике пути с типом `BackgroundTasks`:
-{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
**FastAPI** создаст объект типа `BackgroundTasks` для вас и передаст его через этот параметр.
@@ -31,13 +31,13 @@
Так как операция записи не использует `async` и `await`, мы определим функцию как обычную `def`:
-{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
## Добавление фоновой задачи { #add-the-background-task }
Внутри вашей функции‑обработчика пути передайте функцию задачи объекту фоновых задач методом `.add_task()`:
-{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
`.add_task()` принимает следующие аргументы:
diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md
index 5bb5abbe63..4c914b97f0 100644
--- a/docs/ru/docs/tutorial/body-nested-models.md
+++ b/docs/ru/docs/tutorial/body-nested-models.md
@@ -14,35 +14,14 @@
В Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»:
-### Импортируйте `List` из модуля typing { #import-typings-list }
-
-В Python 3.9 и выше вы можете использовать стандартный тип `list` для объявления аннотаций типов, как мы увидим ниже. 💡
-
-Но в версиях Python до 3.9 (начиная с 3.6) сначала вам необходимо импортировать `List` из стандартного модуля `typing`:
-
-{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
-
### Объявите `list` с параметром типа { #declare-a-list-with-a-type-parameter }
-Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`:
-
-* Если у вас Python версии ниже 3.9, импортируйте их аналоги из модуля `typing`
-* Передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]`
-
-В Python 3.9 это будет:
+Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`, передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]`
```Python
my_list: list[str]
```
-В версиях Python до 3.9 это будет:
-
-```Python
-from typing import List
-
-my_list: List[str]
-```
-
Это всё стандартный синтаксис Python для объявления типов.
Используйте этот же стандартный синтаксис для атрибутов модели с внутренними типами.
@@ -107,7 +86,7 @@ my_list: List[str]
Ещё раз: сделав такое объявление, с помощью **FastAPI** вы получите:
-* Поддержку редактора кода (автозавершение и т. д.), даже для вложенных моделей
+* Поддержку редактора кода (автозавершение и т.д.), даже для вложенных моделей
* Преобразование данных
* Валидацию данных
* Автоматическую документацию
@@ -178,12 +157,6 @@ my_list: List[str]
Если верхний уровень значения тела JSON-объекта представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic:
-```Python
-images: List[Image]
-```
-
-или в Python 3.9 и выше:
-
```Python
images: list[Image]
```
diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md
index 16ff6466c1..b61f3e7a09 100644
--- a/docs/ru/docs/tutorial/body.md
+++ b/docs/ru/docs/tutorial/body.md
@@ -161,7 +161,7 @@ JSON Schema ваших моделей будет частью сгенериро
FastAPI понимает, что значение `q` не является обязательным из-за значения по умолчанию `= None`.
-Аннотации типов `str | None` (Python 3.10+) или `Union[str, None]` (Python 3.8+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`.
+Аннотации типов `str | None` (Python 3.10+) или `Union[str, None]` (Python 3.9+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`.
Но добавление аннотаций типов позволит вашему редактору кода лучше вас поддерживать и обнаруживать ошибки.
diff --git a/docs/ru/docs/tutorial/cors.md b/docs/ru/docs/tutorial/cors.md
index b0704351a9..d09a31e2c3 100644
--- a/docs/ru/docs/tutorial/cors.md
+++ b/docs/ru/docs/tutorial/cors.md
@@ -46,7 +46,7 @@
* Отдельных HTTP-методов (`POST`, `PUT`) или всех вместе, используя `"*"`.
* Отдельных HTTP-заголовков или всех вместе, используя `"*"`.
-{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
+{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
`CORSMiddleware` использует "запрещающие" значения по умолчанию, поэтому вам нужно явным образом разрешить использование отдельных источников, методов или заголовков, чтобы браузеры могли использовать их в кросс-доменном контексте.
diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md
index a5340af089..51955835e6 100644
--- a/docs/ru/docs/tutorial/debugging.md
+++ b/docs/ru/docs/tutorial/debugging.md
@@ -6,7 +6,7 @@
В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую:
-{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
+{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
### Описание `__name__ == "__main__"` { #about-name-main }
diff --git a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md
index ec7770d960..a38e885d43 100644
--- a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -101,7 +101,7 @@ fluffy = Cat(name="Mr Fluffy")
Обратите внимание, что в приведенном выше коде мы два раза пишем `CommonQueryParams`:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
@@ -137,7 +137,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
В этом случае первый `CommonQueryParams`, в:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, ...
@@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
@@ -163,7 +163,7 @@ commons: CommonQueryParams ...
На самом деле можно написать просто:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
@@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
@@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams)
Но вы видите, что здесь мы имеем некоторое повторение кода, дважды написав `CommonQueryParams`:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
@@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
Вместо того чтобы писать:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
-//// tab | Python 3.8+ non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
@@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
...следует написать:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
commons: Annotated[CommonQueryParams, Depends()]
@@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
////
-//// tab | Python 3.8 non-Annotated
+//// tab | Python 3.9+ non-Annotated
/// tip | Подсказка
diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
index 7ff85246dc..dc202db616 100644
--- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
+++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -29,15 +29,15 @@ FastAPI поддерживает зависимости, которые выпо
Перед созданием ответа будет выполнен только код до и включая оператор `yield`:
-{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
Значение, полученное из `yield`, внедряется в *операции пути* и другие зависимости:
-{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
Код, следующий за оператором `yield`, выполняется после ответа:
-{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
/// tip | Подсказка
@@ -57,7 +57,7 @@ FastAPI поддерживает зависимости, которые выпо
Точно так же можно использовать `finally`, чтобы убедиться, что обязательные шаги при выходе выполнены независимо от того, было ли исключение или нет.
-{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
+{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
## Подзависимости с `yield` { #sub-dependencies-with-yield }
@@ -269,7 +269,7 @@ with open("./somefile.txt") as f:
Их также можно использовать внутри зависимостей **FastAPI** с `yield`, применяя операторы
`with` или `async with` внутри функции зависимости:
-{* ../../docs_src/dependencies/tutorial010.py hl[1:9,13] *}
+{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
/// tip | Подсказка
diff --git a/docs/ru/docs/tutorial/dependencies/global-dependencies.md b/docs/ru/docs/tutorial/dependencies/global-dependencies.md
index 075d6b0baa..2347c6dd83 100644
--- a/docs/ru/docs/tutorial/dependencies/global-dependencies.md
+++ b/docs/ru/docs/tutorial/dependencies/global-dependencies.md
@@ -6,7 +6,7 @@
В этом случае они будут применяться ко всем *операциям пути* в приложении:
-{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[16] *}
+{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
Все способы [добавления `dependencies` (зависимостей) в *декораторах операций пути*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} по-прежнему применимы, но в данном случае зависимости применяются ко всем *операциям пути* приложения.
diff --git a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md
index efe8d98c31..da31a6682f 100644
--- a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md
+++ b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md
@@ -62,7 +62,7 @@ query_extractor --> query_or_cookie_extractor --> read_query
В расширенном сценарии, когда вы знаете, что вам нужно, чтобы зависимость вызывалась на каждом шаге (возможно, несколько раз) в одном и том же запросе, вместо использования "кэшированного" значения, вы можете установить параметр `use_cache=False` при использовании `Depends`:
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
@@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
////
-//// tab | Python 3.8+ без Annotated
+//// tab | Python 3.9+ без Annotated
/// tip | Подсказка
diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md
index 6f59d72054..798c03d517 100644
--- a/docs/ru/docs/tutorial/first-steps.md
+++ b/docs/ru/docs/tutorial/first-steps.md
@@ -2,7 +2,7 @@
Самый простой файл FastAPI может выглядеть так:
-{* ../../docs_src/first_steps/tutorial001.py *}
+{* ../../docs_src/first_steps/tutorial001_py39.py *}
Скопируйте это в файл `main.py`.
@@ -183,7 +183,7 @@ Deploying to FastAPI Cloud...
### Шаг 1: импортируйте `FastAPI` { #step-1-import-fastapi }
-{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
`FastAPI` — это класс на Python, который предоставляет всю функциональность для вашего API.
@@ -197,7 +197,7 @@ Deploying to FastAPI Cloud...
### Шаг 2: создайте экземпляр `FastAPI` { #step-2-create-a-fastapi-instance }
-{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
Здесь переменная `app` будет экземпляром класса `FastAPI`.
@@ -266,7 +266,7 @@ https://example.com/items/foo
#### Определите *декоратор операции пути (path operation decorator)* { #define-a-path-operation-decorator }
-{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку запросов, поступающих:
@@ -320,7 +320,7 @@ https://example.com/items/foo
* **операция**: `get`.
* **функция**: функция ниже «декоратора» (ниже `@app.get("/")`).
-{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
Это функция на Python.
@@ -332,7 +332,7 @@ https://example.com/items/foo
Вы также можете определить её как обычную функцию вместо `async def`:
-{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
/// note | Примечание
@@ -342,7 +342,7 @@ https://example.com/items/foo
### Шаг 5: верните содержимое { #step-5-return-the-content }
-{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
Вы можете вернуть `dict`, `list`, отдельные значения `str`, `int` и т.д.
diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md
index 63ca8665ef..2e00d70759 100644
--- a/docs/ru/docs/tutorial/handling-errors.md
+++ b/docs/ru/docs/tutorial/handling-errors.md
@@ -25,7 +25,7 @@
### Импортируйте `HTTPException` { #import-httpexception }
-{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
+{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
### Вызовите `HTTPException` в своем коде { #raise-an-httpexception-in-your-code }
@@ -39,7 +39,7 @@
В данном примере, когда клиент запрашивает элемент по несуществующему ID, возникает исключение со статус-кодом `404`:
-{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
+{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
### Возвращаемый ответ { #the-resulting-response }
@@ -77,7 +77,7 @@
Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские заголовки:
-{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
+{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
## Установка пользовательских обработчиков исключений { #install-custom-exception-handlers }
@@ -89,7 +89,7 @@
Можно добавить собственный обработчик исключений с помощью `@app.exception_handler()`:
-{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *}
+{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
Здесь, если запросить `/unicorns/yolo`, то *операция пути* вызовет `UnicornException`.
@@ -127,7 +127,7 @@
Обработчик исключения получит объект `Request` и исключение.
-{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:19] *}
+{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
Теперь, если перейти к `/items/foo`, то вместо стандартной JSON-ошибки с:
@@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
Например, для этих ошибок можно вернуть обычный текстовый ответ вместо JSON:
-{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,25] *}
+{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
/// note | Технические детали
@@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
Вы можете использовать его при разработке приложения для регистрации тела и его отладки, возврата пользователю и т.д.
-{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
+{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
Теперь попробуйте отправить недействительный элемент, например:
@@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
Если вы хотите использовать исключение вместе с теми же обработчиками исключений по умолчанию из **FastAPI**, вы можете импортировать и повторно использовать обработчики исключений по умолчанию из `fastapi.exception_handlers`:
-{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *}
+{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
В этом примере вы просто `выводите в терминал` ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений.
diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md
index 2e359752e1..e4fe5fb544 100644
--- a/docs/ru/docs/tutorial/metadata.md
+++ b/docs/ru/docs/tutorial/metadata.md
@@ -18,7 +18,7 @@
Вы можете задать их следующим образом:
-{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *}
+{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
/// tip | Подсказка
@@ -36,7 +36,7 @@
К примеру:
-{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
+{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
## Метаданные для тегов { #metadata-for-tags }
@@ -58,7 +58,7 @@
Создайте метаданные для ваших тегов и передайте их в параметре `openapi_tags`:
-{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
+{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
Помните, что вы можете использовать Markdown внутри описания, к примеру "login" будет отображен жирным шрифтом (**login**) и "fancy" будет отображаться курсивом (_fancy_).
@@ -72,7 +72,7 @@
Используйте параметр `tags` с вашими *операциями пути* (и `APIRouter`ами), чтобы присвоить им различные теги:
-{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
+{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
/// info | Дополнительная информация
@@ -100,7 +100,7 @@
К примеру, чтобы задать её отображение по адресу `/api/v1/openapi.json`:
-{* ../../docs_src/metadata/tutorial002.py hl[3] *}
+{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
Если вы хотите отключить схему OpenAPI полностью, вы можете задать `openapi_url=None`, это также отключит пользовательские интерфейсы документации, которые её используют.
@@ -117,4 +117,4 @@
К примеру, чтобы задать отображение Swagger UI по адресу `/documentation` и отключить ReDoc:
-{* ../../docs_src/metadata/tutorial003.py hl[3] *}
+{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
diff --git a/docs/ru/docs/tutorial/middleware.md b/docs/ru/docs/tutorial/middleware.md
index 5803b398b9..a83d3c0111 100644
--- a/docs/ru/docs/tutorial/middleware.md
+++ b/docs/ru/docs/tutorial/middleware.md
@@ -33,7 +33,7 @@
* Затем она возвращает ответ `response`, сгенерированный *операцией пути*.
* Также имеется возможность видоизменить `response`, перед тем как его вернуть.
-{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *}
+{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
/// tip | Примечание
@@ -59,7 +59,7 @@
Например, вы можете добавить собственный заголовок `X-Process-Time`, содержащий время в секундах, необходимое для обработки запроса и генерации ответа:
-{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
+{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
/// tip | Примечание
diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md
index 63b48a3941..96a54ffea0 100644
--- a/docs/ru/docs/tutorial/path-operation-configuration.md
+++ b/docs/ru/docs/tutorial/path-operation-configuration.md
@@ -46,7 +46,7 @@
**FastAPI** поддерживает это так же, как и в случае с обычными строками:
-{* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *}
+{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
## Краткое и развёрнутое содержание { #summary-and-description }
@@ -92,7 +92,7 @@ OpenAPI указывает, что каждой *операции пути* не
Если вам необходимо пометить *операцию пути* как устаревшую, при этом не удаляя её, передайте параметр `deprecated`:
-{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *}
+{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
Он будет четко помечен как устаревший в интерактивной документации:
diff --git a/docs/ru/docs/tutorial/path-params-numeric-validations.md b/docs/ru/docs/tutorial/path-params-numeric-validations.md
index ccea1945e4..f0fe788051 100644
--- a/docs/ru/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/ru/docs/tutorial/path-params-numeric-validations.md
@@ -54,7 +54,7 @@ Path-параметр всегда является обязательным, п
Поэтому вы можете определить функцию так:
-{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
Но имейте в виду, что если вы используете `Annotated`, вы не столкнётесь с этой проблемой, так как вы не используете значения по умолчанию параметров функции для `Query()` или `Path()`.
@@ -83,7 +83,7 @@ Path-параметр всегда является обязательным, п
Python не будет ничего делать с `*`, но он будет знать, что все следующие параметры являются именованными аргументами (парами ключ-значение), также известными как kwargs, даже если у них нет значений по умолчанию.
-{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
### Лучше с `Annotated` { #better-with-annotated }
diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md
index f7d138afbe..83a7ed3ffe 100644
--- a/docs/ru/docs/tutorial/path-params.md
+++ b/docs/ru/docs/tutorial/path-params.md
@@ -2,7 +2,7 @@
Вы можете определить "параметры" или "переменные" пути, используя синтаксис форматированных строк Python:
-{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
+{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
Значение параметра пути `item_id` будет передано в функцию в качестве аргумента `item_id`.
@@ -16,7 +16,7 @@
Вы можете объявить тип параметра пути в функции, используя стандартные аннотации типов Python:
-{* ../../docs_src/path_params/tutorial002.py hl[7] *}
+{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
Здесь, `item_id` объявлен типом `int`.
@@ -118,13 +118,13 @@
Поскольку *операции пути* выполняются в порядке их объявления, необходимо, чтобы путь для `/users/me` был объявлен раньше, чем путь для `/users/{user_id}`:
-{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
+{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
Иначе путь для `/users/{user_id}` также будет соответствовать `/users/me`, "подразумевая", что он получает параметр `user_id` со значением `"me"`.
Аналогично, вы не можете переопределить операцию с путем:
-{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
+{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
Первый будет выполняться всегда, так как путь совпадает первым.
@@ -140,13 +140,7 @@
Затем создайте атрибуты класса с фиксированными допустимыми значениями:
-{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
-
-/// info | Дополнительная информация
-
-Перечисления (enum) доступны в Python начиная с версии 3.4.
-
-///
+{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
/// tip | Подсказка
@@ -158,7 +152,7 @@
Определите *параметр пути*, используя в аннотации типа класс перечисления (`ModelName`), созданный ранее:
-{* ../../docs_src/path_params/tutorial005.py hl[16] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
### Проверьте документацию { #check-the-docs }
@@ -174,13 +168,13 @@
Вы можете сравнить это значение с *элементом перечисления* класса `ModelName`:
-{* ../../docs_src/path_params/tutorial005.py hl[17] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
#### Получение *значения перечисления* { #get-the-enumeration-value }
Можно получить фактическое значение (в данном случае - `str`) с помощью `model_name.value` или в общем случае `your_enum_member.value`:
-{* ../../docs_src/path_params/tutorial005.py hl[20] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
/// tip | Подсказка
@@ -194,7 +188,7 @@
Они будут преобразованы в соответствующие значения (в данном случае - строки) перед их возвратом клиенту:
-{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
Вы отправите клиенту такой JSON-ответ:
```JSON
@@ -232,7 +226,7 @@ OpenAPI не поддерживает способов объявления *п
Можете использовать так:
-{* ../../docs_src/path_params/tutorial004.py hl[6] *}
+{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
/// tip | Подсказка
diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md
index 302901d4ec..3a4ecc37dc 100644
--- a/docs/ru/docs/tutorial/query-params-str-validations.md
+++ b/docs/ru/docs/tutorial/query-params-str-validations.md
@@ -55,7 +55,7 @@ q: str | None = None
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
q: Union[str, None] = None
@@ -73,7 +73,7 @@ q: Annotated[str | None] = None
////
-//// tab | Python 3.8+
+//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md
index 5a84f9768c..be1c0e46e1 100644
--- a/docs/ru/docs/tutorial/query-params.md
+++ b/docs/ru/docs/tutorial/query-params.md
@@ -2,7 +2,7 @@
Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры.
-{* ../../docs_src/query_params/tutorial001.py hl[9] *}
+{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`.
@@ -127,7 +127,7 @@ http://127.0.0.1:8000/items/foo?short=yes
Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию:
-{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
+{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`.
diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md
index c045f9ed78..07308c1db2 100644
--- a/docs/ru/docs/tutorial/response-model.md
+++ b/docs/ru/docs/tutorial/response-model.md
@@ -183,7 +183,7 @@ FastAPI делает несколько вещей внутри вместе с
Самый распространённый случай — [возвращать Response напрямую, как описано далее в разделах для продвинутых](../advanced/response-directly.md){.internal-link target=_blank}.
-{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
+{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
Этот простой случай обрабатывается FastAPI автоматически, потому что аннотация возвращаемого типа — это класс (или подкласс) `Response`.
@@ -193,7 +193,7 @@ FastAPI делает несколько вещей внутри вместе с
Вы также можете использовать подкласс `Response` в аннотации типа:
-{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *}
+{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
Это тоже сработает, так как `RedirectResponse` — подкласс `Response`, и FastAPI автоматически обработает этот случай.
diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md
index f5b1ff6ad7..30f642b643 100644
--- a/docs/ru/docs/tutorial/response-status-code.md
+++ b/docs/ru/docs/tutorial/response-status-code.md
@@ -8,7 +8,7 @@
* `@app.delete()`
* и других.
-{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
/// note | Примечание
@@ -74,7 +74,7 @@ FastAPI знает об этом и создаст документацию Open
Рассмотрим предыдущий пример еще раз:
-{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
`201` – это код статуса "Создано".
@@ -82,7 +82,7 @@ FastAPI знает об этом и создаст документацию Open
Для удобства вы можете использовать переменные из `fastapi.status`.
-{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
+{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
Они содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора кода статуса:
diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md
index 8455aea0a2..f40cfe9b04 100644
--- a/docs/ru/docs/tutorial/static-files.md
+++ b/docs/ru/docs/tutorial/static-files.md
@@ -7,7 +7,7 @@
* Импортируйте `StaticFiles`.
* "Примонтируйте" экземпляр `StaticFiles()` к определённому пути.
-{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
/// note | Технические детали
diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md
index 7354ed895f..ab58429c51 100644
--- a/docs/ru/docs/tutorial/testing.md
+++ b/docs/ru/docs/tutorial/testing.md
@@ -30,7 +30,7 @@ $ pip install httpx
Напишите простое утверждение с `assert` дабы проверить истинность Python-выражения (это тоже стандарт `pytest`).
-{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
+{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
/// tip | Подсказка
@@ -76,7 +76,7 @@ $ pip install httpx
В файле `main.py` находится Ваше приложение **FastAPI**:
-{* ../../docs_src/app_testing/main.py *}
+{* ../../docs_src/app_testing/app_a_py39/main.py *}
### Файл тестов { #testing-file }
@@ -92,7 +92,7 @@ $ pip install httpx
Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт:
-{* ../../docs_src/app_testing/test_main.py hl[3] *}
+{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
...и писать дальше тесты, как и раньше.
diff --git a/docs_src/additional_responses/tutorial001.py b/docs_src/additional_responses/tutorial001_py39.py
similarity index 100%
rename from docs_src/additional_responses/tutorial001.py
rename to docs_src/additional_responses/tutorial001_py39.py
diff --git a/docs_src/additional_responses/tutorial002.py b/docs_src/additional_responses/tutorial002_py39.py
similarity index 100%
rename from docs_src/additional_responses/tutorial002.py
rename to docs_src/additional_responses/tutorial002_py39.py
diff --git a/docs_src/additional_responses/tutorial003.py b/docs_src/additional_responses/tutorial003_py39.py
similarity index 100%
rename from docs_src/additional_responses/tutorial003.py
rename to docs_src/additional_responses/tutorial003_py39.py
diff --git a/docs_src/additional_responses/tutorial004.py b/docs_src/additional_responses/tutorial004_py39.py
similarity index 100%
rename from docs_src/additional_responses/tutorial004.py
rename to docs_src/additional_responses/tutorial004_py39.py
diff --git a/docs_src/additional_status_codes/tutorial001_an.py b/docs_src/additional_status_codes/tutorial001_an.py
deleted file mode 100644
index b5ad6a16b6..0000000000
--- a/docs_src/additional_status_codes/tutorial001_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI, status
-from fastapi.responses import JSONResponse
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
-
-
-@app.put("/items/{item_id}")
-async def upsert_item(
- item_id: str,
- name: Annotated[Union[str, None], Body()] = None,
- size: Annotated[Union[int, None], Body()] = None,
-):
- if item_id in items:
- item = items[item_id]
- item["name"] = name
- item["size"] = size
- return item
- else:
- item = {"name": name, "size": size}
- items[item_id] = item
- return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs_src/additional_status_codes/tutorial001.py b/docs_src/additional_status_codes/tutorial001_py39.py
similarity index 100%
rename from docs_src/additional_status_codes/tutorial001.py
rename to docs_src/additional_status_codes/tutorial001_py39.py
diff --git a/docs_src/advanced_middleware/tutorial001.py b/docs_src/advanced_middleware/tutorial001_py39.py
similarity index 100%
rename from docs_src/advanced_middleware/tutorial001.py
rename to docs_src/advanced_middleware/tutorial001_py39.py
diff --git a/docs_src/advanced_middleware/tutorial002.py b/docs_src/advanced_middleware/tutorial002_py39.py
similarity index 100%
rename from docs_src/advanced_middleware/tutorial002.py
rename to docs_src/advanced_middleware/tutorial002_py39.py
diff --git a/docs_src/advanced_middleware/tutorial003.py b/docs_src/advanced_middleware/tutorial003_py39.py
similarity index 100%
rename from docs_src/advanced_middleware/tutorial003.py
rename to docs_src/advanced_middleware/tutorial003_py39.py
diff --git a/docs_src/app_testing/app_b/__init__.py b/docs_src/app_testing/app_a_py39/__init__.py
similarity index 100%
rename from docs_src/app_testing/app_b/__init__.py
rename to docs_src/app_testing/app_a_py39/__init__.py
diff --git a/docs_src/app_testing/main.py b/docs_src/app_testing/app_a_py39/main.py
similarity index 100%
rename from docs_src/app_testing/main.py
rename to docs_src/app_testing/app_a_py39/main.py
diff --git a/docs_src/app_testing/test_main.py b/docs_src/app_testing/app_a_py39/test_main.py
similarity index 100%
rename from docs_src/app_testing/test_main.py
rename to docs_src/app_testing/app_a_py39/test_main.py
diff --git a/docs_src/app_testing/app_b_an/main.py b/docs_src/app_testing/app_b_an/main.py
deleted file mode 100644
index c66278fdd0..0000000000
--- a/docs_src/app_testing/app_b_an/main.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Header, HTTPException
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-fake_secret_token = "coneofsilence"
-
-fake_db = {
- "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
- "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
-}
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- id: str
- title: str
- description: Union[str, None] = None
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_main(item_id: str, x_token: Annotated[str, Header()]):
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item_id not in fake_db:
- raise HTTPException(status_code=404, detail="Item not found")
- return fake_db[item_id]
-
-
-@app.post("/items/", response_model=Item)
-async def create_item(item: Item, x_token: Annotated[str, Header()]):
- if x_token != fake_secret_token:
- raise HTTPException(status_code=400, detail="Invalid X-Token header")
- if item.id in fake_db:
- raise HTTPException(status_code=409, detail="Item already exists")
- fake_db[item.id] = item
- return item
diff --git a/docs_src/app_testing/app_b_an/test_main.py b/docs_src/app_testing/app_b_an/test_main.py
deleted file mode 100644
index 4e1c51ecc8..0000000000
--- a/docs_src/app_testing/app_b_an/test_main.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from fastapi.testclient import TestClient
-
-from .main import app
-
-client = TestClient(app)
-
-
-def test_read_item():
- response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 200
- assert response.json() == {
- "id": "foo",
- "title": "Foo",
- "description": "There goes my hero",
- }
-
-
-def test_read_item_bad_token():
- response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_read_nonexistent_item():
- response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
- assert response.status_code == 404
- assert response.json() == {"detail": "Item not found"}
-
-
-def test_create_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
- )
- assert response.status_code == 200
- assert response.json() == {
- "id": "foobar",
- "title": "Foo Bar",
- "description": "The Foo Barters",
- }
-
-
-def test_create_item_bad_token():
- response = client.post(
- "/items/",
- headers={"X-Token": "hailhydra"},
- json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
- )
- assert response.status_code == 400
- assert response.json() == {"detail": "Invalid X-Token header"}
-
-
-def test_create_existing_item():
- response = client.post(
- "/items/",
- headers={"X-Token": "coneofsilence"},
- json={
- "id": "foo",
- "title": "The Foo ID Stealers",
- "description": "There goes my stealer",
- },
- )
- assert response.status_code == 409
- assert response.json() == {"detail": "Item already exists"}
diff --git a/docs_src/app_testing/app_b_an/__init__.py b/docs_src/app_testing/app_b_py39/__init__.py
similarity index 100%
rename from docs_src/app_testing/app_b_an/__init__.py
rename to docs_src/app_testing/app_b_py39/__init__.py
diff --git a/docs_src/app_testing/app_b/main.py b/docs_src/app_testing/app_b_py39/main.py
similarity index 100%
rename from docs_src/app_testing/app_b/main.py
rename to docs_src/app_testing/app_b_py39/main.py
diff --git a/docs_src/app_testing/app_b/test_main.py b/docs_src/app_testing/app_b_py39/test_main.py
similarity index 100%
rename from docs_src/app_testing/app_b/test_main.py
rename to docs_src/app_testing/app_b_py39/test_main.py
diff --git a/docs_src/app_testing/tutorial001.py b/docs_src/app_testing/tutorial001_py39.py
similarity index 100%
rename from docs_src/app_testing/tutorial001.py
rename to docs_src/app_testing/tutorial001_py39.py
diff --git a/docs_src/app_testing/tutorial002.py b/docs_src/app_testing/tutorial002_py39.py
similarity index 100%
rename from docs_src/app_testing/tutorial002.py
rename to docs_src/app_testing/tutorial002_py39.py
diff --git a/docs_src/app_testing/tutorial003.py b/docs_src/app_testing/tutorial003_py39.py
similarity index 100%
rename from docs_src/app_testing/tutorial003.py
rename to docs_src/app_testing/tutorial003_py39.py
diff --git a/docs_src/app_testing/tutorial004.py b/docs_src/app_testing/tutorial004_py39.py
similarity index 100%
rename from docs_src/app_testing/tutorial004.py
rename to docs_src/app_testing/tutorial004_py39.py
diff --git a/docs_src/bigger_applications/app/__init__.py b/docs_src/async_tests/app_a_py39/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app/__init__.py
rename to docs_src/async_tests/app_a_py39/__init__.py
diff --git a/docs_src/async_tests/main.py b/docs_src/async_tests/app_a_py39/main.py
similarity index 100%
rename from docs_src/async_tests/main.py
rename to docs_src/async_tests/app_a_py39/main.py
diff --git a/docs_src/async_tests/test_main.py b/docs_src/async_tests/app_a_py39/test_main.py
similarity index 100%
rename from docs_src/async_tests/test_main.py
rename to docs_src/async_tests/app_a_py39/test_main.py
diff --git a/docs_src/authentication_error_status_code/tutorial001_an.py b/docs_src/authentication_error_status_code/tutorial001_an.py
deleted file mode 100644
index 40678e858d..0000000000
--- a/docs_src/authentication_error_status_code/tutorial001_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class HTTPBearer403(HTTPBearer):
- def make_not_authenticated_error(self) -> HTTPException:
- return HTTPException(
- status_code=status.HTTP_403_FORBIDDEN, detail="Not authenticated"
- )
-
-
-CredentialsDep = Annotated[HTTPAuthorizationCredentials, Depends(HTTPBearer403())]
-
-
-@app.get("/me")
-def read_me(credentials: CredentialsDep):
- return {"message": "You are authenticated", "token": credentials.credentials}
diff --git a/docs_src/background_tasks/tutorial001.py b/docs_src/background_tasks/tutorial001_py39.py
similarity index 100%
rename from docs_src/background_tasks/tutorial001.py
rename to docs_src/background_tasks/tutorial001_py39.py
diff --git a/docs_src/background_tasks/tutorial002_an.py b/docs_src/background_tasks/tutorial002_an.py
deleted file mode 100644
index f63502b09a..0000000000
--- a/docs_src/background_tasks/tutorial002_an.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import Union
-
-from fastapi import BackgroundTasks, Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-def write_log(message: str):
- with open("log.txt", mode="a") as log:
- log.write(message)
-
-
-def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None):
- if q:
- message = f"found query: {q}\n"
- background_tasks.add_task(write_log, message)
- return q
-
-
-@app.post("/send-notification/{email}")
-async def send_notification(
- email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
-):
- message = f"message to {email}\n"
- background_tasks.add_task(write_log, message)
- return {"message": "Message sent"}
diff --git a/docs_src/background_tasks/tutorial002.py b/docs_src/background_tasks/tutorial002_py39.py
similarity index 100%
rename from docs_src/background_tasks/tutorial002.py
rename to docs_src/background_tasks/tutorial002_py39.py
diff --git a/docs_src/behind_a_proxy/tutorial001_01.py b/docs_src/behind_a_proxy/tutorial001_01_py39.py
similarity index 100%
rename from docs_src/behind_a_proxy/tutorial001_01.py
rename to docs_src/behind_a_proxy/tutorial001_01_py39.py
diff --git a/docs_src/behind_a_proxy/tutorial001.py b/docs_src/behind_a_proxy/tutorial001_py39.py
similarity index 100%
rename from docs_src/behind_a_proxy/tutorial001.py
rename to docs_src/behind_a_proxy/tutorial001_py39.py
diff --git a/docs_src/behind_a_proxy/tutorial002.py b/docs_src/behind_a_proxy/tutorial002_py39.py
similarity index 100%
rename from docs_src/behind_a_proxy/tutorial002.py
rename to docs_src/behind_a_proxy/tutorial002_py39.py
diff --git a/docs_src/behind_a_proxy/tutorial003.py b/docs_src/behind_a_proxy/tutorial003_py39.py
similarity index 100%
rename from docs_src/behind_a_proxy/tutorial003.py
rename to docs_src/behind_a_proxy/tutorial003_py39.py
diff --git a/docs_src/behind_a_proxy/tutorial004.py b/docs_src/behind_a_proxy/tutorial004_py39.py
similarity index 100%
rename from docs_src/behind_a_proxy/tutorial004.py
rename to docs_src/behind_a_proxy/tutorial004_py39.py
diff --git a/docs_src/bigger_applications/app_an/dependencies.py b/docs_src/bigger_applications/app_an/dependencies.py
deleted file mode 100644
index 1374c54b31..0000000000
--- a/docs_src/bigger_applications/app_an/dependencies.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import Header, HTTPException
-from typing_extensions import Annotated
-
-
-async def get_token_header(x_token: Annotated[str, Header()]):
- if x_token != "fake-super-secret-token":
- raise HTTPException(status_code=400, detail="X-Token header invalid")
-
-
-async def get_query_token(token: str):
- if token != "jessica":
- raise HTTPException(status_code=400, detail="No Jessica token provided")
diff --git a/docs_src/bigger_applications/app_an/internal/admin.py b/docs_src/bigger_applications/app_an/internal/admin.py
deleted file mode 100644
index 99d3da86b9..0000000000
--- a/docs_src/bigger_applications/app_an/internal/admin.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from fastapi import APIRouter
-
-router = APIRouter()
-
-
-@router.post("/")
-async def update_admin():
- return {"message": "Admin getting schwifty"}
diff --git a/docs_src/bigger_applications/app_an/main.py b/docs_src/bigger_applications/app_an/main.py
deleted file mode 100644
index ae544a3aac..0000000000
--- a/docs_src/bigger_applications/app_an/main.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from fastapi import Depends, FastAPI
-
-from .dependencies import get_query_token, get_token_header
-from .internal import admin
-from .routers import items, users
-
-app = FastAPI(dependencies=[Depends(get_query_token)])
-
-
-app.include_router(users.router)
-app.include_router(items.router)
-app.include_router(
- admin.router,
- prefix="/admin",
- tags=["admin"],
- dependencies=[Depends(get_token_header)],
- responses={418: {"description": "I'm a teapot"}},
-)
-
-
-@app.get("/")
-async def root():
- return {"message": "Hello Bigger Applications!"}
diff --git a/docs_src/bigger_applications/app_an/routers/items.py b/docs_src/bigger_applications/app_an/routers/items.py
deleted file mode 100644
index bde9ff4d55..0000000000
--- a/docs_src/bigger_applications/app_an/routers/items.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from fastapi import APIRouter, Depends, HTTPException
-
-from ..dependencies import get_token_header
-
-router = APIRouter(
- prefix="/items",
- tags=["items"],
- dependencies=[Depends(get_token_header)],
- responses={404: {"description": "Not found"}},
-)
-
-
-fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}
-
-
-@router.get("/")
-async def read_items():
- return fake_items_db
-
-
-@router.get("/{item_id}")
-async def read_item(item_id: str):
- if item_id not in fake_items_db:
- raise HTTPException(status_code=404, detail="Item not found")
- return {"name": fake_items_db[item_id]["name"], "item_id": item_id}
-
-
-@router.put(
- "/{item_id}",
- tags=["custom"],
- responses={403: {"description": "Operation forbidden"}},
-)
-async def update_item(item_id: str):
- if item_id != "plumbus":
- raise HTTPException(
- status_code=403, detail="You can only update the item: plumbus"
- )
- return {"item_id": item_id, "name": "The great Plumbus"}
diff --git a/docs_src/bigger_applications/app_an/routers/users.py b/docs_src/bigger_applications/app_an/routers/users.py
deleted file mode 100644
index 39b3d7e7cf..0000000000
--- a/docs_src/bigger_applications/app_an/routers/users.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from fastapi import APIRouter
-
-router = APIRouter()
-
-
-@router.get("/users/", tags=["users"])
-async def read_users():
- return [{"username": "Rick"}, {"username": "Morty"}]
-
-
-@router.get("/users/me", tags=["users"])
-async def read_user_me():
- return {"username": "fakecurrentuser"}
-
-
-@router.get("/users/{username}", tags=["users"])
-async def read_user(username: str):
- return {"username": username}
diff --git a/docs_src/bigger_applications/app/internal/__init__.py b/docs_src/bigger_applications/app_py39/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app/internal/__init__.py
rename to docs_src/bigger_applications/app_py39/__init__.py
diff --git a/docs_src/bigger_applications/app/dependencies.py b/docs_src/bigger_applications/app_py39/dependencies.py
similarity index 100%
rename from docs_src/bigger_applications/app/dependencies.py
rename to docs_src/bigger_applications/app_py39/dependencies.py
diff --git a/docs_src/bigger_applications/app/routers/__init__.py b/docs_src/bigger_applications/app_py39/internal/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app/routers/__init__.py
rename to docs_src/bigger_applications/app_py39/internal/__init__.py
diff --git a/docs_src/bigger_applications/app/internal/admin.py b/docs_src/bigger_applications/app_py39/internal/admin.py
similarity index 100%
rename from docs_src/bigger_applications/app/internal/admin.py
rename to docs_src/bigger_applications/app_py39/internal/admin.py
diff --git a/docs_src/bigger_applications/app/main.py b/docs_src/bigger_applications/app_py39/main.py
similarity index 100%
rename from docs_src/bigger_applications/app/main.py
rename to docs_src/bigger_applications/app_py39/main.py
diff --git a/docs_src/bigger_applications/app_an/__init__.py b/docs_src/bigger_applications/app_py39/routers/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app_an/__init__.py
rename to docs_src/bigger_applications/app_py39/routers/__init__.py
diff --git a/docs_src/bigger_applications/app/routers/items.py b/docs_src/bigger_applications/app_py39/routers/items.py
similarity index 100%
rename from docs_src/bigger_applications/app/routers/items.py
rename to docs_src/bigger_applications/app_py39/routers/items.py
diff --git a/docs_src/bigger_applications/app/routers/users.py b/docs_src/bigger_applications/app_py39/routers/users.py
similarity index 100%
rename from docs_src/bigger_applications/app/routers/users.py
rename to docs_src/bigger_applications/app_py39/routers/users.py
diff --git a/docs_src/body/tutorial001.py b/docs_src/body/tutorial001_py39.py
similarity index 100%
rename from docs_src/body/tutorial001.py
rename to docs_src/body/tutorial001_py39.py
diff --git a/docs_src/body/tutorial002.py b/docs_src/body/tutorial002_py39.py
similarity index 100%
rename from docs_src/body/tutorial002.py
rename to docs_src/body/tutorial002_py39.py
diff --git a/docs_src/body/tutorial003.py b/docs_src/body/tutorial003_py39.py
similarity index 100%
rename from docs_src/body/tutorial003.py
rename to docs_src/body/tutorial003_py39.py
diff --git a/docs_src/body/tutorial004.py b/docs_src/body/tutorial004_py39.py
similarity index 100%
rename from docs_src/body/tutorial004.py
rename to docs_src/body/tutorial004_py39.py
diff --git a/docs_src/body_fields/tutorial001_an.py b/docs_src/body_fields/tutorial001_an.py
deleted file mode 100644
index 15ea1b53dc..0000000000
--- a/docs_src/body_fields/tutorial001_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel, Field
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = Field(
- default=None, title="The description of the item", max_length=300
- )
- price: float = Field(gt=0, description="The price must be greater than zero")
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_fields/tutorial001.py b/docs_src/body_fields/tutorial001_py39.py
similarity index 100%
rename from docs_src/body_fields/tutorial001.py
rename to docs_src/body_fields/tutorial001_py39.py
diff --git a/docs_src/body_multiple_params/tutorial001_an.py b/docs_src/body_multiple_params/tutorial001_an.py
deleted file mode 100644
index 308eee8544..0000000000
--- a/docs_src/body_multiple_params/tutorial001_an.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Path
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
- q: Union[str, None] = None,
- item: Union[Item, None] = None,
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- if item:
- results.update({"item": item})
- return results
diff --git a/docs_src/body_multiple_params/tutorial001.py b/docs_src/body_multiple_params/tutorial001_py39.py
similarity index 100%
rename from docs_src/body_multiple_params/tutorial001.py
rename to docs_src/body_multiple_params/tutorial001_py39.py
diff --git a/docs_src/body_multiple_params/tutorial002.py b/docs_src/body_multiple_params/tutorial002_py39.py
similarity index 100%
rename from docs_src/body_multiple_params/tutorial002.py
rename to docs_src/body_multiple_params/tutorial002_py39.py
diff --git a/docs_src/body_multiple_params/tutorial003_an.py b/docs_src/body_multiple_params/tutorial003_an.py
deleted file mode 100644
index 39ef7340a5..0000000000
--- a/docs_src/body_multiple_params/tutorial003_an.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
-):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- return results
diff --git a/docs_src/body_multiple_params/tutorial003.py b/docs_src/body_multiple_params/tutorial003_py39.py
similarity index 100%
rename from docs_src/body_multiple_params/tutorial003.py
rename to docs_src/body_multiple_params/tutorial003_py39.py
diff --git a/docs_src/body_multiple_params/tutorial004_an.py b/docs_src/body_multiple_params/tutorial004_an.py
deleted file mode 100644
index f6830f3920..0000000000
--- a/docs_src/body_multiple_params/tutorial004_an.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-class User(BaseModel):
- username: str
- full_name: Union[str, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Item,
- user: User,
- importance: Annotated[int, Body(gt=0)],
- q: Union[str, None] = None,
-):
- results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/body_multiple_params/tutorial004.py b/docs_src/body_multiple_params/tutorial004_py39.py
similarity index 100%
rename from docs_src/body_multiple_params/tutorial004.py
rename to docs_src/body_multiple_params/tutorial004_py39.py
diff --git a/docs_src/body_multiple_params/tutorial005_an.py b/docs_src/body_multiple_params/tutorial005_an.py
deleted file mode 100644
index dadde80b55..0000000000
--- a/docs_src/body_multiple_params/tutorial005_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_multiple_params/tutorial005.py b/docs_src/body_multiple_params/tutorial005_py39.py
similarity index 100%
rename from docs_src/body_multiple_params/tutorial005.py
rename to docs_src/body_multiple_params/tutorial005_py39.py
diff --git a/docs_src/body_nested_models/tutorial001.py b/docs_src/body_nested_models/tutorial001_py39.py
similarity index 100%
rename from docs_src/body_nested_models/tutorial001.py
rename to docs_src/body_nested_models/tutorial001_py39.py
diff --git a/docs_src/body_nested_models/tutorial002.py b/docs_src/body_nested_models/tutorial002.py
deleted file mode 100644
index 155cff7885..0000000000
--- a/docs_src/body_nested_models/tutorial002.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: List[str] = []
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_nested_models/tutorial003.py b/docs_src/body_nested_models/tutorial003.py
deleted file mode 100644
index 84ed18bf48..0000000000
--- a/docs_src/body_nested_models/tutorial003.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_nested_models/tutorial004.py b/docs_src/body_nested_models/tutorial004.py
deleted file mode 100644
index a07bfacac1..0000000000
--- a/docs_src/body_nested_models/tutorial004.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: str
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
- image: Union[Image, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_nested_models/tutorial005.py b/docs_src/body_nested_models/tutorial005.py
deleted file mode 100644
index 5a01264eda..0000000000
--- a/docs_src/body_nested_models/tutorial005.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
- image: Union[Image, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_nested_models/tutorial006.py b/docs_src/body_nested_models/tutorial006.py
deleted file mode 100644
index 75f1f30e33..0000000000
--- a/docs_src/body_nested_models/tutorial006.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import List, Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
- images: Union[List[Image], None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/body_nested_models/tutorial007.py b/docs_src/body_nested_models/tutorial007.py
deleted file mode 100644
index 641f09dced..0000000000
--- a/docs_src/body_nested_models/tutorial007.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from typing import List, Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
- images: Union[List[Image], None] = None
-
-
-class Offer(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- items: List[Item]
-
-
-@app.post("/offers/")
-async def create_offer(offer: Offer):
- return offer
diff --git a/docs_src/body_nested_models/tutorial008.py b/docs_src/body_nested_models/tutorial008.py
deleted file mode 100644
index 3431cc6365..0000000000
--- a/docs_src/body_nested_models/tutorial008.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from pydantic import BaseModel, HttpUrl
-
-app = FastAPI()
-
-
-class Image(BaseModel):
- url: HttpUrl
- name: str
-
-
-@app.post("/images/multiple/")
-async def create_multiple_images(images: List[Image]):
- return images
diff --git a/docs_src/body_nested_models/tutorial009.py b/docs_src/body_nested_models/tutorial009.py
deleted file mode 100644
index 41dce946ec..0000000000
--- a/docs_src/body_nested_models/tutorial009.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from typing import Dict
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.post("/index-weights/")
-async def create_index_weights(weights: Dict[int, float]):
- return weights
diff --git a/docs_src/body_updates/tutorial001.py b/docs_src/body_updates/tutorial001.py
deleted file mode 100644
index 4e65d77e26..0000000000
--- a/docs_src/body_updates/tutorial001.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: Union[str, None] = None
- description: Union[str, None] = None
- price: Union[float, None] = None
- tax: float = 10.5
- tags: List[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_item(item_id: str):
- return items[item_id]
-
-
-@app.put("/items/{item_id}", response_model=Item)
-async def update_item(item_id: str, item: Item):
- update_item_encoded = jsonable_encoder(item)
- items[item_id] = update_item_encoded
- return update_item_encoded
diff --git a/docs_src/body_updates/tutorial002.py b/docs_src/body_updates/tutorial002.py
deleted file mode 100644
index c3a0fe79ea..0000000000
--- a/docs_src/body_updates/tutorial002.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from fastapi.encoders import jsonable_encoder
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: Union[str, None] = None
- description: Union[str, None] = None
- price: Union[float, None] = None
- tax: float = 10.5
- tags: List[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item)
-async def read_item(item_id: str):
- return items[item_id]
-
-
-@app.patch("/items/{item_id}", response_model=Item)
-async def update_item(item_id: str, item: Item):
- stored_item_data = items[item_id]
- stored_item_model = Item(**stored_item_data)
- update_data = item.dict(exclude_unset=True)
- updated_item = stored_item_model.copy(update=update_data)
- items[item_id] = jsonable_encoder(updated_item)
- return updated_item
diff --git a/docs_src/conditional_openapi/tutorial001.py b/docs_src/conditional_openapi/tutorial001_py39.py
similarity index 100%
rename from docs_src/conditional_openapi/tutorial001.py
rename to docs_src/conditional_openapi/tutorial001_py39.py
diff --git a/docs_src/configure_swagger_ui/tutorial001.py b/docs_src/configure_swagger_ui/tutorial001_py39.py
similarity index 100%
rename from docs_src/configure_swagger_ui/tutorial001.py
rename to docs_src/configure_swagger_ui/tutorial001_py39.py
diff --git a/docs_src/configure_swagger_ui/tutorial002.py b/docs_src/configure_swagger_ui/tutorial002_py39.py
similarity index 100%
rename from docs_src/configure_swagger_ui/tutorial002.py
rename to docs_src/configure_swagger_ui/tutorial002_py39.py
diff --git a/docs_src/configure_swagger_ui/tutorial003.py b/docs_src/configure_swagger_ui/tutorial003_py39.py
similarity index 100%
rename from docs_src/configure_swagger_ui/tutorial003.py
rename to docs_src/configure_swagger_ui/tutorial003_py39.py
diff --git a/docs_src/cookie_param_models/tutorial001_an.py b/docs_src/cookie_param_models/tutorial001_an.py
deleted file mode 100644
index e5839ffd54..0000000000
--- a/docs_src/cookie_param_models/tutorial001_an.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial001.py b/docs_src/cookie_param_models/tutorial001_py39.py
similarity index 100%
rename from docs_src/cookie_param_models/tutorial001.py
rename to docs_src/cookie_param_models/tutorial001_py39.py
diff --git a/docs_src/cookie_param_models/tutorial002_an.py b/docs_src/cookie_param_models/tutorial002_an.py
deleted file mode 100644
index ce5644b7bd..0000000000
--- a/docs_src/cookie_param_models/tutorial002_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- model_config = {"extra": "forbid"}
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial002_pv1_an.py b/docs_src/cookie_param_models/tutorial002_pv1_an.py
deleted file mode 100644
index ddfda9b6f5..0000000000
--- a/docs_src/cookie_param_models/tutorial002_pv1_an.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- class Config:
- extra = "forbid"
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial002_pv1.py b/docs_src/cookie_param_models/tutorial002_pv1_py39.py
similarity index 100%
rename from docs_src/cookie_param_models/tutorial002_pv1.py
rename to docs_src/cookie_param_models/tutorial002_pv1_py39.py
diff --git a/docs_src/cookie_param_models/tutorial002.py b/docs_src/cookie_param_models/tutorial002_py39.py
similarity index 100%
rename from docs_src/cookie_param_models/tutorial002.py
rename to docs_src/cookie_param_models/tutorial002_py39.py
diff --git a/docs_src/cookie_params/tutorial001_an.py b/docs_src/cookie_params/tutorial001_an.py
deleted file mode 100644
index 6d5931229c..0000000000
--- a/docs_src/cookie_params/tutorial001_an.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
- return {"ads_id": ads_id}
diff --git a/docs_src/cookie_params/tutorial001.py b/docs_src/cookie_params/tutorial001_py39.py
similarity index 100%
rename from docs_src/cookie_params/tutorial001.py
rename to docs_src/cookie_params/tutorial001_py39.py
diff --git a/docs_src/cors/tutorial001.py b/docs_src/cors/tutorial001_py39.py
similarity index 100%
rename from docs_src/cors/tutorial001.py
rename to docs_src/cors/tutorial001_py39.py
diff --git a/docs_src/custom_docs_ui/tutorial001.py b/docs_src/custom_docs_ui/tutorial001_py39.py
similarity index 100%
rename from docs_src/custom_docs_ui/tutorial001.py
rename to docs_src/custom_docs_ui/tutorial001_py39.py
diff --git a/docs_src/custom_docs_ui/tutorial002.py b/docs_src/custom_docs_ui/tutorial002_py39.py
similarity index 100%
rename from docs_src/custom_docs_ui/tutorial002.py
rename to docs_src/custom_docs_ui/tutorial002_py39.py
diff --git a/docs_src/custom_request_and_route/tutorial001.py b/docs_src/custom_request_and_route/tutorial001.py
deleted file mode 100644
index 268ce9019e..0000000000
--- a/docs_src/custom_request_and_route/tutorial001.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import gzip
-from typing import Callable, List
-
-from fastapi import Body, FastAPI, Request, Response
-from fastapi.routing import APIRoute
-
-
-class GzipRequest(Request):
- async def body(self) -> bytes:
- if not hasattr(self, "_body"):
- body = await super().body()
- if "gzip" in self.headers.getlist("Content-Encoding"):
- body = gzip.decompress(body)
- self._body = body
- return self._body
-
-
-class GzipRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- request = GzipRequest(request.scope, request.receive)
- return await original_route_handler(request)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = GzipRoute
-
-
-@app.post("/sum")
-async def sum_numbers(numbers: List[int] = Body()):
- return {"sum": sum(numbers)}
diff --git a/docs_src/custom_request_and_route/tutorial001_an.py b/docs_src/custom_request_and_route/tutorial001_an.py
deleted file mode 100644
index 6224ba8254..0000000000
--- a/docs_src/custom_request_and_route/tutorial001_an.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import gzip
-from typing import Callable, List
-
-from fastapi import Body, FastAPI, Request, Response
-from fastapi.routing import APIRoute
-from typing_extensions import Annotated
-
-
-class GzipRequest(Request):
- async def body(self) -> bytes:
- if not hasattr(self, "_body"):
- body = await super().body()
- if "gzip" in self.headers.getlist("Content-Encoding"):
- body = gzip.decompress(body)
- self._body = body
- return self._body
-
-
-class GzipRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- request = GzipRequest(request.scope, request.receive)
- return await original_route_handler(request)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = GzipRoute
-
-
-@app.post("/sum")
-async def sum_numbers(numbers: Annotated[List[int], Body()]):
- return {"sum": sum(numbers)}
diff --git a/docs_src/custom_request_and_route/tutorial002.py b/docs_src/custom_request_and_route/tutorial002.py
deleted file mode 100644
index cee4a95f08..0000000000
--- a/docs_src/custom_request_and_route/tutorial002.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from typing import Callable, List
-
-from fastapi import Body, FastAPI, HTTPException, Request, Response
-from fastapi.exceptions import RequestValidationError
-from fastapi.routing import APIRoute
-
-
-class ValidationErrorLoggingRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- try:
- return await original_route_handler(request)
- except RequestValidationError as exc:
- body = await request.body()
- detail = {"errors": exc.errors(), "body": body.decode()}
- raise HTTPException(status_code=422, detail=detail)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = ValidationErrorLoggingRoute
-
-
-@app.post("/")
-async def sum_numbers(numbers: List[int] = Body()):
- return sum(numbers)
diff --git a/docs_src/custom_request_and_route/tutorial002_an.py b/docs_src/custom_request_and_route/tutorial002_an.py
deleted file mode 100644
index 127f7a9ce0..0000000000
--- a/docs_src/custom_request_and_route/tutorial002_an.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from typing import Callable, List
-
-from fastapi import Body, FastAPI, HTTPException, Request, Response
-from fastapi.exceptions import RequestValidationError
-from fastapi.routing import APIRoute
-from typing_extensions import Annotated
-
-
-class ValidationErrorLoggingRoute(APIRoute):
- def get_route_handler(self) -> Callable:
- original_route_handler = super().get_route_handler()
-
- async def custom_route_handler(request: Request) -> Response:
- try:
- return await original_route_handler(request)
- except RequestValidationError as exc:
- body = await request.body()
- detail = {"errors": exc.errors(), "body": body.decode()}
- raise HTTPException(status_code=422, detail=detail)
-
- return custom_route_handler
-
-
-app = FastAPI()
-app.router.route_class = ValidationErrorLoggingRoute
-
-
-@app.post("/")
-async def sum_numbers(numbers: Annotated[List[int], Body()]):
- return sum(numbers)
diff --git a/docs_src/custom_request_and_route/tutorial003.py b/docs_src/custom_request_and_route/tutorial003_py39.py
similarity index 100%
rename from docs_src/custom_request_and_route/tutorial003.py
rename to docs_src/custom_request_and_route/tutorial003_py39.py
diff --git a/docs_src/custom_response/tutorial001.py b/docs_src/custom_response/tutorial001_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial001.py
rename to docs_src/custom_response/tutorial001_py39.py
diff --git a/docs_src/custom_response/tutorial001b.py b/docs_src/custom_response/tutorial001b_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial001b.py
rename to docs_src/custom_response/tutorial001b_py39.py
diff --git a/docs_src/custom_response/tutorial002.py b/docs_src/custom_response/tutorial002_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial002.py
rename to docs_src/custom_response/tutorial002_py39.py
diff --git a/docs_src/custom_response/tutorial003.py b/docs_src/custom_response/tutorial003_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial003.py
rename to docs_src/custom_response/tutorial003_py39.py
diff --git a/docs_src/custom_response/tutorial004.py b/docs_src/custom_response/tutorial004_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial004.py
rename to docs_src/custom_response/tutorial004_py39.py
diff --git a/docs_src/custom_response/tutorial005.py b/docs_src/custom_response/tutorial005_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial005.py
rename to docs_src/custom_response/tutorial005_py39.py
diff --git a/docs_src/custom_response/tutorial006.py b/docs_src/custom_response/tutorial006_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial006.py
rename to docs_src/custom_response/tutorial006_py39.py
diff --git a/docs_src/custom_response/tutorial006b.py b/docs_src/custom_response/tutorial006b_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial006b.py
rename to docs_src/custom_response/tutorial006b_py39.py
diff --git a/docs_src/custom_response/tutorial006c.py b/docs_src/custom_response/tutorial006c_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial006c.py
rename to docs_src/custom_response/tutorial006c_py39.py
diff --git a/docs_src/custom_response/tutorial007.py b/docs_src/custom_response/tutorial007_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial007.py
rename to docs_src/custom_response/tutorial007_py39.py
diff --git a/docs_src/custom_response/tutorial008.py b/docs_src/custom_response/tutorial008_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial008.py
rename to docs_src/custom_response/tutorial008_py39.py
diff --git a/docs_src/custom_response/tutorial009.py b/docs_src/custom_response/tutorial009_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial009.py
rename to docs_src/custom_response/tutorial009_py39.py
diff --git a/docs_src/custom_response/tutorial009b.py b/docs_src/custom_response/tutorial009b_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial009b.py
rename to docs_src/custom_response/tutorial009b_py39.py
diff --git a/docs_src/custom_response/tutorial009c.py b/docs_src/custom_response/tutorial009c_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial009c.py
rename to docs_src/custom_response/tutorial009c_py39.py
diff --git a/docs_src/custom_response/tutorial010.py b/docs_src/custom_response/tutorial010_py39.py
similarity index 100%
rename from docs_src/custom_response/tutorial010.py
rename to docs_src/custom_response/tutorial010_py39.py
diff --git a/docs_src/dataclasses/tutorial001.py b/docs_src/dataclasses/tutorial001_py39.py
similarity index 100%
rename from docs_src/dataclasses/tutorial001.py
rename to docs_src/dataclasses/tutorial001_py39.py
diff --git a/docs_src/dataclasses/tutorial002.py b/docs_src/dataclasses/tutorial002.py
deleted file mode 100644
index ece2f150cc..0000000000
--- a/docs_src/dataclasses/tutorial002.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from dataclasses import dataclass, field
-from typing import List, Union
-
-from fastapi import FastAPI
-
-
-@dataclass
-class Item:
- name: str
- price: float
- tags: List[str] = field(default_factory=list)
- description: Union[str, None] = None
- tax: Union[float, None] = None
-
-
-app = FastAPI()
-
-
-@app.get("/items/next", response_model=Item)
-async def read_next_item():
- return {
- "name": "Island In The Moon",
- "price": 12.99,
- "description": "A place to be playin' and havin' fun",
- "tags": ["breater"],
- }
diff --git a/docs_src/dataclasses/tutorial003.py b/docs_src/dataclasses/tutorial003.py
deleted file mode 100644
index c613155133..0000000000
--- a/docs_src/dataclasses/tutorial003.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from dataclasses import field # (1)
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic.dataclasses import dataclass # (2)
-
-
-@dataclass
-class Item:
- name: str
- description: Union[str, None] = None
-
-
-@dataclass
-class Author:
- name: str
- items: List[Item] = field(default_factory=list) # (3)
-
-
-app = FastAPI()
-
-
-@app.post("/authors/{author_id}/items/", response_model=Author) # (4)
-async def create_author_items(author_id: str, items: List[Item]): # (5)
- return {"name": author_id, "items": items} # (6)
-
-
-@app.get("/authors/", response_model=List[Author]) # (7)
-def get_authors(): # (8)
- return [ # (9)
- {
- "name": "Breaters",
- "items": [
- {
- "name": "Island In The Moon",
- "description": "A place to be playin' and havin' fun",
- },
- {"name": "Holy Buddies"},
- ],
- },
- {
- "name": "System of an Up",
- "items": [
- {
- "name": "Salt",
- "description": "The kombucha mushroom people's favorite",
- },
- {"name": "Pad Thai"},
- {
- "name": "Lonely Night",
- "description": "The mostests lonliest nightiest of allest",
- },
- ],
- },
- ]
diff --git a/docs_src/debugging/tutorial001.py b/docs_src/debugging/tutorial001_py39.py
similarity index 100%
rename from docs_src/debugging/tutorial001.py
rename to docs_src/debugging/tutorial001_py39.py
diff --git a/docs_src/dependencies/tutorial001_02_an.py b/docs_src/dependencies/tutorial001_02_an.py
deleted file mode 100644
index 455d60c822..0000000000
--- a/docs_src/dependencies/tutorial001_02_an.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-CommonsDep = Annotated[dict, Depends(common_parameters)]
-
-
-@app.get("/items/")
-async def read_items(commons: CommonsDep):
- return commons
-
-
-@app.get("/users/")
-async def read_users(commons: CommonsDep):
- return commons
diff --git a/docs_src/dependencies/tutorial001_an.py b/docs_src/dependencies/tutorial001_an.py
deleted file mode 100644
index 81e24fe86c..0000000000
--- a/docs_src/dependencies/tutorial001_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
- return commons
-
-
-@app.get("/users/")
-async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
- return commons
diff --git a/docs_src/dependencies/tutorial001.py b/docs_src/dependencies/tutorial001_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial001.py
rename to docs_src/dependencies/tutorial001_py39.py
diff --git a/docs_src/dependencies/tutorial002_an.py b/docs_src/dependencies/tutorial002_an.py
deleted file mode 100644
index 964ccf66ca..0000000000
--- a/docs_src/dependencies/tutorial002_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
diff --git a/docs_src/dependencies/tutorial002.py b/docs_src/dependencies/tutorial002_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial002.py
rename to docs_src/dependencies/tutorial002_py39.py
diff --git a/docs_src/dependencies/tutorial003_an.py b/docs_src/dependencies/tutorial003_an.py
deleted file mode 100644
index ba8e9f7174..0000000000
--- a/docs_src/dependencies/tutorial003_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Any, Union
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
diff --git a/docs_src/dependencies/tutorial003.py b/docs_src/dependencies/tutorial003_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial003.py
rename to docs_src/dependencies/tutorial003_py39.py
diff --git a/docs_src/dependencies/tutorial004_an.py b/docs_src/dependencies/tutorial004_an.py
deleted file mode 100644
index 78881a354c..0000000000
--- a/docs_src/dependencies/tutorial004_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
-
-
-class CommonQueryParams:
- def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
- self.q = q
- self.skip = skip
- self.limit = limit
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
- response = {}
- if commons.q:
- response.update({"q": commons.q})
- items = fake_items_db[commons.skip : commons.skip + commons.limit]
- response.update({"items": items})
- return response
diff --git a/docs_src/dependencies/tutorial004.py b/docs_src/dependencies/tutorial004_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial004.py
rename to docs_src/dependencies/tutorial004_py39.py
diff --git a/docs_src/dependencies/tutorial005_an.py b/docs_src/dependencies/tutorial005_an.py
deleted file mode 100644
index 1d78c17a2a..0000000000
--- a/docs_src/dependencies/tutorial005_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-def query_extractor(q: Union[str, None] = None):
- return q
-
-
-def query_or_cookie_extractor(
- q: Annotated[str, Depends(query_extractor)],
- last_query: Annotated[Union[str, None], Cookie()] = None,
-):
- if not q:
- return last_query
- return q
-
-
-@app.get("/items/")
-async def read_query(
- query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
-):
- return {"q_or_cookie": query_or_default}
diff --git a/docs_src/dependencies/tutorial005.py b/docs_src/dependencies/tutorial005_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial005.py
rename to docs_src/dependencies/tutorial005_py39.py
diff --git a/docs_src/dependencies/tutorial006_an.py b/docs_src/dependencies/tutorial006_an.py
deleted file mode 100644
index 5aaea04d16..0000000000
--- a/docs_src/dependencies/tutorial006_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from fastapi import Depends, FastAPI, Header, HTTPException
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-async def verify_token(x_token: Annotated[str, Header()]):
- if x_token != "fake-super-secret-token":
- raise HTTPException(status_code=400, detail="X-Token header invalid")
-
-
-async def verify_key(x_key: Annotated[str, Header()]):
- if x_key != "fake-super-secret-key":
- raise HTTPException(status_code=400, detail="X-Key header invalid")
- return x_key
-
-
-@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
-async def read_items():
- return [{"item": "Foo"}, {"item": "Bar"}]
diff --git a/docs_src/dependencies/tutorial006.py b/docs_src/dependencies/tutorial006_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial006.py
rename to docs_src/dependencies/tutorial006_py39.py
diff --git a/docs_src/dependencies/tutorial007.py b/docs_src/dependencies/tutorial007_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial007.py
rename to docs_src/dependencies/tutorial007_py39.py
diff --git a/docs_src/dependencies/tutorial008_an.py b/docs_src/dependencies/tutorial008_an.py
deleted file mode 100644
index 2de86f042d..0000000000
--- a/docs_src/dependencies/tutorial008_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from fastapi import Depends
-from typing_extensions import Annotated
-
-
-async def dependency_a():
- dep_a = generate_dep_a()
- try:
- yield dep_a
- finally:
- dep_a.close()
-
-
-async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]):
- dep_b = generate_dep_b()
- try:
- yield dep_b
- finally:
- dep_b.close(dep_a)
-
-
-async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]):
- dep_c = generate_dep_c()
- try:
- yield dep_c
- finally:
- dep_c.close(dep_b)
diff --git a/docs_src/dependencies/tutorial008.py b/docs_src/dependencies/tutorial008_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial008.py
rename to docs_src/dependencies/tutorial008_py39.py
diff --git a/docs_src/dependencies/tutorial008b_an.py b/docs_src/dependencies/tutorial008b_an.py
deleted file mode 100644
index 84d8f12c14..0000000000
--- a/docs_src/dependencies/tutorial008b_an.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from fastapi import Depends, FastAPI, HTTPException
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-data = {
- "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
- "portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
-}
-
-
-class OwnerError(Exception):
- pass
-
-
-def get_username():
- try:
- yield "Rick"
- except OwnerError as e:
- raise HTTPException(status_code=400, detail=f"Owner error: {e}")
-
-
-@app.get("/items/{item_id}")
-def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
- if item_id not in data:
- raise HTTPException(status_code=404, detail="Item not found")
- item = data[item_id]
- if item["owner"] != username:
- raise OwnerError(username)
- return item
diff --git a/docs_src/dependencies/tutorial008b.py b/docs_src/dependencies/tutorial008b_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial008b.py
rename to docs_src/dependencies/tutorial008b_py39.py
diff --git a/docs_src/dependencies/tutorial008c_an.py b/docs_src/dependencies/tutorial008c_an.py
deleted file mode 100644
index 94f59f9aa6..0000000000
--- a/docs_src/dependencies/tutorial008c_an.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from fastapi import Depends, FastAPI, HTTPException
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class InternalError(Exception):
- pass
-
-
-def get_username():
- try:
- yield "Rick"
- except InternalError:
- print("Oops, we didn't raise again, Britney 😱")
-
-
-@app.get("/items/{item_id}")
-def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
- if item_id == "portal-gun":
- raise InternalError(
- f"The portal gun is too dangerous to be owned by {username}"
- )
- if item_id != "plumbus":
- raise HTTPException(
- status_code=404, detail="Item not found, there's only a plumbus here"
- )
- return item_id
diff --git a/docs_src/dependencies/tutorial008c.py b/docs_src/dependencies/tutorial008c_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial008c.py
rename to docs_src/dependencies/tutorial008c_py39.py
diff --git a/docs_src/dependencies/tutorial008d_an.py b/docs_src/dependencies/tutorial008d_an.py
deleted file mode 100644
index c354245744..0000000000
--- a/docs_src/dependencies/tutorial008d_an.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from fastapi import Depends, FastAPI, HTTPException
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class InternalError(Exception):
- pass
-
-
-def get_username():
- try:
- yield "Rick"
- except InternalError:
- print("We don't swallow the internal error here, we raise again 😎")
- raise
-
-
-@app.get("/items/{item_id}")
-def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
- if item_id == "portal-gun":
- raise InternalError(
- f"The portal gun is too dangerous to be owned by {username}"
- )
- if item_id != "plumbus":
- raise HTTPException(
- status_code=404, detail="Item not found, there's only a plumbus here"
- )
- return item_id
diff --git a/docs_src/dependencies/tutorial008d.py b/docs_src/dependencies/tutorial008d_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial008d.py
rename to docs_src/dependencies/tutorial008d_py39.py
diff --git a/docs_src/dependencies/tutorial008e_an.py b/docs_src/dependencies/tutorial008e_an.py
deleted file mode 100644
index c8a0af2b3b..0000000000
--- a/docs_src/dependencies/tutorial008e_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-def get_username():
- try:
- yield "Rick"
- finally:
- print("Cleanup up before response is sent")
-
-
-@app.get("/users/me")
-def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]):
- return username
diff --git a/docs_src/dependencies/tutorial008e.py b/docs_src/dependencies/tutorial008e_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial008e.py
rename to docs_src/dependencies/tutorial008e_py39.py
diff --git a/docs_src/dependencies/tutorial009.py b/docs_src/dependencies/tutorial009.py
deleted file mode 100644
index 8472f642de..0000000000
--- a/docs_src/dependencies/tutorial009.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from fastapi import Depends
-
-
-async def dependency_a():
- dep_a = generate_dep_a()
- try:
- yield dep_a
- finally:
- dep_a.close()
-
-
-async def dependency_b(dep_a=Depends(dependency_a)):
- dep_b = generate_dep_b()
- try:
- yield dep_b
- finally:
- dep_b.close(dep_a)
-
-
-async def dependency_c(dep_b=Depends(dependency_b)):
- dep_c = generate_dep_c()
- try:
- yield dep_c
- finally:
- dep_c.close(dep_b)
diff --git a/docs_src/dependencies/tutorial010.py b/docs_src/dependencies/tutorial010_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial010.py
rename to docs_src/dependencies/tutorial010_py39.py
diff --git a/docs_src/dependencies/tutorial011_an.py b/docs_src/dependencies/tutorial011_an.py
deleted file mode 100644
index 6c13d9033f..0000000000
--- a/docs_src/dependencies/tutorial011_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class FixedContentQueryChecker:
- def __init__(self, fixed_content: str):
- self.fixed_content = fixed_content
-
- def __call__(self, q: str = ""):
- if q:
- return self.fixed_content in q
- return False
-
-
-checker = FixedContentQueryChecker("bar")
-
-
-@app.get("/query-checker/")
-async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]):
- return {"fixed_content_in_query": fixed_content_included}
diff --git a/docs_src/dependencies/tutorial011.py b/docs_src/dependencies/tutorial011_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial011.py
rename to docs_src/dependencies/tutorial011_py39.py
diff --git a/docs_src/dependencies/tutorial012_an.py b/docs_src/dependencies/tutorial012_an.py
deleted file mode 100644
index 7541e6bf41..0000000000
--- a/docs_src/dependencies/tutorial012_an.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from fastapi import Depends, FastAPI, Header, HTTPException
-from typing_extensions import Annotated
-
-
-async def verify_token(x_token: Annotated[str, Header()]):
- if x_token != "fake-super-secret-token":
- raise HTTPException(status_code=400, detail="X-Token header invalid")
-
-
-async def verify_key(x_key: Annotated[str, Header()]):
- if x_key != "fake-super-secret-key":
- raise HTTPException(status_code=400, detail="X-Key header invalid")
- return x_key
-
-
-app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
-
-
-@app.get("/items/")
-async def read_items():
- return [{"item": "Portal Gun"}, {"item": "Plumbus"}]
-
-
-@app.get("/users/")
-async def read_users():
- return [{"username": "Rick"}, {"username": "Morty"}]
diff --git a/docs_src/dependencies/tutorial012_an_py39.py b/docs_src/dependencies/tutorial012_an_py39.py
index 7541e6bf41..6503591fc3 100644
--- a/docs_src/dependencies/tutorial012_an_py39.py
+++ b/docs_src/dependencies/tutorial012_an_py39.py
@@ -1,5 +1,6 @@
+from typing import Annotated
+
from fastapi import Depends, FastAPI, Header, HTTPException
-from typing_extensions import Annotated
async def verify_token(x_token: Annotated[str, Header()]):
diff --git a/docs_src/dependencies/tutorial012.py b/docs_src/dependencies/tutorial012_py39.py
similarity index 100%
rename from docs_src/dependencies/tutorial012.py
rename to docs_src/dependencies/tutorial012_py39.py
diff --git a/docs_src/dependency_testing/tutorial001_an.py b/docs_src/dependency_testing/tutorial001_an.py
deleted file mode 100644
index 4c76a87ff5..0000000000
--- a/docs_src/dependency_testing/tutorial001_an.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from fastapi.testclient import TestClient
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-async def common_parameters(
- q: Union[str, None] = None, skip: int = 0, limit: int = 100
-):
- return {"q": q, "skip": skip, "limit": limit}
-
-
-@app.get("/items/")
-async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
- return {"message": "Hello Items!", "params": commons}
-
-
-@app.get("/users/")
-async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
- return {"message": "Hello Users!", "params": commons}
-
-
-client = TestClient(app)
-
-
-async def override_dependency(q: Union[str, None] = None):
- return {"q": q, "skip": 5, "limit": 10}
-
-
-app.dependency_overrides[common_parameters] = override_dependency
-
-
-def test_override_in_items():
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_q():
- response = client.get("/items/?q=foo")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_items_with_params():
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
diff --git a/docs_src/dependency_testing/tutorial001.py b/docs_src/dependency_testing/tutorial001_py39.py
similarity index 100%
rename from docs_src/dependency_testing/tutorial001.py
rename to docs_src/dependency_testing/tutorial001_py39.py
diff --git a/docs_src/encoder/tutorial001.py b/docs_src/encoder/tutorial001_py39.py
similarity index 100%
rename from docs_src/encoder/tutorial001.py
rename to docs_src/encoder/tutorial001_py39.py
diff --git a/docs_src/events/tutorial001.py b/docs_src/events/tutorial001_py39.py
similarity index 100%
rename from docs_src/events/tutorial001.py
rename to docs_src/events/tutorial001_py39.py
diff --git a/docs_src/events/tutorial002.py b/docs_src/events/tutorial002_py39.py
similarity index 100%
rename from docs_src/events/tutorial002.py
rename to docs_src/events/tutorial002_py39.py
diff --git a/docs_src/events/tutorial003.py b/docs_src/events/tutorial003_py39.py
similarity index 100%
rename from docs_src/events/tutorial003.py
rename to docs_src/events/tutorial003_py39.py
diff --git a/docs_src/extending_openapi/tutorial001.py b/docs_src/extending_openapi/tutorial001_py39.py
similarity index 100%
rename from docs_src/extending_openapi/tutorial001.py
rename to docs_src/extending_openapi/tutorial001_py39.py
diff --git a/docs_src/extra_data_types/tutorial001_an.py b/docs_src/extra_data_types/tutorial001_an.py
deleted file mode 100644
index 257d0c7c86..0000000000
--- a/docs_src/extra_data_types/tutorial001_an.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from datetime import datetime, time, timedelta
-from typing import Union
-from uuid import UUID
-
-from fastapi import Body, FastAPI
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.put("/items/{item_id}")
-async def read_items(
- item_id: UUID,
- start_datetime: Annotated[datetime, Body()],
- end_datetime: Annotated[datetime, Body()],
- process_after: Annotated[timedelta, Body()],
- repeat_at: Annotated[Union[time, None], Body()] = None,
-):
- start_process = start_datetime + process_after
- duration = end_datetime - start_process
- return {
- "item_id": item_id,
- "start_datetime": start_datetime,
- "end_datetime": end_datetime,
- "process_after": process_after,
- "repeat_at": repeat_at,
- "start_process": start_process,
- "duration": duration,
- }
diff --git a/docs_src/extra_data_types/tutorial001.py b/docs_src/extra_data_types/tutorial001_py39.py
similarity index 100%
rename from docs_src/extra_data_types/tutorial001.py
rename to docs_src/extra_data_types/tutorial001_py39.py
diff --git a/docs_src/extra_models/tutorial001.py b/docs_src/extra_models/tutorial001_py39.py
similarity index 100%
rename from docs_src/extra_models/tutorial001.py
rename to docs_src/extra_models/tutorial001_py39.py
diff --git a/docs_src/extra_models/tutorial002.py b/docs_src/extra_models/tutorial002_py39.py
similarity index 100%
rename from docs_src/extra_models/tutorial002.py
rename to docs_src/extra_models/tutorial002_py39.py
diff --git a/docs_src/extra_models/tutorial003.py b/docs_src/extra_models/tutorial003_py39.py
similarity index 100%
rename from docs_src/extra_models/tutorial003.py
rename to docs_src/extra_models/tutorial003_py39.py
diff --git a/docs_src/extra_models/tutorial004.py b/docs_src/extra_models/tutorial004.py
deleted file mode 100644
index a8e0f7af5a..0000000000
--- a/docs_src/extra_models/tutorial004.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: str
-
-
-items = [
- {"name": "Foo", "description": "There comes my hero"},
- {"name": "Red", "description": "It's my aeroplane"},
-]
-
-
-@app.get("/items/", response_model=List[Item])
-async def read_items():
- return items
diff --git a/docs_src/extra_models/tutorial005.py b/docs_src/extra_models/tutorial005.py
deleted file mode 100644
index a81cbc2c58..0000000000
--- a/docs_src/extra_models/tutorial005.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from typing import Dict
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/keyword-weights/", response_model=Dict[str, float])
-async def read_keyword_weights():
- return {"foo": 2.3, "bar": 3.4}
diff --git a/docs_src/first_steps/tutorial001.py b/docs_src/first_steps/tutorial001_py39.py
similarity index 100%
rename from docs_src/first_steps/tutorial001.py
rename to docs_src/first_steps/tutorial001_py39.py
diff --git a/docs_src/first_steps/tutorial002.py b/docs_src/first_steps/tutorial002.py
deleted file mode 100644
index ca7d48cff9..0000000000
--- a/docs_src/first_steps/tutorial002.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from fastapi import FastAPI
-
-my_awesome_api = FastAPI()
-
-
-@my_awesome_api.get("/")
-async def root():
- return {"message": "Hello World"}
diff --git a/docs_src/first_steps/tutorial003.py b/docs_src/first_steps/tutorial003_py39.py
similarity index 100%
rename from docs_src/first_steps/tutorial003.py
rename to docs_src/first_steps/tutorial003_py39.py
diff --git a/docs_src/generate_clients/tutorial001.py b/docs_src/generate_clients/tutorial001.py
deleted file mode 100644
index 2d1f91bc6c..0000000000
--- a/docs_src/generate_clients/tutorial001.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- price: float
-
-
-class ResponseMessage(BaseModel):
- message: str
-
-
-@app.post("/items/", response_model=ResponseMessage)
-async def create_item(item: Item):
- return {"message": "item received"}
-
-
-@app.get("/items/", response_model=List[Item])
-async def get_items():
- return [
- {"name": "Plumbus", "price": 3},
- {"name": "Portal Gun", "price": 9001},
- ]
diff --git a/docs_src/generate_clients/tutorial002.py b/docs_src/generate_clients/tutorial002.py
deleted file mode 100644
index bd80449af9..0000000000
--- a/docs_src/generate_clients/tutorial002.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- price: float
-
-
-class ResponseMessage(BaseModel):
- message: str
-
-
-class User(BaseModel):
- username: str
- email: str
-
-
-@app.post("/items/", response_model=ResponseMessage, tags=["items"])
-async def create_item(item: Item):
- return {"message": "Item received"}
-
-
-@app.get("/items/", response_model=List[Item], tags=["items"])
-async def get_items():
- return [
- {"name": "Plumbus", "price": 3},
- {"name": "Portal Gun", "price": 9001},
- ]
-
-
-@app.post("/users/", response_model=ResponseMessage, tags=["users"])
-async def create_user(user: User):
- return {"message": "User received"}
diff --git a/docs_src/generate_clients/tutorial003.py b/docs_src/generate_clients/tutorial003.py
deleted file mode 100644
index 49eab73a1b..0000000000
--- a/docs_src/generate_clients/tutorial003.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from fastapi.routing import APIRoute
-from pydantic import BaseModel
-
-
-def custom_generate_unique_id(route: APIRoute):
- return f"{route.tags[0]}-{route.name}"
-
-
-app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
-
-
-class Item(BaseModel):
- name: str
- price: float
-
-
-class ResponseMessage(BaseModel):
- message: str
-
-
-class User(BaseModel):
- username: str
- email: str
-
-
-@app.post("/items/", response_model=ResponseMessage, tags=["items"])
-async def create_item(item: Item):
- return {"message": "Item received"}
-
-
-@app.get("/items/", response_model=List[Item], tags=["items"])
-async def get_items():
- return [
- {"name": "Plumbus", "price": 3},
- {"name": "Portal Gun", "price": 9001},
- ]
-
-
-@app.post("/users/", response_model=ResponseMessage, tags=["users"])
-async def create_user(user: User):
- return {"message": "User received"}
diff --git a/docs_src/generate_clients/tutorial004.py b/docs_src/generate_clients/tutorial004_py39.py
similarity index 100%
rename from docs_src/generate_clients/tutorial004.py
rename to docs_src/generate_clients/tutorial004_py39.py
diff --git a/docs_src/graphql/tutorial001.py b/docs_src/graphql/tutorial001_py39.py
similarity index 100%
rename from docs_src/graphql/tutorial001.py
rename to docs_src/graphql/tutorial001_py39.py
diff --git a/docs_src/handling_errors/tutorial001.py b/docs_src/handling_errors/tutorial001_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial001.py
rename to docs_src/handling_errors/tutorial001_py39.py
diff --git a/docs_src/handling_errors/tutorial002.py b/docs_src/handling_errors/tutorial002_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial002.py
rename to docs_src/handling_errors/tutorial002_py39.py
diff --git a/docs_src/handling_errors/tutorial003.py b/docs_src/handling_errors/tutorial003_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial003.py
rename to docs_src/handling_errors/tutorial003_py39.py
diff --git a/docs_src/handling_errors/tutorial004.py b/docs_src/handling_errors/tutorial004_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial004.py
rename to docs_src/handling_errors/tutorial004_py39.py
diff --git a/docs_src/handling_errors/tutorial005.py b/docs_src/handling_errors/tutorial005_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial005.py
rename to docs_src/handling_errors/tutorial005_py39.py
diff --git a/docs_src/handling_errors/tutorial006.py b/docs_src/handling_errors/tutorial006_py39.py
similarity index 100%
rename from docs_src/handling_errors/tutorial006.py
rename to docs_src/handling_errors/tutorial006_py39.py
diff --git a/docs_src/header_param_models/tutorial001.py b/docs_src/header_param_models/tutorial001.py
deleted file mode 100644
index 4caaba87b9..0000000000
--- a/docs_src/header_param_models/tutorial001.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
diff --git a/docs_src/header_param_models/tutorial001_an.py b/docs_src/header_param_models/tutorial001_an.py
deleted file mode 100644
index b55c6b56b1..0000000000
--- a/docs_src/header_param_models/tutorial001_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
diff --git a/docs_src/header_param_models/tutorial002.py b/docs_src/header_param_models/tutorial002.py
deleted file mode 100644
index 3f9aac58d2..0000000000
--- a/docs_src/header_param_models/tutorial002.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- model_config = {"extra": "forbid"}
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_an.py b/docs_src/header_param_models/tutorial002_an.py
deleted file mode 100644
index 771135d770..0000000000
--- a/docs_src/header_param_models/tutorial002_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- model_config = {"extra": "forbid"}
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_pv1.py b/docs_src/header_param_models/tutorial002_pv1.py
deleted file mode 100644
index 7e56cd993b..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_pv1_an.py b/docs_src/header_param_models/tutorial002_pv1_an.py
deleted file mode 100644
index 236778231a..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1_an.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
diff --git a/docs_src/header_param_models/tutorial003.py b/docs_src/header_param_models/tutorial003.py
deleted file mode 100644
index dc2eb74bd1..0000000000
--- a/docs_src/header_param_models/tutorial003.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header(convert_underscores=False)):
- return headers
diff --git a/docs_src/header_param_models/tutorial003_an.py b/docs_src/header_param_models/tutorial003_an.py
deleted file mode 100644
index e3edb11891..0000000000
--- a/docs_src/header_param_models/tutorial003_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(
- headers: Annotated[CommonHeaders, Header(convert_underscores=False)],
-):
- return headers
diff --git a/docs_src/header_params/tutorial001_an.py b/docs_src/header_params/tutorial001_an.py
deleted file mode 100644
index 816c000862..0000000000
--- a/docs_src/header_params/tutorial001_an.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Header
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
- return {"User-Agent": user_agent}
diff --git a/docs_src/header_params/tutorial001.py b/docs_src/header_params/tutorial001_py39.py
similarity index 100%
rename from docs_src/header_params/tutorial001.py
rename to docs_src/header_params/tutorial001_py39.py
diff --git a/docs_src/header_params/tutorial002_an.py b/docs_src/header_params/tutorial002_an.py
deleted file mode 100644
index 82fe49ba2b..0000000000
--- a/docs_src/header_params/tutorial002_an.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Header
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- strange_header: Annotated[
- Union[str, None], Header(convert_underscores=False)
- ] = None,
-):
- return {"strange_header": strange_header}
diff --git a/docs_src/header_params/tutorial002.py b/docs_src/header_params/tutorial002_py39.py
similarity index 100%
rename from docs_src/header_params/tutorial002.py
rename to docs_src/header_params/tutorial002_py39.py
diff --git a/docs_src/header_params/tutorial003.py b/docs_src/header_params/tutorial003.py
deleted file mode 100644
index a61314aedb..0000000000
--- a/docs_src/header_params/tutorial003.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(x_token: Union[List[str], None] = Header(default=None)):
- return {"X-Token values": x_token}
diff --git a/docs_src/header_params/tutorial003_an.py b/docs_src/header_params/tutorial003_an.py
deleted file mode 100644
index 5406fd1f88..0000000000
--- a/docs_src/header_params/tutorial003_an.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Header
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(x_token: Annotated[Union[List[str], None], Header()] = None):
- return {"X-Token values": x_token}
diff --git a/docs_src/header_params/tutorial003_an_py39.py b/docs_src/header_params/tutorial003_an_py39.py
index c1dd499611..5aad89407e 100644
--- a/docs_src/header_params/tutorial003_an_py39.py
+++ b/docs_src/header_params/tutorial003_an_py39.py
@@ -1,4 +1,4 @@
-from typing import Annotated, List, Union
+from typing import Annotated, Union
from fastapi import FastAPI, Header
@@ -6,5 +6,5 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(x_token: Annotated[Union[List[str], None], Header()] = None):
+async def read_items(x_token: Annotated[Union[list[str], None], Header()] = None):
return {"X-Token values": x_token}
diff --git a/docs_src/metadata/tutorial001_1.py b/docs_src/metadata/tutorial001_1_py39.py
similarity index 100%
rename from docs_src/metadata/tutorial001_1.py
rename to docs_src/metadata/tutorial001_1_py39.py
diff --git a/docs_src/metadata/tutorial001.py b/docs_src/metadata/tutorial001_py39.py
similarity index 100%
rename from docs_src/metadata/tutorial001.py
rename to docs_src/metadata/tutorial001_py39.py
diff --git a/docs_src/metadata/tutorial002.py b/docs_src/metadata/tutorial002_py39.py
similarity index 100%
rename from docs_src/metadata/tutorial002.py
rename to docs_src/metadata/tutorial002_py39.py
diff --git a/docs_src/metadata/tutorial003.py b/docs_src/metadata/tutorial003_py39.py
similarity index 100%
rename from docs_src/metadata/tutorial003.py
rename to docs_src/metadata/tutorial003_py39.py
diff --git a/docs_src/metadata/tutorial004.py b/docs_src/metadata/tutorial004_py39.py
similarity index 100%
rename from docs_src/metadata/tutorial004.py
rename to docs_src/metadata/tutorial004_py39.py
diff --git a/docs_src/middleware/tutorial001.py b/docs_src/middleware/tutorial001_py39.py
similarity index 100%
rename from docs_src/middleware/tutorial001.py
rename to docs_src/middleware/tutorial001_py39.py
diff --git a/docs_src/openapi_callbacks/tutorial001.py b/docs_src/openapi_callbacks/tutorial001_py39.py
similarity index 100%
rename from docs_src/openapi_callbacks/tutorial001.py
rename to docs_src/openapi_callbacks/tutorial001_py39.py
diff --git a/docs_src/openapi_webhooks/tutorial001.py b/docs_src/openapi_webhooks/tutorial001_py39.py
similarity index 100%
rename from docs_src/openapi_webhooks/tutorial001.py
rename to docs_src/openapi_webhooks/tutorial001_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial001.py b/docs_src/path_operation_advanced_configuration/tutorial001_py39.py
similarity index 100%
rename from docs_src/path_operation_advanced_configuration/tutorial001.py
rename to docs_src/path_operation_advanced_configuration/tutorial001_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial002.py b/docs_src/path_operation_advanced_configuration/tutorial002_py39.py
similarity index 100%
rename from docs_src/path_operation_advanced_configuration/tutorial002.py
rename to docs_src/path_operation_advanced_configuration/tutorial002_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial003.py b/docs_src/path_operation_advanced_configuration/tutorial003_py39.py
similarity index 100%
rename from docs_src/path_operation_advanced_configuration/tutorial003.py
rename to docs_src/path_operation_advanced_configuration/tutorial003_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial004.py b/docs_src/path_operation_advanced_configuration/tutorial004.py
deleted file mode 100644
index a3aad4ac40..0000000000
--- a/docs_src/path_operation_advanced_configuration/tutorial004.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post("/items/", response_model=Item, summary="Create an item")
-async def create_item(item: Item):
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- \f
- :param item: User input.
- """
- return item
diff --git a/docs_src/path_operation_advanced_configuration/tutorial005.py b/docs_src/path_operation_advanced_configuration/tutorial005_py39.py
similarity index 100%
rename from docs_src/path_operation_advanced_configuration/tutorial005.py
rename to docs_src/path_operation_advanced_configuration/tutorial005_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial006.py b/docs_src/path_operation_advanced_configuration/tutorial006_py39.py
similarity index 100%
rename from docs_src/path_operation_advanced_configuration/tutorial006.py
rename to docs_src/path_operation_advanced_configuration/tutorial006_py39.py
diff --git a/docs_src/path_operation_advanced_configuration/tutorial007.py b/docs_src/path_operation_advanced_configuration/tutorial007.py
deleted file mode 100644
index 54e2e9399e..0000000000
--- a/docs_src/path_operation_advanced_configuration/tutorial007.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import List
-
-import yaml
-from fastapi import FastAPI, HTTPException, Request
-from pydantic import BaseModel, ValidationError
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- tags: List[str]
-
-
-@app.post(
- "/items/",
- openapi_extra={
- "requestBody": {
- "content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
- "required": True,
- },
- },
-)
-async def create_item(request: Request):
- raw_body = await request.body()
- try:
- data = yaml.safe_load(raw_body)
- except yaml.YAMLError:
- raise HTTPException(status_code=422, detail="Invalid YAML")
- try:
- item = Item.model_validate(data)
- except ValidationError as e:
- raise HTTPException(status_code=422, detail=e.errors(include_url=False))
- return item
diff --git a/docs_src/path_operation_advanced_configuration/tutorial007_pv1.py b/docs_src/path_operation_advanced_configuration/tutorial007_pv1.py
deleted file mode 100644
index d51752bb87..0000000000
--- a/docs_src/path_operation_advanced_configuration/tutorial007_pv1.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import List
-
-import yaml
-from fastapi import FastAPI, HTTPException, Request
-from pydantic import BaseModel, ValidationError
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- tags: List[str]
-
-
-@app.post(
- "/items/",
- openapi_extra={
- "requestBody": {
- "content": {"application/x-yaml": {"schema": Item.schema()}},
- "required": True,
- },
- },
-)
-async def create_item(request: Request):
- raw_body = await request.body()
- try:
- data = yaml.safe_load(raw_body)
- except yaml.YAMLError:
- raise HTTPException(status_code=422, detail="Invalid YAML")
- try:
- item = Item.parse_obj(data)
- except ValidationError as e:
- raise HTTPException(status_code=422, detail=e.errors())
- return item
diff --git a/docs_src/path_operation_configuration/tutorial001.py b/docs_src/path_operation_configuration/tutorial001.py
deleted file mode 100644
index 83fd8377ab..0000000000
--- a/docs_src/path_operation_configuration/tutorial001.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI, status
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
-async def create_item(item: Item):
- return item
diff --git a/docs_src/path_operation_configuration/tutorial002.py b/docs_src/path_operation_configuration/tutorial002.py
deleted file mode 100644
index 798b0c2311..0000000000
--- a/docs_src/path_operation_configuration/tutorial002.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post("/items/", response_model=Item, tags=["items"])
-async def create_item(item: Item):
- return item
-
-
-@app.get("/items/", tags=["items"])
-async def read_items():
- return [{"name": "Foo", "price": 42}]
-
-
-@app.get("/users/", tags=["users"])
-async def read_users():
- return [{"username": "johndoe"}]
diff --git a/docs_src/path_operation_configuration/tutorial002b.py b/docs_src/path_operation_configuration/tutorial002b_py39.py
similarity index 100%
rename from docs_src/path_operation_configuration/tutorial002b.py
rename to docs_src/path_operation_configuration/tutorial002b_py39.py
diff --git a/docs_src/path_operation_configuration/tutorial003.py b/docs_src/path_operation_configuration/tutorial003.py
deleted file mode 100644
index 26bf7dabae..0000000000
--- a/docs_src/path_operation_configuration/tutorial003.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post(
- "/items/",
- response_model=Item,
- summary="Create an item",
- description="Create an item with all the information, name, description, price, tax and a set of unique tags",
-)
-async def create_item(item: Item):
- return item
diff --git a/docs_src/path_operation_configuration/tutorial004.py b/docs_src/path_operation_configuration/tutorial004.py
deleted file mode 100644
index 8f865c58a6..0000000000
--- a/docs_src/path_operation_configuration/tutorial004.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post("/items/", response_model=Item, summary="Create an item")
-async def create_item(item: Item):
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- """
- return item
diff --git a/docs_src/path_operation_configuration/tutorial005.py b/docs_src/path_operation_configuration/tutorial005.py
deleted file mode 100644
index 2c1be4a34b..0000000000
--- a/docs_src/path_operation_configuration/tutorial005.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from typing import Set, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: Set[str] = set()
-
-
-@app.post(
- "/items/",
- response_model=Item,
- summary="Create an item",
- response_description="The created item",
-)
-async def create_item(item: Item):
- """
- Create an item with all the information:
-
- - **name**: each item must have a name
- - **description**: a long description
- - **price**: required
- - **tax**: if the item doesn't have tax, you can omit this
- - **tags**: a set of unique tag strings for this item
- """
- return item
diff --git a/docs_src/path_operation_configuration/tutorial006.py b/docs_src/path_operation_configuration/tutorial006_py39.py
similarity index 100%
rename from docs_src/path_operation_configuration/tutorial006.py
rename to docs_src/path_operation_configuration/tutorial006_py39.py
diff --git a/docs_src/path_params/tutorial001.py b/docs_src/path_params/tutorial001_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial001.py
rename to docs_src/path_params/tutorial001_py39.py
diff --git a/docs_src/path_params/tutorial002.py b/docs_src/path_params/tutorial002_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial002.py
rename to docs_src/path_params/tutorial002_py39.py
diff --git a/docs_src/path_params/tutorial003.py b/docs_src/path_params/tutorial003_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial003.py
rename to docs_src/path_params/tutorial003_py39.py
diff --git a/docs_src/path_params/tutorial003b.py b/docs_src/path_params/tutorial003b_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial003b.py
rename to docs_src/path_params/tutorial003b_py39.py
diff --git a/docs_src/path_params/tutorial004.py b/docs_src/path_params/tutorial004_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial004.py
rename to docs_src/path_params/tutorial004_py39.py
diff --git a/docs_src/path_params/tutorial005.py b/docs_src/path_params/tutorial005_py39.py
similarity index 100%
rename from docs_src/path_params/tutorial005.py
rename to docs_src/path_params/tutorial005_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial001_an.py b/docs_src/path_params_numeric_validations/tutorial001_an.py
deleted file mode 100644
index 621be7b045..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial001_an.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Path, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- item_id: Annotated[int, Path(title="The ID of the item to get")],
- q: Annotated[Union[str, None], Query(alias="item-query")] = None,
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial001.py b/docs_src/path_params_numeric_validations/tutorial001_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial001.py
rename to docs_src/path_params_numeric_validations/tutorial001_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial002_an.py b/docs_src/path_params_numeric_validations/tutorial002_an.py
deleted file mode 100644
index 322f8cf0bb..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial002_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from fastapi import FastAPI, Path
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial002.py b/docs_src/path_params_numeric_validations/tutorial002_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial002.py
rename to docs_src/path_params_numeric_validations/tutorial002_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial003_an.py b/docs_src/path_params_numeric_validations/tutorial003_an.py
deleted file mode 100644
index d0fa8b3db9..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial003_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from fastapi import FastAPI, Path
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial003.py b/docs_src/path_params_numeric_validations/tutorial003_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial003.py
rename to docs_src/path_params_numeric_validations/tutorial003_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial004_an.py b/docs_src/path_params_numeric_validations/tutorial004_an.py
deleted file mode 100644
index ffc50f6c5b..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial004_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from fastapi import FastAPI, Path
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial004.py b/docs_src/path_params_numeric_validations/tutorial004_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial004.py
rename to docs_src/path_params_numeric_validations/tutorial004_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial005_an.py b/docs_src/path_params_numeric_validations/tutorial005_an.py
deleted file mode 100644
index 433c69129f..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial005_an.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from fastapi import FastAPI, Path
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
- q: str,
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial005.py b/docs_src/path_params_numeric_validations/tutorial005_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial005.py
rename to docs_src/path_params_numeric_validations/tutorial005_py39.py
diff --git a/docs_src/path_params_numeric_validations/tutorial006_an.py b/docs_src/path_params_numeric_validations/tutorial006_an.py
deleted file mode 100644
index ac47325732..0000000000
--- a/docs_src/path_params_numeric_validations/tutorial006_an.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from fastapi import FastAPI, Path, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_items(
- *,
- item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
- q: str,
- size: Annotated[float, Query(gt=0, lt=10.5)],
-):
- results = {"item_id": item_id}
- if q:
- results.update({"q": q})
- if size:
- results.update({"size": size})
- return results
diff --git a/docs_src/path_params_numeric_validations/tutorial006.py b/docs_src/path_params_numeric_validations/tutorial006_py39.py
similarity index 100%
rename from docs_src/path_params_numeric_validations/tutorial006.py
rename to docs_src/path_params_numeric_validations/tutorial006_py39.py
diff --git a/docs_src/pydantic_v1_in_v2/tutorial001_an.py b/docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py
similarity index 100%
rename from docs_src/pydantic_v1_in_v2/tutorial001_an.py
rename to docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py
diff --git a/docs_src/pydantic_v1_in_v2/tutorial002_an.py b/docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py
similarity index 100%
rename from docs_src/pydantic_v1_in_v2/tutorial002_an.py
rename to docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py
diff --git a/docs_src/pydantic_v1_in_v2/tutorial003_an.py b/docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py
similarity index 100%
rename from docs_src/pydantic_v1_in_v2/tutorial003_an.py
rename to docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py
diff --git a/docs_src/pydantic_v1_in_v2/tutorial004_an.py b/docs_src/pydantic_v1_in_v2/tutorial004_an.py
deleted file mode 100644
index cca8a9ea80..0000000000
--- a/docs_src/pydantic_v1_in_v2/tutorial004_an.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI
-from fastapi.temp_pydantic_v1_params import Body
-from pydantic.v1 import BaseModel
-from typing_extensions import Annotated
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- size: float
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-async def create_item(item: Annotated[Item, Body(embed=True)]) -> Item:
- return item
diff --git a/docs_src/python_types/tutorial001.py b/docs_src/python_types/tutorial001_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial001.py
rename to docs_src/python_types/tutorial001_py39.py
diff --git a/docs_src/python_types/tutorial002.py b/docs_src/python_types/tutorial002_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial002.py
rename to docs_src/python_types/tutorial002_py39.py
diff --git a/docs_src/python_types/tutorial003.py b/docs_src/python_types/tutorial003_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial003.py
rename to docs_src/python_types/tutorial003_py39.py
diff --git a/docs_src/python_types/tutorial004.py b/docs_src/python_types/tutorial004_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial004.py
rename to docs_src/python_types/tutorial004_py39.py
diff --git a/docs_src/python_types/tutorial005.py b/docs_src/python_types/tutorial005_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial005.py
rename to docs_src/python_types/tutorial005_py39.py
diff --git a/docs_src/python_types/tutorial006.py b/docs_src/python_types/tutorial006.py
deleted file mode 100644
index 87394ecb0c..0000000000
--- a/docs_src/python_types/tutorial006.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from typing import List
-
-
-def process_items(items: List[str]):
- for item in items:
- print(item)
diff --git a/docs_src/python_types/tutorial007.py b/docs_src/python_types/tutorial007.py
deleted file mode 100644
index 5b13f15494..0000000000
--- a/docs_src/python_types/tutorial007.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from typing import Set, Tuple
-
-
-def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
- return items_t, items_s
diff --git a/docs_src/python_types/tutorial008.py b/docs_src/python_types/tutorial008.py
deleted file mode 100644
index 9fb1043bb8..0000000000
--- a/docs_src/python_types/tutorial008.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from typing import Dict
-
-
-def process_items(prices: Dict[str, float]):
- for item_name, item_price in prices.items():
- print(item_name)
- print(item_price)
diff --git a/docs_src/python_types/tutorial008b.py b/docs_src/python_types/tutorial008b_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial008b.py
rename to docs_src/python_types/tutorial008b_py39.py
diff --git a/docs_src/python_types/tutorial009.py b/docs_src/python_types/tutorial009_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial009.py
rename to docs_src/python_types/tutorial009_py39.py
diff --git a/docs_src/python_types/tutorial009b.py b/docs_src/python_types/tutorial009b_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial009b.py
rename to docs_src/python_types/tutorial009b_py39.py
diff --git a/docs_src/python_types/tutorial009c.py b/docs_src/python_types/tutorial009c_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial009c.py
rename to docs_src/python_types/tutorial009c_py39.py
diff --git a/docs_src/python_types/tutorial010.py b/docs_src/python_types/tutorial010_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial010.py
rename to docs_src/python_types/tutorial010_py39.py
diff --git a/docs_src/python_types/tutorial011.py b/docs_src/python_types/tutorial011.py
deleted file mode 100644
index 297a84db68..0000000000
--- a/docs_src/python_types/tutorial011.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from datetime import datetime
-from typing import List, Union
-
-from pydantic import BaseModel
-
-
-class User(BaseModel):
- id: int
- name: str = "John Doe"
- signup_ts: Union[datetime, None] = None
- friends: List[int] = []
-
-
-external_data = {
- "id": "123",
- "signup_ts": "2017-06-01 12:22",
- "friends": [1, "2", b"3"],
-}
-user = User(**external_data)
-print(user)
-# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
-print(user.id)
-# > 123
diff --git a/docs_src/python_types/tutorial012.py b/docs_src/python_types/tutorial012_py39.py
similarity index 100%
rename from docs_src/python_types/tutorial012.py
rename to docs_src/python_types/tutorial012_py39.py
diff --git a/docs_src/python_types/tutorial013.py b/docs_src/python_types/tutorial013.py
deleted file mode 100644
index 0ec7735199..0000000000
--- a/docs_src/python_types/tutorial013.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from typing_extensions import Annotated
-
-
-def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
- return f"Hello {name}"
diff --git a/docs_src/query_param_models/tutorial001.py b/docs_src/query_param_models/tutorial001.py
deleted file mode 100644
index 0c0ab315e8..0000000000
--- a/docs_src/query_param_models/tutorial001.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial001_an.py b/docs_src/query_param_models/tutorial001_an.py
deleted file mode 100644
index 28375057c1..0000000000
--- a/docs_src/query_param_models/tutorial001_an.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial001_an_py39.py b/docs_src/query_param_models/tutorial001_an_py39.py
index ba690d3e3f..71427acae1 100644
--- a/docs_src/query_param_models/tutorial001_an_py39.py
+++ b/docs_src/query_param_models/tutorial001_an_py39.py
@@ -1,6 +1,7 @@
+from typing import Annotated, Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial001_py39.py b/docs_src/query_param_models/tutorial001_py39.py
index 54b52a054c..3ebf9f4d70 100644
--- a/docs_src/query_param_models/tutorial001_py39.py
+++ b/docs_src/query_param_models/tutorial001_py39.py
@@ -1,6 +1,7 @@
+from typing import Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Literal
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial002.py b/docs_src/query_param_models/tutorial002.py
deleted file mode 100644
index 1633bc4644..0000000000
--- a/docs_src/query_param_models/tutorial002.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- model_config = {"extra": "forbid"}
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_an.py b/docs_src/query_param_models/tutorial002_an.py
deleted file mode 100644
index 69705d4b4b..0000000000
--- a/docs_src/query_param_models/tutorial002_an.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- model_config = {"extra": "forbid"}
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_an_py39.py b/docs_src/query_param_models/tutorial002_an_py39.py
index 2d4c1a62b5..9759565023 100644
--- a/docs_src/query_param_models/tutorial002_an_py39.py
+++ b/docs_src/query_param_models/tutorial002_an_py39.py
@@ -1,6 +1,7 @@
+from typing import Annotated, Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial002_pv1.py b/docs_src/query_param_models/tutorial002_pv1.py
deleted file mode 100644
index 71ccd961d3..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_pv1_an.py b/docs_src/query_param_models/tutorial002_pv1_an.py
deleted file mode 100644
index 1dd29157a4..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: List[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_pv1_an_py39.py b/docs_src/query_param_models/tutorial002_pv1_an_py39.py
index 494fef11fc..d635aae88f 100644
--- a/docs_src/query_param_models/tutorial002_pv1_an_py39.py
+++ b/docs_src/query_param_models/tutorial002_pv1_an_py39.py
@@ -1,6 +1,7 @@
+from typing import Annotated, Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial002_pv1_py39.py b/docs_src/query_param_models/tutorial002_pv1_py39.py
index 7fa456a791..9ffdeefc06 100644
--- a/docs_src/query_param_models/tutorial002_pv1_py39.py
+++ b/docs_src/query_param_models/tutorial002_pv1_py39.py
@@ -1,6 +1,7 @@
+from typing import Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Literal
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial002_py39.py b/docs_src/query_param_models/tutorial002_py39.py
index f9bba028c2..6ec4184991 100644
--- a/docs_src/query_param_models/tutorial002_py39.py
+++ b/docs_src/query_param_models/tutorial002_py39.py
@@ -1,6 +1,7 @@
+from typing import Literal
+
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
-from typing_extensions import Literal
app = FastAPI()
diff --git a/docs_src/query_params/tutorial001.py b/docs_src/query_params/tutorial001_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial001.py
rename to docs_src/query_params/tutorial001_py39.py
diff --git a/docs_src/query_params/tutorial002.py b/docs_src/query_params/tutorial002_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial002.py
rename to docs_src/query_params/tutorial002_py39.py
diff --git a/docs_src/query_params/tutorial003.py b/docs_src/query_params/tutorial003_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial003.py
rename to docs_src/query_params/tutorial003_py39.py
diff --git a/docs_src/query_params/tutorial004.py b/docs_src/query_params/tutorial004_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial004.py
rename to docs_src/query_params/tutorial004_py39.py
diff --git a/docs_src/query_params/tutorial005.py b/docs_src/query_params/tutorial005_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial005.py
rename to docs_src/query_params/tutorial005_py39.py
diff --git a/docs_src/query_params/tutorial006.py b/docs_src/query_params/tutorial006_py39.py
similarity index 100%
rename from docs_src/query_params/tutorial006.py
rename to docs_src/query_params/tutorial006_py39.py
diff --git a/docs_src/query_params/tutorial006b.py b/docs_src/query_params/tutorial006b.py
deleted file mode 100644
index f0dbfe08fe..0000000000
--- a/docs_src/query_params/tutorial006b.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_user_item(
- item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
-):
- item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
- return item
diff --git a/docs_src/query_params_str_validations/tutorial001.py b/docs_src/query_params_str_validations/tutorial001_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial001.py
rename to docs_src/query_params_str_validations/tutorial001_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial002_an.py b/docs_src/query_params_str_validations/tutorial002_an_py39.py
similarity index 81%
rename from docs_src/query_params_str_validations/tutorial002_an.py
rename to docs_src/query_params_str_validations/tutorial002_an_py39.py
index cb1b38940c..2d8fc97985 100644
--- a/docs_src/query_params_str_validations/tutorial002_an.py
+++ b/docs_src/query_params_str_validations/tutorial002_an_py39.py
@@ -1,7 +1,6 @@
-from typing import Union
+from typing import Annotated, Union
from fastapi import FastAPI, Query
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/docs_src/query_params_str_validations/tutorial002.py b/docs_src/query_params_str_validations/tutorial002_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial002.py
rename to docs_src/query_params_str_validations/tutorial002_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial003_an.py b/docs_src/query_params_str_validations/tutorial003_an.py
deleted file mode 100644
index 0dd14086cf..0000000000
--- a/docs_src/query_params_str_validations/tutorial003_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial003.py b/docs_src/query_params_str_validations/tutorial003_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial003.py
rename to docs_src/query_params_str_validations/tutorial003_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial004_an.py b/docs_src/query_params_str_validations/tutorial004_an.py
deleted file mode 100644
index c75d45d63e..0000000000
--- a/docs_src/query_params_str_validations/tutorial004_an.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial004.py b/docs_src/query_params_str_validations/tutorial004_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial004.py
rename to docs_src/query_params_str_validations/tutorial004_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial005_an.py b/docs_src/query_params_str_validations/tutorial005_an.py
deleted file mode 100644
index 452d4d38d7..0000000000
--- a/docs_src/query_params_str_validations/tutorial005_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial005.py b/docs_src/query_params_str_validations/tutorial005_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial005.py
rename to docs_src/query_params_str_validations/tutorial005_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial006_an.py b/docs_src/query_params_str_validations/tutorial006_an.py
deleted file mode 100644
index 559480d2bf..0000000000
--- a/docs_src/query_params_str_validations/tutorial006_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)]):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006.py b/docs_src/query_params_str_validations/tutorial006_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial006.py
rename to docs_src/query_params_str_validations/tutorial006_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial006c_an.py b/docs_src/query_params_str_validations/tutorial006c_an.py
deleted file mode 100644
index 55c4f4adca..0000000000
--- a/docs_src/query_params_str_validations/tutorial006c_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006c.py b/docs_src/query_params_str_validations/tutorial006c_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial006c.py
rename to docs_src/query_params_str_validations/tutorial006c_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial007_an.py b/docs_src/query_params_str_validations/tutorial007_an.py
deleted file mode 100644
index 4b3c8de4b9..0000000000
--- a/docs_src/query_params_str_validations/tutorial007_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial007.py b/docs_src/query_params_str_validations/tutorial007_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial007.py
rename to docs_src/query_params_str_validations/tutorial007_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial008_an.py b/docs_src/query_params_str_validations/tutorial008_an.py
deleted file mode 100644
index 01606a9203..0000000000
--- a/docs_src/query_params_str_validations/tutorial008_an.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None],
- Query(
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- ),
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial008.py b/docs_src/query_params_str_validations/tutorial008_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial008.py
rename to docs_src/query_params_str_validations/tutorial008_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial009_an.py b/docs_src/query_params_str_validations/tutorial009_an.py
deleted file mode 100644
index 2894e2d51a..0000000000
--- a/docs_src/query_params_str_validations/tutorial009_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial009.py b/docs_src/query_params_str_validations/tutorial009_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial009.py
rename to docs_src/query_params_str_validations/tutorial009_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial010_an.py b/docs_src/query_params_str_validations/tutorial010_an.py
deleted file mode 100644
index ed343230f4..0000000000
--- a/docs_src/query_params_str_validations/tutorial010_an.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- q: Annotated[
- Union[str, None],
- Query(
- alias="item-query",
- title="Query string",
- description="Query string for the items to search in the database that have a good match",
- min_length=3,
- max_length=50,
- pattern="^fixedquery$",
- deprecated=True,
- ),
- ] = None,
-):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial010.py b/docs_src/query_params_str_validations/tutorial010_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial010.py
rename to docs_src/query_params_str_validations/tutorial010_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial011.py b/docs_src/query_params_str_validations/tutorial011.py
deleted file mode 100644
index 65bbce781a..0000000000
--- a/docs_src/query_params_str_validations/tutorial011.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Union[List[str], None] = Query(default=None)):
- query_items = {"q": q}
- return query_items
diff --git a/docs_src/query_params_str_validations/tutorial011_an.py b/docs_src/query_params_str_validations/tutorial011_an.py
deleted file mode 100644
index 8ed699337d..0000000000
--- a/docs_src/query_params_str_validations/tutorial011_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[Union[List[str], None], Query()] = None):
- query_items = {"q": q}
- return query_items
diff --git a/docs_src/query_params_str_validations/tutorial012.py b/docs_src/query_params_str_validations/tutorial012.py
deleted file mode 100644
index e77d56974d..0000000000
--- a/docs_src/query_params_str_validations/tutorial012.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: List[str] = Query(default=["foo", "bar"])):
- query_items = {"q": q}
- return query_items
diff --git a/docs_src/query_params_str_validations/tutorial012_an.py b/docs_src/query_params_str_validations/tutorial012_an.py
deleted file mode 100644
index 261af250a1..0000000000
--- a/docs_src/query_params_str_validations/tutorial012_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[List[str], Query()] = ["foo", "bar"]):
- query_items = {"q": q}
- return query_items
diff --git a/docs_src/query_params_str_validations/tutorial013_an.py b/docs_src/query_params_str_validations/tutorial013_an.py
deleted file mode 100644
index f12a250559..0000000000
--- a/docs_src/query_params_str_validations/tutorial013_an.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[list, Query()] = []):
- query_items = {"q": q}
- return query_items
diff --git a/docs_src/query_params_str_validations/tutorial013.py b/docs_src/query_params_str_validations/tutorial013_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial013.py
rename to docs_src/query_params_str_validations/tutorial013_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial014_an.py b/docs_src/query_params_str_validations/tutorial014_an.py
deleted file mode 100644
index 2eaa585407..0000000000
--- a/docs_src/query_params_str_validations/tutorial014_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(
- hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
-):
- if hidden_query:
- return {"hidden_query": hidden_query}
- else:
- return {"hidden_query": "Not found"}
diff --git a/docs_src/query_params_str_validations/tutorial014.py b/docs_src/query_params_str_validations/tutorial014_py39.py
similarity index 100%
rename from docs_src/query_params_str_validations/tutorial014.py
rename to docs_src/query_params_str_validations/tutorial014_py39.py
diff --git a/docs_src/query_params_str_validations/tutorial015_an.py b/docs_src/query_params_str_validations/tutorial015_an.py
deleted file mode 100644
index f2ec6db123..0000000000
--- a/docs_src/query_params_str_validations/tutorial015_an.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import random
-from typing import Union
-
-from fastapi import FastAPI
-from pydantic import AfterValidator
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-data = {
- "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
- "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
- "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
-}
-
-
-def check_valid_id(id: str):
- if not id.startswith(("isbn-", "imdb-")):
- raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
- return id
-
-
-@app.get("/items/")
-async def read_items(
- id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
-):
- if id:
- item = data.get(id)
- else:
- id, item = random.choice(list(data.items()))
- return {"id": id, "name": item}
diff --git a/docs_src/request_files/tutorial001_02_an.py b/docs_src/request_files/tutorial001_02_an.py
deleted file mode 100644
index 5007fef159..0000000000
--- a/docs_src/request_files/tutorial001_02_an.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, File, UploadFile
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(file: Annotated[Union[bytes, None], File()] = None):
- if not file:
- return {"message": "No file sent"}
- else:
- return {"file_size": len(file)}
-
-
-@app.post("/uploadfile/")
-async def create_upload_file(file: Union[UploadFile, None] = None):
- if not file:
- return {"message": "No upload file sent"}
- else:
- return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_02.py b/docs_src/request_files/tutorial001_02_py39.py
similarity index 100%
rename from docs_src/request_files/tutorial001_02.py
rename to docs_src/request_files/tutorial001_02_py39.py
diff --git a/docs_src/request_files/tutorial001_03_an.py b/docs_src/request_files/tutorial001_03_an.py
deleted file mode 100644
index 8a6b0a2455..0000000000
--- a/docs_src/request_files/tutorial001_03_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from fastapi import FastAPI, File, UploadFile
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
- return {"file_size": len(file)}
-
-
-@app.post("/uploadfile/")
-async def create_upload_file(
- file: Annotated[UploadFile, File(description="A file read as UploadFile")],
-):
- return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_03.py b/docs_src/request_files/tutorial001_03_py39.py
similarity index 100%
rename from docs_src/request_files/tutorial001_03.py
rename to docs_src/request_files/tutorial001_03_py39.py
diff --git a/docs_src/request_files/tutorial001_an.py b/docs_src/request_files/tutorial001_an.py
deleted file mode 100644
index ca2f76d5c6..0000000000
--- a/docs_src/request_files/tutorial001_an.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from fastapi import FastAPI, File, UploadFile
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(file: Annotated[bytes, File()]):
- return {"file_size": len(file)}
-
-
-@app.post("/uploadfile/")
-async def create_upload_file(file: UploadFile):
- return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001.py b/docs_src/request_files/tutorial001_py39.py
similarity index 100%
rename from docs_src/request_files/tutorial001.py
rename to docs_src/request_files/tutorial001_py39.py
diff --git a/docs_src/request_files/tutorial002.py b/docs_src/request_files/tutorial002.py
deleted file mode 100644
index b4d0acc68f..0000000000
--- a/docs_src/request_files/tutorial002.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, File, UploadFile
-from fastapi.responses import HTMLResponse
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_files(files: List[bytes] = File()):
- return {"file_sizes": [len(file) for file in files]}
-
-
-@app.post("/uploadfiles/")
-async def create_upload_files(files: List[UploadFile]):
- return {"filenames": [file.filename for file in files]}
-
-
-@app.get("/")
-async def main():
- content = """
-
-
-
-
- """
- return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial002_an.py b/docs_src/request_files/tutorial002_an.py
deleted file mode 100644
index eaa90da2b6..0000000000
--- a/docs_src/request_files/tutorial002_an.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, File, UploadFile
-from fastapi.responses import HTMLResponse
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_files(files: Annotated[List[bytes], File()]):
- return {"file_sizes": [len(file) for file in files]}
-
-
-@app.post("/uploadfiles/")
-async def create_upload_files(files: List[UploadFile]):
- return {"filenames": [file.filename for file in files]}
-
-
-@app.get("/")
-async def main():
- content = """
-
-
-
-
- """
- return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial003.py b/docs_src/request_files/tutorial003.py
deleted file mode 100644
index e3f805f605..0000000000
--- a/docs_src/request_files/tutorial003.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, File, UploadFile
-from fastapi.responses import HTMLResponse
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_files(
- files: List[bytes] = File(description="Multiple files as bytes"),
-):
- return {"file_sizes": [len(file) for file in files]}
-
-
-@app.post("/uploadfiles/")
-async def create_upload_files(
- files: List[UploadFile] = File(description="Multiple files as UploadFile"),
-):
- return {"filenames": [file.filename for file in files]}
-
-
-@app.get("/")
-async def main():
- content = """
-
-
-
-
- """
- return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial003_an.py b/docs_src/request_files/tutorial003_an.py
deleted file mode 100644
index 2238e3c94b..0000000000
--- a/docs_src/request_files/tutorial003_an.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, File, UploadFile
-from fastapi.responses import HTMLResponse
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_files(
- files: Annotated[List[bytes], File(description="Multiple files as bytes")],
-):
- return {"file_sizes": [len(file) for file in files]}
-
-
-@app.post("/uploadfiles/")
-async def create_upload_files(
- files: Annotated[
- List[UploadFile], File(description="Multiple files as UploadFile")
- ],
-):
- return {"filenames": [file.filename for file in files]}
-
-
-@app.get("/")
-async def main():
- content = """
-
-
-
-
- """
- return HTMLResponse(content=content)
diff --git a/docs_src/request_form_models/tutorial001_an.py b/docs_src/request_form_models/tutorial001_an.py
deleted file mode 100644
index 30483d4455..0000000000
--- a/docs_src/request_form_models/tutorial001_an.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from fastapi import FastAPI, Form
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class FormData(BaseModel):
- username: str
- password: str
-
-
-@app.post("/login/")
-async def login(data: Annotated[FormData, Form()]):
- return data
diff --git a/docs_src/request_form_models/tutorial001.py b/docs_src/request_form_models/tutorial001_py39.py
similarity index 100%
rename from docs_src/request_form_models/tutorial001.py
rename to docs_src/request_form_models/tutorial001_py39.py
diff --git a/docs_src/request_form_models/tutorial002_an.py b/docs_src/request_form_models/tutorial002_an.py
deleted file mode 100644
index bcb0227959..0000000000
--- a/docs_src/request_form_models/tutorial002_an.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from fastapi import FastAPI, Form
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class FormData(BaseModel):
- username: str
- password: str
- model_config = {"extra": "forbid"}
-
-
-@app.post("/login/")
-async def login(data: Annotated[FormData, Form()]):
- return data
diff --git a/docs_src/request_form_models/tutorial002_pv1_an.py b/docs_src/request_form_models/tutorial002_pv1_an.py
deleted file mode 100644
index fe9dbc344b..0000000000
--- a/docs_src/request_form_models/tutorial002_pv1_an.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from fastapi import FastAPI, Form
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class FormData(BaseModel):
- username: str
- password: str
-
- class Config:
- extra = "forbid"
-
-
-@app.post("/login/")
-async def login(data: Annotated[FormData, Form()]):
- return data
diff --git a/docs_src/request_form_models/tutorial002_pv1.py b/docs_src/request_form_models/tutorial002_pv1_py39.py
similarity index 100%
rename from docs_src/request_form_models/tutorial002_pv1.py
rename to docs_src/request_form_models/tutorial002_pv1_py39.py
diff --git a/docs_src/request_form_models/tutorial002.py b/docs_src/request_form_models/tutorial002_py39.py
similarity index 100%
rename from docs_src/request_form_models/tutorial002.py
rename to docs_src/request_form_models/tutorial002_py39.py
diff --git a/docs_src/request_forms/tutorial001_an.py b/docs_src/request_forms/tutorial001_an.py
deleted file mode 100644
index 677fbf2db8..0000000000
--- a/docs_src/request_forms/tutorial001_an.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from fastapi import FastAPI, Form
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/login/")
-async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]):
- return {"username": username}
diff --git a/docs_src/request_forms/tutorial001.py b/docs_src/request_forms/tutorial001_py39.py
similarity index 100%
rename from docs_src/request_forms/tutorial001.py
rename to docs_src/request_forms/tutorial001_py39.py
diff --git a/docs_src/request_forms_and_files/tutorial001_an.py b/docs_src/request_forms_and_files/tutorial001_an.py
deleted file mode 100644
index 0ea285ac87..0000000000
--- a/docs_src/request_forms_and_files/tutorial001_an.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from fastapi import FastAPI, File, Form, UploadFile
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.post("/files/")
-async def create_file(
- file: Annotated[bytes, File()],
- fileb: Annotated[UploadFile, File()],
- token: Annotated[str, Form()],
-):
- return {
- "file_size": len(file),
- "token": token,
- "fileb_content_type": fileb.content_type,
- }
diff --git a/docs_src/request_forms_and_files/tutorial001.py b/docs_src/request_forms_and_files/tutorial001_py39.py
similarity index 100%
rename from docs_src/request_forms_and_files/tutorial001.py
rename to docs_src/request_forms_and_files/tutorial001_py39.py
diff --git a/docs_src/response_change_status_code/tutorial001.py b/docs_src/response_change_status_code/tutorial001_py39.py
similarity index 100%
rename from docs_src/response_change_status_code/tutorial001.py
rename to docs_src/response_change_status_code/tutorial001_py39.py
diff --git a/docs_src/response_cookies/tutorial001.py b/docs_src/response_cookies/tutorial001_py39.py
similarity index 100%
rename from docs_src/response_cookies/tutorial001.py
rename to docs_src/response_cookies/tutorial001_py39.py
diff --git a/docs_src/response_cookies/tutorial002.py b/docs_src/response_cookies/tutorial002_py39.py
similarity index 100%
rename from docs_src/response_cookies/tutorial002.py
rename to docs_src/response_cookies/tutorial002_py39.py
diff --git a/docs_src/response_directly/tutorial001.py b/docs_src/response_directly/tutorial001_py39.py
similarity index 100%
rename from docs_src/response_directly/tutorial001.py
rename to docs_src/response_directly/tutorial001_py39.py
diff --git a/docs_src/response_directly/tutorial002.py b/docs_src/response_directly/tutorial002_py39.py
similarity index 100%
rename from docs_src/response_directly/tutorial002.py
rename to docs_src/response_directly/tutorial002_py39.py
diff --git a/docs_src/response_headers/tutorial001.py b/docs_src/response_headers/tutorial001_py39.py
similarity index 100%
rename from docs_src/response_headers/tutorial001.py
rename to docs_src/response_headers/tutorial001_py39.py
diff --git a/docs_src/response_headers/tutorial002.py b/docs_src/response_headers/tutorial002_py39.py
similarity index 100%
rename from docs_src/response_headers/tutorial002.py
rename to docs_src/response_headers/tutorial002_py39.py
diff --git a/docs_src/response_model/tutorial001.py b/docs_src/response_model/tutorial001.py
deleted file mode 100644
index fd1c902a52..0000000000
--- a/docs_src/response_model/tutorial001.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import Any, List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: List[str] = []
-
-
-@app.post("/items/", response_model=Item)
-async def create_item(item: Item) -> Any:
- return item
-
-
-@app.get("/items/", response_model=List[Item])
-async def read_items() -> Any:
- return [
- {"name": "Portal Gun", "price": 42.0},
- {"name": "Plumbus", "price": 32.0},
- ]
diff --git a/docs_src/response_model/tutorial001_01.py b/docs_src/response_model/tutorial001_01.py
deleted file mode 100644
index 98d30d540f..0000000000
--- a/docs_src/response_model/tutorial001_01.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
- tags: List[str] = []
-
-
-@app.post("/items/")
-async def create_item(item: Item) -> Item:
- return item
-
-
-@app.get("/items/")
-async def read_items() -> List[Item]:
- return [
- Item(name="Portal Gun", price=42.0),
- Item(name="Plumbus", price=32.0),
- ]
diff --git a/docs_src/response_model/tutorial002.py b/docs_src/response_model/tutorial002_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial002.py
rename to docs_src/response_model/tutorial002_py39.py
diff --git a/docs_src/response_model/tutorial003_01.py b/docs_src/response_model/tutorial003_01_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003_01.py
rename to docs_src/response_model/tutorial003_01_py39.py
diff --git a/docs_src/response_model/tutorial003_02.py b/docs_src/response_model/tutorial003_02_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003_02.py
rename to docs_src/response_model/tutorial003_02_py39.py
diff --git a/docs_src/response_model/tutorial003_03.py b/docs_src/response_model/tutorial003_03_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003_03.py
rename to docs_src/response_model/tutorial003_03_py39.py
diff --git a/docs_src/response_model/tutorial003_04.py b/docs_src/response_model/tutorial003_04_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003_04.py
rename to docs_src/response_model/tutorial003_04_py39.py
diff --git a/docs_src/response_model/tutorial003_05.py b/docs_src/response_model/tutorial003_05_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003_05.py
rename to docs_src/response_model/tutorial003_05_py39.py
diff --git a/docs_src/response_model/tutorial003.py b/docs_src/response_model/tutorial003_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial003.py
rename to docs_src/response_model/tutorial003_py39.py
diff --git a/docs_src/response_model/tutorial004.py b/docs_src/response_model/tutorial004.py
deleted file mode 100644
index 10b48039ae..0000000000
--- a/docs_src/response_model/tutorial004.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: float = 10.5
- tags: List[str] = []
-
-
-items = {
- "foo": {"name": "Foo", "price": 50.2},
- "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
- "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
-}
-
-
-@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
-async def read_item(item_id: str):
- return items[item_id]
diff --git a/docs_src/response_model/tutorial005.py b/docs_src/response_model/tutorial005_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial005.py
rename to docs_src/response_model/tutorial005_py39.py
diff --git a/docs_src/response_model/tutorial006.py b/docs_src/response_model/tutorial006_py39.py
similarity index 100%
rename from docs_src/response_model/tutorial006.py
rename to docs_src/response_model/tutorial006_py39.py
diff --git a/docs_src/response_status_code/tutorial001.py b/docs_src/response_status_code/tutorial001_py39.py
similarity index 100%
rename from docs_src/response_status_code/tutorial001.py
rename to docs_src/response_status_code/tutorial001_py39.py
diff --git a/docs_src/response_status_code/tutorial002.py b/docs_src/response_status_code/tutorial002_py39.py
similarity index 100%
rename from docs_src/response_status_code/tutorial002.py
rename to docs_src/response_status_code/tutorial002_py39.py
diff --git a/docs_src/schema_extra_example/tutorial001_pv1.py b/docs_src/schema_extra_example/tutorial001_pv1_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial001_pv1.py
rename to docs_src/schema_extra_example/tutorial001_pv1_py39.py
diff --git a/docs_src/schema_extra_example/tutorial001.py b/docs_src/schema_extra_example/tutorial001_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial001.py
rename to docs_src/schema_extra_example/tutorial001_py39.py
diff --git a/docs_src/schema_extra_example/tutorial002.py b/docs_src/schema_extra_example/tutorial002_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial002.py
rename to docs_src/schema_extra_example/tutorial002_py39.py
diff --git a/docs_src/schema_extra_example/tutorial003_an.py b/docs_src/schema_extra_example/tutorial003_an.py
deleted file mode 100644
index 23675aba14..0000000000
--- a/docs_src/schema_extra_example/tutorial003_an.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- item_id: int,
- item: Annotated[
- Item,
- Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ],
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/schema_extra_example/tutorial003.py b/docs_src/schema_extra_example/tutorial003_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial003.py
rename to docs_src/schema_extra_example/tutorial003_py39.py
diff --git a/docs_src/schema_extra_example/tutorial004_an.py b/docs_src/schema_extra_example/tutorial004_an.py
deleted file mode 100644
index e817302a22..0000000000
--- a/docs_src/schema_extra_example/tutorial004_an.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Annotated[
- Item,
- Body(
- examples=[
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- {
- "name": "Bar",
- "price": "35.4",
- },
- {
- "name": "Baz",
- "price": "thirty five point four",
- },
- ],
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/schema_extra_example/tutorial004.py b/docs_src/schema_extra_example/tutorial004_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial004.py
rename to docs_src/schema_extra_example/tutorial004_py39.py
diff --git a/docs_src/schema_extra_example/tutorial005_an.py b/docs_src/schema_extra_example/tutorial005_an.py
deleted file mode 100644
index 4b2d9c662b..0000000000
--- a/docs_src/schema_extra_example/tutorial005_an.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from typing import Union
-
-from fastapi import Body, FastAPI
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
- price: float
- tax: Union[float, None] = None
-
-
-@app.put("/items/{item_id}")
-async def update_item(
- *,
- item_id: int,
- item: Annotated[
- Item,
- Body(
- openapi_examples={
- "normal": {
- "summary": "A normal example",
- "description": "A **normal** item works correctly.",
- "value": {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- },
- },
- "converted": {
- "summary": "An example with converted data",
- "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
- "value": {
- "name": "Bar",
- "price": "35.4",
- },
- },
- "invalid": {
- "summary": "Invalid data is rejected with an error",
- "value": {
- "name": "Baz",
- "price": "thirty five point four",
- },
- },
- },
- ),
- ],
-):
- results = {"item_id": item_id, "item": item}
- return results
diff --git a/docs_src/schema_extra_example/tutorial005.py b/docs_src/schema_extra_example/tutorial005_py39.py
similarity index 100%
rename from docs_src/schema_extra_example/tutorial005.py
rename to docs_src/schema_extra_example/tutorial005_py39.py
diff --git a/docs_src/security/tutorial001_an.py b/docs_src/security/tutorial001_an.py
deleted file mode 100644
index dac915b7ca..0000000000
--- a/docs_src/security/tutorial001_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import Depends, FastAPI
-from fastapi.security import OAuth2PasswordBearer
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-@app.get("/items/")
-async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
- return {"token": token}
diff --git a/docs_src/security/tutorial001.py b/docs_src/security/tutorial001_py39.py
similarity index 100%
rename from docs_src/security/tutorial001.py
rename to docs_src/security/tutorial001_py39.py
diff --git a/docs_src/security/tutorial002_an.py b/docs_src/security/tutorial002_an.py
deleted file mode 100644
index 291b3bf530..0000000000
--- a/docs_src/security/tutorial002_an.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI
-from fastapi.security import OAuth2PasswordBearer
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-def fake_decode_token(token):
- return User(
- username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
- )
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- user = fake_decode_token(token)
- return user
-
-
-@app.get("/users/me")
-async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
- return current_user
diff --git a/docs_src/security/tutorial002.py b/docs_src/security/tutorial002_py39.py
similarity index 100%
rename from docs_src/security/tutorial002.py
rename to docs_src/security/tutorial002_py39.py
diff --git a/docs_src/security/tutorial003_an.py b/docs_src/security/tutorial003_an.py
deleted file mode 100644
index 1b7056a209..0000000000
--- a/docs_src/security/tutorial003_an.py
+++ /dev/null
@@ -1,95 +0,0 @@
-from typing import Union
-
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "fakehashedsecret",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Wonderson",
- "email": "alice@example.com",
- "hashed_password": "fakehashedsecret2",
- "disabled": True,
- },
-}
-
-app = FastAPI()
-
-
-def fake_hash_password(password: str):
- return "fakehashed" + password
-
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def fake_decode_token(token):
- # This doesn't provide any security at all
- # Check the next version
- user = get_user(fake_users_db, token)
- return user
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- user = fake_decode_token(token)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not authenticated",
- headers={"WWW-Authenticate": "Bearer"},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
- user_dict = fake_users_db.get(form_data.username)
- if not user_dict:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- user = UserInDB(**user_dict)
- hashed_password = fake_hash_password(form_data.password)
- if not hashed_password == user.hashed_password:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
-
- return {"access_token": user.username, "token_type": "bearer"}
-
-
-@app.get("/users/me")
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return current_user
diff --git a/docs_src/security/tutorial003.py b/docs_src/security/tutorial003_py39.py
similarity index 100%
rename from docs_src/security/tutorial003.py
rename to docs_src/security/tutorial003_py39.py
diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py
deleted file mode 100644
index 018234e300..0000000000
--- a/docs_src/security/tutorial004_an.py
+++ /dev/null
@@ -1,148 +0,0 @@
-from datetime import datetime, timedelta, timezone
-from typing import Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel
-from typing_extensions import Annotated
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- }
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": "Bearer"},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username = payload.get("sub")
- if username is None:
- raise credentials_exception
- token_data = TokenData(username=username)
- except InvalidTokenError:
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect username or password",
- headers={"WWW-Authenticate": "Bearer"},
- )
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username}, expires_delta=access_token_expires
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/", response_model=User)
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004_py39.py
similarity index 100%
rename from docs_src/security/tutorial004.py
rename to docs_src/security/tutorial004_py39.py
diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py
deleted file mode 100644
index fdd73bcd8a..0000000000
--- a/docs_src/security/tutorial005.py
+++ /dev/null
@@ -1,177 +0,0 @@
-from datetime import datetime, timedelta, timezone
-from typing import List, Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, Security, status
-from fastapi.security import (
- OAuth2PasswordBearer,
- OAuth2PasswordRequestForm,
- SecurityScopes,
-)
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel, ValidationError
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Chains",
- "email": "alicechains@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE",
- "disabled": True,
- },
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
- scopes: List[str] = []
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(
- tokenUrl="token",
- scopes={"me": "Read information about the current user.", "items": "Read items."},
-)
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(
- security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme)
-):
- if security_scopes.scopes:
- authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
- else:
- authenticate_value = "Bearer"
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": authenticate_value},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
- if username is None:
- raise credentials_exception
- scope: str = payload.get("scope", "")
- token_scopes = scope.split(" ")
- token_data = TokenData(scopes=token_scopes, username=username)
- except (InvalidTokenError, ValidationError):
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- for scope in security_scopes.scopes:
- if scope not in token_data.scopes:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not enough permissions",
- headers={"WWW-Authenticate": authenticate_value},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: User = Security(get_current_user, scopes=["me"]),
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends(),
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username, "scope": " ".join(form_data.scopes)},
- expires_delta=access_token_expires,
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/", response_model=User)
-async def read_users_me(current_user: User = Depends(get_current_active_user)):
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: User = Security(get_current_active_user, scopes=["items"]),
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
-
-
-@app.get("/status/")
-async def read_system_status(current_user: User = Depends(get_current_user)):
- return {"status": "ok"}
diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py
deleted file mode 100644
index e1d7b4f62a..0000000000
--- a/docs_src/security/tutorial005_an.py
+++ /dev/null
@@ -1,180 +0,0 @@
-from datetime import datetime, timedelta, timezone
-from typing import List, Union
-
-import jwt
-from fastapi import Depends, FastAPI, HTTPException, Security, status
-from fastapi.security import (
- OAuth2PasswordBearer,
- OAuth2PasswordRequestForm,
- SecurityScopes,
-)
-from jwt.exceptions import InvalidTokenError
-from pwdlib import PasswordHash
-from pydantic import BaseModel, ValidationError
-from typing_extensions import Annotated
-
-# to get a string like this run:
-# openssl rand -hex 32
-SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
-ALGORITHM = "HS256"
-ACCESS_TOKEN_EXPIRE_MINUTES = 30
-
-
-fake_users_db = {
- "johndoe": {
- "username": "johndoe",
- "full_name": "John Doe",
- "email": "johndoe@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc",
- "disabled": False,
- },
- "alice": {
- "username": "alice",
- "full_name": "Alice Chains",
- "email": "alicechains@example.com",
- "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE",
- "disabled": True,
- },
-}
-
-
-class Token(BaseModel):
- access_token: str
- token_type: str
-
-
-class TokenData(BaseModel):
- username: Union[str, None] = None
- scopes: List[str] = []
-
-
-class User(BaseModel):
- username: str
- email: Union[str, None] = None
- full_name: Union[str, None] = None
- disabled: Union[bool, None] = None
-
-
-class UserInDB(User):
- hashed_password: str
-
-
-password_hash = PasswordHash.recommended()
-
-oauth2_scheme = OAuth2PasswordBearer(
- tokenUrl="token",
- scopes={"me": "Read information about the current user.", "items": "Read items."},
-)
-
-app = FastAPI()
-
-
-def verify_password(plain_password, hashed_password):
- return password_hash.verify(plain_password, hashed_password)
-
-
-def get_password_hash(password):
- return password_hash.hash(password)
-
-
-def get_user(db, username: str):
- if username in db:
- user_dict = db[username]
- return UserInDB(**user_dict)
-
-
-def authenticate_user(fake_db, username: str, password: str):
- user = get_user(fake_db, username)
- if not user:
- return False
- if not verify_password(password, user.hashed_password):
- return False
- return user
-
-
-def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
- to_encode = data.copy()
- if expires_delta:
- expire = datetime.now(timezone.utc) + expires_delta
- else:
- expire = datetime.now(timezone.utc) + timedelta(minutes=15)
- to_encode.update({"exp": expire})
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- return encoded_jwt
-
-
-async def get_current_user(
- security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)]
-):
- if security_scopes.scopes:
- authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
- else:
- authenticate_value = "Bearer"
- credentials_exception = HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Could not validate credentials",
- headers={"WWW-Authenticate": authenticate_value},
- )
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username = payload.get("sub")
- if username is None:
- raise credentials_exception
- scope: str = payload.get("scope", "")
- token_scopes = scope.split(" ")
- token_data = TokenData(scopes=token_scopes, username=username)
- except (InvalidTokenError, ValidationError):
- raise credentials_exception
- user = get_user(fake_users_db, username=token_data.username)
- if user is None:
- raise credentials_exception
- for scope in security_scopes.scopes:
- if scope not in token_data.scopes:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Not enough permissions",
- headers={"WWW-Authenticate": authenticate_value},
- )
- return user
-
-
-async def get_current_active_user(
- current_user: Annotated[User, Security(get_current_user, scopes=["me"])],
-):
- if current_user.disabled:
- raise HTTPException(status_code=400, detail="Inactive user")
- return current_user
-
-
-@app.post("/token")
-async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
-) -> Token:
- user = authenticate_user(fake_users_db, form_data.username, form_data.password)
- if not user:
- raise HTTPException(status_code=400, detail="Incorrect username or password")
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
- access_token = create_access_token(
- data={"sub": user.username, "scope": " ".join(form_data.scopes)},
- expires_delta=access_token_expires,
- )
- return Token(access_token=access_token, token_type="bearer")
-
-
-@app.get("/users/me/", response_model=User)
-async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)],
-):
- return current_user
-
-
-@app.get("/users/me/items/")
-async def read_own_items(
- current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])],
-):
- return [{"item_id": "Foo", "owner": current_user.username}]
-
-
-@app.get("/status/")
-async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]):
- return {"status": "ok"}
diff --git a/docs_src/security/tutorial006_an.py b/docs_src/security/tutorial006_an.py
deleted file mode 100644
index 985e4b2ad2..0000000000
--- a/docs_src/security/tutorial006_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import Depends, FastAPI
-from fastapi.security import HTTPBasic, HTTPBasicCredentials
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-security = HTTPBasic()
-
-
-@app.get("/users/me")
-def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):
- return {"username": credentials.username, "password": credentials.password}
diff --git a/docs_src/security/tutorial006.py b/docs_src/security/tutorial006_py39.py
similarity index 100%
rename from docs_src/security/tutorial006.py
rename to docs_src/security/tutorial006_py39.py
diff --git a/docs_src/security/tutorial007_an.py b/docs_src/security/tutorial007_an.py
deleted file mode 100644
index 0d211dfde5..0000000000
--- a/docs_src/security/tutorial007_an.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import secrets
-
-from fastapi import Depends, FastAPI, HTTPException, status
-from fastapi.security import HTTPBasic, HTTPBasicCredentials
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-security = HTTPBasic()
-
-
-def get_current_username(
- credentials: Annotated[HTTPBasicCredentials, Depends(security)],
-):
- current_username_bytes = credentials.username.encode("utf8")
- correct_username_bytes = b"stanleyjobson"
- is_correct_username = secrets.compare_digest(
- current_username_bytes, correct_username_bytes
- )
- current_password_bytes = credentials.password.encode("utf8")
- correct_password_bytes = b"swordfish"
- is_correct_password = secrets.compare_digest(
- current_password_bytes, correct_password_bytes
- )
- if not (is_correct_username and is_correct_password):
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect username or password",
- headers={"WWW-Authenticate": "Basic"},
- )
- return credentials.username
-
-
-@app.get("/users/me")
-def read_current_user(username: Annotated[str, Depends(get_current_username)]):
- return {"username": username}
diff --git a/docs_src/security/tutorial007.py b/docs_src/security/tutorial007_py39.py
similarity index 100%
rename from docs_src/security/tutorial007.py
rename to docs_src/security/tutorial007_py39.py
diff --git a/docs_src/separate_openapi_schemas/tutorial001.py b/docs_src/separate_openapi_schemas/tutorial001.py
deleted file mode 100644
index 415eef8e28..0000000000
--- a/docs_src/separate_openapi_schemas/tutorial001.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
-
-
-app = FastAPI()
-
-
-@app.post("/items/")
-def create_item(item: Item):
- return item
-
-
-@app.get("/items/")
-def read_items() -> List[Item]:
- return [
- Item(
- name="Portal Gun",
- description="Device to travel through the multi-rick-verse",
- ),
- Item(name="Plumbus"),
- ]
diff --git a/docs_src/separate_openapi_schemas/tutorial002.py b/docs_src/separate_openapi_schemas/tutorial002.py
deleted file mode 100644
index 7df93783b9..0000000000
--- a/docs_src/separate_openapi_schemas/tutorial002.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import List, Union
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-
-class Item(BaseModel):
- name: str
- description: Union[str, None] = None
-
-
-app = FastAPI(separate_input_output_schemas=False)
-
-
-@app.post("/items/")
-def create_item(item: Item):
- return item
-
-
-@app.get("/items/")
-def read_items() -> List[Item]:
- return [
- Item(
- name="Portal Gun",
- description="Device to travel through the multi-rick-verse",
- ),
- Item(name="Plumbus"),
- ]
diff --git a/docs_src/bigger_applications/app_an/internal/__init__.py b/docs_src/settings/app01_py39/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app_an/internal/__init__.py
rename to docs_src/settings/app01_py39/__init__.py
diff --git a/docs_src/settings/app01/config.py b/docs_src/settings/app01_py39/config.py
similarity index 100%
rename from docs_src/settings/app01/config.py
rename to docs_src/settings/app01_py39/config.py
diff --git a/docs_src/settings/app01/main.py b/docs_src/settings/app01_py39/main.py
similarity index 100%
rename from docs_src/settings/app01/main.py
rename to docs_src/settings/app01_py39/main.py
diff --git a/docs_src/settings/app02_an/__init__.py b/docs_src/settings/app02_an/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/docs_src/settings/app02_an/config.py b/docs_src/settings/app02_an/config.py
deleted file mode 100644
index e17b5035dc..0000000000
--- a/docs_src/settings/app02_an/config.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from pydantic_settings import BaseSettings
-
-
-class Settings(BaseSettings):
- app_name: str = "Awesome API"
- admin_email: str
- items_per_user: int = 50
diff --git a/docs_src/settings/app02_an/main.py b/docs_src/settings/app02_an/main.py
deleted file mode 100644
index 3a578cc338..0000000000
--- a/docs_src/settings/app02_an/main.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from functools import lru_cache
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-from .config import Settings
-
-app = FastAPI()
-
-
-@lru_cache
-def get_settings():
- return Settings()
-
-
-@app.get("/info")
-async def info(settings: Annotated[Settings, Depends(get_settings)]):
- return {
- "app_name": settings.app_name,
- "admin_email": settings.admin_email,
- "items_per_user": settings.items_per_user,
- }
diff --git a/docs_src/settings/app02_an/test_main.py b/docs_src/settings/app02_an/test_main.py
deleted file mode 100644
index 7a04d7e8ee..0000000000
--- a/docs_src/settings/app02_an/test_main.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from fastapi.testclient import TestClient
-
-from .config import Settings
-from .main import app, get_settings
-
-client = TestClient(app)
-
-
-def get_settings_override():
- return Settings(admin_email="testing_admin@example.com")
-
-
-app.dependency_overrides[get_settings] = get_settings_override
-
-
-def test_app():
- response = client.get("/info")
- data = response.json()
- assert data == {
- "app_name": "Awesome API",
- "admin_email": "testing_admin@example.com",
- "items_per_user": 50,
- }
diff --git a/docs_src/bigger_applications/app_an/routers/__init__.py b/docs_src/settings/app02_py39/__init__.py
similarity index 100%
rename from docs_src/bigger_applications/app_an/routers/__init__.py
rename to docs_src/settings/app02_py39/__init__.py
diff --git a/docs_src/settings/app02/config.py b/docs_src/settings/app02_py39/config.py
similarity index 100%
rename from docs_src/settings/app02/config.py
rename to docs_src/settings/app02_py39/config.py
diff --git a/docs_src/settings/app02/main.py b/docs_src/settings/app02_py39/main.py
similarity index 100%
rename from docs_src/settings/app02/main.py
rename to docs_src/settings/app02_py39/main.py
diff --git a/docs_src/settings/app02/test_main.py b/docs_src/settings/app02_py39/test_main.py
similarity index 100%
rename from docs_src/settings/app02/test_main.py
rename to docs_src/settings/app02_py39/test_main.py
diff --git a/docs_src/settings/app03/__init__.py b/docs_src/settings/app03/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/docs_src/settings/app03_an/__init__.py b/docs_src/settings/app03_an/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/docs_src/settings/app03_an/config.py b/docs_src/settings/app03_an/config.py
deleted file mode 100644
index 08f8f88c28..0000000000
--- a/docs_src/settings/app03_an/config.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from pydantic_settings import BaseSettings, SettingsConfigDict
-
-
-class Settings(BaseSettings):
- app_name: str = "Awesome API"
- admin_email: str
- items_per_user: int = 50
-
- model_config = SettingsConfigDict(env_file=".env")
diff --git a/docs_src/settings/app03_an/config_pv1.py b/docs_src/settings/app03_an/config_pv1.py
deleted file mode 100644
index e1c3ee3006..0000000000
--- a/docs_src/settings/app03_an/config_pv1.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from pydantic import BaseSettings
-
-
-class Settings(BaseSettings):
- app_name: str = "Awesome API"
- admin_email: str
- items_per_user: int = 50
-
- class Config:
- env_file = ".env"
diff --git a/docs_src/settings/app03_an/main.py b/docs_src/settings/app03_an/main.py
deleted file mode 100644
index 62f3476396..0000000000
--- a/docs_src/settings/app03_an/main.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from functools import lru_cache
-
-from fastapi import Depends, FastAPI
-from typing_extensions import Annotated
-
-from . import config
-
-app = FastAPI()
-
-
-@lru_cache
-def get_settings():
- return config.Settings()
-
-
-@app.get("/info")
-async def info(settings: Annotated[config.Settings, Depends(get_settings)]):
- return {
- "app_name": settings.app_name,
- "admin_email": settings.admin_email,
- "items_per_user": settings.items_per_user,
- }
diff --git a/docs_src/settings/app01/__init__.py b/docs_src/settings/app03_py39/__init__.py
similarity index 100%
rename from docs_src/settings/app01/__init__.py
rename to docs_src/settings/app03_py39/__init__.py
diff --git a/docs_src/settings/app03/config.py b/docs_src/settings/app03_py39/config.py
similarity index 100%
rename from docs_src/settings/app03/config.py
rename to docs_src/settings/app03_py39/config.py
diff --git a/docs_src/settings/app03/config_pv1.py b/docs_src/settings/app03_py39/config_pv1.py
similarity index 100%
rename from docs_src/settings/app03/config_pv1.py
rename to docs_src/settings/app03_py39/config_pv1.py
diff --git a/docs_src/settings/app03/main.py b/docs_src/settings/app03_py39/main.py
similarity index 100%
rename from docs_src/settings/app03/main.py
rename to docs_src/settings/app03_py39/main.py
diff --git a/docs_src/settings/tutorial001_pv1.py b/docs_src/settings/tutorial001_pv1_py39.py
similarity index 100%
rename from docs_src/settings/tutorial001_pv1.py
rename to docs_src/settings/tutorial001_pv1_py39.py
diff --git a/docs_src/settings/tutorial001.py b/docs_src/settings/tutorial001_py39.py
similarity index 100%
rename from docs_src/settings/tutorial001.py
rename to docs_src/settings/tutorial001_py39.py
diff --git a/docs_src/sql_databases/tutorial001.py b/docs_src/sql_databases/tutorial001.py
deleted file mode 100644
index be86ec0eeb..0000000000
--- a/docs_src/sql_databases/tutorial001.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from typing import List, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class Hero(SQLModel, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
- secret_name: str
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/")
-def create_hero(hero: Hero, session: Session = Depends(get_session)) -> Hero:
- session.add(hero)
- session.commit()
- session.refresh(hero)
- return hero
-
-
-@app.get("/heroes/")
-def read_heroes(
- session: Session = Depends(get_session),
- offset: int = 0,
- limit: int = Query(default=100, le=100),
-) -> List[Hero]:
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}")
-def read_hero(hero_id: int, session: Session = Depends(get_session)) -> Hero:
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
diff --git a/docs_src/sql_databases/tutorial001_an.py b/docs_src/sql_databases/tutorial001_an.py
deleted file mode 100644
index 8c000d31c7..0000000000
--- a/docs_src/sql_databases/tutorial001_an.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from typing import List, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-from typing_extensions import Annotated
-
-
-class Hero(SQLModel, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
- secret_name: str
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-SessionDep = Annotated[Session, Depends(get_session)]
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/")
-def create_hero(hero: Hero, session: SessionDep) -> Hero:
- session.add(hero)
- session.commit()
- session.refresh(hero)
- return hero
-
-
-@app.get("/heroes/")
-def read_heroes(
- session: SessionDep,
- offset: int = 0,
- limit: Annotated[int, Query(le=100)] = 100,
-) -> List[Hero]:
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}")
-def read_hero(hero_id: int, session: SessionDep) -> Hero:
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
diff --git a/docs_src/sql_databases/tutorial002.py b/docs_src/sql_databases/tutorial002.py
deleted file mode 100644
index 4350d19c61..0000000000
--- a/docs_src/sql_databases/tutorial002.py
+++ /dev/null
@@ -1,104 +0,0 @@
-from typing import List, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-
-
-class HeroBase(SQLModel):
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
-
-
-class Hero(HeroBase, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- secret_name: str
-
-
-class HeroPublic(HeroBase):
- id: int
-
-
-class HeroCreate(HeroBase):
- secret_name: str
-
-
-class HeroUpdate(HeroBase):
- name: Union[str, None] = None
- age: Union[int, None] = None
- secret_name: Union[str, None] = None
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/", response_model=HeroPublic)
-def create_hero(hero: HeroCreate, session: Session = Depends(get_session)):
- db_hero = Hero.model_validate(hero)
- session.add(db_hero)
- session.commit()
- session.refresh(db_hero)
- return db_hero
-
-
-@app.get("/heroes/", response_model=List[HeroPublic])
-def read_heroes(
- session: Session = Depends(get_session),
- offset: int = 0,
- limit: int = Query(default=100, le=100),
-):
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}", response_model=HeroPublic)
-def read_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
-def update_hero(
- hero_id: int, hero: HeroUpdate, session: Session = Depends(get_session)
-):
- hero_db = session.get(Hero, hero_id)
- if not hero_db:
- raise HTTPException(status_code=404, detail="Hero not found")
- hero_data = hero.model_dump(exclude_unset=True)
- hero_db.sqlmodel_update(hero_data)
- session.add(hero_db)
- session.commit()
- session.refresh(hero_db)
- return hero_db
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: Session = Depends(get_session)):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
diff --git a/docs_src/sql_databases/tutorial002_an.py b/docs_src/sql_databases/tutorial002_an.py
deleted file mode 100644
index 15e3d7c3a5..0000000000
--- a/docs_src/sql_databases/tutorial002_an.py
+++ /dev/null
@@ -1,104 +0,0 @@
-from typing import List, Union
-
-from fastapi import Depends, FastAPI, HTTPException, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
-from typing_extensions import Annotated
-
-
-class HeroBase(SQLModel):
- name: str = Field(index=True)
- age: Union[int, None] = Field(default=None, index=True)
-
-
-class Hero(HeroBase, table=True):
- id: Union[int, None] = Field(default=None, primary_key=True)
- secret_name: str
-
-
-class HeroPublic(HeroBase):
- id: int
-
-
-class HeroCreate(HeroBase):
- secret_name: str
-
-
-class HeroUpdate(HeroBase):
- name: Union[str, None] = None
- age: Union[int, None] = None
- secret_name: Union[str, None] = None
-
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-connect_args = {"check_same_thread": False}
-engine = create_engine(sqlite_url, connect_args=connect_args)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
-
-
-def get_session():
- with Session(engine) as session:
- yield session
-
-
-SessionDep = Annotated[Session, Depends(get_session)]
-app = FastAPI()
-
-
-@app.on_event("startup")
-def on_startup():
- create_db_and_tables()
-
-
-@app.post("/heroes/", response_model=HeroPublic)
-def create_hero(hero: HeroCreate, session: SessionDep):
- db_hero = Hero.model_validate(hero)
- session.add(db_hero)
- session.commit()
- session.refresh(db_hero)
- return db_hero
-
-
-@app.get("/heroes/", response_model=List[HeroPublic])
-def read_heroes(
- session: SessionDep,
- offset: int = 0,
- limit: Annotated[int, Query(le=100)] = 100,
-):
- heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
- return heroes
-
-
-@app.get("/heroes/{hero_id}", response_model=HeroPublic)
-def read_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- return hero
-
-
-@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
-def update_hero(hero_id: int, hero: HeroUpdate, session: SessionDep):
- hero_db = session.get(Hero, hero_id)
- if not hero_db:
- raise HTTPException(status_code=404, detail="Hero not found")
- hero_data = hero.model_dump(exclude_unset=True)
- hero_db.sqlmodel_update(hero_data)
- session.add(hero_db)
- session.commit()
- session.refresh(hero_db)
- return hero_db
-
-
-@app.delete("/heroes/{hero_id}")
-def delete_hero(hero_id: int, session: SessionDep):
- hero = session.get(Hero, hero_id)
- if not hero:
- raise HTTPException(status_code=404, detail="Hero not found")
- session.delete(hero)
- session.commit()
- return {"ok": True}
diff --git a/docs_src/static_files/tutorial001.py b/docs_src/static_files/tutorial001_py39.py
similarity index 100%
rename from docs_src/static_files/tutorial001.py
rename to docs_src/static_files/tutorial001_py39.py
diff --git a/docs_src/sub_applications/tutorial001.py b/docs_src/sub_applications/tutorial001_py39.py
similarity index 100%
rename from docs_src/sub_applications/tutorial001.py
rename to docs_src/sub_applications/tutorial001_py39.py
diff --git a/docs_src/templates/tutorial001.py b/docs_src/templates/tutorial001_py39.py
similarity index 100%
rename from docs_src/templates/tutorial001.py
rename to docs_src/templates/tutorial001_py39.py
diff --git a/docs_src/using_request_directly/tutorial001.py b/docs_src/using_request_directly/tutorial001_py39.py
similarity index 100%
rename from docs_src/using_request_directly/tutorial001.py
rename to docs_src/using_request_directly/tutorial001_py39.py
diff --git a/docs_src/websockets/tutorial001.py b/docs_src/websockets/tutorial001_py39.py
similarity index 100%
rename from docs_src/websockets/tutorial001.py
rename to docs_src/websockets/tutorial001_py39.py
diff --git a/docs_src/websockets/tutorial002_an.py b/docs_src/websockets/tutorial002_an.py
deleted file mode 100644
index c838fbd306..0000000000
--- a/docs_src/websockets/tutorial002_an.py
+++ /dev/null
@@ -1,93 +0,0 @@
-from typing import Union
-
-from fastapi import (
- Cookie,
- Depends,
- FastAPI,
- Query,
- WebSocket,
- WebSocketException,
- status,
-)
-from fastapi.responses import HTMLResponse
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-html = """
-
-
-
- Chat
-
-
- WebSocket Chat
-
-
-
-
-
-"""
-
-
-@app.get("/")
-async def get():
- return HTMLResponse(html)
-
-
-async def get_cookie_or_token(
- websocket: WebSocket,
- session: Annotated[Union[str, None], Cookie()] = None,
- token: Annotated[Union[str, None], Query()] = None,
-):
- if session is None and token is None:
- raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
- return session or token
-
-
-@app.websocket("/items/{item_id}/ws")
-async def websocket_endpoint(
- *,
- websocket: WebSocket,
- item_id: str,
- q: Union[int, None] = None,
- cookie_or_token: Annotated[str, Depends(get_cookie_or_token)],
-):
- await websocket.accept()
- while True:
- data = await websocket.receive_text()
- await websocket.send_text(
- f"Session cookie or query token value is: {cookie_or_token}"
- )
- if q is not None:
- await websocket.send_text(f"Query parameter q is: {q}")
- await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}")
diff --git a/docs_src/websockets/tutorial002.py b/docs_src/websockets/tutorial002_py39.py
similarity index 100%
rename from docs_src/websockets/tutorial002.py
rename to docs_src/websockets/tutorial002_py39.py
diff --git a/docs_src/websockets/tutorial003.py b/docs_src/websockets/tutorial003.py
deleted file mode 100644
index d561633a8d..0000000000
--- a/docs_src/websockets/tutorial003.py
+++ /dev/null
@@ -1,83 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI, WebSocket, WebSocketDisconnect
-from fastapi.responses import HTMLResponse
-
-app = FastAPI()
-
-html = """
-
-
-
- Chat
-
-
- WebSocket Chat
- Your ID:
-
-
-
-
-
-"""
-
-
-class ConnectionManager:
- def __init__(self):
- self.active_connections: List[WebSocket] = []
-
- async def connect(self, websocket: WebSocket):
- await websocket.accept()
- self.active_connections.append(websocket)
-
- def disconnect(self, websocket: WebSocket):
- self.active_connections.remove(websocket)
-
- async def send_personal_message(self, message: str, websocket: WebSocket):
- await websocket.send_text(message)
-
- async def broadcast(self, message: str):
- for connection in self.active_connections:
- await connection.send_text(message)
-
-
-manager = ConnectionManager()
-
-
-@app.get("/")
-async def get():
- return HTMLResponse(html)
-
-
-@app.websocket("/ws/{client_id}")
-async def websocket_endpoint(websocket: WebSocket, client_id: int):
- await manager.connect(websocket)
- try:
- while True:
- data = await websocket.receive_text()
- await manager.send_personal_message(f"You wrote: {data}", websocket)
- await manager.broadcast(f"Client #{client_id} says: {data}")
- except WebSocketDisconnect:
- manager.disconnect(websocket)
- await manager.broadcast(f"Client #{client_id} left the chat")
diff --git a/docs_src/wsgi/tutorial001.py b/docs_src/wsgi/tutorial001_py39.py
similarity index 100%
rename from docs_src/wsgi/tutorial001.py
rename to docs_src/wsgi/tutorial001_py39.py
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index e02969c55f..2f13448467 100644
--- a/fastapi/__init__.py
+++ b/fastapi/__init__.py
@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
-__version__ = "0.124.4"
+__version__ = "0.125.0"
from starlette import status as status
diff --git a/fastapi/_compat/main.py b/fastapi/_compat/main.py
index e5275950e8..2043a66781 100644
--- a/fastapi/_compat/main.py
+++ b/fastapi/_compat/main.py
@@ -1,12 +1,8 @@
import sys
+from collections.abc import Sequence
from functools import lru_cache
from typing import (
Any,
- Dict,
- List,
- Sequence,
- Tuple,
- Type,
)
from fastapi._compat import may_v1
@@ -50,7 +46,7 @@ else:
@lru_cache
-def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
+def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]:
if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1
@@ -119,7 +115,7 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
def create_body_model(
*, fields: Sequence[ModelField], model_name: str
-) -> Type[BaseModel]:
+) -> type[BaseModel]:
if fields and isinstance(fields[0], may_v1.ModelField):
from fastapi._compat import v1
@@ -221,7 +217,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type]
-def _model_rebuild(model: Type[BaseModel]) -> None:
+def _model_rebuild(model: type[BaseModel]) -> None:
if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1
@@ -232,7 +228,7 @@ def _model_rebuild(model: Type[BaseModel]) -> None:
v2._model_rebuild(model)
-def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
+def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
v1_model_fields = [
field for field in fields if isinstance(field, may_v1.ModelField)
]
@@ -266,15 +262,15 @@ def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
def get_definitions(
*,
- fields: List[ModelField],
+ fields: list[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
-) -> Tuple[
- Dict[
- Tuple[ModelField, Literal["validation", "serialization"]],
+) -> tuple[
+ dict[
+ tuple[ModelField, Literal["validation", "serialization"]],
may_v1.JsonSchemaValue,
],
- Dict[str, Dict[str, Any]],
+ dict[str, dict[str, Any]],
]:
if sys.version_info < (3, 14):
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
@@ -315,12 +311,12 @@ def get_schema_from_model_field(
*,
field: ModelField,
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]],
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]],
may_v1.JsonSchemaValue,
],
separate_input_output_schemas: bool = True,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
diff --git a/fastapi/_compat/may_v1.py b/fastapi/_compat/may_v1.py
index beea4d167f..c772162283 100644
--- a/fastapi/_compat/may_v1.py
+++ b/fastapi/_compat/may_v1.py
@@ -1,5 +1,6 @@
import sys
-from typing import Any, Dict, List, Literal, Sequence, Tuple, Type, Union
+from collections.abc import Sequence
+from typing import Any, Literal, Union
from fastapi.types import ModelNameMap
@@ -60,14 +61,14 @@ if sys.version_info >= (3, 14):
def get_definitions(
*,
- fields: List[ModelField],
+ fields: list[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
- ) -> Tuple[
- Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ ) -> tuple[
+ dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
- Dict[str, Dict[str, Any]],
+ dict[str, dict[str, Any]],
]:
return {}, {} # pragma: no cover
@@ -94,11 +95,11 @@ else:
from .v1 import get_definitions as get_definitions
-RequestErrorModel: Type[BaseModel] = create_model("Request")
+RequestErrorModel: type[BaseModel] = create_model("Request")
-def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
- use_errors: List[Any] = []
+def _normalize_errors(errors: Sequence[Any]) -> list[dict[str, Any]]:
+ use_errors: list[Any] = []
for error in errors:
if isinstance(error, ErrorWrapper):
new_errors = ValidationError( # type: ignore[call-arg]
@@ -113,9 +114,9 @@ def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
def _regenerate_error_with_loc(
- *, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...]
-) -> List[Dict[str, Any]]:
- updated_loc_errors: List[Any] = [
+ *, errors: Sequence[Any], loc_prefix: tuple[Union[str, int], ...]
+) -> list[dict[str, Any]]:
+ updated_loc_errors: list[Any] = [
{**err, "loc": loc_prefix + err.get("loc", ())}
for err in _normalize_errors(errors)
]
diff --git a/fastapi/_compat/model_field.py b/fastapi/_compat/model_field.py
index fa2008c5e0..47d05cb946 100644
--- a/fastapi/_compat/model_field.py
+++ b/fastapi/_compat/model_field.py
@@ -1,8 +1,5 @@
from typing import (
Any,
- Dict,
- List,
- Tuple,
Union,
)
@@ -34,10 +31,10 @@ class ModelField(Protocol):
def validate(
self,
value: Any,
- values: Dict[str, Any] = {}, # noqa: B006
+ values: dict[str, Any] = {}, # noqa: B006
*,
- loc: Tuple[Union[int, str], ...] = (),
- ) -> Tuple[Any, Union[List[Dict[str, Any]], None]]: ...
+ loc: tuple[Union[int, str], ...] = (),
+ ) -> tuple[Any, Union[list[dict[str, Any]], None]]: ...
def serialize(
self,
diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py
index cabf482283..3a11e88ac9 100644
--- a/fastapi/_compat/shared.py
+++ b/fastapi/_compat/shared.py
@@ -2,17 +2,11 @@ import sys
import types
import typing
from collections import deque
+from collections.abc import Mapping, Sequence
from dataclasses import is_dataclass
from typing import (
+ Annotated,
Any,
- Deque,
- FrozenSet,
- List,
- Mapping,
- Sequence,
- Set,
- Tuple,
- Type,
Union,
)
@@ -21,16 +15,10 @@ from fastapi.types import UnionType
from pydantic import BaseModel
from pydantic.version import VERSION as PYDANTIC_VERSION
from starlette.datastructures import UploadFile
-from typing_extensions import Annotated, get_args, get_origin
+from typing_extensions import get_args, get_origin
# Copy from Pydantic v2, compatible with v1
-if sys.version_info < (3, 9):
- # Pydantic no longer supports Python 3.8, this might be incorrect, but the code
- # this is used for is also never reached in this codebase, as it's a copy of
- # Pydantic's lenient_issubclass, just for compatibility with v1
- # TODO: remove when dropping support for Python 3.8
- WithArgsTypes: Tuple[Any, ...] = ()
-elif sys.version_info < (3, 10):
+if sys.version_info < (3, 10):
WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # type: ignore[attr-defined]
else:
WithArgsTypes: tuple[Any, ...] = (
@@ -45,26 +33,21 @@ PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
sequence_annotation_to_type = {
Sequence: list,
- List: list,
list: list,
- Tuple: tuple,
tuple: tuple,
- Set: set,
set: set,
- FrozenSet: frozenset,
frozenset: frozenset,
- Deque: deque,
deque: deque,
}
sequence_types = tuple(sequence_annotation_to_type.keys())
-Url: Type[Any]
+Url: type[Any]
# Copy of Pydantic v2, compatible with v1
def lenient_issubclass(
- cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]
+ cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]
) -> bool:
try:
return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]
@@ -74,13 +57,13 @@ def lenient_issubclass(
raise # pragma: no cover
-def _annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
+def _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
if lenient_issubclass(annotation, (str, bytes)):
return False
- return lenient_issubclass(annotation, sequence_types) # type: ignore[arg-type]
+ return lenient_issubclass(annotation, sequence_types)
-def field_annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
+def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
origin = get_origin(annotation)
if origin is Union or origin is UnionType:
for arg in get_args(annotation):
@@ -93,10 +76,10 @@ def field_annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
def value_is_sequence(value: Any) -> bool:
- return isinstance(value, sequence_types) and not isinstance(value, (str, bytes)) # type: ignore[arg-type]
+ return isinstance(value, sequence_types) and not isinstance(value, (str, bytes))
-def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
+def _annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
return (
lenient_issubclass(
annotation, (BaseModel, may_v1.BaseModel, Mapping, UploadFile)
@@ -106,7 +89,7 @@ def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
)
-def field_annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
+def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
origin = get_origin(annotation)
if origin is Union or origin is UnionType:
return any(field_annotation_is_complex(arg) for arg in get_args(annotation))
@@ -127,7 +110,7 @@ def field_annotation_is_scalar(annotation: Any) -> bool:
return annotation is Ellipsis or not field_annotation_is_complex(annotation)
-def field_annotation_is_scalar_sequence(annotation: Union[Type[Any], None]) -> bool:
+def field_annotation_is_scalar_sequence(annotation: Union[type[Any], None]) -> bool:
origin = get_origin(annotation)
if origin is Union or origin is UnionType:
at_least_one_scalar_sequence = False
diff --git a/fastapi/_compat/v1.py b/fastapi/_compat/v1.py
index e17ce8beaf..b29a61f734 100644
--- a/fastapi/_compat/v1.py
+++ b/fastapi/_compat/v1.py
@@ -1,15 +1,10 @@
+from collections.abc import Sequence
from copy import copy
from dataclasses import dataclass, is_dataclass
from enum import Enum
from typing import (
Any,
Callable,
- Dict,
- List,
- Sequence,
- Set,
- Tuple,
- Type,
Union,
)
@@ -124,7 +119,7 @@ else:
GetJsonSchemaHandler = Any
-JsonSchemaValue = Dict[str, Any]
+JsonSchemaValue = dict[str, Any]
CoreSchema = Any
Url = AnyUrl
@@ -154,7 +149,7 @@ class PydanticSchemaGenerationError(Exception):
pass
-RequestErrorModel: Type[BaseModel] = create_model("Request")
+RequestErrorModel: type[BaseModel] = create_model("Request")
def with_info_plain_validator_function(
@@ -169,10 +164,10 @@ def with_info_plain_validator_function(
def get_model_definitions(
*,
- flat_models: Set[Union[Type[BaseModel], Type[Enum]]],
- model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str],
-) -> Dict[str, Any]:
- definitions: Dict[str, Dict[str, Any]] = {}
+ flat_models: set[Union[type[BaseModel], type[Enum]]],
+ model_name_map: dict[Union[type[BaseModel], type[Enum]], str],
+) -> dict[str, Any]:
+ definitions: dict[str, dict[str, Any]] = {}
for model in flat_models:
m_schema, m_definitions, m_nested_models = model_process_schema(
model, model_name_map=model_name_map, ref_prefix=REF_PREFIX
@@ -219,7 +214,7 @@ def is_pv1_scalar_sequence_field(field: ModelField) -> bool:
return False
-def _model_rebuild(model: Type[BaseModel]) -> None:
+def _model_rebuild(model: type[BaseModel]) -> None:
model.update_forward_refs()
@@ -237,11 +232,11 @@ def get_schema_from_model_field(
*,
field: ModelField,
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
separate_input_output_schemas: bool = True,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
return field_schema( # type: ignore[no-any-return]
field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
)[0]
@@ -254,12 +249,12 @@ def get_schema_from_model_field(
def get_definitions(
*,
- fields: List[ModelField],
+ fields: list[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
-) -> Tuple[
- Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
- Dict[str, Dict[str, Any]],
+) -> tuple[
+ dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
+ dict[str, dict[str, Any]],
]:
models = get_flat_models_from_fields(fields, known_models=set())
return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map)
@@ -293,7 +288,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
return sequence_shape_to_type[field.shape](value) # type: ignore[no-any-return]
-def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
+def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]:
missing_field_error = ErrorWrapper(MissingError(), loc=loc)
new_error = ValidationError([missing_field_error], RequestErrorModel)
return new_error.errors()[0] # type: ignore[return-value]
@@ -301,12 +296,12 @@ def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
def create_body_model(
*, fields: Sequence[ModelField], model_name: str
-) -> Type[BaseModel]:
+) -> type[BaseModel]:
BodyModel = create_model(model_name)
for f in fields:
BodyModel.__fields__[f.name] = f # type: ignore[index]
return BodyModel
-def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
+def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
return list(model.__fields__.values()) # type: ignore[attr-defined]
diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py
index a17d625568..c4fa49e403 100644
--- a/fastapi/_compat/v2.py
+++ b/fastapi/_compat/v2.py
@@ -1,16 +1,12 @@
import re
import warnings
+from collections.abc import Sequence
from copy import copy, deepcopy
from dataclasses import dataclass, is_dataclass
from enum import Enum
from typing import (
+ Annotated,
Any,
- Dict,
- List,
- Sequence,
- Set,
- Tuple,
- Type,
Union,
cast,
)
@@ -33,7 +29,7 @@ from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue
from pydantic_core import CoreSchema as CoreSchema
from pydantic_core import PydanticUndefined, PydanticUndefinedType
from pydantic_core import Url as Url
-from typing_extensions import Annotated, Literal, get_args, get_origin
+from typing_extensions import Literal, get_args, get_origin
try:
from pydantic_core.core_schema import (
@@ -77,7 +73,7 @@ _Attrs = {
# TODO: remove when dropping support for Pydantic < v2.12.3
-def asdict(field_info: FieldInfo) -> Dict[str, Any]:
+def asdict(field_info: FieldInfo) -> dict[str, Any]:
attributes = {}
for attr in _Attrs:
value = getattr(field_info, attr, Undefined)
@@ -169,10 +165,10 @@ class ModelField:
def validate(
self,
value: Any,
- values: Dict[str, Any] = {}, # noqa: B006
+ values: dict[str, Any] = {}, # noqa: B006
*,
- loc: Tuple[Union[int, str], ...] = (),
- ) -> Tuple[Any, Union[List[Dict[str, Any]], None]]:
+ loc: tuple[Union[int, str], ...] = (),
+ ) -> tuple[Any, Union[list[dict[str, Any]], None]]:
try:
return (
self._type_adapter.validate_python(value, from_attributes=True),
@@ -220,7 +216,7 @@ def get_annotation_from_field_info(
return annotation
-def _model_rebuild(model: Type[BaseModel]) -> None:
+def _model_rebuild(model: type[BaseModel]) -> None:
model.model_rebuild()
@@ -245,11 +241,11 @@ def get_schema_from_model_field(
*,
field: ModelField,
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
separate_input_output_schemas: bool = True,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
override_mode: Union[Literal["validation"], None] = (
None
if (separate_input_output_schemas or _has_computed_fields(field))
@@ -277,9 +273,9 @@ def get_definitions(
fields: Sequence[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
-) -> Tuple[
- Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
- Dict[str, Dict[str, Any]],
+) -> tuple[
+ dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
+ dict[str, dict[str, Any]],
]:
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
validation_fields = [field for field in fields if field.mode == "validation"]
@@ -324,7 +320,7 @@ def get_definitions(
for field in list(fields) + list(unique_flat_model_fields)
]
field_mapping, definitions = schema_generator.generate_definitions(inputs=inputs)
- for item_def in cast(Dict[str, Dict[str, Any]], definitions).values():
+ for item_def in cast(dict[str, dict[str, Any]], definitions).values():
if "description" in item_def:
item_description = cast(str, item_def["description"]).split("\f")[0]
item_def["description"] = item_description
@@ -338,9 +334,9 @@ def get_definitions(
def _replace_refs(
*,
- schema: Dict[str, Any],
- old_name_to_new_name_map: Dict[str, str],
-) -> Dict[str, Any]:
+ schema: dict[str, Any],
+ old_name_to_new_name_map: dict[str, str],
+) -> dict[str, Any]:
new_schema = deepcopy(schema)
for key, value in new_schema.items():
if key == "$ref":
@@ -375,13 +371,13 @@ def _replace_refs(
def _remap_definitions_and_field_mappings(
*,
model_name_map: ModelNameMap,
- definitions: Dict[str, Any],
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ definitions: dict[str, Any],
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
-) -> Tuple[
- Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
- Dict[str, Any],
+) -> tuple[
+ dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
+ dict[str, Any],
]:
old_name_to_new_name_map = {}
for field_key, schema in field_mapping.items():
@@ -394,8 +390,8 @@ def _remap_definitions_and_field_mappings(
continue
old_name_to_new_name_map[old_name] = new_name
- new_field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ new_field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
] = {}
for field_key, schema in field_mapping.items():
new_schema = _replace_refs(
@@ -461,10 +457,10 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
origin_type = get_origin(union_arg) or union_arg
break
assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type]
- return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return]
+ return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index]
-def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
+def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]:
error = ValidationError.from_exception_data(
"Field required", [{"type": "missing", "loc": loc, "input": {}}]
).errors(include_url=False)[0]
@@ -474,14 +470,14 @@ def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
def create_body_model(
*, fields: Sequence[ModelField], model_name: str
-) -> Type[BaseModel]:
+) -> type[BaseModel]:
field_params = {f.name: (f.field_info.annotation, f.field_info) for f in fields}
- BodyModel: Type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload]
+ BodyModel: type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload]
return BodyModel
-def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
- model_fields: List[ModelField] = []
+def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
+ model_fields: list[ModelField] = []
for name, field_info in model.model_fields.items():
type_ = field_info.annotation
if lenient_issubclass(type_, (BaseModel, dict)) or is_dataclass(type_):
@@ -501,17 +497,17 @@ def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
# Duplicate of several schema functions from Pydantic v1 to make them compatible with
# Pydantic v2 and allow mixing the models
-TypeModelOrEnum = Union[Type["BaseModel"], Type[Enum]]
-TypeModelSet = Set[TypeModelOrEnum]
+TypeModelOrEnum = Union[type["BaseModel"], type[Enum]]
+TypeModelSet = set[TypeModelOrEnum]
def normalize_name(name: str) -> str:
return re.sub(r"[^a-zA-Z0-9.\-_]", "_", name)
-def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str]:
+def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str]:
name_model_map = {}
- conflicting_names: Set[str] = set()
+ conflicting_names: set[str] = set()
for model in unique_models:
model_name = normalize_name(model.__name__)
if model_name in conflicting_names:
@@ -528,7 +524,7 @@ def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str
def get_flat_models_from_model(
- model: Type["BaseModel"], known_models: Union[TypeModelSet, None] = None
+ model: type["BaseModel"], known_models: Union[TypeModelSet, None] = None
) -> TypeModelSet:
known_models = known_models or set()
fields = get_model_fields(model)
diff --git a/fastapi/applications.py b/fastapi/applications.py
index 02193312b9..54175cb3b0 100644
--- a/fastapi/applications.py
+++ b/fastapi/applications.py
@@ -1,14 +1,10 @@
+from collections.abc import Awaitable, Coroutine, Sequence
from enum import Enum
from typing import (
+ Annotated,
Any,
- Awaitable,
Callable,
- Coroutine,
- Dict,
- List,
Optional,
- Sequence,
- Type,
TypeVar,
Union,
)
@@ -44,7 +40,7 @@ from starlette.requests import Request
from starlette.responses import HTMLResponse, JSONResponse, Response
from starlette.routing import BaseRoute
from starlette.types import ASGIApp, ExceptionHandler, Lifespan, Receive, Scope, Send
-from typing_extensions import Annotated, deprecated
+from typing_extensions import deprecated
AppType = TypeVar("AppType", bound="FastAPI")
@@ -81,7 +77,7 @@ class FastAPI(Starlette):
),
] = False,
routes: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
**Note**: you probably shouldn't use this parameter, it is inherited
@@ -230,7 +226,7 @@ class FastAPI(Starlette):
),
] = "/openapi.json",
openapi_tags: Annotated[
- Optional[List[Dict[str, Any]]],
+ Optional[list[dict[str, Any]]],
Doc(
"""
A list of tags used by OpenAPI, these are the same `tags` you can set
@@ -290,7 +286,7 @@ class FastAPI(Starlette):
),
] = None,
servers: Annotated[
- Optional[List[Dict[str, Union[str, Any]]]],
+ Optional[list[dict[str, Union[str, Any]]]],
Doc(
"""
A `list` of `dict`s with connectivity information to a target server.
@@ -361,7 +357,7 @@ class FastAPI(Starlette):
),
] = None,
default_response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
The default response class to be used.
@@ -467,7 +463,7 @@ class FastAPI(Starlette):
),
] = "/docs/oauth2-redirect",
swagger_ui_init_oauth: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
OAuth2 configuration for the Swagger UI, by default shown at `/docs`.
@@ -493,8 +489,8 @@ class FastAPI(Starlette):
] = None,
exception_handlers: Annotated[
Optional[
- Dict[
- Union[int, Type[Exception]],
+ dict[
+ Union[int, type[Exception]],
Callable[[Request, Any], Coroutine[Any, Any, Response]],
]
],
@@ -567,7 +563,7 @@ class FastAPI(Starlette):
),
] = None,
contact: Annotated[
- Optional[Dict[str, Union[str, Any]]],
+ Optional[dict[str, Union[str, Any]]],
Doc(
"""
A dictionary with the contact information for the exposed API.
@@ -600,7 +596,7 @@ class FastAPI(Starlette):
),
] = None,
license_info: Annotated[
- Optional[Dict[str, Union[str, Any]]],
+ Optional[dict[str, Union[str, Any]]],
Doc(
"""
A dictionary with the license information for the exposed API.
@@ -689,7 +685,7 @@ class FastAPI(Starlette):
),
] = True,
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses to be shown in OpenAPI.
@@ -705,7 +701,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
OpenAPI callbacks that should apply to all *path operations*.
@@ -762,7 +758,7 @@ class FastAPI(Starlette):
),
] = True,
swagger_ui_parameters: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Parameters to configure Swagger UI, the autogenerated interactive API
@@ -820,7 +816,7 @@ class FastAPI(Starlette):
),
] = True,
openapi_external_docs: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
This field allows you to provide additional external documentation links.
@@ -906,7 +902,7 @@ class FastAPI(Starlette):
"""
),
] = "3.1.0"
- self.openapi_schema: Optional[Dict[str, Any]] = None
+ self.openapi_schema: Optional[dict[str, Any]] = None
if self.openapi_url:
assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'"
assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'"
@@ -949,7 +945,7 @@ class FastAPI(Starlette):
),
] = State()
self.dependency_overrides: Annotated[
- Dict[Callable[..., Any], Callable[..., Any]],
+ dict[Callable[..., Any], Callable[..., Any]],
Doc(
"""
A dictionary with overrides for the dependencies.
@@ -980,7 +976,7 @@ class FastAPI(Starlette):
responses=responses,
generate_unique_id_function=generate_unique_id_function,
)
- self.exception_handlers: Dict[
+ self.exception_handlers: dict[
Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]]
] = {} if exception_handlers is None else dict(exception_handlers)
self.exception_handlers.setdefault(HTTPException, http_exception_handler)
@@ -993,7 +989,7 @@ class FastAPI(Starlette):
websocket_request_validation_exception_handler, # type: ignore
)
- self.user_middleware: List[Middleware] = (
+ self.user_middleware: list[Middleware] = (
[] if middleware is None else list(middleware)
)
self.middleware_stack: Union[ASGIApp, None] = None
@@ -1047,7 +1043,7 @@ class FastAPI(Starlette):
app = cls(app, *args, **kwargs)
return app
- def openapi(self) -> Dict[str, Any]:
+ def openapi(self) -> dict[str, Any]:
"""
Generate the OpenAPI schema of the application. This is called by FastAPI
internally.
@@ -1145,14 +1141,14 @@ class FastAPI(Starlette):
*,
response_model: Any = Default(None),
status_code: Optional[int] = None,
- tags: Optional[List[Union[str, Enum]]] = None,
+ tags: Optional[list[Union[str, Enum]]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
response_description: str = "Successful Response",
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
+ responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
deprecated: Optional[bool] = None,
- methods: Optional[List[str]] = None,
+ methods: Optional[list[str]] = None,
operation_id: Optional[str] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -1161,11 +1157,11 @@ class FastAPI(Starlette):
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(
+ response_class: Union[type[Response], DefaultPlaceholder] = Default(
JSONResponse
),
name: Optional[str] = None,
- openapi_extra: Optional[Dict[str, Any]] = None,
+ openapi_extra: Optional[dict[str, Any]] = None,
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
generate_unique_id
),
@@ -1203,14 +1199,14 @@ class FastAPI(Starlette):
*,
response_model: Any = Default(None),
status_code: Optional[int] = None,
- tags: Optional[List[Union[str, Enum]]] = None,
+ tags: Optional[list[Union[str, Enum]]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
response_description: str = "Successful Response",
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
+ responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
deprecated: Optional[bool] = None,
- methods: Optional[List[str]] = None,
+ methods: Optional[list[str]] = None,
operation_id: Optional[str] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -1219,9 +1215,9 @@ class FastAPI(Starlette):
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
- response_class: Type[Response] = Default(JSONResponse),
+ response_class: type[Response] = Default(JSONResponse),
name: Optional[str] = None,
- openapi_extra: Optional[Dict[str, Any]] = None,
+ openapi_extra: Optional[dict[str, Any]] = None,
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
generate_unique_id
),
@@ -1343,7 +1339,7 @@ class FastAPI(Starlette):
*,
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to all the *path operations* in this
@@ -1385,7 +1381,7 @@ class FastAPI(Starlette):
),
] = None,
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses to be shown in OpenAPI.
@@ -1452,7 +1448,7 @@ class FastAPI(Starlette):
),
] = True,
default_response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Default response class to be used for the *path operations* in this
@@ -1480,7 +1476,7 @@ class FastAPI(Starlette):
),
] = Default(JSONResponse),
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -1603,7 +1599,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -1669,7 +1665,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -1810,7 +1806,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -1831,7 +1827,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -1847,7 +1843,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -1976,7 +1972,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2042,7 +2038,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2183,7 +2179,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2204,7 +2200,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2220,7 +2216,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -2354,7 +2350,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2420,7 +2416,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2561,7 +2557,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2582,7 +2578,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2598,7 +2594,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -2732,7 +2728,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2798,7 +2794,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2939,7 +2935,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2960,7 +2956,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2976,7 +2972,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3105,7 +3101,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3171,7 +3167,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -3312,7 +3308,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -3333,7 +3329,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -3349,7 +3345,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3478,7 +3474,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3544,7 +3540,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -3685,7 +3681,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -3706,7 +3702,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -3722,7 +3718,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3851,7 +3847,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3917,7 +3913,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -4058,7 +4054,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -4079,7 +4075,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -4095,7 +4091,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -4229,7 +4225,7 @@ class FastAPI(Starlette):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -4295,7 +4291,7 @@ class FastAPI(Starlette):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -4436,7 +4432,7 @@ class FastAPI(Starlette):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -4457,7 +4453,7 @@ class FastAPI(Starlette):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -4473,7 +4469,7 @@ class FastAPI(Starlette):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -4628,7 +4624,7 @@ class FastAPI(Starlette):
def exception_handler(
self,
exc_class_or_status_code: Annotated[
- Union[int, Type[Exception]],
+ Union[int, type[Exception]],
Doc(
"""
The Exception class this would handle, or a status code.
diff --git a/fastapi/background.py b/fastapi/background.py
index 6d4a30d442..20803ba670 100644
--- a/fastapi/background.py
+++ b/fastapi/background.py
@@ -1,8 +1,8 @@
-from typing import Any, Callable
+from typing import Annotated, Any, Callable
from annotated_doc import Doc
from starlette.background import BackgroundTasks as StarletteBackgroundTasks
-from typing_extensions import Annotated, ParamSpec
+from typing_extensions import ParamSpec
P = ParamSpec("P")
diff --git a/fastapi/concurrency.py b/fastapi/concurrency.py
index 3202c70789..76a5a2eb12 100644
--- a/fastapi/concurrency.py
+++ b/fastapi/concurrency.py
@@ -1,5 +1,7 @@
+from collections.abc import AsyncGenerator
+from contextlib import AbstractContextManager
from contextlib import asynccontextmanager as asynccontextmanager
-from typing import AsyncGenerator, ContextManager, TypeVar
+from typing import TypeVar
import anyio.to_thread
from anyio import CapacityLimiter
@@ -14,7 +16,7 @@ _T = TypeVar("_T")
@asynccontextmanager
async def contextmanager_in_threadpool(
- cm: ContextManager[_T],
+ cm: AbstractContextManager[_T],
) -> AsyncGenerator[_T, None]:
# blocking __exit__ from running waiting on a free thread
# can create race conditions/deadlocks if the context manager itself
diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py
index 8ad9aa11a6..b38a326def 100644
--- a/fastapi/datastructures.py
+++ b/fastapi/datastructures.py
@@ -1,11 +1,10 @@
+from collections.abc import Iterable
from typing import (
+ Annotated,
Any,
BinaryIO,
Callable,
- Dict,
- Iterable,
Optional,
- Type,
TypeVar,
cast,
)
@@ -23,7 +22,6 @@ from starlette.datastructures import Headers as Headers # noqa: F401
from starlette.datastructures import QueryParams as QueryParams # noqa: F401
from starlette.datastructures import State as State # noqa: F401
from starlette.datastructures import UploadFile as StarletteUploadFile
-from typing_extensions import Annotated
class UploadFile(StarletteUploadFile):
@@ -138,11 +136,11 @@ class UploadFile(StarletteUploadFile):
return await super().close()
@classmethod
- def __get_validators__(cls: Type["UploadFile"]) -> Iterable[Callable[..., Any]]:
+ def __get_validators__(cls: type["UploadFile"]) -> Iterable[Callable[..., Any]]:
yield cls.validate
@classmethod
- def validate(cls: Type["UploadFile"], v: Any) -> Any:
+ def validate(cls: type["UploadFile"], v: Any) -> Any:
if not isinstance(v, StarletteUploadFile):
raise ValueError(f"Expected UploadFile, received: {type(v)}")
return v
@@ -155,7 +153,7 @@ class UploadFile(StarletteUploadFile):
# TODO: remove when deprecating Pydantic v1
@classmethod
- def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
+ def __modify_schema__(cls, field_schema: dict[str, Any]) -> None:
field_schema.update({"type": "string", "format": "binary"})
@classmethod
@@ -166,7 +164,7 @@ class UploadFile(StarletteUploadFile):
@classmethod
def __get_pydantic_core_schema__(
- cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
+ cls, source: type[Any], handler: Callable[[Any], CoreSchema]
) -> CoreSchema:
from ._compat.v2 import with_info_plain_validator_function
diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py
index 6c4bf18b37..58392326d6 100644
--- a/fastapi/dependencies/models.py
+++ b/fastapi/dependencies/models.py
@@ -2,7 +2,7 @@ import inspect
import sys
from dataclasses import dataclass, field
from functools import cached_property, partial
-from typing import Any, Callable, List, Optional, Union
+from typing import Any, Callable, Optional, Union
from fastapi._compat import ModelField
from fastapi.security.base import SecurityBase
@@ -30,12 +30,12 @@ def _impartial(func: Callable[..., Any]) -> Callable[..., Any]:
@dataclass
class Dependant:
- path_params: List[ModelField] = field(default_factory=list)
- query_params: List[ModelField] = field(default_factory=list)
- header_params: List[ModelField] = field(default_factory=list)
- cookie_params: List[ModelField] = field(default_factory=list)
- body_params: List[ModelField] = field(default_factory=list)
- dependencies: List["Dependant"] = field(default_factory=list)
+ path_params: list[ModelField] = field(default_factory=list)
+ query_params: list[ModelField] = field(default_factory=list)
+ header_params: list[ModelField] = field(default_factory=list)
+ cookie_params: list[ModelField] = field(default_factory=list)
+ body_params: list[ModelField] = field(default_factory=list)
+ dependencies: list["Dependant"] = field(default_factory=list)
name: Optional[str] = None
call: Optional[Callable[..., Any]] = None
request_param_name: Optional[str] = None
@@ -44,14 +44,14 @@ class Dependant:
response_param_name: Optional[str] = None
background_tasks_param_name: Optional[str] = None
security_scopes_param_name: Optional[str] = None
- own_oauth_scopes: Optional[List[str]] = None
- parent_oauth_scopes: Optional[List[str]] = None
+ own_oauth_scopes: Optional[list[str]] = None
+ parent_oauth_scopes: Optional[list[str]] = None
use_cache: bool = True
path: Optional[str] = None
scope: Union[Literal["function", "request"], None] = None
@cached_property
- def oauth_scopes(self) -> List[str]:
+ def oauth_scopes(self) -> list[str]:
scopes = self.parent_oauth_scopes.copy() if self.parent_oauth_scopes else []
# This doesn't use a set to preserve order, just in case
for scope in self.own_oauth_scopes or []:
@@ -98,7 +98,7 @@ class Dependant:
return unwrapped
@cached_property
- def _security_dependencies(self) -> List["Dependant"]:
+ def _security_dependencies(self) -> list["Dependant"]:
security_deps = [dep for dep in self.dependencies if dep._is_security_scheme]
return security_deps
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index daaf6a9904..706533055c 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -1,21 +1,16 @@
import dataclasses
import inspect
import sys
+from collections.abc import Coroutine, Mapping, Sequence
from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy
from dataclasses import dataclass
from typing import (
+ Annotated,
Any,
Callable,
- Coroutine,
- Dict,
ForwardRef,
- List,
- Mapping,
Optional,
- Sequence,
- Tuple,
- Type,
Union,
cast,
)
@@ -75,7 +70,7 @@ from starlette.datastructures import (
from starlette.requests import HTTPConnection, Request
from starlette.responses import Response
from starlette.websockets import WebSocket
-from typing_extensions import Annotated, Literal, get_args, get_origin
+from typing_extensions import Literal, get_args, get_origin
from .. import temp_pydantic_v1_params
@@ -125,7 +120,7 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De
assert callable(depends.dependency), (
"A parameter-less dependency must have a callable dependency"
)
- own_oauth_scopes: List[str] = []
+ own_oauth_scopes: list[str] = []
if isinstance(depends, params.Security) and depends.scopes:
own_oauth_scopes.extend(depends.scopes)
return get_dependant(
@@ -140,8 +135,8 @@ def get_flat_dependant(
dependant: Dependant,
*,
skip_repeats: bool = False,
- visited: Optional[List[DependencyCacheKey]] = None,
- parent_oauth_scopes: Optional[List[str]] = None,
+ visited: Optional[list[DependencyCacheKey]] = None,
+ parent_oauth_scopes: Optional[list[str]] = None,
) -> Dependant:
if visited is None:
visited = []
@@ -190,7 +185,7 @@ def get_flat_dependant(
return flat_dependant
-def _get_flat_fields_from_params(fields: List[ModelField]) -> List[ModelField]:
+def _get_flat_fields_from_params(fields: list[ModelField]) -> list[ModelField]:
if not fields:
return fields
first_field = fields[0]
@@ -200,7 +195,7 @@ def _get_flat_fields_from_params(fields: List[ModelField]) -> List[ModelField]:
return fields
-def get_flat_params(dependant: Dependant) -> List[ModelField]:
+def get_flat_params(dependant: Dependant) -> list[ModelField]:
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
path_params = _get_flat_fields_from_params(flat_dependant.path_params)
query_params = _get_flat_fields_from_params(flat_dependant.query_params)
@@ -255,7 +250,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
return typed_signature
-def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
+def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any:
if isinstance(annotation, str):
# Special handling for Annotated types with forward references
# When using `from __future__ import annotations`, the entire annotation
@@ -387,8 +382,8 @@ def get_dependant(
path: str,
call: Callable[..., Any],
name: Optional[str] = None,
- own_oauth_scopes: Optional[List[str]] = None,
- parent_oauth_scopes: Optional[List[str]] = None,
+ own_oauth_scopes: Optional[list[str]] = None,
+ parent_oauth_scopes: Optional[list[str]] = None,
use_cache: bool = True,
scope: Union[Literal["function", "request"], None] = None,
) -> Dependant:
@@ -425,7 +420,7 @@ def get_dependant(
f'The dependency "{dependant.call.__name__}" has a scope of '
'"request", it cannot depend on dependencies with scope "function".'
)
- sub_own_oauth_scopes: List[str] = []
+ sub_own_oauth_scopes: list[str] = []
if isinstance(param_details.depends, params.Security):
if param_details.depends.scopes:
sub_own_oauth_scopes = list(param_details.depends.scopes)
@@ -694,7 +689,7 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
async def _solve_generator(
- *, dependant: Dependant, stack: AsyncExitStack, sub_values: Dict[str, Any]
+ *, dependant: Dependant, stack: AsyncExitStack, sub_values: dict[str, Any]
) -> Any:
assert dependant.call
if dependant.is_async_gen_callable:
@@ -706,22 +701,22 @@ async def _solve_generator(
@dataclass
class SolvedDependency:
- values: Dict[str, Any]
- errors: List[Any]
+ values: dict[str, Any]
+ errors: list[Any]
background_tasks: Optional[StarletteBackgroundTasks]
response: Response
- dependency_cache: Dict[DependencyCacheKey, Any]
+ dependency_cache: dict[DependencyCacheKey, Any]
async def solve_dependencies(
*,
request: Union[Request, WebSocket],
dependant: Dependant,
- body: Optional[Union[Dict[str, Any], FormData]] = None,
+ body: Optional[Union[dict[str, Any], FormData]] = None,
background_tasks: Optional[StarletteBackgroundTasks] = None,
response: Optional[Response] = None,
dependency_overrides_provider: Optional[Any] = None,
- dependency_cache: Optional[Dict[DependencyCacheKey, Any]] = None,
+ dependency_cache: Optional[dict[DependencyCacheKey, Any]] = None,
# TODO: remove this parameter later, no longer used, not removing it yet as some
# people might be monkey patching this function (although that's not supported)
async_exit_stack: AsyncExitStack,
@@ -735,8 +730,8 @@ async def solve_dependencies(
assert isinstance(function_astack, AsyncExitStack), (
"fastapi_function_astack not found in request scope"
)
- values: Dict[str, Any] = {}
- errors: List[Any] = []
+ values: dict[str, Any] = {}
+ errors: list[Any] = []
if response is None:
response = Response()
del response.headers["content-length"]
@@ -854,8 +849,8 @@ async def solve_dependencies(
def _validate_value_with_model_field(
- *, field: ModelField, value: Any, values: Dict[str, Any], loc: Tuple[str, ...]
-) -> Tuple[Any, List[Any]]:
+ *, field: ModelField, value: Any, values: dict[str, Any], loc: tuple[str, ...]
+) -> tuple[Any, list[Any]]:
if value is None:
if field.required:
return None, [get_missing_field_error(loc=loc)]
@@ -898,9 +893,9 @@ def _get_multidict_value(
def request_params_to_args(
fields: Sequence[ModelField],
received_params: Union[Mapping[str, Any], QueryParams, Headers],
-) -> Tuple[Dict[str, Any], List[Any]]:
- values: Dict[str, Any] = {}
- errors: List[Dict[str, Any]] = []
+) -> tuple[dict[str, Any], list[Any]]:
+ values: dict[str, Any] = {}
+ errors: list[dict[str, Any]] = []
if not fields:
return values, errors
@@ -918,7 +913,7 @@ def request_params_to_args(
first_field.field_info, "convert_underscores", True
)
- params_to_process: Dict[str, Any] = {}
+ params_to_process: dict[str, Any] = {}
processed_keys = set()
@@ -955,7 +950,7 @@ def request_params_to_args(
assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (
"Params must be subclasses of Param"
)
- loc: Tuple[str, ...] = (field_info.in_.value,)
+ loc: tuple[str, ...] = (field_info.in_.value,)
v_, errors_ = _validate_value_with_model_field(
field=first_field, value=params_to_process, values=values, loc=loc
)
@@ -997,7 +992,7 @@ def is_union_of_base_models(field_type: Any) -> bool:
return True
-def _should_embed_body_fields(fields: List[ModelField]) -> bool:
+def _should_embed_body_fields(fields: list[ModelField]) -> bool:
if not fields:
return False
# More than one dependency could have the same field, it would show up as multiple
@@ -1022,9 +1017,9 @@ def _should_embed_body_fields(fields: List[ModelField]) -> bool:
async def _extract_form_body(
- body_fields: List[ModelField],
+ body_fields: list[ModelField],
received_body: FormData,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
values = {}
for field in body_fields:
@@ -1042,8 +1037,8 @@ async def _extract_form_body(
and value_is_sequence(value)
):
# For types
- assert isinstance(value, sequence_types) # type: ignore[arg-type]
- results: List[Union[bytes, str]] = []
+ assert isinstance(value, sequence_types)
+ results: list[Union[bytes, str]] = []
async def process_fn(
fn: Callable[[], Coroutine[Any, Any, Any]],
@@ -1069,18 +1064,18 @@ async def _extract_form_body(
async def request_body_to_args(
- body_fields: List[ModelField],
- received_body: Optional[Union[Dict[str, Any], FormData]],
+ body_fields: list[ModelField],
+ received_body: Optional[Union[dict[str, Any], FormData]],
embed_body_fields: bool,
-) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
- values: Dict[str, Any] = {}
- errors: List[Dict[str, Any]] = []
+) -> tuple[dict[str, Any], list[dict[str, Any]]]:
+ values: dict[str, Any] = {}
+ errors: list[dict[str, Any]] = []
assert body_fields, "request_body_to_args() should be called with fields"
single_not_embedded_field = len(body_fields) == 1 and not embed_body_fields
first_field = body_fields[0]
body_to_process = received_body
- fields_to_extract: List[ModelField] = body_fields
+ fields_to_extract: list[ModelField] = body_fields
if (
single_not_embedded_field
@@ -1093,7 +1088,7 @@ async def request_body_to_args(
body_to_process = await _extract_form_body(fields_to_extract, received_body)
if single_not_embedded_field:
- loc: Tuple[str, ...] = ("body",)
+ loc: tuple[str, ...] = ("body",)
v_, errors_ = _validate_value_with_model_field(
field=first_field, value=body_to_process, values=values, loc=loc
)
@@ -1141,19 +1136,19 @@ def get_body_field(
fields=flat_dependant.body_params, model_name=model_name
)
required = any(True for f in flat_dependant.body_params if f.required)
- BodyFieldInfo_kwargs: Dict[str, Any] = {
+ BodyFieldInfo_kwargs: dict[str, Any] = {
"annotation": BodyModel,
"alias": "body",
}
if not required:
BodyFieldInfo_kwargs["default"] = None
if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params):
- BodyFieldInfo: Type[params.Body] = params.File
+ BodyFieldInfo: type[params.Body] = params.File
elif any(
isinstance(f.field_info, temp_pydantic_v1_params.File)
for f in flat_dependant.body_params
):
- BodyFieldInfo: Type[temp_pydantic_v1_params.Body] = temp_pydantic_v1_params.File # type: ignore[no-redef]
+ BodyFieldInfo: type[temp_pydantic_v1_params.Body] = temp_pydantic_v1_params.File # type: ignore[no-redef]
elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params):
BodyFieldInfo = params.Form
elif any(
diff --git a/fastapi/encoders.py b/fastapi/encoders.py
index 7939510895..cbeeee4559 100644
--- a/fastapi/encoders.py
+++ b/fastapi/encoders.py
@@ -14,7 +14,7 @@ from ipaddress import (
from pathlib import Path, PurePath
from re import Pattern
from types import GeneratorType
-from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
+from typing import Annotated, Any, Callable, Optional, Union
from uuid import UUID
from annotated_doc import Doc
@@ -24,7 +24,6 @@ from pydantic import BaseModel
from pydantic.color import Color
from pydantic.networks import AnyUrl, NameEmail
from pydantic.types import SecretBytes, SecretStr
-from typing_extensions import Annotated
from ._compat import Url, _is_undefined, _model_dump
@@ -61,7 +60,7 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
return float(dec_value)
-ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
+ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = {
bytes: lambda o: o.decode(),
Color: str,
may_v1.Color: str,
@@ -98,9 +97,9 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
def generate_encoders_by_class_tuples(
- type_encoder_map: Dict[Any, Callable[[Any], Any]],
-) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
- encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
+ type_encoder_map: dict[Any, Callable[[Any], Any]],
+) -> dict[Callable[[Any], Any], tuple[Any, ...]]:
+ encoders_by_class_tuples: dict[Callable[[Any], Any], tuple[Any, ...]] = defaultdict(
tuple
)
for type_, encoder in type_encoder_map.items():
@@ -180,7 +179,7 @@ def jsonable_encoder(
),
] = False,
custom_encoder: Annotated[
- Optional[Dict[Any, Callable[[Any], Any]]],
+ Optional[dict[Any, Callable[[Any], Any]]],
Doc(
"""
Pydantic's `custom_encoder` parameter, passed to Pydantic models to define
@@ -227,7 +226,7 @@ def jsonable_encoder(
exclude = set(exclude)
if isinstance(obj, (BaseModel, may_v1.BaseModel)):
# TODO: remove when deprecating Pydantic v1
- encoders: Dict[Any, Any] = {}
+ encoders: dict[Any, Any] = {}
if isinstance(obj, may_v1.BaseModel):
encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined]
if custom_encoder:
@@ -336,7 +335,7 @@ def jsonable_encoder(
try:
data = dict(obj)
except Exception as e:
- errors: List[Exception] = []
+ errors: list[Exception] = []
errors.append(e)
try:
data = vars(obj)
diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py
index a46e823506..8e0c559023 100644
--- a/fastapi/exceptions.py
+++ b/fastapi/exceptions.py
@@ -1,10 +1,10 @@
-from typing import Any, Dict, Optional, Sequence, Type, TypedDict, Union
+from collections.abc import Sequence
+from typing import Annotated, Any, Optional, TypedDict, Union
from annotated_doc import Doc
from pydantic import BaseModel, create_model
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.exceptions import WebSocketException as StarletteWebSocketException
-from typing_extensions import Annotated
class EndpointContext(TypedDict, total=False):
@@ -62,7 +62,7 @@ class HTTPException(StarletteHTTPException):
),
] = None,
headers: Annotated[
- Optional[Dict[str, str]],
+ Optional[dict[str, str]],
Doc(
"""
Any headers to send to the client in the response.
@@ -144,8 +144,8 @@ class WebSocketException(StarletteWebSocketException):
super().__init__(code=code, reason=reason)
-RequestErrorModel: Type[BaseModel] = create_model("Request")
-WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket")
+RequestErrorModel: type[BaseModel] = create_model("Request")
+WebSocketErrorModel: type[BaseModel] = create_model("WebSocket")
class FastAPIError(RuntimeError):
diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py
index 74b23a3706..82380f85d9 100644
--- a/fastapi/openapi/docs.py
+++ b/fastapi/openapi/docs.py
@@ -1,13 +1,12 @@
import json
-from typing import Any, Dict, Optional
+from typing import Annotated, Any, Optional
from annotated_doc import Doc
from fastapi.encoders import jsonable_encoder
from starlette.responses import HTMLResponse
-from typing_extensions import Annotated
swagger_ui_default_parameters: Annotated[
- Dict[str, Any],
+ dict[str, Any],
Doc(
"""
Default configurations for Swagger UI.
@@ -82,7 +81,7 @@ def get_swagger_ui_html(
),
] = None,
init_oauth: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
A dictionary with Swagger UI OAuth2 initialization configurations.
@@ -90,7 +89,7 @@ def get_swagger_ui_html(
),
] = None,
swagger_ui_parameters: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Configuration parameters for Swagger UI.
diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py
index 81d276aed6..7aa80f5cb0 100644
--- a/fastapi/openapi/models.py
+++ b/fastapi/openapi/models.py
@@ -1,5 +1,6 @@
+from collections.abc import Iterable
from enum import Enum
-from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Type, Union
+from typing import Annotated, Any, Callable, Optional, Union
from fastapi._compat import (
PYDANTIC_V2,
@@ -11,7 +12,7 @@ from fastapi._compat import (
)
from fastapi.logger import logger
from pydantic import AnyUrl, BaseModel, Field
-from typing_extensions import Annotated, Literal, TypedDict
+from typing_extensions import Literal, TypedDict
from typing_extensions import deprecated as typing_deprecated
try:
@@ -50,7 +51,7 @@ except ImportError: # pragma: no cover
@classmethod
def __get_pydantic_core_schema__(
- cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
+ cls, source: type[Any], handler: Callable[[Any], CoreSchema]
) -> CoreSchema:
return with_info_plain_validator_function(cls._validate)
@@ -88,7 +89,7 @@ class Info(BaseModelWithConfig):
class ServerVariable(BaseModelWithConfig):
- enum: Annotated[Optional[List[str]], Field(min_length=1)] = None
+ enum: Annotated[Optional[list[str]], Field(min_length=1)] = None
default: str
description: Optional[str] = None
@@ -96,7 +97,7 @@ class ServerVariable(BaseModelWithConfig):
class Server(BaseModelWithConfig):
url: Union[AnyUrl, str]
description: Optional[str] = None
- variables: Optional[Dict[str, ServerVariable]] = None
+ variables: Optional[dict[str, ServerVariable]] = None
class Reference(BaseModel):
@@ -105,7 +106,7 @@ class Reference(BaseModel):
class Discriminator(BaseModel):
propertyName: str
- mapping: Optional[Dict[str, str]] = None
+ mapping: Optional[dict[str, str]] = None
class XML(BaseModelWithConfig):
@@ -137,34 +138,34 @@ class Schema(BaseModelWithConfig):
dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor")
ref: Optional[str] = Field(default=None, alias="$ref")
dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef")
- defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
+ defs: Optional[dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
comment: Optional[str] = Field(default=None, alias="$comment")
# Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s
# A Vocabulary for Applying Subschemas
- allOf: Optional[List["SchemaOrBool"]] = None
- anyOf: Optional[List["SchemaOrBool"]] = None
- oneOf: Optional[List["SchemaOrBool"]] = None
+ allOf: Optional[list["SchemaOrBool"]] = None
+ anyOf: Optional[list["SchemaOrBool"]] = None
+ oneOf: Optional[list["SchemaOrBool"]] = None
not_: Optional["SchemaOrBool"] = Field(default=None, alias="not")
if_: Optional["SchemaOrBool"] = Field(default=None, alias="if")
then: Optional["SchemaOrBool"] = None
else_: Optional["SchemaOrBool"] = Field(default=None, alias="else")
- dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None
- prefixItems: Optional[List["SchemaOrBool"]] = None
+ dependentSchemas: Optional[dict[str, "SchemaOrBool"]] = None
+ prefixItems: Optional[list["SchemaOrBool"]] = None
# TODO: uncomment and remove below when deprecating Pydantic v1
# It generates a list of schemas for tuples, before prefixItems was available
# items: Optional["SchemaOrBool"] = None
- items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None
+ items: Optional[Union["SchemaOrBool", list["SchemaOrBool"]]] = None
contains: Optional["SchemaOrBool"] = None
- properties: Optional[Dict[str, "SchemaOrBool"]] = None
- patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None
+ properties: Optional[dict[str, "SchemaOrBool"]] = None
+ patternProperties: Optional[dict[str, "SchemaOrBool"]] = None
additionalProperties: Optional["SchemaOrBool"] = None
propertyNames: Optional["SchemaOrBool"] = None
unevaluatedItems: Optional["SchemaOrBool"] = None
unevaluatedProperties: Optional["SchemaOrBool"] = None
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
# A Vocabulary for Structural Validation
- type: Optional[Union[SchemaType, List[SchemaType]]] = None
- enum: Optional[List[Any]] = None
+ type: Optional[Union[SchemaType, list[SchemaType]]] = None
+ enum: Optional[list[Any]] = None
const: Optional[Any] = None
multipleOf: Optional[float] = Field(default=None, gt=0)
maximum: Optional[float] = None
@@ -181,8 +182,8 @@ class Schema(BaseModelWithConfig):
minContains: Optional[int] = Field(default=None, ge=0)
maxProperties: Optional[int] = Field(default=None, ge=0)
minProperties: Optional[int] = Field(default=None, ge=0)
- required: Optional[List[str]] = None
- dependentRequired: Optional[Dict[str, Set[str]]] = None
+ required: Optional[list[str]] = None
+ dependentRequired: Optional[dict[str, set[str]]] = None
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c
# Vocabularies for Semantic Content With "format"
format: Optional[str] = None
@@ -199,7 +200,7 @@ class Schema(BaseModelWithConfig):
deprecated: Optional[bool] = None
readOnly: Optional[bool] = None
writeOnly: Optional[bool] = None
- examples: Optional[List[Any]] = None
+ examples: Optional[list[Any]] = None
# Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object
# Schema Object
discriminator: Optional[Discriminator] = None
@@ -243,7 +244,7 @@ class ParameterInType(Enum):
class Encoding(BaseModelWithConfig):
contentType: Optional[str] = None
- headers: Optional[Dict[str, Union["Header", Reference]]] = None
+ headers: Optional[dict[str, Union["Header", Reference]]] = None
style: Optional[str] = None
explode: Optional[bool] = None
allowReserved: Optional[bool] = None
@@ -252,8 +253,8 @@ class Encoding(BaseModelWithConfig):
class MediaType(BaseModelWithConfig):
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
example: Optional[Any] = None
- examples: Optional[Dict[str, Union[Example, Reference]]] = None
- encoding: Optional[Dict[str, Encoding]] = None
+ examples: Optional[dict[str, Union[Example, Reference]]] = None
+ encoding: Optional[dict[str, Encoding]] = None
class ParameterBase(BaseModelWithConfig):
@@ -266,9 +267,9 @@ class ParameterBase(BaseModelWithConfig):
allowReserved: Optional[bool] = None
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
example: Optional[Any] = None
- examples: Optional[Dict[str, Union[Example, Reference]]] = None
+ examples: Optional[dict[str, Union[Example, Reference]]] = None
# Serialization rules for more complex scenarios
- content: Optional[Dict[str, MediaType]] = None
+ content: Optional[dict[str, MediaType]] = None
class Parameter(ParameterBase):
@@ -282,14 +283,14 @@ class Header(ParameterBase):
class RequestBody(BaseModelWithConfig):
description: Optional[str] = None
- content: Dict[str, MediaType]
+ content: dict[str, MediaType]
required: Optional[bool] = None
class Link(BaseModelWithConfig):
operationRef: Optional[str] = None
operationId: Optional[str] = None
- parameters: Optional[Dict[str, Union[Any, str]]] = None
+ parameters: Optional[dict[str, Union[Any, str]]] = None
requestBody: Optional[Union[Any, str]] = None
description: Optional[str] = None
server: Optional[Server] = None
@@ -297,25 +298,25 @@ class Link(BaseModelWithConfig):
class Response(BaseModelWithConfig):
description: str
- headers: Optional[Dict[str, Union[Header, Reference]]] = None
- content: Optional[Dict[str, MediaType]] = None
- links: Optional[Dict[str, Union[Link, Reference]]] = None
+ headers: Optional[dict[str, Union[Header, Reference]]] = None
+ content: Optional[dict[str, MediaType]] = None
+ links: Optional[dict[str, Union[Link, Reference]]] = None
class Operation(BaseModelWithConfig):
- tags: Optional[List[str]] = None
+ tags: Optional[list[str]] = None
summary: Optional[str] = None
description: Optional[str] = None
externalDocs: Optional[ExternalDocumentation] = None
operationId: Optional[str] = None
- parameters: Optional[List[Union[Parameter, Reference]]] = None
+ parameters: Optional[list[Union[Parameter, Reference]]] = None
requestBody: Optional[Union[RequestBody, Reference]] = None
# Using Any for Specification Extensions
- responses: Optional[Dict[str, Union[Response, Any]]] = None
- callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None
+ responses: Optional[dict[str, Union[Response, Any]]] = None
+ callbacks: Optional[dict[str, Union[dict[str, "PathItem"], Reference]]] = None
deprecated: Optional[bool] = None
- security: Optional[List[Dict[str, List[str]]]] = None
- servers: Optional[List[Server]] = None
+ security: Optional[list[dict[str, list[str]]]] = None
+ servers: Optional[list[Server]] = None
class PathItem(BaseModelWithConfig):
@@ -330,8 +331,8 @@ class PathItem(BaseModelWithConfig):
head: Optional[Operation] = None
patch: Optional[Operation] = None
trace: Optional[Operation] = None
- servers: Optional[List[Server]] = None
- parameters: Optional[List[Union[Parameter, Reference]]] = None
+ servers: Optional[list[Server]] = None
+ parameters: Optional[list[Union[Parameter, Reference]]] = None
class SecuritySchemeType(Enum):
@@ -370,7 +371,7 @@ class HTTPBearer(HTTPBase):
class OAuthFlow(BaseModelWithConfig):
refreshUrl: Optional[str] = None
- scopes: Dict[str, str] = {}
+ scopes: dict[str, str] = {}
class OAuthFlowImplicit(OAuthFlow):
@@ -413,17 +414,17 @@ SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer]
class Components(BaseModelWithConfig):
- schemas: Optional[Dict[str, Union[Schema, Reference]]] = None
- responses: Optional[Dict[str, Union[Response, Reference]]] = None
- parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None
- examples: Optional[Dict[str, Union[Example, Reference]]] = None
- requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None
- headers: Optional[Dict[str, Union[Header, Reference]]] = None
- securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None
- links: Optional[Dict[str, Union[Link, Reference]]] = None
+ schemas: Optional[dict[str, Union[Schema, Reference]]] = None
+ responses: Optional[dict[str, Union[Response, Reference]]] = None
+ parameters: Optional[dict[str, Union[Parameter, Reference]]] = None
+ examples: Optional[dict[str, Union[Example, Reference]]] = None
+ requestBodies: Optional[dict[str, Union[RequestBody, Reference]]] = None
+ headers: Optional[dict[str, Union[Header, Reference]]] = None
+ securitySchemes: Optional[dict[str, Union[SecurityScheme, Reference]]] = None
+ links: Optional[dict[str, Union[Link, Reference]]] = None
# Using Any for Specification Extensions
- callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None
- pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None
+ callbacks: Optional[dict[str, Union[dict[str, PathItem], Reference, Any]]] = None
+ pathItems: Optional[dict[str, Union[PathItem, Reference]]] = None
class Tag(BaseModelWithConfig):
@@ -436,13 +437,13 @@ class OpenAPI(BaseModelWithConfig):
openapi: str
info: Info
jsonSchemaDialect: Optional[str] = None
- servers: Optional[List[Server]] = None
+ servers: Optional[list[Server]] = None
# Using Any for Specification Extensions
- paths: Optional[Dict[str, Union[PathItem, Any]]] = None
- webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None
+ paths: Optional[dict[str, Union[PathItem, Any]]] = None
+ webhooks: Optional[dict[str, Union[PathItem, Reference]]] = None
components: Optional[Components] = None
- security: Optional[List[Dict[str, List[str]]]] = None
- tags: Optional[List[Tag]] = None
+ security: Optional[list[dict[str, list[str]]]] = None
+ tags: Optional[list[Tag]] = None
externalDocs: Optional[ExternalDocumentation] = None
diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py
index 9fe2044f26..a99d4188e7 100644
--- a/fastapi/openapi/utils.py
+++ b/fastapi/openapi/utils.py
@@ -1,7 +1,8 @@
import http.client
import inspect
import warnings
-from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
+from collections.abc import Sequence
+from typing import Any, Optional, Union, cast
from fastapi import routing
from fastapi._compat import (
@@ -66,7 +67,7 @@ validation_error_response_definition = {
},
}
-status_code_ranges: Dict[str, str] = {
+status_code_ranges: dict[str, str] = {
"1XX": "Information",
"2XX": "Success",
"3XX": "Redirection",
@@ -78,10 +79,10 @@ status_code_ranges: Dict[str, str] = {
def get_openapi_security_definitions(
flat_dependant: Dependant,
-) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
+) -> tuple[dict[str, Any], list[dict[str, Any]]]:
security_definitions = {}
# Use a dict to merge scopes for same security scheme
- operation_security_dict: Dict[str, List[str]] = {}
+ operation_security_dict: dict[str, list[str]] = {}
for security_dependency in flat_dependant._security_dependencies:
security_definition = jsonable_encoder(
security_dependency._security_scheme.model,
@@ -106,11 +107,11 @@ def _get_openapi_operation_parameters(
*,
dependant: Dependant,
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
separate_input_output_schemas: bool = True,
-) -> List[Dict[str, Any]]:
+) -> list[dict[str, Any]]:
parameters = []
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
path_params = _get_flat_fields_from_params(flat_dependant.path_params)
@@ -179,11 +180,11 @@ def get_openapi_operation_request_body(
*,
body_field: Optional[ModelField],
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
separate_input_output_schemas: bool = True,
-) -> Optional[Dict[str, Any]]:
+) -> Optional[dict[str, Any]]:
if not body_field:
return None
assert _is_model_field(body_field)
@@ -196,10 +197,10 @@ def get_openapi_operation_request_body(
field_info = cast(Body, body_field.field_info)
request_media_type = field_info.media_type
required = body_field.required
- request_body_oai: Dict[str, Any] = {}
+ request_body_oai: dict[str, Any] = {}
if required:
request_body_oai["required"] = required
- request_media_content: Dict[str, Any] = {"schema": body_schema}
+ request_media_content: dict[str, Any] = {"schema": body_schema}
if field_info.openapi_examples:
request_media_content["examples"] = jsonable_encoder(
field_info.openapi_examples
@@ -232,9 +233,9 @@ def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str:
def get_openapi_operation_metadata(
- *, route: routing.APIRoute, method: str, operation_ids: Set[str]
-) -> Dict[str, Any]:
- operation: Dict[str, Any] = {}
+ *, route: routing.APIRoute, method: str, operation_ids: set[str]
+) -> dict[str, Any]:
+ operation: dict[str, Any] = {}
if route.tags:
operation["tags"] = route.tags
operation["summary"] = generate_operation_summary(route=route, method=method)
@@ -260,19 +261,19 @@ def get_openapi_operation_metadata(
def get_openapi_path(
*,
route: routing.APIRoute,
- operation_ids: Set[str],
+ operation_ids: set[str],
model_name_map: ModelNameMap,
- field_mapping: Dict[
- Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
+ field_mapping: dict[
+ tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
separate_input_output_schemas: bool = True,
-) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
+) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
path = {}
- security_schemes: Dict[str, Any] = {}
- definitions: Dict[str, Any] = {}
+ security_schemes: dict[str, Any] = {}
+ definitions: dict[str, Any] = {}
assert route.methods is not None, "Methods must be a list"
if isinstance(route.response_class, DefaultPlaceholder):
- current_response_class: Type[Response] = route.response_class.value
+ current_response_class: type[Response] = route.response_class.value
else:
current_response_class = route.response_class
assert current_response_class, "A response class is needed to generate OpenAPI"
@@ -282,7 +283,7 @@ def get_openapi_path(
operation = get_openapi_operation_metadata(
route=route, method=method, operation_ids=operation_ids
)
- parameters: List[Dict[str, Any]] = []
+ parameters: list[dict[str, Any]] = []
flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True)
security_definitions, operation_security = get_openapi_security_definitions(
flat_dependant=flat_dependant
@@ -390,7 +391,7 @@ def get_openapi_path(
"An additional response must be a dict"
)
field = route.response_fields.get(additional_status_code)
- additional_field_schema: Optional[Dict[str, Any]] = None
+ additional_field_schema: Optional[dict[str, Any]] = None
if field:
additional_field_schema = get_schema_from_model_field(
field=field,
@@ -445,11 +446,11 @@ def get_openapi_path(
def get_fields_from_routes(
routes: Sequence[BaseRoute],
-) -> List[ModelField]:
- body_fields_from_routes: List[ModelField] = []
- responses_from_routes: List[ModelField] = []
- request_fields_from_routes: List[ModelField] = []
- callback_flat_models: List[ModelField] = []
+) -> list[ModelField]:
+ body_fields_from_routes: list[ModelField] = []
+ responses_from_routes: list[ModelField] = []
+ request_fields_from_routes: list[ModelField] = []
+ callback_flat_models: list[ModelField] = []
for route in routes:
if getattr(route, "include_in_schema", None) and isinstance(
route, routing.APIRoute
@@ -483,15 +484,15 @@ def get_openapi(
description: Optional[str] = None,
routes: Sequence[BaseRoute],
webhooks: Optional[Sequence[BaseRoute]] = None,
- tags: Optional[List[Dict[str, Any]]] = None,
- servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
+ tags: Optional[list[dict[str, Any]]] = None,
+ servers: Optional[list[dict[str, Union[str, Any]]]] = None,
terms_of_service: Optional[str] = None,
- contact: Optional[Dict[str, Union[str, Any]]] = None,
- license_info: Optional[Dict[str, Union[str, Any]]] = None,
+ contact: Optional[dict[str, Union[str, Any]]] = None,
+ license_info: Optional[dict[str, Union[str, Any]]] = None,
separate_input_output_schemas: bool = True,
- external_docs: Optional[Dict[str, Any]] = None,
-) -> Dict[str, Any]:
- info: Dict[str, Any] = {"title": title, "version": version}
+ external_docs: Optional[dict[str, Any]] = None,
+) -> dict[str, Any]:
+ info: dict[str, Any] = {"title": title, "version": version}
if summary:
info["summary"] = summary
if description:
@@ -502,13 +503,13 @@ def get_openapi(
info["contact"] = contact
if license_info:
info["license"] = license_info
- output: Dict[str, Any] = {"openapi": openapi_version, "info": info}
+ output: dict[str, Any] = {"openapi": openapi_version, "info": info}
if servers:
output["servers"] = servers
- components: Dict[str, Dict[str, Any]] = {}
- paths: Dict[str, Dict[str, Any]] = {}
- webhook_paths: Dict[str, Dict[str, Any]] = {}
- operation_ids: Set[str] = set()
+ components: dict[str, dict[str, Any]] = {}
+ paths: dict[str, dict[str, Any]] = {}
+ webhook_paths: dict[str, dict[str, Any]] = {}
+ operation_ids: set[str] = set()
all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or []))
model_name_map = get_compat_model_name_map(all_fields)
field_mapping, definitions = get_definitions(
diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py
index e32f755933..844542594b 100644
--- a/fastapi/param_functions.py
+++ b/fastapi/param_functions.py
@@ -1,10 +1,11 @@
-from typing import Any, Callable, Dict, List, Optional, Sequence, Union
+from collections.abc import Sequence
+from typing import Annotated, Any, Callable, Optional, Union
from annotated_doc import Doc
from fastapi import params
from fastapi._compat import Undefined
from fastapi.openapi.models import Example
-from typing_extensions import Annotated, Literal, deprecated
+from typing_extensions import Literal, deprecated
_Unset: Any = Undefined
@@ -209,7 +210,7 @@ def Path( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -224,7 +225,7 @@ def Path( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -262,7 +263,7 @@ def Path( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -534,7 +535,7 @@ def Query( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -549,7 +550,7 @@ def Query( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -587,7 +588,7 @@ def Query( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -849,7 +850,7 @@ def Header( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -864,7 +865,7 @@ def Header( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -902,7 +903,7 @@ def Header( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -1154,7 +1155,7 @@ def Cookie( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -1169,7 +1170,7 @@ def Cookie( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -1207,7 +1208,7 @@ def Cookie( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -1481,7 +1482,7 @@ def Body( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -1496,7 +1497,7 @@ def Body( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -1534,7 +1535,7 @@ def Body( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -1796,7 +1797,7 @@ def Form( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -1811,7 +1812,7 @@ def Form( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -1849,7 +1850,7 @@ def Form( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
@@ -2110,7 +2111,7 @@ def File( # noqa: N802
),
] = _Unset,
examples: Annotated[
- Optional[List[Any]],
+ Optional[list[Any]],
Doc(
"""
Example values for this field.
@@ -2125,7 +2126,7 @@ def File( # noqa: N802
),
] = _Unset,
openapi_examples: Annotated[
- Optional[Dict[str, Example]],
+ Optional[dict[str, Example]],
Doc(
"""
OpenAPI-specific examples.
@@ -2163,7 +2164,7 @@ def File( # noqa: N802
),
] = True,
json_schema_extra: Annotated[
- Union[Dict[str, Any], None],
+ Union[dict[str, Any], None],
Doc(
"""
Any additional JSON schema data.
diff --git a/fastapi/params.py b/fastapi/params.py
index b6d0f08e31..4990d0e70e 100644
--- a/fastapi/params.py
+++ b/fastapi/params.py
@@ -1,11 +1,12 @@
import warnings
+from collections.abc import Sequence
from dataclasses import dataclass
from enum import Enum
-from typing import Any, Callable, Dict, List, Optional, Sequence, Union
+from typing import Annotated, Any, Callable, Optional, Union
from fastapi.openapi.models import Example
from pydantic.fields import FieldInfo
-from typing_extensions import Annotated, Literal, deprecated
+from typing_extensions import Literal, deprecated
from ._compat import (
PYDANTIC_V2,
@@ -59,7 +60,7 @@ class Param(FieldInfo): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -67,10 +68,10 @@ class Param(FieldInfo): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
if example is not _Unset:
@@ -177,7 +178,7 @@ class Path(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -185,10 +186,10 @@ class Path(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
assert default is ..., "Path parameters cannot have a default value"
@@ -263,7 +264,7 @@ class Query(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -271,10 +272,10 @@ class Query(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -348,7 +349,7 @@ class Header(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -356,10 +357,10 @@ class Header(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
self.convert_underscores = convert_underscores
@@ -433,7 +434,7 @@ class Cookie(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -441,10 +442,10 @@ class Cookie(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -517,7 +518,7 @@ class Body(FieldInfo): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -525,10 +526,10 @@ class Body(FieldInfo): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
self.embed = embed
@@ -637,7 +638,7 @@ class Form(Body): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -645,10 +646,10 @@ class Form(Body): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -721,7 +722,7 @@ class File(Form): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -729,10 +730,10 @@ class File(Form): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
diff --git a/fastapi/routing.py b/fastapi/routing.py
index 9be2b44bc1..fa6904a6b6 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -3,23 +3,21 @@ import email.message
import functools
import inspect
import json
+from collections.abc import (
+ AsyncIterator,
+ Awaitable,
+ Collection,
+ Coroutine,
+ Mapping,
+ Sequence,
+)
from contextlib import AsyncExitStack, asynccontextmanager
from enum import Enum, IntEnum
from typing import (
+ Annotated,
Any,
- AsyncIterator,
- Awaitable,
Callable,
- Collection,
- Coroutine,
- Dict,
- List,
- Mapping,
Optional,
- Sequence,
- Set,
- Tuple,
- Type,
Union,
)
@@ -77,7 +75,7 @@ from starlette.routing import (
from starlette.routing import Mount as Mount # noqa
from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send
from starlette.websockets import WebSocket
-from typing_extensions import Annotated, deprecated
+from typing_extensions import deprecated
# Copy of starlette.routing.request_response modified to include the
@@ -214,7 +212,7 @@ def _merge_lifespan_context(
# Cache for endpoint context to avoid re-extracting on every request
-_endpoint_context_cache: Dict[int, EndpointContext] = {}
+_endpoint_context_cache: dict[int, EndpointContext] = {}
def _extract_endpoint_context(func: Any) -> EndpointContext:
@@ -306,7 +304,7 @@ async def serialize_response(
async def run_endpoint_function(
- *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool
+ *, dependant: Dependant, values: dict[str, Any], is_coroutine: bool
) -> Any:
# Only called by get_request_handler. Has been split into its own function to
# facilitate profiling endpoints, since inner functions are harder to profile.
@@ -322,7 +320,7 @@ def get_request_handler(
dependant: Dependant,
body_field: Optional[ModelField] = None,
status_code: Optional[int] = None,
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
+ response_class: Union[type[Response], DefaultPlaceholder] = Default(JSONResponse),
response_field: Optional[ModelField] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -339,7 +337,7 @@ def get_request_handler(
body_field.field_info, (params.Form, temp_pydantic_v1_params.Form)
)
if isinstance(response_class, DefaultPlaceholder):
- actual_response_class: Type[Response] = response_class.value
+ actual_response_class: type[Response] = response_class.value
else:
actual_response_class = response_class
@@ -412,7 +410,7 @@ def get_request_handler(
raise http_error from e
# Solve dependencies and run path operation function, auto-closing dependencies
- errors: List[Any] = []
+ errors: list[Any] = []
async_exit_stack = request.scope.get("fastapi_inner_astack")
assert isinstance(async_exit_stack, AsyncExitStack), (
"fastapi_inner_astack not found in request scope"
@@ -437,7 +435,7 @@ def get_request_handler(
raw_response.background = solved_result.background_tasks
response = raw_response
else:
- response_args: Dict[str, Any] = {
+ response_args: dict[str, Any] = {
"background": solved_result.background_tasks
}
# If status_code was set, use it, otherwise use the default from the
@@ -550,7 +548,7 @@ class APIWebSocketRoute(routing.WebSocketRoute):
)
)
- def matches(self, scope: Scope) -> Tuple[Match, Scope]:
+ def matches(self, scope: Scope) -> tuple[Match, Scope]:
match, child_scope = super().matches(scope)
if match != Match.NONE:
child_scope["route"] = self
@@ -565,15 +563,15 @@ class APIRoute(routing.Route):
*,
response_model: Any = Default(None),
status_code: Optional[int] = None,
- tags: Optional[List[Union[str, Enum]]] = None,
+ tags: Optional[list[Union[str, Enum]]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
response_description: str = "Successful Response",
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
+ responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
deprecated: Optional[bool] = None,
name: Optional[str] = None,
- methods: Optional[Union[Set[str], List[str]]] = None,
+ methods: Optional[Union[set[str], list[str]]] = None,
operation_id: Optional[str] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -582,12 +580,12 @@ class APIRoute(routing.Route):
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(
+ response_class: Union[type[Response], DefaultPlaceholder] = Default(
JSONResponse
),
dependency_overrides_provider: Optional[Any] = None,
- callbacks: Optional[List[BaseRoute]] = None,
- openapi_extra: Optional[Dict[str, Any]] = None,
+ callbacks: Optional[list[BaseRoute]] = None,
+ openapi_extra: Optional[dict[str, Any]] = None,
generate_unique_id_function: Union[
Callable[["APIRoute"], str], DefaultPlaceholder
] = Default(generate_unique_id),
@@ -623,7 +621,7 @@ class APIRoute(routing.Route):
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
if methods is None:
methods = ["GET"]
- self.methods: Set[str] = {method.upper() for method in methods}
+ self.methods: set[str] = {method.upper() for method in methods}
if isinstance(generate_unique_id_function, DefaultPlaceholder):
current_generate_unique_id: Callable[[APIRoute], str] = (
generate_unique_id_function.value
@@ -678,7 +676,7 @@ class APIRoute(routing.Route):
)
response_fields[additional_status_code] = response_field
if response_fields:
- self.response_fields: Dict[Union[int, str], ModelField] = response_fields
+ self.response_fields: dict[Union[int, str], ModelField] = response_fields
else:
self.response_fields = {}
@@ -719,7 +717,7 @@ class APIRoute(routing.Route):
embed_body_fields=self._embed_body_fields,
)
- def matches(self, scope: Scope) -> Tuple[Match, Scope]:
+ def matches(self, scope: Scope) -> tuple[Match, Scope]:
match, child_scope = super().matches(scope)
if match != Match.NONE:
child_scope["route"] = self
@@ -758,7 +756,7 @@ class APIRouter(routing.Router):
*,
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to all the *path operations* in this
@@ -784,7 +782,7 @@ class APIRouter(routing.Router):
),
] = None,
default_response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
The default response class to be used.
@@ -795,7 +793,7 @@ class APIRouter(routing.Router):
),
] = Default(JSONResponse),
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses to be shown in OpenAPI.
@@ -811,7 +809,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
OpenAPI callbacks that should apply to all *path operations* in this
@@ -825,7 +823,7 @@ class APIRouter(routing.Router):
),
] = None,
routes: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
**Note**: you probably shouldn't use this parameter, it is inherited
@@ -876,7 +874,7 @@ class APIRouter(routing.Router):
),
] = None,
route_class: Annotated[
- Type[APIRoute],
+ type[APIRoute],
Doc(
"""
Custom route (*path operation*) class to be used by this router.
@@ -982,7 +980,7 @@ class APIRouter(routing.Router):
"A path prefix must not end with '/', as the routes will start with '/'"
)
self.prefix = prefix
- self.tags: List[Union[str, Enum]] = tags or []
+ self.tags: list[Union[str, Enum]] = tags or []
self.dependencies = list(dependencies or [])
self.deprecated = deprecated
self.include_in_schema = include_in_schema
@@ -1019,14 +1017,14 @@ class APIRouter(routing.Router):
*,
response_model: Any = Default(None),
status_code: Optional[int] = None,
- tags: Optional[List[Union[str, Enum]]] = None,
+ tags: Optional[list[Union[str, Enum]]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
response_description: str = "Successful Response",
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
+ responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
deprecated: Optional[bool] = None,
- methods: Optional[Union[Set[str], List[str]]] = None,
+ methods: Optional[Union[set[str], list[str]]] = None,
operation_id: Optional[str] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -1035,13 +1033,13 @@ class APIRouter(routing.Router):
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(
+ response_class: Union[type[Response], DefaultPlaceholder] = Default(
JSONResponse
),
name: Optional[str] = None,
- route_class_override: Optional[Type[APIRoute]] = None,
- callbacks: Optional[List[BaseRoute]] = None,
- openapi_extra: Optional[Dict[str, Any]] = None,
+ route_class_override: Optional[type[APIRoute]] = None,
+ callbacks: Optional[list[BaseRoute]] = None,
+ openapi_extra: Optional[dict[str, Any]] = None,
generate_unique_id_function: Union[
Callable[[APIRoute], str], DefaultPlaceholder
] = Default(generate_unique_id),
@@ -1100,14 +1098,14 @@ class APIRouter(routing.Router):
*,
response_model: Any = Default(None),
status_code: Optional[int] = None,
- tags: Optional[List[Union[str, Enum]]] = None,
+ tags: Optional[list[Union[str, Enum]]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
response_description: str = "Successful Response",
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
+ responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
deprecated: Optional[bool] = None,
- methods: Optional[List[str]] = None,
+ methods: Optional[list[str]] = None,
operation_id: Optional[str] = None,
response_model_include: Optional[IncEx] = None,
response_model_exclude: Optional[IncEx] = None,
@@ -1116,10 +1114,10 @@ class APIRouter(routing.Router):
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
- response_class: Type[Response] = Default(JSONResponse),
+ response_class: type[Response] = Default(JSONResponse),
name: Optional[str] = None,
- callbacks: Optional[List[BaseRoute]] = None,
- openapi_extra: Optional[Dict[str, Any]] = None,
+ callbacks: Optional[list[BaseRoute]] = None,
+ openapi_extra: Optional[dict[str, Any]] = None,
generate_unique_id_function: Callable[[APIRoute], str] = Default(
generate_unique_id
),
@@ -1259,7 +1257,7 @@ class APIRouter(routing.Router):
*,
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to all the *path operations* in this
@@ -1285,7 +1283,7 @@ class APIRouter(routing.Router):
),
] = None,
default_response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
The default response class to be used.
@@ -1296,7 +1294,7 @@ class APIRouter(routing.Router):
),
] = Default(JSONResponse),
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses to be shown in OpenAPI.
@@ -1312,7 +1310,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
OpenAPI callbacks that should apply to all *path operations* in this
@@ -1417,7 +1415,7 @@ class APIRouter(routing.Router):
current_tags.extend(tags)
if route.tags:
current_tags.extend(route.tags)
- current_dependencies: List[params.Depends] = []
+ current_dependencies: list[params.Depends] = []
if dependencies:
current_dependencies.extend(dependencies)
if route.dependencies:
@@ -1558,7 +1556,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -1624,7 +1622,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -1765,7 +1763,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -1786,7 +1784,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -1802,7 +1800,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -1935,7 +1933,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2001,7 +1999,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2142,7 +2140,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2163,7 +2161,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2179,7 +2177,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -2317,7 +2315,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2383,7 +2381,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2524,7 +2522,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2545,7 +2543,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2561,7 +2559,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -2699,7 +2697,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -2765,7 +2763,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -2906,7 +2904,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -2927,7 +2925,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -2943,7 +2941,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3076,7 +3074,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3142,7 +3140,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -3283,7 +3281,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -3304,7 +3302,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -3320,7 +3318,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3453,7 +3451,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3519,7 +3517,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -3660,7 +3658,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -3681,7 +3679,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -3697,7 +3695,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -3835,7 +3833,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -3901,7 +3899,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -4042,7 +4040,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -4063,7 +4061,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -4079,7 +4077,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
@@ -4217,7 +4215,7 @@ class APIRouter(routing.Router):
),
] = None,
tags: Annotated[
- Optional[List[Union[str, Enum]]],
+ Optional[list[Union[str, Enum]]],
Doc(
"""
A list of tags to be applied to the *path operation*.
@@ -4283,7 +4281,7 @@ class APIRouter(routing.Router):
),
] = "Successful Response",
responses: Annotated[
- Optional[Dict[Union[int, str], Dict[str, Any]]],
+ Optional[dict[Union[int, str], dict[str, Any]]],
Doc(
"""
Additional responses that could be returned by this *path operation*.
@@ -4424,7 +4422,7 @@ class APIRouter(routing.Router):
),
] = True,
response_class: Annotated[
- Type[Response],
+ type[Response],
Doc(
"""
Response class to be used for this *path operation*.
@@ -4445,7 +4443,7 @@ class APIRouter(routing.Router):
),
] = None,
callbacks: Annotated[
- Optional[List[BaseRoute]],
+ Optional[list[BaseRoute]],
Doc(
"""
List of *path operations* that will be used as OpenAPI callbacks.
@@ -4461,7 +4459,7 @@ class APIRouter(routing.Router):
),
] = None,
openapi_extra: Annotated[
- Optional[Dict[str, Any]],
+ Optional[dict[str, Any]],
Doc(
"""
Extra metadata to be included in the OpenAPI schema for this *path
diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py
index 81c7be10d6..18dfb8e618 100644
--- a/fastapi/security/api_key.py
+++ b/fastapi/security/api_key.py
@@ -1,4 +1,4 @@
-from typing import Optional, Union
+from typing import Annotated, Optional, Union
from annotated_doc import Doc
from fastapi.openapi.models import APIKey, APIKeyIn
@@ -6,7 +6,6 @@ from fastapi.security.base import SecurityBase
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZED
-from typing_extensions import Annotated
class APIKeyBase(SecurityBase):
diff --git a/fastapi/security/http.py b/fastapi/security/http.py
index 0d1bbba3a0..b4c3bc6d85 100644
--- a/fastapi/security/http.py
+++ b/fastapi/security/http.py
@@ -1,6 +1,6 @@
import binascii
from base64 import b64decode
-from typing import Dict, Optional
+from typing import Annotated, Optional
from annotated_doc import Doc
from fastapi.exceptions import HTTPException
@@ -11,7 +11,6 @@ from fastapi.security.utils import get_authorization_scheme_param
from pydantic import BaseModel
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZED
-from typing_extensions import Annotated
class HTTPBasicCredentials(BaseModel):
@@ -82,7 +81,7 @@ class HTTPBase(SecurityBase):
self.scheme_name = scheme_name or self.__class__.__name__
self.auto_error = auto_error
- def make_authenticate_headers(self) -> Dict[str, str]:
+ def make_authenticate_headers(self) -> dict[str, str]:
return {"WWW-Authenticate": f"{self.model.scheme.title()}"}
def make_not_authenticated_error(self) -> HTTPException:
@@ -197,7 +196,7 @@ class HTTPBasic(HTTPBase):
self.realm = realm
self.auto_error = auto_error
- def make_authenticate_headers(self) -> Dict[str, str]:
+ def make_authenticate_headers(self) -> dict[str, str]:
if self.realm:
return {"WWW-Authenticate": f'Basic realm="{self.realm}"'}
return {"WWW-Authenticate": "Basic"}
diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py
index b41b0f8778..fc49ba1903 100644
--- a/fastapi/security/oauth2.py
+++ b/fastapi/security/oauth2.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, List, Optional, Union, cast
+from typing import Annotated, Any, Optional, Union, cast
from annotated_doc import Doc
from fastapi.exceptions import HTTPException
@@ -10,9 +10,6 @@ from fastapi.security.utils import get_authorization_scheme_param
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZED
-# TODO: import from typing when deprecating Python 3.9
-from typing_extensions import Annotated
-
class OAuth2PasswordRequestForm:
"""
@@ -323,7 +320,7 @@ class OAuth2(SecurityBase):
self,
*,
flows: Annotated[
- Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]],
+ Union[OAuthFlowsModel, dict[str, dict[str, Any]]],
Doc(
"""
The dictionary of OAuth2 flows.
@@ -440,7 +437,7 @@ class OAuth2PasswordBearer(OAuth2):
),
] = None,
scopes: Annotated[
- Optional[Dict[str, str]],
+ Optional[dict[str, str]],
Doc(
"""
The OAuth2 scopes that would be required by the *path operations* that
@@ -553,7 +550,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2):
),
] = None,
scopes: Annotated[
- Optional[Dict[str, str]],
+ Optional[dict[str, str]],
Doc(
"""
The OAuth2 scopes that would be required by the *path operations* that
@@ -639,7 +636,7 @@ class SecurityScopes:
def __init__(
self,
scopes: Annotated[
- Optional[List[str]],
+ Optional[list[str]],
Doc(
"""
This will be filled by FastAPI.
@@ -648,7 +645,7 @@ class SecurityScopes:
] = None,
):
self.scopes: Annotated[
- List[str],
+ list[str],
Doc(
"""
The list of all the scopes required by dependencies.
diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py
index e574a56a82..f4d953351e 100644
--- a/fastapi/security/open_id_connect_url.py
+++ b/fastapi/security/open_id_connect_url.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Annotated, Optional
from annotated_doc import Doc
from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel
@@ -6,7 +6,6 @@ from fastapi.security.base import SecurityBase
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZED
-from typing_extensions import Annotated
class OpenIdConnect(SecurityBase):
diff --git a/fastapi/security/utils.py b/fastapi/security/utils.py
index fa7a450b74..002e68b445 100644
--- a/fastapi/security/utils.py
+++ b/fastapi/security/utils.py
@@ -1,9 +1,9 @@
-from typing import Optional, Tuple
+from typing import Optional
def get_authorization_scheme_param(
authorization_header_value: Optional[str],
-) -> Tuple[str, str]:
+) -> tuple[str, str]:
if not authorization_header_value:
return "", ""
scheme, _, param = authorization_header_value.partition(" ")
diff --git a/fastapi/temp_pydantic_v1_params.py b/fastapi/temp_pydantic_v1_params.py
index e41d712308..b6c804dc44 100644
--- a/fastapi/temp_pydantic_v1_params.py
+++ b/fastapi/temp_pydantic_v1_params.py
@@ -1,9 +1,9 @@
import warnings
-from typing import Any, Callable, Dict, List, Optional, Union
+from typing import Annotated, Any, Callable, Optional, Union
from fastapi.openapi.models import Example
from fastapi.params import ParamTypes
-from typing_extensions import Annotated, deprecated
+from typing_extensions import deprecated
from ._compat.may_v1 import FieldInfo, Undefined
from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE
@@ -47,7 +47,7 @@ class Param(FieldInfo): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -55,10 +55,10 @@ class Param(FieldInfo): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
if example is not _Unset:
@@ -148,7 +148,7 @@ class Path(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -156,10 +156,10 @@ class Path(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
assert default is ..., "Path parameters cannot have a default value"
@@ -234,7 +234,7 @@ class Query(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -242,10 +242,10 @@ class Query(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -319,7 +319,7 @@ class Header(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -327,10 +327,10 @@ class Header(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
self.convert_underscores = convert_underscores
@@ -404,7 +404,7 @@ class Cookie(Param): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -412,10 +412,10 @@ class Cookie(Param): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -488,7 +488,7 @@ class Body(FieldInfo): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -496,10 +496,10 @@ class Body(FieldInfo): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
self.embed = embed
@@ -591,7 +591,7 @@ class Form(Body): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -599,10 +599,10 @@ class Form(Body): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
@@ -675,7 +675,7 @@ class File(Form): # type: ignore[misc]
allow_inf_nan: Union[bool, None] = _Unset,
max_digits: Union[int, None] = _Unset,
decimal_places: Union[int, None] = _Unset,
- examples: Optional[List[Any]] = None,
+ examples: Optional[list[Any]] = None,
example: Annotated[
Optional[Any],
deprecated(
@@ -683,10 +683,10 @@ class File(Form): # type: ignore[misc]
"although still supported. Use examples instead."
),
] = _Unset,
- openapi_examples: Optional[Dict[str, Example]] = None,
+ openapi_examples: Optional[dict[str, Example]] = None,
deprecated: Union[deprecated, str, bool, None] = None,
include_in_schema: bool = True,
- json_schema_extra: Union[Dict[str, Any], None] = None,
+ json_schema_extra: Union[dict[str, Any], None] = None,
**extra: Any,
):
super().__init__(
diff --git a/fastapi/types.py b/fastapi/types.py
index 3f4e81a7cc..d3e980cb43 100644
--- a/fastapi/types.py
+++ b/fastapi/types.py
@@ -1,11 +1,11 @@
import types
from enum import Enum
-from typing import Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union
+from typing import Any, Callable, Optional, TypeVar, Union
from pydantic import BaseModel
DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any])
UnionType = getattr(types, "UnionType", Union)
-ModelNameMap = Dict[Union[Type[BaseModel], Type[Enum]], str]
-IncEx = Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]]
-DependencyCacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...], str]
+ModelNameMap = dict[Union[type[BaseModel], type[Enum]], str]
+IncEx = Union[set[int], set[str], dict[int, Any], dict[str, Any]]
+DependencyCacheKey = tuple[Optional[Callable[..., Any]], tuple[str, ...], str]
diff --git a/fastapi/utils.py b/fastapi/utils.py
index b3b89ed2b4..5b93b9af8e 100644
--- a/fastapi/utils.py
+++ b/fastapi/utils.py
@@ -1,14 +1,11 @@
import re
import warnings
+from collections.abc import MutableMapping
from dataclasses import is_dataclass
from typing import (
TYPE_CHECKING,
Any,
- Dict,
- MutableMapping,
Optional,
- Set,
- Type,
Union,
cast,
)
@@ -36,7 +33,7 @@ if TYPE_CHECKING: # pragma: nocover
from .routing import APIRoute
# Cache for `create_cloned_field`
-_CLONED_TYPES_CACHE: MutableMapping[Type[BaseModel], Type[BaseModel]] = (
+_CLONED_TYPES_CACHE: MutableMapping[type[BaseModel], type[BaseModel]] = (
WeakKeyDictionary()
)
@@ -58,7 +55,7 @@ def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
return not (current_status_code < 200 or current_status_code in {204, 205, 304})
-def get_path_param_names(path: str) -> Set[str]:
+def get_path_param_names(path: str) -> set[str]:
return set(re.findall("{(.*?)}", path))
@@ -76,10 +73,10 @@ _invalid_args_message = (
def create_model_field(
name: str,
type_: Any,
- class_validators: Optional[Dict[str, Validator]] = None,
+ class_validators: Optional[dict[str, Validator]] = None,
default: Optional[Any] = Undefined,
required: Union[bool, UndefinedType] = Undefined,
- model_config: Union[Type[BaseConfig], None] = None,
+ model_config: Union[type[BaseConfig], None] = None,
field_info: Optional[FieldInfo] = None,
alias: Optional[str] = None,
mode: Literal["validation", "serialization"] = "validation",
@@ -141,7 +138,7 @@ def create_model_field(
def create_cloned_field(
field: ModelField,
*,
- cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None,
+ cloned_types: Optional[MutableMapping[type[BaseModel], type[BaseModel]]] = None,
) -> ModelField:
if PYDANTIC_V2:
from ._compat import v2
@@ -161,7 +158,7 @@ def create_cloned_field(
original_type = original_type.__pydantic_model__
use_type = original_type
if lenient_issubclass(original_type, v1.BaseModel):
- original_type = cast(Type[v1.BaseModel], original_type)
+ original_type = cast(type[v1.BaseModel], original_type)
use_type = cloned_types.get(original_type)
if use_type is None:
use_type = v1.create_model(original_type.__name__, __base__=original_type)
@@ -224,7 +221,7 @@ def generate_unique_id(route: "APIRoute") -> str:
return operation_id
-def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None:
+def deep_dict_update(main_dict: dict[Any, Any], update_dict: dict[Any, Any]) -> None:
for key, value in update_dict.items():
if (
key in main_dict
diff --git a/pdm_build.py b/pdm_build.py
index c83222b336..a0eb88eebb 100644
--- a/pdm_build.py
+++ b/pdm_build.py
@@ -1,5 +1,5 @@
import os
-from typing import Any, Dict
+from typing import Any
from pdm.backend.hooks import Context
@@ -9,12 +9,12 @@ TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "fastapi")
def pdm_build_initialize(context: Context) -> None:
metadata = context.config.metadata
# Get custom config for the current package, from the env var
- config: Dict[str, Any] = context.config.data["tool"]["tiangolo"][
+ config: dict[str, Any] = context.config.data["tool"]["tiangolo"][
"_internal-slim-build"
]["packages"].get(TIANGOLO_BUILD_PACKAGE)
if not config:
return
- project_config: Dict[str, Any] = config["project"]
+ project_config: dict[str, Any] = config["project"]
# Override main [project] configs with custom configs for this package
for key, value in project_config.items():
metadata[key] = value
diff --git a/pyproject.toml b/pyproject.toml
index ef4440b1b4..dd16e1f8fa 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,7 +9,7 @@ description = "FastAPI framework, high performance, easy to learn, fast to code,
readme = "README.md"
license = "MIT"
license-files = ["LICENSE"]
-requires-python = ">=3.8"
+requires-python = ">=3.9"
authors = [
{ name = "Sebastián Ramírez", email = "tiangolo@gmail.com" },
]
@@ -34,7 +34,6 @@ classifiers = [
"Framework :: Pydantic :: 2",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3 :: Only",
- "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
@@ -200,7 +199,7 @@ relative_files = true
context = '${CONTEXT}'
dynamic_context = "test_function"
omit = [
- "docs_src/response_model/tutorial003_04.py",
+ "docs_src/response_model/tutorial003_04_py39.py",
"docs_src/response_model/tutorial003_04_py310.py",
]
@@ -230,41 +229,30 @@ ignore = [
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
-"docs_src/dependencies/tutorial007.py" = ["F821"]
-"docs_src/dependencies/tutorial008.py" = ["F821"]
-"docs_src/dependencies/tutorial009.py" = ["F821"]
-"docs_src/dependencies/tutorial010.py" = ["F821"]
-"docs_src/custom_response/tutorial007.py" = ["B007"]
-"docs_src/dataclasses/tutorial003.py" = ["I001"]
-"docs_src/path_operation_advanced_configuration/tutorial007.py" = ["B904"]
+"docs_src/dependencies/tutorial007_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial008_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial009_py39.py" = ["F821"]
+"docs_src/dependencies/tutorial010_py39.py" = ["F821"]
+"docs_src/custom_response/tutorial007_py39.py" = ["B007"]
+"docs_src/dataclasses/tutorial003_py39.py" = ["I001"]
"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"]
-"docs_src/path_operation_advanced_configuration/tutorial007_pv1.py" = ["B904"]
"docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002.py" = ["B904"]
"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"]
"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"]
-"docs_src/custom_request_and_route/tutorial002_an.py" = ["B904"]
"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"]
"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"]
-"docs_src/dependencies/tutorial008_an.py" = ["F821"]
"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"]
-"docs_src/query_params_str_validations/tutorial012_an.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"]
-"docs_src/query_params_str_validations/tutorial013_an.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"]
-"docs_src/security/tutorial004.py" = ["B904"]
-"docs_src/security/tutorial004_an.py" = ["B904"]
-"docs_src/security/tutorial004_an_py310.py" = ["B904"]
+"docs_src/security/tutorial004_py39.py" = ["B904"]
"docs_src/security/tutorial004_an_py39.py" = ["B904"]
+"docs_src/security/tutorial004_an_py310.py" = ["B904"]
"docs_src/security/tutorial004_py310.py" = ["B904"]
-"docs_src/security/tutorial005.py" = ["B904"]
-"docs_src/security/tutorial005_an.py" = ["B904"]
"docs_src/security/tutorial005_an_py310.py" = ["B904"]
"docs_src/security/tutorial005_an_py39.py" = ["B904"]
"docs_src/security/tutorial005_py310.py" = ["B904"]
"docs_src/security/tutorial005_py39.py" = ["B904"]
-"docs_src/dependencies/tutorial008b.py" = ["B904"]
-"docs_src/dependencies/tutorial008b_an.py" = ["B904"]
+"docs_src/dependencies/tutorial008b_py39.py" = ["B904"]
"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
diff --git a/requirements-tests.txt b/requirements-tests.txt
index c5de4157e7..ee188b496c 100644
--- a/requirements-tests.txt
+++ b/requirements-tests.txt
@@ -11,6 +11,7 @@ PyJWT==2.9.0
pyyaml >=5.3.1,<7.0.0
pwdlib[argon2] >=0.2.1
inline-snapshot>=0.21.1
+pytest-codspeed==4.2.0
# types
types-ujson ==5.10.0.20240515
types-orjson ==3.6.2
diff --git a/scripts/docs.py b/scripts/docs.py
index b35bb3627f..bf7d9de395 100644
--- a/scripts/docs.py
+++ b/scripts/docs.py
@@ -8,7 +8,7 @@ from html.parser import HTMLParser
from http.server import HTTPServer, SimpleHTTPRequestHandler
from multiprocessing import Pool
from pathlib import Path
-from typing import Any, Dict, List, Optional, Union
+from typing import Any, Optional, Union
import mkdocs.utils
import typer
@@ -82,11 +82,11 @@ def slugify(text: str) -> str:
)
-def get_en_config() -> Dict[str, Any]:
+def get_en_config() -> dict[str, Any]:
return mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8"))
-def get_lang_paths() -> List[Path]:
+def get_lang_paths() -> list[Path]:
return sorted(docs_path.iterdir())
@@ -334,14 +334,14 @@ def live(
)
-def get_updated_config_content() -> Dict[str, Any]:
+def get_updated_config_content() -> dict[str, Any]:
config = get_en_config()
languages = [{"en": "/"}]
- new_alternate: List[Dict[str, str]] = []
+ new_alternate: list[dict[str, str]] = []
# Language names sourced from https://quickref.me/iso-639-1
# Contributors may wish to update or change these, e.g. to fix capitalization.
language_names_path = Path(__file__).parent / "../docs/language_names.yml"
- local_language_names: Dict[str, str] = mkdocs.utils.yaml_load(
+ local_language_names: dict[str, str] = mkdocs.utils.yaml_load(
language_names_path.read_text(encoding="utf-8")
)
for lang_path in get_lang_paths():
@@ -530,7 +530,7 @@ def add_permalinks_page(path: Path, update_existing: bool = False):
@app.command()
-def add_permalinks_pages(pages: List[Path], update_existing: bool = False) -> None:
+def add_permalinks_pages(pages: list[Path], update_existing: bool = False) -> None:
"""
Add or update header permalinks in specific pages of En docs.
"""
diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py
index 09cfa99e38..4b781270a2 100644
--- a/scripts/mkdocs_hooks.py
+++ b/scripts/mkdocs_hooks.py
@@ -1,6 +1,6 @@
from functools import lru_cache
from pathlib import Path
-from typing import Any, List, Union
+from typing import Any, Union
import material
from mkdocs.config.defaults import MkDocsConfig
@@ -27,7 +27,7 @@ def get_missing_translation_content(docs_dir: str) -> str:
@lru_cache
-def get_mkdocs_material_langs() -> List[str]:
+def get_mkdocs_material_langs() -> list[str]:
material_path = Path(material.__file__).parent
material_langs_path = material_path / "templates" / "partials" / "languages"
langs = [file.stem for file in material_langs_path.glob("*.html")]
@@ -65,7 +65,7 @@ def resolve_file(*, item: str, files: Files, config: MkDocsConfig) -> None:
)
-def resolve_files(*, items: List[Any], files: Files, config: MkDocsConfig) -> None:
+def resolve_files(*, items: list[Any], files: Files, config: MkDocsConfig) -> None:
for item in items:
if isinstance(item, str):
resolve_file(item=item, files=files, config=config)
@@ -94,9 +94,9 @@ def on_files(files: Files, *, config: MkDocsConfig) -> Files:
def generate_renamed_section_items(
- items: List[Union[Page, Section, Link]], *, config: MkDocsConfig
-) -> List[Union[Page, Section, Link]]:
- new_items: List[Union[Page, Section, Link]] = []
+ items: list[Union[Page, Section, Link]], *, config: MkDocsConfig
+) -> list[Union[Page, Section, Link]]:
+ new_items: list[Union[Page, Section, Link]] = []
for item in items:
if isinstance(item, Section):
new_title = item.title
diff --git a/scripts/notify_translations.py b/scripts/notify_translations.py
index c300624db2..2ca740a607 100644
--- a/scripts/notify_translations.py
+++ b/scripts/notify_translations.py
@@ -3,7 +3,7 @@ import random
import sys
import time
from pathlib import Path
-from typing import Any, Dict, List, Union, cast
+from typing import Any, Union, cast
import httpx
from github import Github
@@ -120,7 +120,7 @@ class CommentsEdge(BaseModel):
class Comments(BaseModel):
- edges: List[CommentsEdge]
+ edges: list[CommentsEdge]
class CommentsDiscussion(BaseModel):
@@ -149,7 +149,7 @@ class AllDiscussionsLabelsEdge(BaseModel):
class AllDiscussionsDiscussionLabels(BaseModel):
- edges: List[AllDiscussionsLabelsEdge]
+ edges: list[AllDiscussionsLabelsEdge]
class AllDiscussionsDiscussionNode(BaseModel):
@@ -160,7 +160,7 @@ class AllDiscussionsDiscussionNode(BaseModel):
class AllDiscussionsDiscussions(BaseModel):
- nodes: List[AllDiscussionsDiscussionNode]
+ nodes: list[AllDiscussionsDiscussionNode]
class AllDiscussionsRepository(BaseModel):
@@ -205,7 +205,7 @@ def get_graphql_response(
discussion_id: Union[str, None] = None,
comment_id: Union[str, None] = None,
body: Union[str, None] = None,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"}
variables = {
"after": after,
@@ -233,12 +233,12 @@ def get_graphql_response(
logging.error(data["errors"])
logging.error(response.text)
raise RuntimeError(response.text)
- return cast(Dict[str, Any], data)
+ return cast(dict[str, Any], data)
def get_graphql_translation_discussions(
*, settings: Settings
-) -> List[AllDiscussionsDiscussionNode]:
+) -> list[AllDiscussionsDiscussionNode]:
data = get_graphql_response(
settings=settings,
query=all_discussions_query,
@@ -250,7 +250,7 @@ def get_graphql_translation_discussions(
def get_graphql_translation_discussion_comments_edges(
*, settings: Settings, discussion_number: int, after: Union[str, None] = None
-) -> List[CommentsEdge]:
+) -> list[CommentsEdge]:
data = get_graphql_response(
settings=settings,
query=translation_discussion_query,
@@ -264,7 +264,7 @@ def get_graphql_translation_discussion_comments_edges(
def get_graphql_translation_discussion_comments(
*, settings: Settings, discussion_number: int
) -> list[Comment]:
- comment_nodes: List[Comment] = []
+ comment_nodes: list[Comment] = []
discussion_edges = get_graphql_translation_discussion_comments_edges(
settings=settings, discussion_number=discussion_number
)
@@ -348,7 +348,7 @@ def main() -> None:
# Generate translation map, lang ID to discussion
discussions = get_graphql_translation_discussions(settings=settings)
- lang_to_discussion_map: Dict[str, AllDiscussionsDiscussionNode] = {}
+ lang_to_discussion_map: dict[str, AllDiscussionsDiscussionNode] = {}
for discussion in discussions:
for edge in discussion.labels.edges:
label = edge.node.name
diff --git a/scripts/people.py b/scripts/people.py
index 65e009944c..207ab46493 100644
--- a/scripts/people.py
+++ b/scripts/people.py
@@ -3,9 +3,10 @@ import secrets
import subprocess
import time
from collections import Counter
+from collections.abc import Container
from datetime import datetime, timedelta, timezone
from pathlib import Path
-from typing import Any, Container, Union
+from typing import Any, Union
import httpx
import yaml
diff --git a/docs_src/settings/app02/__init__.py b/tests/benchmarks/__init__.py
similarity index 100%
rename from docs_src/settings/app02/__init__.py
rename to tests/benchmarks/__init__.py
diff --git a/tests/benchmarks/test_general_performance.py b/tests/benchmarks/test_general_performance.py
new file mode 100644
index 0000000000..dca3613d00
--- /dev/null
+++ b/tests/benchmarks/test_general_performance.py
@@ -0,0 +1,396 @@
+import json
+import sys
+from collections.abc import Iterator
+from typing import Annotated, Any
+
+import pytest
+from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
+
+if "--codspeed" not in sys.argv:
+ pytest.skip(
+ "Benchmark tests are skipped by default; run with --codspeed.",
+ allow_module_level=True,
+ )
+
+LARGE_ITEMS: list[dict[str, Any]] = [
+ {
+ "id": i,
+ "name": f"item-{i}",
+ "values": list(range(25)),
+ "meta": {
+ "active": True,
+ "group": i % 10,
+ "tag": f"t{i % 5}",
+ },
+ }
+ for i in range(300)
+]
+
+LARGE_METADATA: dict[str, Any] = {
+ "source": "benchmark",
+ "version": 1,
+ "flags": {"a": True, "b": False, "c": True},
+ "notes": ["x" * 50, "y" * 50, "z" * 50],
+}
+
+LARGE_PAYLOAD: dict[str, Any] = {"items": LARGE_ITEMS, "metadata": LARGE_METADATA}
+
+
+def dep_a():
+ return 40
+
+
+def dep_b(a: Annotated[int, Depends(dep_a)]):
+ return a + 2
+
+
+@pytest.fixture(
+ scope="module",
+ params=[
+ "pydantic-v2",
+ "pydantic-v1",
+ ],
+)
+def basemodel_class(request: pytest.FixtureRequest) -> type[Any]:
+ if request.param == "pydantic-v2":
+ from pydantic import BaseModel
+
+ return BaseModel
+ else:
+ from pydantic.v1 import BaseModel
+
+ return BaseModel
+
+
+@pytest.fixture(scope="module")
+def app(basemodel_class: type[Any]) -> FastAPI:
+ class ItemIn(basemodel_class):
+ name: str
+ value: int
+
+ class ItemOut(basemodel_class):
+ name: str
+ value: int
+ dep: int
+
+ class LargeIn(basemodel_class):
+ items: list[dict[str, Any]]
+ metadata: dict[str, Any]
+
+ class LargeOut(basemodel_class):
+ items: list[dict[str, Any]]
+ metadata: dict[str, Any]
+
+ app = FastAPI()
+
+ @app.post("/sync/validated", response_model=ItemOut)
+ def sync_validated(item: ItemIn, dep: Annotated[int, Depends(dep_b)]):
+ return ItemOut(name=item.name, value=item.value, dep=dep)
+
+ @app.get("/sync/dict-no-response-model")
+ def sync_dict_no_response_model():
+ return {"name": "foo", "value": 123}
+
+ @app.get("/sync/dict-with-response-model", response_model=ItemOut)
+ def sync_dict_with_response_model(
+ dep: Annotated[int, Depends(dep_b)],
+ ):
+ return {"name": "foo", "value": 123, "dep": dep}
+
+ @app.get("/sync/model-no-response-model")
+ def sync_model_no_response_model(dep: Annotated[int, Depends(dep_b)]):
+ return ItemOut(name="foo", value=123, dep=dep)
+
+ @app.get("/sync/model-with-response-model", response_model=ItemOut)
+ def sync_model_with_response_model(dep: Annotated[int, Depends(dep_b)]):
+ return ItemOut(name="foo", value=123, dep=dep)
+
+ @app.post("/async/validated", response_model=ItemOut)
+ async def async_validated(
+ item: ItemIn,
+ dep: Annotated[int, Depends(dep_b)],
+ ):
+ return ItemOut(name=item.name, value=item.value, dep=dep)
+
+ @app.post("/sync/large-receive")
+ def sync_large_receive(payload: LargeIn):
+ return {"received": len(payload.items)}
+
+ @app.post("/async/large-receive")
+ async def async_large_receive(payload: LargeIn):
+ return {"received": len(payload.items)}
+
+ @app.get("/sync/large-dict-no-response-model")
+ def sync_large_dict_no_response_model():
+ return LARGE_PAYLOAD
+
+ @app.get("/sync/large-dict-with-response-model", response_model=LargeOut)
+ def sync_large_dict_with_response_model():
+ return LARGE_PAYLOAD
+
+ @app.get("/sync/large-model-no-response-model")
+ def sync_large_model_no_response_model():
+ return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
+
+ @app.get("/sync/large-model-with-response-model", response_model=LargeOut)
+ def sync_large_model_with_response_model():
+ return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
+
+ @app.get("/async/large-dict-no-response-model")
+ async def async_large_dict_no_response_model():
+ return LARGE_PAYLOAD
+
+ @app.get("/async/large-dict-with-response-model", response_model=LargeOut)
+ async def async_large_dict_with_response_model():
+ return LARGE_PAYLOAD
+
+ @app.get("/async/large-model-no-response-model")
+ async def async_large_model_no_response_model():
+ return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
+
+ @app.get("/async/large-model-with-response-model", response_model=LargeOut)
+ async def async_large_model_with_response_model():
+ return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
+
+ @app.get("/async/dict-no-response-model")
+ async def async_dict_no_response_model():
+ return {"name": "foo", "value": 123}
+
+ @app.get("/async/dict-with-response-model", response_model=ItemOut)
+ async def async_dict_with_response_model(
+ dep: Annotated[int, Depends(dep_b)],
+ ):
+ return {"name": "foo", "value": 123, "dep": dep}
+
+ @app.get("/async/model-no-response-model")
+ async def async_model_no_response_model(
+ dep: Annotated[int, Depends(dep_b)],
+ ):
+ return ItemOut(name="foo", value=123, dep=dep)
+
+ @app.get("/async/model-with-response-model", response_model=ItemOut)
+ async def async_model_with_response_model(
+ dep: Annotated[int, Depends(dep_b)],
+ ):
+ return ItemOut(name="foo", value=123, dep=dep)
+
+ return app
+
+
+@pytest.fixture(scope="module")
+def client(app: FastAPI) -> Iterator[TestClient]:
+ with TestClient(app) as client:
+ yield client
+
+
+def _bench_get(benchmark, client: TestClient, path: str) -> tuple[int, bytes]:
+ warmup = client.get(path)
+ assert warmup.status_code == 200
+
+ def do_request() -> tuple[int, bytes]:
+ response = client.get(path)
+ return response.status_code, response.content
+
+ return benchmark(do_request)
+
+
+def _bench_post_json(
+ benchmark, client: TestClient, path: str, json: dict[str, Any]
+) -> tuple[int, bytes]:
+ warmup = client.post(path, json=json)
+ assert warmup.status_code == 200
+
+ def do_request() -> tuple[int, bytes]:
+ response = client.post(path, json=json)
+ return response.status_code, response.content
+
+ return benchmark(do_request)
+
+
+def test_sync_receiving_validated_pydantic_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_post_json(
+ benchmark,
+ client,
+ "/sync/validated",
+ json={"name": "foo", "value": 123},
+ )
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_sync_return_dict_without_response_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_get(benchmark, client, "/sync/dict-no-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123}'
+
+
+def test_sync_return_dict_with_response_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_get(benchmark, client, "/sync/dict-with-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_sync_return_model_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(benchmark, client, "/sync/model-no-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_sync_return_model_with_response_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_get(benchmark, client, "/sync/model-with-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_async_receiving_validated_pydantic_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_post_json(
+ benchmark, client, "/async/validated", json={"name": "foo", "value": 123}
+ )
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_async_return_dict_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(benchmark, client, "/async/dict-no-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123}'
+
+
+def test_async_return_dict_with_response_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_get(benchmark, client, "/async/dict-with-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_async_return_model_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(benchmark, client, "/async/model-no-response-model")
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_async_return_model_with_response_model(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/async/model-with-response-model"
+ )
+ assert status_code == 200
+ assert body == b'{"name":"foo","value":123,"dep":42}'
+
+
+def test_sync_receiving_large_payload(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_post_json(
+ benchmark,
+ client,
+ "/sync/large-receive",
+ json=LARGE_PAYLOAD,
+ )
+ assert status_code == 200
+ assert body == b'{"received":300}'
+
+
+def test_async_receiving_large_payload(benchmark, client: TestClient) -> None:
+ status_code, body = _bench_post_json(
+ benchmark,
+ client,
+ "/async/large-receive",
+ json=LARGE_PAYLOAD,
+ )
+ assert status_code == 200
+ assert body == b'{"received":300}'
+
+
+def _expected_large_payload_json_bytes() -> bytes:
+ return json.dumps(
+ LARGE_PAYLOAD,
+ ensure_ascii=False,
+ allow_nan=False,
+ separators=(",", ":"),
+ ).encode("utf-8")
+
+
+def test_sync_return_large_dict_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/sync/large-dict-no-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_sync_return_large_dict_with_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/sync/large-dict-with-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_sync_return_large_model_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/sync/large-model-no-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_sync_return_large_model_with_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/sync/large-model-with-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_async_return_large_dict_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/async/large-dict-no-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_async_return_large_dict_with_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/async/large-dict-with-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_async_return_large_model_without_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/async/large-model-no-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
+
+
+def test_async_return_large_model_with_response_model(
+ benchmark, client: TestClient
+) -> None:
+ status_code, body = _bench_get(
+ benchmark, client, "/async/large-model-with-response-model"
+ )
+ assert status_code == 200
+ assert body == _expected_large_payload_json_bytes()
diff --git a/tests/main.py b/tests/main.py
index 2f1d617115..7edb16c615 100644
--- a/tests/main.py
+++ b/tests/main.py
@@ -1,5 +1,5 @@
import http
-from typing import FrozenSet, List, Optional
+from typing import Optional
from fastapi import FastAPI, Path, Query
@@ -195,15 +195,15 @@ def get_enum_status_code():
@app.get("/query/frozenset")
-def get_query_type_frozenset(query: FrozenSet[int] = Query(...)):
+def get_query_type_frozenset(query: frozenset[int] = Query(...)):
return ",".join(map(str, sorted(query)))
@app.get("/query/list")
-def get_query_list(device_ids: List[int] = Query()) -> List[int]:
+def get_query_list(device_ids: list[int] = Query()) -> list[int]:
return device_ids
@app.get("/query/list-default")
-def get_query_list_default(device_ids: List[int] = Query(default=[])) -> List[int]:
+def get_query_list_default(device_ids: list[int] = Query(default=[])) -> list[int]:
return device_ids
diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py
index be14d10edc..2622366400 100644
--- a/tests/test_additional_properties.py
+++ b/tests/test_additional_properties.py
@@ -1,5 +1,3 @@
-from typing import Dict
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -8,7 +6,7 @@ app = FastAPI()
class Items(BaseModel):
- items: Dict[str, int]
+ items: dict[str, int]
@app.post("/foo")
diff --git a/tests/test_additional_responses_custom_validationerror.py b/tests/test_additional_responses_custom_validationerror.py
index 9fec5c96d4..8724e5ecb8 100644
--- a/tests/test_additional_responses_custom_validationerror.py
+++ b/tests/test_additional_responses_custom_validationerror.py
@@ -1,5 +1,3 @@
-import typing
-
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
@@ -18,7 +16,7 @@ class Error(BaseModel):
class JsonApiError(BaseModel):
- errors: typing.List[Error]
+ errors: list[Error]
@app.get(
diff --git a/tests/test_additional_responses_response_class.py b/tests/test_additional_responses_response_class.py
index 68753561c9..fecc3ee16b 100644
--- a/tests/test_additional_responses_response_class.py
+++ b/tests/test_additional_responses_response_class.py
@@ -1,5 +1,3 @@
-import typing
-
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
@@ -18,7 +16,7 @@ class Error(BaseModel):
class JsonApiError(BaseModel):
- errors: typing.List[Error]
+ errors: list[Error]
@app.get(
diff --git a/tests/test_allow_inf_nan_in_enforcing.py b/tests/test_allow_inf_nan_in_enforcing.py
index 9e855fdf81..083a024af0 100644
--- a/tests/test_allow_inf_nan_in_enforcing.py
+++ b/tests/test_allow_inf_nan_in_enforcing.py
@@ -1,7 +1,8 @@
+from typing import Annotated
+
import pytest
from fastapi import Body, FastAPI, Query
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_ambiguous_params.py b/tests/test_ambiguous_params.py
index 8a31442eb0..5e48782f8d 100644
--- a/tests/test_ambiguous_params.py
+++ b/tests/test_ambiguous_params.py
@@ -1,9 +1,10 @@
+from typing import Annotated
+
import pytest
from fastapi import Depends, FastAPI, Path
from fastapi.param_functions import Query
from fastapi.testclient import TestClient
from fastapi.utils import PYDANTIC_V2
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_annotated.py b/tests/test_annotated.py
index 473d33e52c..a9e7c78c99 100644
--- a/tests/test_annotated.py
+++ b/tests/test_annotated.py
@@ -1,8 +1,9 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict
from fastapi import APIRouter, FastAPI, Query
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_arbitrary_types.py b/tests/test_arbitrary_types.py
index e5fa95ef22..8b8417bae0 100644
--- a/tests/test_arbitrary_types.py
+++ b/tests/test_arbitrary_types.py
@@ -1,10 +1,9 @@
-from typing import List
+from typing import Annotated
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from typing_extensions import Annotated
from .utils import needs_pydanticv2
@@ -25,7 +24,7 @@ def get_client():
FakeNumpyArrayPydantic = Annotated[
FakeNumpyArray,
- WithJsonSchema(TypeAdapter(List[float]).json_schema()),
+ WithJsonSchema(TypeAdapter(list[float]).json_schema()),
PlainSerializer(lambda v: v.data),
]
@@ -66,7 +65,7 @@ def test_typeadapter():
FakeNumpyArrayPydantic = Annotated[
FakeNumpyArray,
- WithJsonSchema(TypeAdapter(List[float]).json_schema()),
+ WithJsonSchema(TypeAdapter(list[float]).json_schema()),
PlainSerializer(lambda v: v.data),
]
diff --git a/tests/test_compat.py b/tests/test_compat.py
index 26537c5ab7..3f9d84d894 100644
--- a/tests/test_compat.py
+++ b/tests/test_compat.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, List, Union
+from typing import Any, Union
from fastapi import FastAPI, UploadFile
from fastapi._compat import (
@@ -61,7 +61,7 @@ def test_complex():
app = FastAPI()
@app.post("/")
- def foo(foo: Union[str, List[int]]):
+ def foo(foo: Union[str, list[int]]):
return foo
client = TestClient(app)
@@ -95,7 +95,7 @@ def test_propagates_pydantic2_model_config():
embedded_model: EmbeddedModel = EmbeddedModel()
@app.post("/")
- def foo(req: Model) -> Dict[str, Union[str, None]]:
+ def foo(req: Model) -> dict[str, Union[str, None]]:
return {
"value": req.value or None,
"embedded_value": req.embedded_model.value or None,
@@ -125,7 +125,7 @@ def test_is_bytes_sequence_annotation_union():
# TODO: in theory this would allow declaring types that could be lists of bytes
# to be read from files and other types, but I'm not even sure it's a good idea
# to support it as a first class "feature"
- assert is_bytes_sequence_annotation(Union[List[str], List[bytes]])
+ assert is_bytes_sequence_annotation(Union[list[str], list[bytes]])
def test_is_uploadfile_sequence_annotation():
@@ -133,7 +133,7 @@ def test_is_uploadfile_sequence_annotation():
# TODO: in theory this would allow declaring types that could be lists of UploadFile
# and other types, but I'm not even sure it's a good idea to support it as a first
# class "feature"
- assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]])
+ assert is_uploadfile_sequence_annotation(Union[list[str], list[UploadFile]])
@needs_pydanticv2
@@ -141,7 +141,7 @@ def test_serialize_sequence_value_with_optional_list():
"""Test that serialize_sequence_value handles optional lists correctly."""
from fastapi._compat import v2
- field_info = FieldInfo(annotation=Union[List[str], None])
+ field_info = FieldInfo(annotation=Union[list[str], None])
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"])
assert result == ["a", "b", "c"]
@@ -166,7 +166,7 @@ def test_serialize_sequence_value_with_none_first_in_union():
"""Test that serialize_sequence_value handles Union[None, List[...]] correctly."""
from fastapi._compat import v2
- field_info = FieldInfo(annotation=Union[None, List[str]])
+ field_info = FieldInfo(annotation=Union[None, list[str]])
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["x", "y"])
assert result == ["x", "y"]
@@ -179,7 +179,7 @@ def test_is_pv1_scalar_field():
# For coverage
class Model(v1.BaseModel):
- foo: Union[str, Dict[str, Any]]
+ foo: Union[str, dict[str, Any]]
fields = v1.get_model_fields(Model)
assert not is_scalar_field(fields[0])
diff --git a/tests/test_compat_params_v1.py b/tests/test_compat_params_v1.py
index 7064761cb5..8829a0a611 100644
--- a/tests/test_compat_params_v1.py
+++ b/tests/test_compat_params_v1.py
@@ -1,5 +1,5 @@
import sys
-from typing import List, Optional
+from typing import Optional
import pytest
@@ -8,6 +8,8 @@ from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
+from typing import Annotated
+
from fastapi import FastAPI
from fastapi._compat.v1 import BaseModel
from fastapi.temp_pydantic_v1_params import (
@@ -21,7 +23,6 @@ from fastapi.temp_pydantic_v1_params import (
)
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from typing_extensions import Annotated
class Item(BaseModel):
@@ -112,7 +113,7 @@ def upload_file(
@app.post("/upload-multiple/")
def upload_multiple_files(
- files: Annotated[List[bytes], File()],
+ files: Annotated[list[bytes], File()],
note: Annotated[str, Form()] = "",
):
return {
diff --git a/tests/test_custom_schema_fields.py b/tests/test_custom_schema_fields.py
index d890291b19..bc3e1c5ec3 100644
--- a/tests/test_custom_schema_fields.py
+++ b/tests/test_custom_schema_fields.py
@@ -1,10 +1,9 @@
-from typing import Optional
+from typing import Annotated, Optional
from fastapi import FastAPI
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel
-from typing_extensions import Annotated
if PYDANTIC_V2:
from pydantic import WithJsonSchema
diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py
index 7e57d525ce..c175147bc3 100644
--- a/tests/test_datastructures.py
+++ b/tests/test_datastructures.py
@@ -1,6 +1,5 @@
import io
from pathlib import Path
-from typing import List
import pytest
from fastapi import FastAPI, UploadFile
@@ -38,7 +37,7 @@ def test_upload_file_is_closed(tmp_path: Path):
path.write_bytes(b"")
app = FastAPI()
- testing_file_store: List[UploadFile] = []
+ testing_file_store: list[UploadFile] = []
@app.post("/uploadfile/")
def create_upload_file(file: UploadFile):
diff --git a/tests/test_dependency_after_yield_raise.py b/tests/test_dependency_after_yield_raise.py
index b560dc36f9..b561402772 100644
--- a/tests/test_dependency_after_yield_raise.py
+++ b/tests/test_dependency_after_yield_raise.py
@@ -1,9 +1,8 @@
-from typing import Any
+from typing import Annotated, Any
import pytest
from fastapi import Depends, FastAPI, HTTPException
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
class CustomError(Exception):
diff --git a/tests/test_dependency_after_yield_streaming.py b/tests/test_dependency_after_yield_streaming.py
index 7e1c8822b8..cbadff8f87 100644
--- a/tests/test_dependency_after_yield_streaming.py
+++ b/tests/test_dependency_after_yield_streaming.py
@@ -1,11 +1,11 @@
+from collections.abc import Generator
from contextlib import contextmanager
-from typing import Any, Generator
+from typing import Annotated, Any
import pytest
from fastapi import Depends, FastAPI
from fastapi.responses import StreamingResponse
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
class Session:
diff --git a/tests/test_dependency_after_yield_websockets.py b/tests/test_dependency_after_yield_websockets.py
index 7c323c338b..0fdf697b6c 100644
--- a/tests/test_dependency_after_yield_websockets.py
+++ b/tests/test_dependency_after_yield_websockets.py
@@ -1,10 +1,10 @@
+from collections.abc import Generator
from contextlib import contextmanager
-from typing import Any, Generator
+from typing import Annotated, Any
import pytest
from fastapi import Depends, FastAPI, WebSocket
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
class Session:
diff --git a/tests/test_dependency_class.py b/tests/test_dependency_class.py
index 75241b467a..95ff3e9d95 100644
--- a/tests/test_dependency_class.py
+++ b/tests/test_dependency_class.py
@@ -1,4 +1,4 @@
-from typing import AsyncGenerator, Generator
+from collections.abc import AsyncGenerator, Generator
import pytest
from fastapi import Depends, FastAPI
diff --git a/tests/test_dependency_contextmanager.py b/tests/test_dependency_contextmanager.py
index 02c10458cb..5a89934741 100644
--- a/tests/test_dependency_contextmanager.py
+++ b/tests/test_dependency_contextmanager.py
@@ -1,5 +1,4 @@
import json
-from typing import Dict
import pytest
from fastapi import BackgroundTasks, Depends, FastAPI
@@ -37,19 +36,19 @@ class OtherDependencyError(Exception):
pass
-async def asyncgen_state(state: Dict[str, str] = Depends(get_state)):
+async def asyncgen_state(state: dict[str, str] = Depends(get_state)):
state["/async"] = "asyncgen started"
yield state["/async"]
state["/async"] = "asyncgen completed"
-def generator_state(state: Dict[str, str] = Depends(get_state)):
+def generator_state(state: dict[str, str] = Depends(get_state)):
state["/sync"] = "generator started"
yield state["/sync"]
state["/sync"] = "generator completed"
-async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
+async def asyncgen_state_try(state: dict[str, str] = Depends(get_state)):
state["/async_raise"] = "asyncgen raise started"
try:
yield state["/async_raise"]
@@ -60,7 +59,7 @@ async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
state["/async_raise"] = "asyncgen raise finalized"
-def generator_state_try(state: Dict[str, str] = Depends(get_state)):
+def generator_state_try(state: dict[str, str] = Depends(get_state)):
state["/sync_raise"] = "generator raise started"
try:
yield state["/sync_raise"]
diff --git a/tests/test_dependency_contextvars.py b/tests/test_dependency_contextvars.py
index 076802df84..0c2e5594b6 100644
--- a/tests/test_dependency_contextvars.py
+++ b/tests/test_dependency_contextvars.py
@@ -1,10 +1,11 @@
+from collections.abc import Awaitable
from contextvars import ContextVar
-from typing import Any, Awaitable, Callable, Dict, Optional
+from typing import Any, Callable, Optional
from fastapi import Depends, FastAPI, Request, Response
from fastapi.testclient import TestClient
-legacy_request_state_context_var: ContextVar[Optional[Dict[str, Any]]] = ContextVar(
+legacy_request_state_context_var: ContextVar[Optional[dict[str, Any]]] = ContextVar(
"legacy_request_state_context_var", default=None
)
diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py
index 8e8d07c2d6..7c6717e2aa 100644
--- a/tests/test_dependency_duplicates.py
+++ b/tests/test_dependency_duplicates.py
@@ -1,5 +1,3 @@
-from typing import List
-
from dirty_equals import IsDict
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
@@ -40,7 +38,7 @@ async def no_duplicates(item: Item, item2: Item = Depends(dependency)):
@app.post("/with-duplicates-sub")
async def no_duplicates_sub(
- item: Item, sub_items: List[Item] = Depends(sub_duplicate_dependency)
+ item: Item, sub_items: list[Item] = Depends(sub_duplicate_dependency)
):
return [item, sub_items]
diff --git a/tests/test_dependency_paramless.py b/tests/test_dependency_paramless.py
index 9c3cc3878b..1774196fe4 100644
--- a/tests/test_dependency_paramless.py
+++ b/tests/test_dependency_paramless.py
@@ -1,4 +1,4 @@
-from typing import Union
+from typing import Annotated, Union
from fastapi import FastAPI, HTTPException, Security
from fastapi.security import (
@@ -6,7 +6,6 @@ from fastapi.security import (
SecurityScopes,
)
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_dependency_partial.py b/tests/test_dependency_partial.py
index 61a76236f8..05a3cffa5a 100644
--- a/tests/test_dependency_partial.py
+++ b/tests/test_dependency_partial.py
@@ -1,10 +1,10 @@
+from collections.abc import AsyncGenerator, Generator
from functools import partial
-from typing import AsyncGenerator, Generator
+from typing import Annotated
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_dependency_security_overrides.py b/tests/test_dependency_security_overrides.py
index b89d82db43..14b65c7770 100644
--- a/tests/test_dependency_security_overrides.py
+++ b/tests/test_dependency_security_overrides.py
@@ -1,5 +1,3 @@
-from typing import List, Tuple
-
from fastapi import Depends, FastAPI, Security
from fastapi.security import SecurityScopes
from fastapi.testclient import TestClient
@@ -25,8 +23,8 @@ def get_data_override():
@app.get("/user")
def read_user(
- user_data: Tuple[str, List[str]] = Security(get_user, scopes=["foo", "bar"]),
- data: List[int] = Depends(get_data),
+ user_data: tuple[str, list[str]] = Security(get_user, scopes=["foo", "bar"]),
+ data: list[int] = Depends(get_data),
):
return {"user": user_data[0], "scopes": user_data[1], "data": data}
diff --git a/tests/test_dependency_wrapped.py b/tests/test_dependency_wrapped.py
index 08356712d6..a4044112a2 100644
--- a/tests/test_dependency_wrapped.py
+++ b/tests/test_dependency_wrapped.py
@@ -1,7 +1,7 @@
import inspect
import sys
+from collections.abc import AsyncGenerator, Generator
from functools import wraps
-from typing import AsyncGenerator, Generator
import pytest
from fastapi import Depends, FastAPI
diff --git a/tests/test_dependency_yield_scope.py b/tests/test_dependency_yield_scope.py
index d87164fe80..f3fc3cc94f 100644
--- a/tests/test_dependency_yield_scope.py
+++ b/tests/test_dependency_yield_scope.py
@@ -1,12 +1,11 @@
import json
-from typing import Any, Tuple
+from typing import Annotated, Any
import pytest
from fastapi import APIRouter, Depends, FastAPI, HTTPException
from fastapi.exceptions import FastAPIError
from fastapi.responses import StreamingResponse
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
class Session:
@@ -43,7 +42,7 @@ def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep)
named_session.open = False
-NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)]
+NamedSessionsDep = Annotated[tuple[NamedSession, Session], Depends(get_named_session)]
def get_named_func_session(session: SessionFuncDep) -> Any:
@@ -58,14 +57,14 @@ def get_named_regular_func_session(session: SessionFuncDep) -> Any:
BrokenSessionsDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_func_session)
+ tuple[NamedSession, Session], Depends(get_named_func_session)
]
NamedSessionsFuncDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
+ tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
]
RegularSessionsDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_regular_func_session)
+ tuple[NamedSession, Session], Depends(get_named_regular_func_session)
]
app = FastAPI()
diff --git a/tests/test_dependency_yield_scope_websockets.py b/tests/test_dependency_yield_scope_websockets.py
index 52a30ae7a7..dbe35e576c 100644
--- a/tests/test_dependency_yield_scope_websockets.py
+++ b/tests/test_dependency_yield_scope_websockets.py
@@ -1,13 +1,12 @@
from contextvars import ContextVar
-from typing import Any, Dict, Tuple
+from typing import Annotated, Any
import pytest
from fastapi import Depends, FastAPI, WebSocket
from fastapi.exceptions import FastAPIError
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
-global_context: ContextVar[Dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039
+global_context: ContextVar[dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039
class Session:
@@ -43,7 +42,7 @@ def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep)
global_state["named_session_closed"] = True
-NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)]
+NamedSessionsDep = Annotated[tuple[NamedSession, Session], Depends(get_named_session)]
def get_named_func_session(session: SessionFuncDep) -> Any:
@@ -60,14 +59,14 @@ def get_named_regular_func_session(session: SessionFuncDep) -> Any:
BrokenSessionsDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_func_session)
+ tuple[NamedSession, Session], Depends(get_named_func_session)
]
NamedSessionsFuncDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
+ tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
]
RegularSessionsDep = Annotated[
- Tuple[NamedSession, Session], Depends(get_named_regular_func_session)
+ tuple[NamedSession, Session], Depends(get_named_regular_func_session)
]
app = FastAPI()
diff --git a/tests/test_file_and_form_order_issue_9116.py b/tests/test_file_and_form_order_issue_9116.py
index cb9a31d314..75290b60cd 100644
--- a/tests/test_file_and_form_order_issue_9116.py
+++ b/tests/test_file_and_form_order_issue_9116.py
@@ -4,12 +4,11 @@ See https://github.com/tiangolo/fastapi/discussions/9116
"""
from pathlib import Path
-from typing import List
+from typing import Annotated
import pytest
from fastapi import FastAPI, File, Form
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
@@ -32,7 +31,7 @@ def file_after_form(
@app.post("/file_list_before_form")
def file_list_before_form(
- files: Annotated[List[bytes], File()],
+ files: Annotated[list[bytes], File()],
city: Annotated[str, Form()],
):
return {"file_contents": files, "city": city}
@@ -41,7 +40,7 @@ def file_list_before_form(
@app.post("/file_list_after_form")
def file_list_after_form(
city: Annotated[str, Form()],
- files: Annotated[List[bytes], File()],
+ files: Annotated[list[bytes], File()],
):
return {"file_contents": files, "city": city}
diff --git a/tests/test_form_default.py b/tests/test_form_default.py
index 2a12049d1a..0b3eb8f2e2 100644
--- a/tests/test_form_default.py
+++ b/tests/test_form_default.py
@@ -1,8 +1,7 @@
-from typing import Optional
+from typing import Annotated, Optional
from fastapi import FastAPI, File, Form
from starlette.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_forms_single_model.py b/tests/test_forms_single_model.py
index 1db63f0214..b149b76539 100644
--- a/tests/test_forms_single_model.py
+++ b/tests/test_forms_single_model.py
@@ -1,11 +1,10 @@
-from typing import List, Optional
+from typing import Annotated, Optional
from dirty_equals import IsDict
from fastapi import FastAPI, Form
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
app = FastAPI()
@@ -14,7 +13,7 @@ class FormModel(BaseModel):
username: str
lastname: str
age: Optional[int] = None
- tags: List[str] = ["foo", "bar"]
+ tags: list[str] = ["foo", "bar"]
alias_with: str = Field(alias="with", default="nothing")
diff --git a/tests/test_forms_single_param.py b/tests/test_forms_single_param.py
index 3bb951441f..67f054b34e 100644
--- a/tests/test_forms_single_param.py
+++ b/tests/test_forms_single_param.py
@@ -1,6 +1,7 @@
+from typing import Annotated
+
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_generate_unique_id_function.py b/tests/test_generate_unique_id_function.py
index 5aeec66367..62ebfbc964 100644
--- a/tests/test_generate_unique_id_function.py
+++ b/tests/test_generate_unique_id_function.py
@@ -1,5 +1,4 @@
import warnings
-from typing import List
from fastapi import APIRouter, FastAPI
from fastapi.routing import APIRoute
@@ -33,12 +32,12 @@ def test_top_level_generate_unique_id():
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
router = APIRouter()
- @app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
+ @app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
def post_root(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@router.post(
- "/router", response_model=List[Item], responses={404: {"model": List[Message]}}
+ "/router", response_model=list[Item], responses={404: {"model": list[Message]}}
)
def post_router(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@@ -234,12 +233,12 @@ def test_router_overrides_generate_unique_id():
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
- @app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
+ @app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
def post_root(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@router.post(
- "/router", response_model=List[Item], responses={404: {"model": List[Message]}}
+ "/router", response_model=list[Item], responses={404: {"model": list[Message]}}
)
def post_router(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@@ -435,12 +434,12 @@ def test_router_include_overrides_generate_unique_id():
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
- @app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
+ @app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
def post_root(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@router.post(
- "/router", response_model=List[Item], responses={404: {"model": List[Message]}}
+ "/router", response_model=list[Item], responses={404: {"model": list[Message]}}
)
def post_router(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@@ -637,20 +636,20 @@ def test_subrouter_top_level_include_overrides_generate_unique_id():
router = APIRouter()
sub_router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
- @app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
+ @app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
def post_root(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@router.post(
- "/router", response_model=List[Item], responses={404: {"model": List[Message]}}
+ "/router", response_model=list[Item], responses={404: {"model": list[Message]}}
)
def post_router(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@sub_router.post(
"/subrouter",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
)
def post_subrouter(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@@ -910,14 +909,14 @@ def test_router_path_operation_overrides_generate_unique_id():
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
- @app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
+ @app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
def post_root(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@router.post(
"/router",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
generate_unique_id_function=custom_generate_unique_id3,
)
def post_router(item1: Item, item2: Item):
@@ -1116,8 +1115,8 @@ def test_app_path_operation_overrides_generate_unique_id():
@app.post(
"/",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
generate_unique_id_function=custom_generate_unique_id3,
)
def post_root(item1: Item, item2: Item):
@@ -1125,8 +1124,8 @@ def test_app_path_operation_overrides_generate_unique_id():
@router.post(
"/router",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
)
def post_router(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
@@ -1324,8 +1323,8 @@ def test_callback_override_generate_unique_id():
@callback_router.post(
"/post-callback",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
generate_unique_id_function=custom_generate_unique_id3,
)
def post_callback(item1: Item, item2: Item):
@@ -1333,8 +1332,8 @@ def test_callback_override_generate_unique_id():
@app.post(
"/",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
generate_unique_id_function=custom_generate_unique_id3,
callbacks=callback_router.routes,
)
@@ -1343,8 +1342,8 @@ def test_callback_override_generate_unique_id():
@app.post(
"/tocallback",
- response_model=List[Item],
- responses={404: {"model": List[Message]}},
+ response_model=list[Item],
+ responses={404: {"model": list[Message]}},
)
def post_with_callback(item1: Item, item2: Item):
return item1, item2 # pragma: nocover
diff --git a/tests/test_generic_parameterless_depends.py b/tests/test_generic_parameterless_depends.py
index 5aa35320c9..93b72ad243 100644
--- a/tests/test_generic_parameterless_depends.py
+++ b/tests/test_generic_parameterless_depends.py
@@ -1,8 +1,7 @@
-from typing import TypeVar
+from typing import Annotated, TypeVar
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_get_model_definitions_formfeed_escape.py b/tests/test_get_model_definitions_formfeed_escape.py
index 6601585ef0..215d06a072 100644
--- a/tests/test_get_model_definitions_formfeed_escape.py
+++ b/tests/test_get_model_definitions_formfeed_escape.py
@@ -1,4 +1,5 @@
-from typing import Any, Iterator, Set, Type
+from collections.abc import Iterator
+from typing import Any
import fastapi._compat
import fastapi.openapi.utils
@@ -143,11 +144,11 @@ class SortedTypeSet(set):
Set of Types whose `__iter__()` method yields results sorted by the type names
"""
- def __init__(self, seq: Set[Type[Any]], *, sort_reversed: bool):
+ def __init__(self, seq: set[type[Any]], *, sort_reversed: bool):
super().__init__(seq)
self.sort_reversed = sort_reversed
- def __iter__(self) -> Iterator[Type[Any]]:
+ def __iter__(self) -> Iterator[type[Any]]:
members_sorted = sorted(
super().__iter__(),
key=lambda type_: type_.__name__,
diff --git a/tests/test_invalid_path_param.py b/tests/test_invalid_path_param.py
index d5fa53c1fc..35c00363da 100644
--- a/tests/test_invalid_path_param.py
+++ b/tests/test_invalid_path_param.py
@@ -1,5 +1,3 @@
-from typing import Dict, List, Tuple
-
import pytest
from fastapi import FastAPI
from pydantic import BaseModel
@@ -13,7 +11,7 @@ def test_invalid_sequence():
title: str
@app.get("/items/{id}")
- def read_items(id: List[Item]):
+ def read_items(id: list[Item]):
pass # pragma: no cover
@@ -25,7 +23,7 @@ def test_invalid_tuple():
title: str
@app.get("/items/{id}")
- def read_items(id: Tuple[Item, Item]):
+ def read_items(id: tuple[Item, Item]):
pass # pragma: no cover
@@ -37,7 +35,7 @@ def test_invalid_dict():
title: str
@app.get("/items/{id}")
- def read_items(id: Dict[str, Item]):
+ def read_items(id: dict[str, Item]):
pass # pragma: no cover
diff --git a/tests/test_invalid_sequence_param.py b/tests/test_invalid_sequence_param.py
index 475786adbf..2b8fd059e1 100644
--- a/tests/test_invalid_sequence_param.py
+++ b/tests/test_invalid_sequence_param.py
@@ -1,4 +1,4 @@
-from typing import Dict, List, Optional, Tuple
+from typing import Optional
import pytest
from fastapi import FastAPI, Query
@@ -13,7 +13,7 @@ def test_invalid_sequence():
title: str
@app.get("/items/")
- def read_items(q: List[Item] = Query(default=None)):
+ def read_items(q: list[Item] = Query(default=None)):
pass # pragma: no cover
@@ -25,7 +25,7 @@ def test_invalid_tuple():
title: str
@app.get("/items/")
- def read_items(q: Tuple[Item, Item] = Query(default=None)):
+ def read_items(q: tuple[Item, Item] = Query(default=None)):
pass # pragma: no cover
@@ -37,7 +37,7 @@ def test_invalid_dict():
title: str
@app.get("/items/")
- def read_items(q: Dict[str, Item] = Query(default=None)):
+ def read_items(q: dict[str, Item] = Query(default=None)):
pass # pragma: no cover
diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py
index 33304827a9..6ea405fe70 100644
--- a/tests/test_multi_body_errors.py
+++ b/tests/test_multi_body_errors.py
@@ -1,5 +1,4 @@
from decimal import Decimal
-from typing import List
from dirty_equals import IsDict, IsOneOf
from fastapi import FastAPI
@@ -15,7 +14,7 @@ class Item(BaseModel):
@app.post("/items/")
-def save_item_no_body(item: List[Item]):
+def save_item_no_body(item: list[Item]):
return {"item": item}
diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py
index 8162d986c5..7387a81ddf 100644
--- a/tests/test_multi_query_errors.py
+++ b/tests/test_multi_query_errors.py
@@ -1,5 +1,3 @@
-from typing import List
-
from dirty_equals import IsDict
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
@@ -8,7 +6,7 @@ app = FastAPI()
@app.get("/items/")
-def read_items(q: List[int] = Query(default=None)):
+def read_items(q: list[int] = Query(default=None)):
return {"q": q}
diff --git a/tests/test_no_schema_split.py b/tests/test_no_schema_split.py
index b0b5958c1b..6169867ba3 100644
--- a/tests/test_no_schema_split.py
+++ b/tests/test_no_schema_split.py
@@ -3,7 +3,6 @@
# Made an issue in:
# https://github.com/fastapi/fastapi/issues/14247
from enum import Enum
-from typing import List
from fastapi import FastAPI
from fastapi.testclient import TestClient
@@ -25,7 +24,7 @@ class MessageEvent(BaseModel):
class MessageOutput(BaseModel):
body: str = ""
- events: List[MessageEvent] = []
+ events: list[MessageEvent] = []
class Message(BaseModel):
diff --git a/tests/test_openapi_schema_type.py b/tests/test_openapi_schema_type.py
index a45ea20c8c..98d9787455 100644
--- a/tests/test_openapi_schema_type.py
+++ b/tests/test_openapi_schema_type.py
@@ -1,4 +1,4 @@
-from typing import List, Optional, Union
+from typing import Optional, Union
import pytest
from fastapi.openapi.models import Schema, SchemaType
@@ -13,7 +13,7 @@ from fastapi.openapi.models import Schema, SchemaType
],
)
def test_allowed_schema_type(
- type_value: Optional[Union[SchemaType, List[SchemaType]]],
+ type_value: Optional[Union[SchemaType, list[SchemaType]]],
) -> None:
"""Test that Schema accepts SchemaType, List[SchemaType] and None for type field."""
schema = Schema(type=type_value)
diff --git a/tests/test_openapi_separate_input_output_schemas.py b/tests/test_openapi_separate_input_output_schemas.py
index c9a05418bf..bfe5e9a712 100644
--- a/tests/test_openapi_separate_input_output_schemas.py
+++ b/tests/test_openapi_separate_input_output_schemas.py
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
@@ -11,7 +11,7 @@ from .utils import PYDANTIC_V2, needs_pydanticv2
class SubItem(BaseModel):
subname: str
sub_description: Optional[str] = None
- tags: List[str] = []
+ tags: list[str] = []
if PYDANTIC_V2:
model_config = {"json_schema_serialization_defaults_required": True}
@@ -44,11 +44,11 @@ def get_app_client(separate_input_output_schemas: bool = True) -> TestClient:
return item
@app.post("/items-list/")
- def create_item_list(item: List[Item]):
+ def create_item_list(item: list[Item]):
return item
@app.get("/items/")
- def read_items() -> List[Item]:
+ def read_items() -> list[Item]:
return [
Item(
name="Portal Gun",
diff --git a/tests/test_optional_file_list.py b/tests/test_optional_file_list.py
index 0228900cf6..6860258643 100644
--- a/tests/test_optional_file_list.py
+++ b/tests/test_optional_file_list.py
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import Optional
from fastapi import FastAPI, File
from fastapi.testclient import TestClient
@@ -7,7 +7,7 @@ app = FastAPI()
@app.post("/files")
-async def upload_files(files: Optional[List[bytes]] = File(None)):
+async def upload_files(files: Optional[list[bytes]] = File(None)):
if files is None:
return {"files_count": 0}
return {"files_count": len(files), "sizes": [len(f) for f in files]}
diff --git a/tests/test_params_repr.py b/tests/test_params_repr.py
index baa172497d..19c2e8d696 100644
--- a/tests/test_params_repr.py
+++ b/tests/test_params_repr.py
@@ -1,9 +1,9 @@
-from typing import Any, List
+from typing import Any
from dirty_equals import IsOneOf
from fastapi.params import Body, Cookie, Header, Param, Path, Query
-test_data: List[Any] = ["teststr", None, ..., 1, []]
+test_data: list[Any] = ["teststr", None, ..., 1, []]
def get_user():
diff --git a/tests/test_pydantic_v1_v2_01.py b/tests/test_pydantic_v1_v2_01.py
index 769e5fab62..ebf86b99f0 100644
--- a/tests/test_pydantic_v1_v2_01.py
+++ b/tests/test_pydantic_v1_v2_01.py
@@ -1,5 +1,5 @@
import sys
-from typing import Any, List, Union
+from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
@@ -21,7 +21,7 @@ class Item(BaseModel):
size: int
description: Union[str, None] = None
sub: SubItem
- multi: List[SubItem] = []
+ multi: list[SubItem] = []
app = FastAPI()
diff --git a/tests/test_pydantic_v1_v2_list.py b/tests/test_pydantic_v1_v2_list.py
index 64f3dd3446..8879b010de 100644
--- a/tests/test_pydantic_v1_v2_list.py
+++ b/tests/test_pydantic_v1_v2_list.py
@@ -1,5 +1,5 @@
import sys
-from typing import Any, List, Union
+from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
@@ -21,18 +21,18 @@ class Item(BaseModel):
size: int
description: Union[str, None] = None
sub: SubItem
- multi: List[SubItem] = []
+ multi: list[SubItem] = []
app = FastAPI()
@app.post("/item")
-def handle_item(data: Item) -> List[Item]:
+def handle_item(data: Item) -> list[Item]:
return [data, data]
-@app.post("/item-filter", response_model=List[Item])
+@app.post("/item-filter", response_model=list[Item])
def handle_item_filter(data: Item) -> Any:
extended_data = data.dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
@@ -41,14 +41,14 @@ def handle_item_filter(data: Item) -> Any:
@app.post("/item-list")
-def handle_item_list(data: List[Item]) -> Item:
+def handle_item_list(data: list[Item]) -> Item:
if data:
return data[0]
return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-filter", response_model=Item)
-def handle_item_list_filter(data: List[Item]) -> Any:
+def handle_item_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
@@ -58,12 +58,12 @@ def handle_item_list_filter(data: List[Item]) -> Any:
@app.post("/item-list-to-list")
-def handle_item_list_to_list(data: List[Item]) -> List[Item]:
+def handle_item_list_to_list(data: list[Item]) -> list[Item]:
return data
-@app.post("/item-list-to-list-filter", response_model=List[Item])
-def handle_item_list_to_list_filter(data: List[Item]) -> Any:
+@app.post("/item-list-to-list-filter", response_model=list[Item])
+def handle_item_list_to_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
diff --git a/tests/test_pydantic_v1_v2_mixed.py b/tests/test_pydantic_v1_v2_mixed.py
index 54d408827f..e66583cd54 100644
--- a/tests/test_pydantic_v1_v2_mixed.py
+++ b/tests/test_pydantic_v1_v2_mixed.py
@@ -1,5 +1,5 @@
import sys
-from typing import Any, List, Union
+from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
@@ -22,7 +22,7 @@ class Item(BaseModel):
size: int
description: Union[str, None] = None
sub: SubItem
- multi: List[SubItem] = []
+ multi: list[SubItem] = []
class NewSubItem(NewBaseModel):
@@ -34,7 +34,7 @@ class NewItem(NewBaseModel):
new_size: int
new_description: Union[str, None] = None
new_sub: NewSubItem
- new_multi: List[NewSubItem] = []
+ new_multi: list[NewSubItem] = []
app = FastAPI()
@@ -93,7 +93,7 @@ def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
@app.post("/v1-to-v2/item-to-list")
-def handle_v1_item_to_v2_list(data: Item) -> List[NewItem]:
+def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
converted = NewItem(
new_title=data.title,
new_size=data.size,
@@ -105,7 +105,7 @@ def handle_v1_item_to_v2_list(data: Item) -> List[NewItem]:
@app.post("/v1-to-v2/list-to-list")
-def handle_v1_list_to_v2_list(data: List[Item]) -> List[NewItem]:
+def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
result = []
for item in data:
result.append(
@@ -120,8 +120,8 @@ def handle_v1_list_to_v2_list(data: List[Item]) -> List[NewItem]:
return result
-@app.post("/v1-to-v2/list-to-list-filter", response_model=List[NewItem])
-def handle_v1_list_to_v2_list_filter(data: List[Item]) -> Any:
+@app.post("/v1-to-v2/list-to-list-filter", response_model=list[NewItem])
+def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
result = []
for item in data:
converted = {
@@ -140,7 +140,7 @@ def handle_v1_list_to_v2_list_filter(data: List[Item]) -> Any:
@app.post("/v1-to-v2/list-to-item")
-def handle_v1_list_to_v2_item(data: List[Item]) -> NewItem:
+def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
if data:
item = data[0]
return NewItem(
@@ -154,7 +154,7 @@ def handle_v1_list_to_v2_item(data: List[Item]) -> NewItem:
@app.post("/v2-to-v1/item-to-list")
-def handle_v2_item_to_v1_list(data: NewItem) -> List[Item]:
+def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
converted = Item(
title=data.new_title,
size=data.new_size,
@@ -166,7 +166,7 @@ def handle_v2_item_to_v1_list(data: NewItem) -> List[Item]:
@app.post("/v2-to-v1/list-to-list")
-def handle_v2_list_to_v1_list(data: List[NewItem]) -> List[Item]:
+def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
result = []
for item in data:
result.append(
@@ -181,8 +181,8 @@ def handle_v2_list_to_v1_list(data: List[NewItem]) -> List[Item]:
return result
-@app.post("/v2-to-v1/list-to-list-filter", response_model=List[Item])
-def handle_v2_list_to_v1_list_filter(data: List[NewItem]) -> Any:
+@app.post("/v2-to-v1/list-to-list-filter", response_model=list[Item])
+def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
result = []
for item in data:
converted = {
@@ -201,7 +201,7 @@ def handle_v2_list_to_v1_list_filter(data: List[NewItem]) -> Any:
@app.post("/v2-to-v1/list-to-item")
-def handle_v2_list_to_v1_item(data: List[NewItem]) -> Item:
+def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
if data:
item = data[0]
return Item(
diff --git a/tests/test_pydantic_v1_v2_multifile/main.py b/tests/test_pydantic_v1_v2_multifile/main.py
index 8985cb7b4c..9397368abf 100644
--- a/tests/test_pydantic_v1_v2_multifile/main.py
+++ b/tests/test_pydantic_v1_v2_multifile/main.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from . import modelsv1, modelsv2, modelsv2b
@@ -30,7 +28,7 @@ def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
@app.post("/v1-to-v2/item-to-list")
-def handle_v1_item_to_v2_list(data: modelsv1.Item) -> List[modelsv2.Item]:
+def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
converted = modelsv2.Item(
new_title=data.title,
new_size=data.size,
@@ -42,7 +40,7 @@ def handle_v1_item_to_v2_list(data: modelsv1.Item) -> List[modelsv2.Item]:
@app.post("/v1-to-v2/list-to-list")
-def handle_v1_list_to_v2_list(data: List[modelsv1.Item]) -> List[modelsv2.Item]:
+def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
result = []
for item in data:
result.append(
@@ -58,7 +56,7 @@ def handle_v1_list_to_v2_list(data: List[modelsv1.Item]) -> List[modelsv2.Item]:
@app.post("/v1-to-v2/list-to-item")
-def handle_v1_list_to_v2_item(data: List[modelsv1.Item]) -> modelsv2.Item:
+def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
if data:
item = data[0]
return modelsv2.Item(
@@ -74,7 +72,7 @@ def handle_v1_list_to_v2_item(data: List[modelsv1.Item]) -> modelsv2.Item:
@app.post("/v2-to-v1/item-to-list")
-def handle_v2_item_to_v1_list(data: modelsv2.Item) -> List[modelsv1.Item]:
+def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
converted = modelsv1.Item(
title=data.new_title,
size=data.new_size,
@@ -86,7 +84,7 @@ def handle_v2_item_to_v1_list(data: modelsv2.Item) -> List[modelsv1.Item]:
@app.post("/v2-to-v1/list-to-list")
-def handle_v2_list_to_v1_list(data: List[modelsv2.Item]) -> List[modelsv1.Item]:
+def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
result = []
for item in data:
result.append(
@@ -102,7 +100,7 @@ def handle_v2_list_to_v1_list(data: List[modelsv2.Item]) -> List[modelsv1.Item]:
@app.post("/v2-to-v1/list-to-item")
-def handle_v2_list_to_v1_item(data: List[modelsv2.Item]) -> modelsv1.Item:
+def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
if data:
item = data[0]
return modelsv1.Item(
@@ -130,8 +128,8 @@ def handle_v2_same_name_to_v1(
@app.post("/v2-to-v1/list-of-items-to-list-of-items")
def handle_v2_items_in_list_to_v1_item_in_list(
- data1: List[modelsv2.ItemInList], data2: List[modelsv2b.ItemInList]
-) -> List[modelsv1.ItemInList]:
+ data1: list[modelsv2.ItemInList], data2: list[modelsv2b.ItemInList]
+) -> list[modelsv1.ItemInList]:
result = []
item1 = data1[0]
item2 = data2[0]
diff --git a/tests/test_pydantic_v1_v2_multifile/modelsv1.py b/tests/test_pydantic_v1_v2_multifile/modelsv1.py
index 889291a1a7..0cc8de4559 100644
--- a/tests/test_pydantic_v1_v2_multifile/modelsv1.py
+++ b/tests/test_pydantic_v1_v2_multifile/modelsv1.py
@@ -1,4 +1,4 @@
-from typing import List, Union
+from typing import Union
from fastapi._compat.v1 import BaseModel
@@ -12,7 +12,7 @@ class Item(BaseModel):
size: int
description: Union[str, None] = None
sub: SubItem
- multi: List[SubItem] = []
+ multi: list[SubItem] = []
class ItemInList(BaseModel):
diff --git a/tests/test_pydantic_v1_v2_multifile/modelsv2.py b/tests/test_pydantic_v1_v2_multifile/modelsv2.py
index 2c8c6ea356..d80b77e103 100644
--- a/tests/test_pydantic_v1_v2_multifile/modelsv2.py
+++ b/tests/test_pydantic_v1_v2_multifile/modelsv2.py
@@ -1,4 +1,4 @@
-from typing import List, Union
+from typing import Union
from pydantic import BaseModel
@@ -12,7 +12,7 @@ class Item(BaseModel):
new_size: int
new_description: Union[str, None] = None
new_sub: SubItem
- new_multi: List[SubItem] = []
+ new_multi: list[SubItem] = []
class ItemInList(BaseModel):
diff --git a/tests/test_pydantic_v1_v2_multifile/modelsv2b.py b/tests/test_pydantic_v1_v2_multifile/modelsv2b.py
index dc0c06c669..e992bea2e1 100644
--- a/tests/test_pydantic_v1_v2_multifile/modelsv2b.py
+++ b/tests/test_pydantic_v1_v2_multifile/modelsv2b.py
@@ -1,4 +1,4 @@
-from typing import List, Union
+from typing import Union
from pydantic import BaseModel
@@ -12,7 +12,7 @@ class Item(BaseModel):
dup_size: int
dup_description: Union[str, None] = None
dup_sub: SubItem
- dup_multi: List[SubItem] = []
+ dup_multi: list[SubItem] = []
class ItemInList(BaseModel):
diff --git a/tests/test_pydantic_v1_v2_noneable.py b/tests/test_pydantic_v1_v2_noneable.py
index d2d6f6635b..3e86469908 100644
--- a/tests/test_pydantic_v1_v2_noneable.py
+++ b/tests/test_pydantic_v1_v2_noneable.py
@@ -1,5 +1,5 @@
import sys
-from typing import Any, List, Union
+from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
@@ -22,7 +22,7 @@ class Item(BaseModel):
size: int
description: Union[str, None] = None
sub: SubItem
- multi: List[SubItem] = []
+ multi: list[SubItem] = []
class NewSubItem(NewBaseModel):
@@ -34,7 +34,7 @@ class NewItem(NewBaseModel):
new_size: int
new_description: Union[str, None] = None
new_sub: NewSubItem
- new_multi: List[NewSubItem] = []
+ new_multi: list[NewSubItem] = []
app = FastAPI()
diff --git a/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py b/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py
index c9f94563bb..b72b0518a1 100644
--- a/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py
+++ b/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py
@@ -2,7 +2,7 @@ from __future__ import annotations
import uuid
from dataclasses import dataclass, field
-from typing import List, Union
+from typing import Union
from dirty_equals import IsUUID
from fastapi import FastAPI
@@ -15,7 +15,7 @@ class Item:
id: uuid.UUID
name: str
price: float
- tags: List[str] = field(default_factory=list)
+ tags: list[str] = field(default_factory=list)
description: Union[str, None] = None
tax: Union[float, None] = None
diff --git a/tests/test_regex_deprecated_body.py b/tests/test_regex_deprecated_body.py
index 74654ff3ce..cfbff19c87 100644
--- a/tests/test_regex_deprecated_body.py
+++ b/tests/test_regex_deprecated_body.py
@@ -1,8 +1,9 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from .utils import needs_py310
diff --git a/tests/test_regex_deprecated_params.py b/tests/test_regex_deprecated_params.py
index 2ce64c6862..7d9988f9f8 100644
--- a/tests/test_regex_deprecated_params.py
+++ b/tests/test_regex_deprecated_params.py
@@ -1,8 +1,9 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from .utils import needs_py310
diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py
index 8c72fee54a..d1bff9ddf4 100644
--- a/tests/test_request_body_parameters_media_type.py
+++ b/tests/test_request_body_parameters_media_type.py
@@ -1,5 +1,3 @@
-import typing
-
from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -28,7 +26,7 @@ async def create_product(data: Product = Body(media_type=media_type, embed=True)
@app.post("/shops")
async def create_shop(
data: Shop = Body(media_type=media_type),
- included: typing.List[Product] = Body(default=[], media_type=media_type),
+ included: list[Product] = Body(default=[], media_type=media_type),
):
pass # pragma: no cover
diff --git a/tests/test_request_params/test_body/test_list.py b/tests/test_request_params/test_body/test_list.py
index 18a2a2f308..b2503a1c44 100644
--- a/tests/test_request_params/test_body/test_list.py
+++ b/tests/test_request_params/test_body/test_list.py
@@ -1,11 +1,10 @@
-from typing import List, Union
+from typing import Annotated, Union
import pytest
from dirty_equals import IsDict, IsOneOf, IsPartialDict
from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -18,12 +17,12 @@ app = FastAPI()
@app.post("/required-list-str", operation_id="required_list_str")
-async def read_required_list_str(p: Annotated[List[str], Body(embed=True)]):
+async def read_required_list_str(p: Annotated[list[str], Body(embed=True)]):
return {"p": p}
class BodyModelRequiredListStr(BaseModel):
- p: List[str]
+ p: list[str]
@app.post("/model-required-list-str", operation_id="model_required_list_str")
@@ -103,13 +102,13 @@ def test_required_list_str(path: str):
@app.post("/required-list-alias", operation_id="required_list_alias")
async def read_required_list_alias(
- p: Annotated[List[str], Body(embed=True, alias="p_alias")],
+ p: Annotated[list[str], Body(embed=True, alias="p_alias")],
):
return {"p": p}
class BodyModelRequiredListAlias(BaseModel):
- p: List[str] = Field(alias="p_alias")
+ p: list[str] = Field(alias="p_alias")
@app.post("/model-required-list-alias", operation_id="model_required_list_alias")
@@ -228,13 +227,13 @@ def test_required_list_alias_by_alias(path: str):
"/required-list-validation-alias", operation_id="required_list_validation_alias"
)
def read_required_list_validation_alias(
- p: Annotated[List[str], Body(embed=True, validation_alias="p_val_alias")],
+ p: Annotated[list[str], Body(embed=True, validation_alias="p_val_alias")],
):
return {"p": p}
class BodyModelRequiredListValidationAlias(BaseModel):
- p: List[str] = Field(validation_alias="p_val_alias")
+ p: list[str] = Field(validation_alias="p_val_alias")
@app.post(
@@ -345,14 +344,14 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
)
def read_required_list_alias_and_validation_alias(
p: Annotated[
- List[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
+ list[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
],
):
return {"p": p}
class BodyModelRequiredListAliasAndValidationAlias(BaseModel):
- p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
+ p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
@app.post(
diff --git a/tests/test_request_params/test_body/test_optional_list.py b/tests/test_request_params/test_body/test_optional_list.py
index e2ecdc7f43..ede635f840 100644
--- a/tests/test_request_params/test_body/test_optional_list.py
+++ b/tests/test_request_params/test_body/test_optional_list.py
@@ -1,11 +1,10 @@
-from typing import List, Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -19,13 +18,13 @@ app = FastAPI()
@app.post("/optional-list-str", operation_id="optional_list_str")
async def read_optional_list_str(
- p: Annotated[Optional[List[str]], Body(embed=True)] = None,
+ p: Annotated[Optional[list[str]], Body(embed=True)] = None,
):
return {"p": p}
class BodyModelOptionalListStr(BaseModel):
- p: Optional[List[str]] = None
+ p: Optional[list[str]] = None
@app.post("/model-optional-list-str", operation_id="model_optional_list_str")
@@ -131,13 +130,13 @@ def test_optional_list_str(path: str):
@app.post("/optional-list-alias", operation_id="optional_list_alias")
async def read_optional_list_alias(
- p: Annotated[Optional[List[str]], Body(embed=True, alias="p_alias")] = None,
+ p: Annotated[Optional[list[str]], Body(embed=True, alias="p_alias")] = None,
):
return {"p": p}
class BodyModelOptionalListAlias(BaseModel):
- p: Optional[List[str]] = Field(None, alias="p_alias")
+ p: Optional[list[str]] = Field(None, alias="p_alias")
@app.post("/model-optional-list-alias", operation_id="model_optional_list_alias")
@@ -264,14 +263,14 @@ def test_optional_list_alias_by_alias(path: str):
)
def read_optional_list_validation_alias(
p: Annotated[
- Optional[List[str]], Body(embed=True, validation_alias="p_val_alias")
+ Optional[list[str]], Body(embed=True, validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class BodyModelOptionalListValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(None, validation_alias="p_val_alias")
+ p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
@app.post(
@@ -410,7 +409,7 @@ def test_optional_list_validation_alias_by_validation_alias(path: str):
)
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[List[str]],
+ Optional[list[str]],
Body(embed=True, alias="p_alias", validation_alias="p_val_alias"),
] = None,
):
@@ -418,7 +417,7 @@ def read_optional_list_alias_and_validation_alias(
class BodyModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(
+ p: Optional[list[str]] = Field(
None, alias="p_alias", validation_alias="p_val_alias"
)
diff --git a/tests/test_request_params/test_body/test_optional_str.py b/tests/test_request_params/test_body/test_optional_str.py
index a49f5a3675..9e0c7217cc 100644
--- a/tests/test_request_params/test_body/test_optional_str.py
+++ b/tests/test_request_params/test_body/test_optional_str.py
@@ -1,11 +1,10 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_body/test_required_str.py b/tests/test_request_params/test_body/test_required_str.py
index 18c660cad2..aa47a4ede3 100644
--- a/tests/test_request_params/test_body/test_required_str.py
+++ b/tests/test_request_params/test_body/test_required_str.py
@@ -1,11 +1,10 @@
-from typing import Any, Dict, Union
+from typing import Annotated, Any, Union
import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -54,7 +53,7 @@ def test_required_str_schema(path: str):
"path",
["/required-str", "/model-required-str"],
)
-def test_required_str_missing(path: str, json: Union[Dict[str, Any], None]):
+def test_required_str_missing(path: str, json: Union[dict[str, Any], None]):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
@@ -140,7 +139,7 @@ def test_required_str_alias_schema(path: str):
"path",
["/required-alias", "/model-required-alias"],
)
-def test_required_alias_missing(path: str, json: Union[Dict[str, Any], None]):
+def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
@@ -266,7 +265,7 @@ def test_required_validation_alias_schema(path: str):
],
)
def test_required_validation_alias_missing(
- path: str, json: Union[Dict[str, Any], None]
+ path: str, json: Union[dict[str, Any], None]
):
client = TestClient(app)
response = client.post(path, json=json)
@@ -386,7 +385,7 @@ def test_required_alias_and_validation_alias_schema(path: str):
],
)
def test_required_alias_and_validation_alias_missing(
- path: str, json: Union[Dict[str, Any], None]
+ path: str, json: Union[dict[str, Any], None]
):
client = TestClient(app)
response = client.post(path, json=json)
diff --git a/tests/test_request_params/test_body/utils.py b/tests/test_request_params/test_body/utils.py
index 5151a82d36..bf07394f90 100644
--- a/tests/test_request_params/test_body/utils.py
+++ b/tests/test_request_params/test_body/utils.py
@@ -1,7 +1,7 @@
-from typing import Any, Dict
+from typing import Any
-def get_body_model_name(openapi: Dict[str, Any], path: str) -> str:
+def get_body_model_name(openapi: dict[str, Any], path: str) -> str:
body = openapi["paths"][path]["post"]["requestBody"]
body_schema = body["content"]["application/json"]["schema"]
return body_schema.get("$ref", "").split("/")[-1]
diff --git a/tests/test_request_params/test_cookie/test_optional_str.py b/tests/test_request_params/test_cookie/test_optional_str.py
index 1eec45689d..f2d02dae54 100644
--- a/tests/test_request_params/test_cookie/test_optional_str.py
+++ b/tests/test_request_params/test_cookie/test_optional_str.py
@@ -1,11 +1,10 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_cookie/test_required_str.py b/tests/test_request_params/test_cookie/test_required_str.py
index 6d0fa2ef29..3255857d44 100644
--- a/tests/test_request_params/test_cookie/test_required_str.py
+++ b/tests/test_request_params/test_cookie/test_required_str.py
@@ -1,9 +1,10 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_file/test_list.py b/tests/test_request_params/test_file/test_list.py
index 94a33967f3..52b032e441 100644
--- a/tests/test_request_params/test_file/test_list.py
+++ b/tests/test_request_params/test_file/test_list.py
@@ -1,10 +1,9 @@
-from typing import List
+from typing import Annotated
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -17,12 +16,12 @@ app = FastAPI()
@app.post("/list-bytes", operation_id="list_bytes")
-async def read_list_bytes(p: Annotated[List[bytes], File()]):
+async def read_list_bytes(p: Annotated[list[bytes], File()]):
return {"file_size": [len(file) for file in p]}
@app.post("/list-uploadfile", operation_id="list_uploadfile")
-async def read_list_uploadfile(p: Annotated[List[UploadFile], File()]):
+async def read_list_uploadfile(p: Annotated[list[UploadFile], File()]):
return {"file_size": [file.size for file in p]}
@@ -122,13 +121,13 @@ def test_list(path: str):
@app.post("/list-bytes-alias", operation_id="list_bytes_alias")
-async def read_list_bytes_alias(p: Annotated[List[bytes], File(alias="p_alias")]):
+async def read_list_bytes_alias(p: Annotated[list[bytes], File(alias="p_alias")]):
return {"file_size": [len(file) for file in p]}
@app.post("/list-uploadfile-alias", operation_id="list_uploadfile_alias")
async def read_list_uploadfile_alias(
- p: Annotated[List[UploadFile], File(alias="p_alias")],
+ p: Annotated[list[UploadFile], File(alias="p_alias")],
):
return {"file_size": [file.size for file in p]}
@@ -266,7 +265,7 @@ def test_list_alias_by_alias(path: str):
@app.post("/list-bytes-validation-alias", operation_id="list_bytes_validation_alias")
def read_list_bytes_validation_alias(
- p: Annotated[List[bytes], File(validation_alias="p_val_alias")],
+ p: Annotated[list[bytes], File(validation_alias="p_val_alias")],
):
return {"file_size": [len(file) for file in p]}
@@ -276,7 +275,7 @@ def read_list_bytes_validation_alias(
operation_id="list_uploadfile_validation_alias",
)
def read_list_uploadfile_validation_alias(
- p: Annotated[List[UploadFile], File(validation_alias="p_val_alias")],
+ p: Annotated[list[UploadFile], File(validation_alias="p_val_alias")],
):
return {"file_size": [file.size for file in p]}
@@ -401,7 +400,7 @@ def test_list_validation_alias_by_validation_alias(path: str):
operation_id="list_bytes_alias_and_validation_alias",
)
def read_list_bytes_alias_and_validation_alias(
- p: Annotated[List[bytes], File(alias="p_alias", validation_alias="p_val_alias")],
+ p: Annotated[list[bytes], File(alias="p_alias", validation_alias="p_val_alias")],
):
return {"file_size": [len(file) for file in p]}
@@ -412,7 +411,7 @@ def read_list_bytes_alias_and_validation_alias(
)
def read_list_uploadfile_alias_and_validation_alias(
p: Annotated[
- List[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
+ list[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
],
):
return {"file_size": [file.size for file in p]}
diff --git a/tests/test_request_params/test_file/test_optional.py b/tests/test_request_params/test_file/test_optional.py
index 2c1ca9530e..b7177e071d 100644
--- a/tests/test_request_params/test_file/test_optional.py
+++ b/tests/test_request_params/test_file/test_optional.py
@@ -1,10 +1,9 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_file/test_optional_list.py b/tests/test_request_params/test_file/test_optional_list.py
index 20e36501f8..af9fe552c9 100644
--- a/tests/test_request_params/test_file/test_optional_list.py
+++ b/tests/test_request_params/test_file/test_optional_list.py
@@ -1,10 +1,9 @@
-from typing import List, Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -17,13 +16,13 @@ app = FastAPI()
@app.post("/optional-list-bytes")
-async def read_optional_list_bytes(p: Annotated[Optional[List[bytes]], File()] = None):
+async def read_optional_list_bytes(p: Annotated[Optional[list[bytes]], File()] = None):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile")
async def read_optional_list_uploadfile(
- p: Annotated[Optional[List[UploadFile]], File()] = None,
+ p: Annotated[Optional[list[UploadFile]], File()] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@@ -103,14 +102,14 @@ def test_optional_list(path: str):
@app.post("/optional-list-bytes-alias")
async def read_optional_list_bytes_alias(
- p: Annotated[Optional[List[bytes]], File(alias="p_alias")] = None,
+ p: Annotated[Optional[list[bytes]], File(alias="p_alias")] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile-alias")
async def read_optional_list_uploadfile_alias(
- p: Annotated[Optional[List[UploadFile]], File(alias="p_alias")] = None,
+ p: Annotated[Optional[list[UploadFile]], File(alias="p_alias")] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@@ -204,7 +203,7 @@ def test_optional_list_alias_by_alias(path: str):
@app.post("/optional-list-bytes-validation-alias")
def read_optional_list_bytes_validation_alias(
- p: Annotated[Optional[List[bytes]], File(validation_alias="p_val_alias")] = None,
+ p: Annotated[Optional[list[bytes]], File(validation_alias="p_val_alias")] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@@ -212,7 +211,7 @@ def read_optional_list_bytes_validation_alias(
@app.post("/optional-list-uploadfile-validation-alias")
def read_optional_list_uploadfile_validation_alias(
p: Annotated[
- Optional[List[UploadFile]], File(validation_alias="p_val_alias")
+ Optional[list[UploadFile]], File(validation_alias="p_val_alias")
] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@@ -314,7 +313,7 @@ def test_optional_validation_alias_by_validation_alias(path: str):
@app.post("/optional-list-bytes-alias-and-validation-alias")
def read_optional_list_bytes_alias_and_validation_alias(
p: Annotated[
- Optional[List[bytes]], File(alias="p_alias", validation_alias="p_val_alias")
+ Optional[list[bytes]], File(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@@ -323,7 +322,7 @@ def read_optional_list_bytes_alias_and_validation_alias(
@app.post("/optional-list-uploadfile-alias-and-validation-alias")
def read_optional_list_uploadfile_alias_and_validation_alias(
p: Annotated[
- Optional[List[UploadFile]],
+ Optional[list[UploadFile]],
File(alias="p_alias", validation_alias="p_val_alias"),
] = None,
):
diff --git a/tests/test_request_params/test_file/test_required.py b/tests/test_request_params/test_file/test_required.py
index f041ac1ccf..2979a1040a 100644
--- a/tests/test_request_params/test_file/test_required.py
+++ b/tests/test_request_params/test_file/test_required.py
@@ -1,8 +1,9 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_file/utils.py b/tests/test_request_params/test_file/utils.py
index e33f64385f..e2a97ccd9b 100644
--- a/tests/test_request_params/test_file/utils.py
+++ b/tests/test_request_params/test_file/utils.py
@@ -1,7 +1,7 @@
-from typing import Any, Dict
+from typing import Any
-def get_body_model_name(openapi: Dict[str, Any], path: str) -> str:
+def get_body_model_name(openapi: dict[str, Any], path: str) -> str:
body = openapi["paths"][path]["post"]["requestBody"]
body_schema = body["content"]["multipart/form-data"]["schema"]
return body_schema.get("$ref", "").split("/")[-1]
diff --git a/tests/test_request_params/test_form/test_list.py b/tests/test_request_params/test_form/test_list.py
index 69a1b6a380..9f45aa755d 100644
--- a/tests/test_request_params/test_form/test_list.py
+++ b/tests/test_request_params/test_form/test_list.py
@@ -1,11 +1,10 @@
-from typing import List
+from typing import Annotated
import pytest
from dirty_equals import IsDict, IsOneOf, IsPartialDict
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -18,12 +17,12 @@ app = FastAPI()
@app.post("/required-list-str", operation_id="required_list_str")
-async def read_required_list_str(p: Annotated[List[str], Form()]):
+async def read_required_list_str(p: Annotated[list[str], Form()]):
return {"p": p}
class FormModelRequiredListStr(BaseModel):
- p: List[str]
+ p: list[str]
@app.post("/model-required-list-str", operation_id="model_required_list_str")
@@ -101,12 +100,12 @@ def test_required_list_str(path: str):
@app.post("/required-list-alias", operation_id="required_list_alias")
-async def read_required_list_alias(p: Annotated[List[str], Form(alias="p_alias")]):
+async def read_required_list_alias(p: Annotated[list[str], Form(alias="p_alias")]):
return {"p": p}
class FormModelRequiredListAlias(BaseModel):
- p: List[str] = Field(alias="p_alias")
+ p: list[str] = Field(alias="p_alias")
@app.post("/model-required-list-alias", operation_id="model_required_list_alias")
@@ -229,13 +228,13 @@ def test_required_list_alias_by_alias(path: str):
"/required-list-validation-alias", operation_id="required_list_validation_alias"
)
def read_required_list_validation_alias(
- p: Annotated[List[str], Form(validation_alias="p_val_alias")],
+ p: Annotated[list[str], Form(validation_alias="p_val_alias")],
):
return {"p": p}
class FormModelRequiredListValidationAlias(BaseModel):
- p: List[str] = Field(validation_alias="p_val_alias")
+ p: list[str] = Field(validation_alias="p_val_alias")
@app.post(
@@ -345,13 +344,13 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
operation_id="required_list_alias_and_validation_alias",
)
def read_required_list_alias_and_validation_alias(
- p: Annotated[List[str], Form(alias="p_alias", validation_alias="p_val_alias")],
+ p: Annotated[list[str], Form(alias="p_alias", validation_alias="p_val_alias")],
):
return {"p": p}
class FormModelRequiredListAliasAndValidationAlias(BaseModel):
- p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
+ p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
@app.post(
diff --git a/tests/test_request_params/test_form/test_optional_list.py b/tests/test_request_params/test_form/test_optional_list.py
index 1f779a7ed9..0af6d34777 100644
--- a/tests/test_request_params/test_form/test_optional_list.py
+++ b/tests/test_request_params/test_form/test_optional_list.py
@@ -1,11 +1,10 @@
-from typing import List, Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -19,13 +18,13 @@ app = FastAPI()
@app.post("/optional-list-str", operation_id="optional_list_str")
async def read_optional_list_str(
- p: Annotated[Optional[List[str]], Form()] = None,
+ p: Annotated[Optional[list[str]], Form()] = None,
):
return {"p": p}
class FormModelOptionalListStr(BaseModel):
- p: Optional[List[str]] = None
+ p: Optional[list[str]] = None
@app.post("/model-optional-list-str", operation_id="model_optional_list_str")
@@ -95,13 +94,13 @@ def test_optional_list_str(path: str):
@app.post("/optional-list-alias", operation_id="optional_list_alias")
async def read_optional_list_alias(
- p: Annotated[Optional[List[str]], Form(alias="p_alias")] = None,
+ p: Annotated[Optional[list[str]], Form(alias="p_alias")] = None,
):
return {"p": p}
class FormModelOptionalListAlias(BaseModel):
- p: Optional[List[str]] = Field(None, alias="p_alias")
+ p: Optional[list[str]] = Field(None, alias="p_alias")
@app.post("/model-optional-list-alias", operation_id="model_optional_list_alias")
@@ -193,13 +192,13 @@ def test_optional_list_alias_by_alias(path: str):
"/optional-list-validation-alias", operation_id="optional_list_validation_alias"
)
def read_optional_list_validation_alias(
- p: Annotated[Optional[List[str]], Form(validation_alias="p_val_alias")] = None,
+ p: Annotated[Optional[list[str]], Form(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class FormModelOptionalListValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(None, validation_alias="p_val_alias")
+ p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
@app.post(
@@ -300,14 +299,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str):
)
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[List[str]], Form(alias="p_alias", validation_alias="p_val_alias")
+ Optional[list[str]], Form(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class FormModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(
+ p: Optional[list[str]] = Field(
None, alias="p_alias", validation_alias="p_val_alias"
)
diff --git a/tests/test_request_params/test_form/test_optional_str.py b/tests/test_request_params/test_form/test_optional_str.py
index 9698659452..92329216ec 100644
--- a/tests/test_request_params/test_form/test_optional_str.py
+++ b/tests/test_request_params/test_form/test_optional_str.py
@@ -1,11 +1,10 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_form/test_required_str.py b/tests/test_request_params/test_form/test_required_str.py
index c901e7b445..1e33038040 100644
--- a/tests/test_request_params/test_form/test_required_str.py
+++ b/tests/test_request_params/test_form/test_required_str.py
@@ -1,9 +1,10 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_form/utils.py b/tests/test_request_params/test_form/utils.py
index d200650dfd..9132173111 100644
--- a/tests/test_request_params/test_form/utils.py
+++ b/tests/test_request_params/test_form/utils.py
@@ -1,7 +1,7 @@
-from typing import Any, Dict
+from typing import Any
-def get_body_model_name(openapi: Dict[str, Any], path: str) -> str:
+def get_body_model_name(openapi: dict[str, Any], path: str) -> str:
body = openapi["paths"][path]["post"]["requestBody"]
body_schema = body["content"]["application/x-www-form-urlencoded"]["schema"]
return body_schema.get("$ref", "").split("/")[-1]
diff --git a/tests/test_request_params/test_header/test_list.py b/tests/test_request_params/test_header/test_list.py
index 4a5f4bb647..62f9f36ff6 100644
--- a/tests/test_request_params/test_header/test_list.py
+++ b/tests/test_request_params/test_header/test_list.py
@@ -1,11 +1,10 @@
-from typing import List
+from typing import Annotated
import pytest
from dirty_equals import AnyThing, IsDict, IsOneOf, IsPartialDict
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -16,12 +15,12 @@ app = FastAPI()
@app.get("/required-list-str")
-async def read_required_list_str(p: Annotated[List[str], Header()]):
+async def read_required_list_str(p: Annotated[list[str], Header()]):
return {"p": p}
class HeaderModelRequiredListStr(BaseModel):
- p: List[str]
+ p: list[str]
@app.get("/model-required-list-str")
@@ -96,12 +95,12 @@ def test_required_list_str(path: str):
@app.get("/required-list-alias")
-async def read_required_list_alias(p: Annotated[List[str], Header(alias="p_alias")]):
+async def read_required_list_alias(p: Annotated[list[str], Header(alias="p_alias")]):
return {"p": p}
class HeaderModelRequiredListAlias(BaseModel):
- p: List[str] = Field(alias="p_alias")
+ p: list[str] = Field(alias="p_alias")
@app.get("/model-required-list-alias")
@@ -219,13 +218,13 @@ def test_required_list_alias_by_alias(path: str):
@app.get("/required-list-validation-alias")
def read_required_list_validation_alias(
- p: Annotated[List[str], Header(validation_alias="p_val_alias")],
+ p: Annotated[list[str], Header(validation_alias="p_val_alias")],
):
return {"p": p}
class HeaderModelRequiredListValidationAlias(BaseModel):
- p: List[str] = Field(validation_alias="p_val_alias")
+ p: list[str] = Field(validation_alias="p_val_alias")
@app.get("/model-required-list-validation-alias")
@@ -328,13 +327,13 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
@app.get("/required-list-alias-and-validation-alias")
def read_required_list_alias_and_validation_alias(
- p: Annotated[List[str], Header(alias="p_alias", validation_alias="p_val_alias")],
+ p: Annotated[list[str], Header(alias="p_alias", validation_alias="p_val_alias")],
):
return {"p": p}
class HeaderModelRequiredListAliasAndValidationAlias(BaseModel):
- p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
+ p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-required-list-alias-and-validation-alias")
diff --git a/tests/test_request_params/test_header/test_optional_list.py b/tests/test_request_params/test_header/test_optional_list.py
index e81025c02b..88243f05a9 100644
--- a/tests/test_request_params/test_header/test_optional_list.py
+++ b/tests/test_request_params/test_header/test_optional_list.py
@@ -1,11 +1,10 @@
-from typing import List, Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -17,13 +16,13 @@ app = FastAPI()
@app.get("/optional-list-str")
async def read_optional_list_str(
- p: Annotated[Optional[List[str]], Header()] = None,
+ p: Annotated[Optional[list[str]], Header()] = None,
):
return {"p": p}
class HeaderModelOptionalListStr(BaseModel):
- p: Optional[List[str]] = None
+ p: Optional[list[str]] = None
@app.get("/model-optional-list-str")
@@ -93,13 +92,13 @@ def test_optional_list_str(path: str):
@app.get("/optional-list-alias")
async def read_optional_list_alias(
- p: Annotated[Optional[List[str]], Header(alias="p_alias")] = None,
+ p: Annotated[Optional[list[str]], Header(alias="p_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalListAlias(BaseModel):
- p: Optional[List[str]] = Field(None, alias="p_alias")
+ p: Optional[list[str]] = Field(None, alias="p_alias")
@app.get("/model-optional-list-alias")
@@ -187,13 +186,13 @@ def test_optional_list_alias_by_alias(path: str):
@app.get("/optional-list-validation-alias")
def read_optional_list_validation_alias(
- p: Annotated[Optional[List[str]], Header(validation_alias="p_val_alias")] = None,
+ p: Annotated[Optional[list[str]], Header(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalListValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(None, validation_alias="p_val_alias")
+ p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-list-validation-alias")
@@ -273,14 +272,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str):
@app.get("/optional-list-alias-and-validation-alias")
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[List[str]], Header(alias="p_alias", validation_alias="p_val_alias")
+ Optional[list[str]], Header(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class HeaderModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(
+ p: Optional[list[str]] = Field(
None, alias="p_alias", validation_alias="p_val_alias"
)
diff --git a/tests/test_request_params/test_header/test_optional_str.py b/tests/test_request_params/test_header/test_optional_str.py
index 5ae9f26701..e40b1669ee 100644
--- a/tests/test_request_params/test_header/test_optional_str.py
+++ b/tests/test_request_params/test_header/test_optional_str.py
@@ -1,11 +1,10 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_header/test_required_str.py b/tests/test_request_params/test_header/test_required_str.py
index d57c66919d..23554d3e4a 100644
--- a/tests/test_request_params/test_header/test_required_str.py
+++ b/tests/test_request_params/test_header/test_required_str.py
@@ -1,9 +1,10 @@
+from typing import Annotated
+
import pytest
from dirty_equals import AnyThing, IsDict, IsOneOf, IsPartialDict
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_path/test_required_str.py b/tests/test_request_params/test_path/test_required_str.py
index 6417199674..ecd4eb61cd 100644
--- a/tests/test_request_params/test_path/test_required_str.py
+++ b/tests/test_request_params/test_path/test_required_str.py
@@ -1,7 +1,8 @@
+from typing import Annotated
+
import pytest
from fastapi import FastAPI, Path
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_query/test_list.py b/tests/test_request_params/test_query/test_list.py
index 71cbca51fb..6a3000fbf6 100644
--- a/tests/test_request_params/test_query/test_list.py
+++ b/tests/test_request_params/test_query/test_list.py
@@ -1,11 +1,10 @@
-from typing import List
+from typing import Annotated
import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -16,12 +15,12 @@ app = FastAPI()
@app.get("/required-list-str")
-async def read_required_list_str(p: Annotated[List[str], Query()]):
+async def read_required_list_str(p: Annotated[list[str], Query()]):
return {"p": p}
class QueryModelRequiredListStr(BaseModel):
- p: List[str]
+ p: list[str]
@app.get("/model-required-list-str")
@@ -96,12 +95,12 @@ def test_required_list_str(path: str):
@app.get("/required-list-alias")
-async def read_required_list_alias(p: Annotated[List[str], Query(alias="p_alias")]):
+async def read_required_list_alias(p: Annotated[list[str], Query(alias="p_alias")]):
return {"p": p}
class QueryModelRequiredListAlias(BaseModel):
- p: List[str] = Field(alias="p_alias")
+ p: list[str] = Field(alias="p_alias")
@app.get("/model-required-list-alias")
@@ -219,13 +218,13 @@ def test_required_list_alias_by_alias(path: str):
@app.get("/required-list-validation-alias")
def read_required_list_validation_alias(
- p: Annotated[List[str], Query(validation_alias="p_val_alias")],
+ p: Annotated[list[str], Query(validation_alias="p_val_alias")],
):
return {"p": p}
class QueryModelRequiredListValidationAlias(BaseModel):
- p: List[str] = Field(validation_alias="p_val_alias")
+ p: list[str] = Field(validation_alias="p_val_alias")
@app.get("/model-required-list-validation-alias")
@@ -326,13 +325,13 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
@app.get("/required-list-alias-and-validation-alias")
def read_required_list_alias_and_validation_alias(
- p: Annotated[List[str], Query(alias="p_alias", validation_alias="p_val_alias")],
+ p: Annotated[list[str], Query(alias="p_alias", validation_alias="p_val_alias")],
):
return {"p": p}
class QueryModelRequiredListAliasAndValidationAlias(BaseModel):
- p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
+ p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-required-list-alias-and-validation-alias")
diff --git a/tests/test_request_params/test_query/test_optional_list.py b/tests/test_request_params/test_query/test_optional_list.py
index 5609213364..f4b8ec6a82 100644
--- a/tests/test_request_params/test_query/test_optional_list.py
+++ b/tests/test_request_params/test_query/test_optional_list.py
@@ -1,11 +1,10 @@
-from typing import List, Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
@@ -17,13 +16,13 @@ app = FastAPI()
@app.get("/optional-list-str")
async def read_optional_list_str(
- p: Annotated[Optional[List[str]], Query()] = None,
+ p: Annotated[Optional[list[str]], Query()] = None,
):
return {"p": p}
class QueryModelOptionalListStr(BaseModel):
- p: Optional[List[str]] = None
+ p: Optional[list[str]] = None
@app.get("/model-optional-list-str")
@@ -93,13 +92,13 @@ def test_optional_list_str(path: str):
@app.get("/optional-list-alias")
async def read_optional_list_alias(
- p: Annotated[Optional[List[str]], Query(alias="p_alias")] = None,
+ p: Annotated[Optional[list[str]], Query(alias="p_alias")] = None,
):
return {"p": p}
class QueryModelOptionalListAlias(BaseModel):
- p: Optional[List[str]] = Field(None, alias="p_alias")
+ p: Optional[list[str]] = Field(None, alias="p_alias")
@app.get("/model-optional-list-alias")
@@ -187,13 +186,13 @@ def test_optional_list_alias_by_alias(path: str):
@app.get("/optional-list-validation-alias")
def read_optional_list_validation_alias(
- p: Annotated[Optional[List[str]], Query(validation_alias="p_val_alias")] = None,
+ p: Annotated[Optional[list[str]], Query(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class QueryModelOptionalListValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(None, validation_alias="p_val_alias")
+ p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-list-validation-alias")
@@ -271,14 +270,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str):
@app.get("/optional-list-alias-and-validation-alias")
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[List[str]], Query(alias="p_alias", validation_alias="p_val_alias")
+ Optional[list[str]], Query(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class QueryModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[List[str]] = Field(
+ p: Optional[list[str]] = Field(
None, alias="p_alias", validation_alias="p_val_alias"
)
diff --git a/tests/test_request_params/test_query/test_optional_str.py b/tests/test_request_params/test_query/test_optional_str.py
index 25e4ea42e6..c7d20e37d1 100644
--- a/tests/test_request_params/test_query/test_optional_str.py
+++ b/tests/test_request_params/test_query/test_optional_str.py
@@ -1,11 +1,10 @@
-from typing import Optional
+from typing import Annotated, Optional
import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_request_params/test_query/test_required_str.py b/tests/test_request_params/test_query/test_required_str.py
index aa0731e2c6..ce30f3b1f8 100644
--- a/tests/test_request_params/test_query/test_required_str.py
+++ b/tests/test_request_params/test_query/test_required_str.py
@@ -1,9 +1,10 @@
+from typing import Annotated
+
import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from typing_extensions import Annotated
from tests.utils import needs_pydanticv2
diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py
index e162cd39b5..5b241c76b6 100644
--- a/tests/test_response_by_alias.py
+++ b/tests/test_response_by_alias.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
@@ -45,7 +43,7 @@ def read_model():
return Model(alias="Foo")
-@app.get("/list", response_model=List[Model], response_model_by_alias=False)
+@app.get("/list", response_model=list[Model], response_model_by_alias=False)
def read_list():
return [{"alias": "Foo"}, {"alias": "Bar"}]
@@ -60,7 +58,7 @@ def by_alias_model():
return Model(alias="Foo")
-@app.get("/by-alias/list", response_model=List[Model])
+@app.get("/by-alias/list", response_model=list[Model])
def by_alias_list():
return [{"alias": "Foo"}, {"alias": "Bar"}]
@@ -75,7 +73,7 @@ def no_alias_model():
return ModelNoAlias(name="Foo")
-@app.get("/no-alias/list", response_model=List[ModelNoAlias])
+@app.get("/no-alias/list", response_model=list[ModelNoAlias])
def no_alias_list():
return [{"name": "Foo"}, {"name": "Bar"}]
diff --git a/tests/test_response_class_no_mediatype.py b/tests/test_response_class_no_mediatype.py
index 706929ac36..4dc164bf92 100644
--- a/tests/test_response_class_no_mediatype.py
+++ b/tests/test_response_class_no_mediatype.py
@@ -1,5 +1,3 @@
-import typing
-
from fastapi import FastAPI, Response
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
@@ -18,7 +16,7 @@ class Error(BaseModel):
class JsonApiError(BaseModel):
- errors: typing.List[Error]
+ errors: list[Error]
@app.get(
diff --git a/tests/test_response_code_no_body.py b/tests/test_response_code_no_body.py
index 3ca8708f12..70456a7462 100644
--- a/tests/test_response_code_no_body.py
+++ b/tests/test_response_code_no_body.py
@@ -1,5 +1,3 @@
-import typing
-
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
@@ -18,7 +16,7 @@ class Error(BaseModel):
class JsonApiError(BaseModel):
- errors: typing.List[Error]
+ errors: list[Error]
@app.get(
diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py
index 1745c69b60..44e882a76e 100644
--- a/tests/test_response_model_as_return_annotation.py
+++ b/tests/test_response_model_as_return_annotation.py
@@ -1,4 +1,4 @@
-from typing import List, Union
+from typing import Union
import pytest
from fastapi import FastAPI
@@ -191,7 +191,7 @@ def response_model_filtering_model_annotation_submodel_return_submodel() -> DBUs
return DBUser(name="John", surname="Doe", password_hash="secret")
-@app.get("/response_model_list_of_model-no_annotation", response_model=List[User])
+@app.get("/response_model_list_of_model-no_annotation", response_model=list[User])
def response_model_list_of_model_no_annotation():
return [
DBUser(name="John", surname="Doe", password_hash="secret"),
@@ -200,7 +200,7 @@ def response_model_list_of_model_no_annotation():
@app.get("/no_response_model-annotation_list_of_model")
-def no_response_model_annotation_list_of_model() -> List[User]:
+def no_response_model_annotation_list_of_model() -> list[User]:
return [
DBUser(name="John", surname="Doe", password_hash="secret"),
DBUser(name="Jane", surname="Does", password_hash="secret2"),
@@ -208,7 +208,7 @@ def no_response_model_annotation_list_of_model() -> List[User]:
@app.get("/no_response_model-annotation_forward_ref_list_of_model")
-def no_response_model_annotation_forward_ref_list_of_model() -> "List[User]":
+def no_response_model_annotation_forward_ref_list_of_model() -> "list[User]":
return [
DBUser(name="John", surname="Doe", password_hash="secret"),
DBUser(name="Jane", surname="Does", password_hash="secret2"),
diff --git a/tests/test_response_model_data_filter.py b/tests/test_response_model_data_filter.py
index a3e0f95f04..358697d6df 100644
--- a/tests/test_response_model_data_filter.py
+++ b/tests/test_response_model_data_filter.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -44,7 +42,7 @@ async def read_pet(pet_id: int):
return pet
-@app.get("/pets/", response_model=List[PetOut])
+@app.get("/pets/", response_model=list[PetOut])
async def read_pets():
user = UserDB(
email="johndoe@example.com",
diff --git a/tests/test_response_model_data_filter_no_inheritance.py b/tests/test_response_model_data_filter_no_inheritance.py
index 64003a8417..c0c2f3a9dc 100644
--- a/tests/test_response_model_data_filter_no_inheritance.py
+++ b/tests/test_response_model_data_filter_no_inheritance.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -46,7 +44,7 @@ async def read_pet(pet_id: int):
return pet
-@app.get("/pets/", response_model=List[PetOut])
+@app.get("/pets/", response_model=list[PetOut])
async def read_pets():
user = UserDB(
email="johndoe@example.com",
diff --git a/tests/test_response_model_invalid.py b/tests/test_response_model_invalid.py
index 88b55a436d..f884b5c74a 100644
--- a/tests/test_response_model_invalid.py
+++ b/tests/test_response_model_invalid.py
@@ -1,5 +1,3 @@
-from typing import List
-
import pytest
from fastapi import FastAPI
from fastapi.exceptions import FastAPIError
@@ -22,7 +20,7 @@ def test_invalid_response_model_sub_type_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
- @app.get("/", response_model=List[NonPydanticModel])
+ @app.get("/", response_model=list[NonPydanticModel])
def read_root():
pass # pragma: nocover
@@ -40,6 +38,6 @@ def test_invalid_response_model_sub_type_in_responses_raises():
with pytest.raises(FastAPIError):
app = FastAPI()
- @app.get("/", responses={"500": {"model": List[NonPydanticModel]}})
+ @app.get("/", responses={"500": {"model": list[NonPydanticModel]}})
def read_root():
pass # pragma: nocover
diff --git a/tests/test_response_model_sub_types.py b/tests/test_response_model_sub_types.py
index 660bcee1bb..8036bcb07d 100644
--- a/tests/test_response_model_sub_types.py
+++ b/tests/test_response_model_sub_types.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -17,7 +15,7 @@ def valid1():
pass
-@app.get("/valid2", responses={"500": {"model": List[int]}})
+@app.get("/valid2", responses={"500": {"model": list[int]}})
def valid2():
pass
@@ -27,7 +25,7 @@ def valid3():
pass
-@app.get("/valid4", responses={"500": {"model": List[Model]}})
+@app.get("/valid4", responses={"500": {"model": list[Model]}})
def valid4():
pass
diff --git a/tests/test_router_events.py b/tests/test_router_events.py
index dd7ff3314b..9df299cdaa 100644
--- a/tests/test_router_events.py
+++ b/tests/test_router_events.py
@@ -1,5 +1,6 @@
+from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
-from typing import AsyncGenerator, Dict, Union
+from typing import Union
import pytest
from fastapi import APIRouter, FastAPI, Request
@@ -28,7 +29,7 @@ def test_router_events(state: State) -> None:
app = FastAPI()
@app.get("/")
- def main() -> Dict[str, str]:
+ def main() -> dict[str, str]:
return {"message": "Hello World"}
@app.on_event("startup")
@@ -96,7 +97,7 @@ def test_app_lifespan_state(state: State) -> None:
app = FastAPI(lifespan=lifespan)
@app.get("/")
- def main() -> Dict[str, str]:
+ def main() -> dict[str, str]:
return {"message": "Hello World"}
assert state.app_startup is False
@@ -113,19 +114,19 @@ def test_app_lifespan_state(state: State) -> None:
def test_router_nested_lifespan_state(state: State) -> None:
@asynccontextmanager
- async def lifespan(app: FastAPI) -> AsyncGenerator[Dict[str, bool], None]:
+ async def lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
state.app_startup = True
yield {"app": True}
state.app_shutdown = True
@asynccontextmanager
- async def router_lifespan(app: FastAPI) -> AsyncGenerator[Dict[str, bool], None]:
+ async def router_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
state.router_startup = True
yield {"router": True}
state.router_shutdown = True
@asynccontextmanager
- async def subrouter_lifespan(app: FastAPI) -> AsyncGenerator[Dict[str, bool], None]:
+ async def subrouter_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
state.sub_router_startup = True
yield {"sub_router": True}
state.sub_router_shutdown = True
@@ -139,7 +140,7 @@ def test_router_nested_lifespan_state(state: State) -> None:
app.include_router(router)
@app.get("/")
- def main(request: Request) -> Dict[str, str]:
+ def main(request: Request) -> dict[str, str]:
assert request.state.app
assert request.state.router
assert request.state.sub_router
@@ -175,7 +176,7 @@ def test_router_nested_lifespan_state_overriding_by_parent() -> None:
@asynccontextmanager
async def lifespan(
app: FastAPI,
- ) -> AsyncGenerator[Dict[str, Union[str, bool]], None]:
+ ) -> AsyncGenerator[dict[str, Union[str, bool]], None]:
yield {
"app_specific": True,
"overridden": "app",
@@ -184,7 +185,7 @@ def test_router_nested_lifespan_state_overriding_by_parent() -> None:
@asynccontextmanager
async def router_lifespan(
app: FastAPI,
- ) -> AsyncGenerator[Dict[str, Union[str, bool]], None]:
+ ) -> AsyncGenerator[dict[str, Union[str, bool]], None]:
yield {
"router_specific": True,
"overridden": "router", # should override parent
@@ -225,7 +226,7 @@ def test_merged_mixed_state_lifespans() -> None:
yield
@asynccontextmanager
- async def router_lifespan(app: FastAPI) -> AsyncGenerator[Dict[str, bool], None]:
+ async def router_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"router": True}
@asynccontextmanager
diff --git a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py
index d41f1dc1f0..583007c8b7 100644
--- a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py
+++ b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py
@@ -1,12 +1,11 @@
# Ref: https://github.com/fastapi/fastapi/issues/14454
-from typing import Optional
+from typing import Annotated, Optional
from fastapi import APIRouter, Depends, FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from typing_extensions import Annotated
oauth2_scheme = OAuth2AuthorizationCodeBearer(
authorizationUrl="authorize",
diff --git a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi_simple.py b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi_simple.py
index ff866d4fc9..1c21369d33 100644
--- a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi_simple.py
+++ b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi_simple.py
@@ -1,10 +1,11 @@
# Ref: https://github.com/fastapi/fastapi/issues/14454
+from typing import Annotated
+
from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from typing_extensions import Annotated
oauth2_scheme = OAuth2AuthorizationCodeBearer(
authorizationUrl="api/oauth/authorize",
diff --git a/tests/test_security_scopes.py b/tests/test_security_scopes.py
index 248fd2bcc2..fccb026fe2 100644
--- a/tests/test_security_scopes.py
+++ b/tests/test_security_scopes.py
@@ -1,9 +1,8 @@
-from typing import Dict
+from typing import Annotated
import pytest
from fastapi import Depends, FastAPI, Security
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
@pytest.fixture(name="call_counter")
@@ -12,7 +11,7 @@ def call_counter_fixture():
@pytest.fixture(name="app")
-def app_fixture(call_counter: Dict[str, int]):
+def app_fixture(call_counter: dict[str, int]):
def get_db():
call_counter["count"] += 1
return f"db_{call_counter['count']}"
@@ -38,7 +37,7 @@ def client_fixture(app: FastAPI):
def test_security_scopes_dependency_called_once(
- client: TestClient, call_counter: Dict[str, int]
+ client: TestClient, call_counter: dict[str, int]
):
response = client.get("/")
diff --git a/tests/test_security_scopes_dont_propagate.py b/tests/test_security_scopes_dont_propagate.py
index 2bbcc749d3..c306ed0590 100644
--- a/tests/test_security_scopes_dont_propagate.py
+++ b/tests/test_security_scopes_dont_propagate.py
@@ -1,11 +1,10 @@
# Ref: https://github.com/tiangolo/fastapi/issues/5623
-from typing import Any, Dict, List
+from typing import Annotated, Any
from fastapi import FastAPI, Security
from fastapi.security import SecurityScopes
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
async def security1(scopes: SecurityScopes):
@@ -17,8 +16,8 @@ async def security2(scopes: SecurityScopes):
async def dep3(
- dep1: Annotated[List[str], Security(security1, scopes=["scope1"])],
- dep2: Annotated[List[str], Security(security2, scopes=["scope2"])],
+ dep1: Annotated[list[str], Security(security1, scopes=["scope1"])],
+ dep2: Annotated[list[str], Security(security2, scopes=["scope2"])],
):
return {"dep1": dep1, "dep2": dep2}
@@ -28,7 +27,7 @@ app = FastAPI()
@app.get("/scopes")
def get_scopes(
- dep3: Annotated[Dict[str, Any], Security(dep3, scopes=["scope3"])],
+ dep3: Annotated[dict[str, Any], Security(dep3, scopes=["scope3"])],
):
return dep3
diff --git a/tests/test_security_scopes_sub_dependency.py b/tests/test_security_scopes_sub_dependency.py
index 9cc668d8e7..2c64d5f3d5 100644
--- a/tests/test_security_scopes_sub_dependency.py
+++ b/tests/test_security_scopes_sub_dependency.py
@@ -1,12 +1,12 @@
# Ref: https://github.com/fastapi/fastapi/discussions/6024#discussioncomment-8541913
-from typing import Dict
+
+from typing import Annotated
import pytest
from fastapi import Depends, FastAPI, Security
from fastapi.security import SecurityScopes
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
@pytest.fixture(name="call_counts")
@@ -20,7 +20,7 @@ def call_counts_fixture():
@pytest.fixture(name="app")
-def app_fixture(call_counts: Dict[str, int]):
+def app_fixture(call_counts: dict[str, int]):
def get_db_session():
call_counts["get_db_session"] += 1
return f"db_session_{call_counts['get_db_session']}"
@@ -75,7 +75,7 @@ def client_fixture(app: FastAPI):
def test_security_scopes_sub_dependency_caching(
- client: TestClient, call_counts: Dict[str, int]
+ client: TestClient, call_counts: dict[str, int]
):
response = client.get("/")
diff --git a/tests/test_serialize_response.py b/tests/test_serialize_response.py
index d823e5e04a..14f88dd931 100644
--- a/tests/test_serialize_response.py
+++ b/tests/test_serialize_response.py
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
@@ -10,7 +10,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: Optional[float] = None
- owner_ids: Optional[List[int]] = None
+ owner_ids: Optional[list[int]] = None
@app.get("/items/valid", response_model=Item)
@@ -23,7 +23,7 @@ def get_coerce():
return {"name": "coerce", "price": "1.0"}
-@app.get("/items/validlist", response_model=List[Item])
+@app.get("/items/validlist", response_model=list[Item])
def get_validlist():
return [
{"name": "foo"},
diff --git a/tests/test_serialize_response_dataclass.py b/tests/test_serialize_response_dataclass.py
index 1e3bf3b28b..ee695368b8 100644
--- a/tests/test_serialize_response_dataclass.py
+++ b/tests/test_serialize_response_dataclass.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass
from datetime import datetime
-from typing import List, Optional
+from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
@@ -13,7 +13,7 @@ class Item:
name: str
date: datetime
price: Optional[float] = None
- owner_ids: Optional[List[int]] = None
+ owner_ids: Optional[list[int]] = None
@app.get("/items/valid", response_model=Item)
@@ -33,7 +33,7 @@ def get_coerce():
return {"name": "coerce", "date": datetime(2021, 7, 26).isoformat(), "price": "1.0"}
-@app.get("/items/validlist", response_model=List[Item])
+@app.get("/items/validlist", response_model=list[Item])
def get_validlist():
return [
{"name": "foo", "date": datetime(2021, 7, 26)},
@@ -47,7 +47,7 @@ def get_validlist():
]
-@app.get("/items/objectlist", response_model=List[Item])
+@app.get("/items/objectlist", response_model=list[Item])
def get_objectlist():
return [
Item(name="foo", date=datetime(2021, 7, 26)),
diff --git a/tests/test_serialize_response_model.py b/tests/test_serialize_response_model.py
index 3bb46b2e9b..79c90c9c29 100644
--- a/tests/test_serialize_response_model.py
+++ b/tests/test_serialize_response_model.py
@@ -1,4 +1,4 @@
-from typing import Dict, List, Optional
+from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, Field
@@ -10,7 +10,7 @@ app = FastAPI()
class Item(BaseModel):
name: str = Field(alias="aliased_name")
price: Optional[float] = None
- owner_ids: Optional[List[int]] = None
+ owner_ids: Optional[list[int]] = None
@app.get("/items/valid", response_model=Item)
@@ -23,7 +23,7 @@ def get_coerce():
return Item(aliased_name="coerce", price="1.0")
-@app.get("/items/validlist", response_model=List[Item])
+@app.get("/items/validlist", response_model=list[Item])
def get_validlist():
return [
Item(aliased_name="foo"),
@@ -32,7 +32,7 @@ def get_validlist():
]
-@app.get("/items/validdict", response_model=Dict[str, Item])
+@app.get("/items/validdict", response_model=dict[str, Item])
def get_validdict():
return {
"k1": Item(aliased_name="foo"),
@@ -59,7 +59,7 @@ def get_coerce_exclude_unset():
@app.get(
"/items/validlist-exclude-unset",
- response_model=List[Item],
+ response_model=list[Item],
response_model_exclude_unset=True,
)
def get_validlist_exclude_unset():
@@ -72,7 +72,7 @@ def get_validlist_exclude_unset():
@app.get(
"/items/validdict-exclude-unset",
- response_model=Dict[str, Item],
+ response_model=dict[str, Item],
response_model_exclude_unset=True,
)
def get_validdict_exclude_unset():
diff --git a/tests/test_stringified_annotation_dependency.py b/tests/test_stringified_annotation_dependency.py
index 89bb884b5c..ce88074957 100644
--- a/tests/test_stringified_annotation_dependency.py
+++ b/tests/test_stringified_annotation_dependency.py
@@ -1,12 +1,11 @@
from __future__ import annotations
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Annotated
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from typing_extensions import Annotated
if TYPE_CHECKING: # pragma: no cover
from collections.abc import AsyncGenerator
diff --git a/tests/test_stringified_annotations_simple.py b/tests/test_stringified_annotations_simple.py
index 9bd6d09d63..6e037fb21f 100644
--- a/tests/test_stringified_annotations_simple.py
+++ b/tests/test_stringified_annotations_simple.py
@@ -1,8 +1,9 @@
from __future__ import annotations
+from typing import Annotated
+
from fastapi import Depends, FastAPI, Request
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
from .utils import needs_py310
diff --git a/tests/test_tuples.py b/tests/test_tuples.py
index ca33d2580c..fbc69a6145 100644
--- a/tests/test_tuples.py
+++ b/tests/test_tuples.py
@@ -1,5 +1,3 @@
-from typing import List, Tuple
-
from dirty_equals import IsDict
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
@@ -9,7 +7,7 @@ app = FastAPI()
class ItemGroup(BaseModel):
- items: List[Tuple[str, str]]
+ items: list[tuple[str, str]]
class Coordinate(BaseModel):
@@ -23,12 +21,12 @@ def post_model_with_tuple(item_group: ItemGroup):
@app.post("/tuple-of-models/")
-def post_tuple_of_models(square: Tuple[Coordinate, Coordinate]):
+def post_tuple_of_models(square: tuple[Coordinate, Coordinate]):
return square
@app.post("/tuple-form/")
-def hello(values: Tuple[int, int] = Form()):
+def hello(values: tuple[int, int] = Form()):
return values
diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py
index 3afeaff840..1a18db75ce 100644
--- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py
+++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.additional_responses.tutorial001 import app
+from docs_src.additional_responses.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py
index 91d6ff101f..bbcad8f294 100644
--- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py
+++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py
@@ -12,7 +12,7 @@ from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002"),
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py
index bd34d2938c..90dc4e371e 100644
--- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py
+++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.additional_responses.tutorial003 import app
+from docs_src.additional_responses.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py
index 2d9491467e..cbd4fff7d6 100644
--- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py
+++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py
@@ -12,7 +12,7 @@ from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004"),
+ pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py b/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py
index b304f70153..bced1f6dfe 100644
--- a/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py
+++ b/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py
@@ -3,16 +3,15 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
index 157fa5caf1..f17391956e 100644
--- a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
+++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial001 import app
+from docs_src.advanced_middleware.tutorial001_py39 import app
def test_middleware():
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py
index 79be52f4db..bae915406e 100644
--- a/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py
+++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial002 import app
+from docs_src.advanced_middleware.tutorial002_py39 import app
def test_middleware():
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py
index 04a922ff7b..66697997c8 100644
--- a/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py
+++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py
@@ -1,7 +1,7 @@
from fastapi.responses import PlainTextResponse
from fastapi.testclient import TestClient
-from docs_src.advanced_middleware.tutorial003 import app
+from docs_src.advanced_middleware.tutorial003_py39 import app
@app.get("/large")
diff --git a/tests/test_tutorial/test_async_tests/test_main.py b/tests/test_tutorial/test_async_tests/test_main_a.py
similarity index 58%
rename from tests/test_tutorial/test_async_tests/test_main.py
rename to tests/test_tutorial/test_async_tests/test_main_a.py
index 1f5d7186cc..f29acaa9a0 100644
--- a/tests/test_tutorial/test_async_tests/test_main.py
+++ b/tests/test_tutorial/test_async_tests/test_main_a.py
@@ -1,6 +1,6 @@
import pytest
-from docs_src.async_tests.test_main import test_root
+from docs_src.async_tests.app_a_py39.test_main import test_root
@pytest.mark.anyio
diff --git a/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py b/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py
index bbd7bff30f..6f58116313 100644
--- a/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py
+++ b/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py
@@ -4,14 +4,11 @@ import pytest
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_background_tasks/test_tutorial001.py b/tests/test_tutorial/test_background_tasks/test_tutorial001.py
index 0602cd8aa4..c0ad27a6f5 100644
--- a/tests/test_tutorial/test_background_tasks/test_tutorial001.py
+++ b/tests/test_tutorial/test_background_tasks/test_tutorial001.py
@@ -3,7 +3,7 @@ from pathlib import Path
from fastapi.testclient import TestClient
-from docs_src.background_tasks.tutorial001 import app
+from docs_src.background_tasks.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_background_tasks/test_tutorial002.py b/tests/test_tutorial/test_background_tasks/test_tutorial002.py
index d5ef51ee2b..288a1c244e 100644
--- a/tests/test_tutorial/test_background_tasks/test_tutorial002.py
+++ b/tests/test_tutorial/test_background_tasks/test_tutorial002.py
@@ -5,16 +5,15 @@ from pathlib import Path
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial002",
+ "tutorial002_py39",
pytest.param("tutorial002_py310", marks=needs_py310),
- "tutorial002_an",
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ "tutorial002_an_py39",
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py
index a070f850f7..00574b5b0f 100644
--- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py
+++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial001 import app
+from docs_src.behind_a_proxy.tutorial001_py39 import app
client = TestClient(app, root_path="/api/v1")
diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py
index f13046e018..da4acb28cc 100644
--- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py
+++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial001_01 import app
+from docs_src.behind_a_proxy.tutorial001_01_py39 import app
client = TestClient(
app,
diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py
index ce791e2157..1a49c0dfeb 100644
--- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py
+++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial002 import app
+from docs_src.behind_a_proxy.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py
index ec17b41790..2d1d1b03c8 100644
--- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py
+++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py
@@ -1,7 +1,7 @@
from dirty_equals import IsOneOf
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial003 import app
+from docs_src.behind_a_proxy.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py
index 2f8eb46995..e8a03e8112 100644
--- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py
+++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py
@@ -1,7 +1,7 @@
from dirty_equals import IsOneOf
from fastapi.testclient import TestClient
-from docs_src.behind_a_proxy.tutorial004 import app
+from docs_src.behind_a_proxy.tutorial004_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py
index fe40fad7d0..7493a9e661 100644
--- a/tests/test_tutorial/test_bigger_applications/test_main.py
+++ b/tests/test_tutorial/test_bigger_applications/test_main.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "app_an.main",
- pytest.param("app_an_py39.main", marks=needs_py39),
- "app.main",
+ "app_py39.main",
+ "app_an_py39.main",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py
index f8b5aee8d2..6aa9f2593e 100644
--- a/tests/test_tutorial/test_body/test_tutorial001.py
+++ b/tests/test_tutorial/test_body/test_tutorial001.py
@@ -11,7 +11,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py
index fb68f28689..d54ec7191a 100644
--- a/tests/test_tutorial/test_body_fields/test_tutorial001.py
+++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py
index 1424055952..2035cf9448 100644
--- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py
+++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py
index d18ceae486..d3e6401af2 100644
--- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py
+++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
+ "tutorial003_py39",
pytest.param("tutorial003_py310", marks=needs_py310),
- "tutorial003_an",
- pytest.param("tutorial003_an_py39", marks=needs_py39),
+ "tutorial003_an_py39",
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py
index 38ba3c8875..db9f04546e 100644
--- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py
+++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py
@@ -4,14 +4,11 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial009",
- pytest.param("tutorial009_py39", marks=needs_py39),
+ "tutorial009_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py
index f874dc9bd6..8bbc4d6992 100644
--- a/tests/test_tutorial/test_body_updates/test_tutorial001.py
+++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py
@@ -3,15 +3,14 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_py39", marks=needs_py39),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
index b098f259c2..a425e893d8 100644
--- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
+++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
@@ -6,11 +6,11 @@ from ...utils import needs_pydanticv2
def get_client() -> TestClient:
- from docs_src.conditional_openapi import tutorial001
+ from docs_src.conditional_openapi import tutorial001_py39
- importlib.reload(tutorial001)
+ importlib.reload(tutorial001_py39)
- client = TestClient(tutorial001.app)
+ client = TestClient(tutorial001_py39.app)
return client
diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py
index a04dba2197..1fa9419a76 100644
--- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py
+++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial001 import app
+from docs_src.configure_swagger_ui.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
index ea56b6f21c..c218cc858c 100644
--- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
+++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial002 import app
+from docs_src.configure_swagger_ui.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py
index 926bbb14f0..8b73685499 100644
--- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py
+++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.configure_swagger_ui.tutorial003 import app
+from docs_src.configure_swagger_ui.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py
index 60643185a4..265dee944e 100644
--- a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py
+++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py
@@ -5,16 +5,15 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
index cef6f66309..4a826a5374 100644
--- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
@@ -6,7 +6,6 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import (
- needs_py39,
needs_py310,
needs_pydanticv1,
needs_pydanticv2,
@@ -17,15 +16,13 @@ from tests.utils import (
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002", marks=needs_pydanticv2),
+ pytest.param("tutorial002_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py39", marks=[needs_py39, needs_pydanticv2]),
+ pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1", marks=[needs_pydanticv1, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an", marks=[needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=[needs_py39, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
],
)
diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py
index 90e8dfd37c..a65249d657 100644
--- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py
+++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py
@@ -5,16 +5,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="mod",
params=[
- "tutorial001",
+ "tutorial001_py39",
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_cors/test_tutorial001.py b/tests/test_tutorial/test_cors/test_tutorial001.py
index f62c9df4f9..6a733693ae 100644
--- a/tests/test_tutorial/test_cors/test_tutorial001.py
+++ b/tests/test_tutorial/test_cors/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.cors.tutorial001 import app
+from docs_src.cors.tutorial001_py39 import app
def test_cors():
diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py
index cb8e8c2248..1816e5d975 100644
--- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py
+++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py
@@ -10,7 +10,7 @@ def client():
static_dir: Path = Path(os.getcwd()) / "static"
print(static_dir)
static_dir.mkdir(exist_ok=True)
- from docs_src.custom_docs_ui.tutorial001 import app
+ from docs_src.custom_docs_ui.tutorial001_py39 import app
with TestClient(app) as client:
yield client
diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py
index 712618807c..e8b7eb7aa3 100644
--- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py
+++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py
@@ -10,7 +10,7 @@ def client():
static_dir: Path = Path(os.getcwd()) / "static"
print(static_dir)
static_dir.mkdir(exist_ok=True)
- from docs_src.custom_docs_ui.tutorial002 import app
+ from docs_src.custom_docs_ui.tutorial002_py39 import app
with TestClient(app) as client:
yield client
diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
index f9fd0d1af8..b4ea537846 100644
--- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
+++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
@@ -6,17 +6,15 @@ import pytest
from fastapi import Request
from fastapi.testclient import TestClient
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001"),
- pytest.param("tutorial001_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_an"),
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py
index c35752ed13..643011637e 100644
--- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py
+++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py
@@ -4,17 +4,15 @@ import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002"),
- pytest.param("tutorial002_py39", marks=needs_py39),
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_an"),
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py
index 9e895b2daf..6cad7bd3f0 100644
--- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py
+++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py
@@ -9,7 +9,7 @@ from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003"),
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py
index fc83624673..c81e991ebf 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial001.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial001 import app
+from docs_src.custom_response.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py
index 91e5c501e3..3337f47d5f 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial001b import app
+from docs_src.custom_response.tutorial001b_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial004.py
index de60574f5e..0e7d69791b 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial004.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial004.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial004 import app
+from docs_src.custom_response.tutorial004_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py
index 889bf3e929..fea105c28e 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial005.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial005.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial005 import app
+from docs_src.custom_response.tutorial005_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py
index 2d0a2cd3f6..e9e6ca1086 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial006.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial006 import app
+from docs_src.custom_response.tutorial006_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py
index 1739fd4570..7ca727d2cd 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial006b import app
+from docs_src.custom_response.tutorial006b_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py
index 2675f2a93c..e3f76c8403 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial006c import app
+from docs_src.custom_response.tutorial006c_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial007.py b/tests/test_tutorial/test_custom_response/test_tutorial007.py
index 4ede820b94..a62476ec14 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial007.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial007.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial007 import app
+from docs_src.custom_response.tutorial007_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial008.py b/tests/test_tutorial/test_custom_response/test_tutorial008.py
index 10d88a5948..d9fe61f539 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial008.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial008.py
@@ -2,15 +2,15 @@ from pathlib import Path
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial008
-from docs_src.custom_response.tutorial008 import app
+from docs_src.custom_response import tutorial008_py39
+from docs_src.custom_response.tutorial008_py39 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial008.some_file_path = str(file_path)
+ tutorial008_py39.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009.py b/tests/test_tutorial/test_custom_response/test_tutorial009.py
index ac20f89e67..cb6a514be6 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial009.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial009.py
@@ -2,15 +2,15 @@ from pathlib import Path
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial009
-from docs_src.custom_response.tutorial009 import app
+from docs_src.custom_response import tutorial009_py39
+from docs_src.custom_response.tutorial009_py39 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial009.some_file_path = str(file_path)
+ tutorial009_py39.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009b.py b/tests/test_tutorial/test_custom_response/test_tutorial009b.py
index 4f56e2f3fe..9918bdb1ac 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial009b.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial009b.py
@@ -2,15 +2,15 @@ from pathlib import Path
from fastapi.testclient import TestClient
-from docs_src.custom_response import tutorial009b
-from docs_src.custom_response.tutorial009b import app
+from docs_src.custom_response import tutorial009b_py39
+from docs_src.custom_response.tutorial009b_py39 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
- tutorial009b.some_file_path = str(file_path)
+ tutorial009b_py39.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009c.py b/tests/test_tutorial/test_custom_response/test_tutorial009c.py
index 23c711abe9..efc3a6b4a0 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial009c.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial009c.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.custom_response.tutorial009c import app
+from docs_src.custom_response.tutorial009c_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py
index b36dee7684..d5f230bc42 100644
--- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py
+++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py
@@ -10,7 +10,7 @@ from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001"),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial002.py b/tests/test_tutorial/test_dataclasses/test_tutorial002.py
index baaea45d8f..4cf8933805 100644
--- a/tests/test_tutorial/test_dataclasses/test_tutorial002.py
+++ b/tests/test_tutorial/test_dataclasses/test_tutorial002.py
@@ -4,14 +4,13 @@ import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002"),
- pytest.param("tutorial002_py39", marks=needs_py39),
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py
index 5728d2b6b3..d8cc45dd69 100644
--- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py
+++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py
@@ -3,14 +3,13 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial003"),
- pytest.param("tutorial003_py39", marks=needs_py39),
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001.py b/tests/test_tutorial/test_dependencies/test_tutorial001.py
index ed9944912e..8dac99cf30 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial001.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial001.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial004.py
index 8221c83d44..8a1346d0d2 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial004.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial004.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial004",
+ pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- "tutorial004_an",
- pytest.param("tutorial004_an_py39", marks=needs_py39),
+ pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py
index 4530762f76..46f0066f9f 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial006.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial006",
- "tutorial006_an",
- pytest.param("tutorial006_an_py39", marks=needs_py39),
+ pytest.param("tutorial006_py39"),
+ pytest.param("tutorial006_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008b.py b/tests/test_tutorial/test_dependencies/test_tutorial008b.py
index 4d70922657..91e00b3705 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial008b.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008b.py
@@ -3,15 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial008b",
- "tutorial008b_an",
- pytest.param("tutorial008b_an_py39", marks=needs_py39),
+ pytest.param("tutorial008b_py39"),
+ pytest.param("tutorial008b_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c.py b/tests/test_tutorial/test_dependencies/test_tutorial008c.py
index 369b0a221d..aede6f8d25 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial008c.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008c.py
@@ -5,15 +5,12 @@ import pytest
from fastapi.exceptions import FastAPIError
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="mod",
params=[
- "tutorial008c",
- "tutorial008c_an",
- pytest.param("tutorial008c_an_py39", marks=needs_py39),
+ pytest.param("tutorial008c_py39"),
+ pytest.param("tutorial008c_an_py39"),
],
)
def get_mod(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008d.py b/tests/test_tutorial/test_dependencies/test_tutorial008d.py
index bc99bb3835..5477f8b953 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial008d.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008d.py
@@ -4,15 +4,12 @@ from types import ModuleType
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="mod",
params=[
- "tutorial008d",
- "tutorial008d_an",
- pytest.param("tutorial008d_an_py39", marks=needs_py39),
+ pytest.param("tutorial008d_py39"),
+ pytest.param("tutorial008d_an_py39"),
],
)
def get_mod(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008e.py b/tests/test_tutorial/test_dependencies/test_tutorial008e.py
index 1ae9ab2cd1..c433157ea1 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial008e.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008e.py
@@ -3,15 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial008e",
- "tutorial008e_an",
- pytest.param("tutorial008e_an_py39", marks=needs_py39),
+ pytest.param("tutorial008e_py39"),
+ pytest.param("tutorial008e_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py
index 0af17e9bc5..b791ee0aa1 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial012.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial012",
- "tutorial012_an",
- pytest.param("tutorial012_an_py39", marks=needs_py39),
+ pytest.param("tutorial012_py39"),
+ pytest.param("tutorial012_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py
index f65b92d127..5fe99d50df 100644
--- a/tests/test_tutorial/test_events/test_tutorial001.py
+++ b/tests/test_tutorial/test_events/test_tutorial001.py
@@ -6,7 +6,7 @@ from fastapi.testclient import TestClient
@pytest.fixture(name="app", scope="module")
def get_app():
with pytest.warns(DeprecationWarning):
- from docs_src.events.tutorial001 import app
+ from docs_src.events.tutorial001_py39 import app
yield app
diff --git a/tests/test_tutorial/test_events/test_tutorial002.py b/tests/test_tutorial/test_events/test_tutorial002.py
index 137294d737..0612899b55 100644
--- a/tests/test_tutorial/test_events/test_tutorial002.py
+++ b/tests/test_tutorial/test_events/test_tutorial002.py
@@ -6,7 +6,7 @@ from fastapi.testclient import TestClient
@pytest.fixture(name="app", scope="module")
def get_app():
with pytest.warns(DeprecationWarning):
- from docs_src.events.tutorial002 import app
+ from docs_src.events.tutorial002_py39 import app
yield app
diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py
index 0ad1a1f8b2..38710edfea 100644
--- a/tests/test_tutorial/test_events/test_tutorial003.py
+++ b/tests/test_tutorial/test_events/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.events.tutorial003 import (
+from docs_src.events.tutorial003_py39 import (
app,
fake_answer_to_everything_ml_model,
ml_models,
diff --git a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py
index a85a313501..83ecb300ee 100644
--- a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py
+++ b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.extending_openapi.tutorial001 import app
+from docs_src.extending_openapi.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py
index b816c9cab5..e11f73fe35 100644
--- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py
+++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py
index 73aa299039..3aa83c0c40 100644
--- a/tests/test_tutorial/test_extra_models/test_tutorial003.py
+++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004.py b/tests/test_tutorial/test_extra_models/test_tutorial004.py
index 7628db30c7..073375ccc9 100644
--- a/tests/test_tutorial/test_extra_models/test_tutorial004.py
+++ b/tests/test_tutorial/test_extra_models/test_tutorial004.py
@@ -3,14 +3,11 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial004",
- pytest.param("tutorial004_py39", marks=needs_py39),
+ pytest.param("tutorial004_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py
index 553e442385..8e52d8d4ba 100644
--- a/tests/test_tutorial/test_extra_models/test_tutorial005.py
+++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py
@@ -3,14 +3,11 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial005",
- pytest.param("tutorial005_py39", marks=needs_py39),
+ pytest.param("tutorial005_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001.py b/tests/test_tutorial/test_first_steps/test_tutorial001.py
index 6cc9fc2282..c102bb9999 100644
--- a/tests/test_tutorial/test_first_steps/test_tutorial001.py
+++ b/tests/test_tutorial/test_first_steps/test_tutorial001.py
@@ -1,7 +1,7 @@
import pytest
from fastapi.testclient import TestClient
-from docs_src.first_steps.tutorial001 import app
+from docs_src.first_steps.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py
index 1cd9678a1c..bac52e4fd6 100644
--- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py
+++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.generate_clients.tutorial003 import app
+from docs_src.generate_clients.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py
index 8809c135bd..c01850fae6 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial001 import app
+from docs_src.handling_errors.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py
index efd86ebdec..09366a86fa 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial002 import app
+from docs_src.handling_errors.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py
index 4763f68f3f..51ac3e7b28 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial003 import app
+from docs_src.handling_errors.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py
index c04bf37245..376bc8266f 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial004 import app
+from docs_src.handling_errors.tutorial004_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py
index 581b2e4c75..d713c5d876 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py
@@ -1,7 +1,7 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial005 import app
+from docs_src.handling_errors.tutorial005_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py
index 7d2f553aac..491e461b3d 100644
--- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py
+++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py
@@ -1,7 +1,7 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from docs_src.handling_errors.tutorial006 import app
+from docs_src.handling_errors.tutorial006_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial001.py b/tests/test_tutorial/test_header_param_models/test_tutorial001.py
index bc876897b2..f59d50762c 100644
--- a/tests/test_tutorial/test_header_param_models/test_tutorial001.py
+++ b/tests/test_tutorial/test_header_param_models/test_tutorial001.py
@@ -5,17 +5,15 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- pytest.param("tutorial001_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py
index 0615521c43..a7a271ba41 100644
--- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py
@@ -5,21 +5,19 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from tests.utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002", marks=needs_pydanticv2),
+ pytest.param("tutorial002_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py39", marks=[needs_py39, needs_pydanticv2]),
+ pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1", marks=[needs_pydanticv1, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an", marks=[needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=[needs_py39, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
],
)
diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial003.py b/tests/test_tutorial/test_header_param_models/test_tutorial003.py
index 554a48d2e8..947587504f 100644
--- a/tests/test_tutorial/test_header_param_models/test_tutorial003.py
+++ b/tests/test_tutorial/test_header_param_models/test_tutorial003.py
@@ -5,17 +5,15 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
- pytest.param("tutorial003_py39", marks=needs_py39),
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- "tutorial003_an",
- pytest.param("tutorial003_an_py39", marks=needs_py39),
+ pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py
index d6f7fe6189..beaf917f92 100644
--- a/tests/test_tutorial/test_header_params/test_tutorial001.py
+++ b/tests/test_tutorial/test_header_params/test_tutorial001.py
@@ -10,9 +10,9 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py
index 7158f8651b..b892ff905f 100644
--- a/tests/test_tutorial/test_header_params/test_tutorial002.py
+++ b/tests/test_tutorial/test_header_params/test_tutorial002.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial002",
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- "tutorial002_an",
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py
index 473b961236..ef76244159 100644
--- a/tests/test_tutorial/test_header_params/test_tutorial003.py
+++ b/tests/test_tutorial/test_header_params/test_tutorial003.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- "tutorial003_an",
- pytest.param("tutorial003_an_py39", marks=needs_py39),
+ pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_metadata/test_tutorial001.py b/tests/test_tutorial/test_metadata/test_tutorial001.py
index 04e8ff82b0..ead48577d0 100644
--- a/tests/test_tutorial/test_metadata/test_tutorial001.py
+++ b/tests/test_tutorial/test_metadata/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.metadata.tutorial001 import app
+from docs_src.metadata.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_metadata/test_tutorial001_1.py b/tests/test_tutorial/test_metadata/test_tutorial001_1.py
index 3efb1c4329..40878ccfd4 100644
--- a/tests/test_tutorial/test_metadata/test_tutorial001_1.py
+++ b/tests/test_tutorial/test_metadata/test_tutorial001_1.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.metadata.tutorial001_1 import app
+from docs_src.metadata.tutorial001_1_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_metadata/test_tutorial004.py b/tests/test_tutorial/test_metadata/test_tutorial004.py
index 5072203712..4ef93fd5e3 100644
--- a/tests/test_tutorial/test_metadata/test_tutorial004.py
+++ b/tests/test_tutorial/test_metadata/test_tutorial004.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.metadata.tutorial004 import app
+from docs_src.metadata.tutorial004_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py
index 2df2b98893..975e07cbdd 100644
--- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py
+++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py
@@ -11,7 +11,7 @@ from tests.utils import needs_py310
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial001"),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py
index dc67ec401d..27619489fa 100644
--- a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py
+++ b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.openapi_webhooks.tutorial001 import app
+from docs_src.openapi_webhooks.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py
index 95542398e4..ee0b707108 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_advanced_configuration.tutorial001 import app
+from docs_src.path_operation_advanced_configuration.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py
index d1388c3670..f6580d72e3 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_advanced_configuration.tutorial002 import app
+from docs_src.path_operation_advanced_configuration.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py
index 313bb2a04a..104554fce3 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_advanced_configuration.tutorial003 import app
+from docs_src.path_operation_advanced_configuration.tutorial003_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
index da5782d189..3805536e76 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
@@ -3,14 +3,13 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial004"),
- pytest.param("tutorial004_py39", marks=needs_py39),
+ pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py
index 07e2d7d202..e2a71236ff 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_advanced_configuration.tutorial005 import app
+from docs_src.path_operation_advanced_configuration.tutorial005_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
index f92c59015e..9484f7f573 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_advanced_configuration.tutorial006 import app
+from docs_src.path_operation_advanced_configuration.tutorial006_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
index a90337a63d..204cca09ed 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
@@ -3,14 +3,13 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_pydanticv2
+from ...utils import needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007"),
- pytest.param("tutorial007_py39", marks=needs_py39),
+ pytest.param("tutorial007_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007_pv1.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007_pv1.py
index b38e4947cc..62b67a98c1 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007_pv1.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007_pv1.py
@@ -3,14 +3,13 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_pydanticv1
+from ...utils import needs_pydanticv1
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial007_pv1"),
- pytest.param("tutorial007_pv1_py39", marks=needs_py39),
+ pytest.param("tutorial007_pv1_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py
index 58dec5769d..5a0193adfa 100644
--- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py
+++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_operation_configuration.tutorial002b import app
+from docs_src.path_operation_configuration.tutorial002b_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
index 0742f5d0e8..2a7a2b78b2 100644
--- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
+++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
@@ -3,14 +3,13 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial005",
- pytest.param("tutorial005_py39", marks=needs_py39),
+ pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py
index 91180d1097..5d9c55675f 100644
--- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py
+++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py
@@ -1,7 +1,7 @@
import pytest
from fastapi.testclient import TestClient
-from docs_src.path_operation_configuration.tutorial006 import app
+from docs_src.path_operation_configuration.tutorial006_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py
index acbeaca769..f7f233ccff 100644
--- a/tests/test_tutorial/test_path_params/test_tutorial004.py
+++ b/tests/test_tutorial/test_path_params/test_tutorial004.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.path_params.tutorial004 import app
+from docs_src.path_params.tutorial004_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py
index 2e4b0146be..b3be70471a 100644
--- a/tests/test_tutorial/test_path_params/test_tutorial005.py
+++ b/tests/test_tutorial/test_path_params/test_tutorial005.py
@@ -1,7 +1,7 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from docs_src.path_params.tutorial005 import app
+from docs_src.path_params.tutorial005_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
index 3075a05f51..ce53a36eb8 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
@@ -23,7 +23,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="mod",
params=[
- "tutorial001_an",
+ "tutorial001_an_py39",
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
index a402c663d1..57720bf489 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
@@ -24,7 +24,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial002_an",
+ "tutorial002_an_py39",
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
index 03155c9249..f020d4a975 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
@@ -23,7 +23,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003_an",
+ "tutorial003_an_py39",
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
index d2e204ddaf..daa6f0b050 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
@@ -17,14 +17,13 @@ import importlib
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial004_an",
- pytest.param("tutorial004_an_py39", marks=needs_py39),
+ pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial001.py b/tests/test_tutorial/test_query_param_models/test_tutorial001.py
index 5b7bc7b424..86830b9341 100644
--- a/tests/test_tutorial/test_query_param_models/test_tutorial001.py
+++ b/tests/test_tutorial/test_query_param_models/test_tutorial001.py
@@ -5,17 +5,15 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- pytest.param("tutorial001_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial002.py b/tests/test_tutorial/test_query_param_models/test_tutorial002.py
index 4432c9d8a3..e7de73f804 100644
--- a/tests/test_tutorial/test_query_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_query_param_models/test_tutorial002.py
@@ -5,23 +5,19 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2
+from tests.utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002", marks=needs_pydanticv2),
- pytest.param("tutorial002_py39", marks=[needs_py39, needs_pydanticv2]),
+ pytest.param("tutorial002_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py39", marks=[needs_py39, needs_pydanticv2]),
+ pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1", marks=[needs_pydanticv1, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_py39", marks=[needs_py39, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an", marks=[needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=[needs_py39, needs_pydanticv1]),
+ pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
],
)
diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py
index 05ae85b451..ad4e4efa6b 100644
--- a/tests/test_tutorial/test_query_params/test_tutorial005.py
+++ b/tests/test_tutorial/test_query_params/test_tutorial005.py
@@ -1,7 +1,7 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from docs_src.query_params.tutorial005 import app
+from docs_src.query_params.tutorial005_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py
index a0b5ef4943..349f8dd223 100644
--- a/tests/test_tutorial/test_query_params/test_tutorial006.py
+++ b/tests/test_tutorial/test_query_params/test_tutorial006.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial006",
+ pytest.param("tutorial006_py39"),
pytest.param("tutorial006_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
index e08e169633..de5dbbb2ee 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
@@ -5,16 +5,15 @@ from dirty_equals import IsDict
from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial010",
+ pytest.param("tutorial010_py39"),
pytest.param("tutorial010_py310", marks=needs_py310),
- "tutorial010_an",
- pytest.param("tutorial010_an_py39", marks=needs_py39),
+ pytest.param("tutorial010_an_py39"),
pytest.param("tutorial010_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
index f4da25752b..50b3c5683c 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
@@ -4,17 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial011",
- pytest.param("tutorial011_py39", marks=needs_py310),
+ pytest.param("tutorial011_py39"),
pytest.param("tutorial011_py310", marks=needs_py310),
- "tutorial011_an",
- pytest.param("tutorial011_an_py39", marks=needs_py39),
+ pytest.param("tutorial011_an_py39"),
pytest.param("tutorial011_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
index 549a90519e..1826928611 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
@@ -3,16 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial012",
- pytest.param("tutorial012_py39", marks=needs_py39),
- "tutorial012_an",
- pytest.param("tutorial012_an_py39", marks=needs_py39),
+ pytest.param("tutorial012_py39"),
+ pytest.param("tutorial012_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
index f2f5f7a858..46c367c86b 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
@@ -3,15 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial013",
- "tutorial013_an",
- pytest.param("tutorial013_an_py39", marks=needs_py39),
+ "tutorial013_py39",
+ "tutorial013_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
index edd40bb1ab..0feaccfa44 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
@@ -3,16 +3,15 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial014",
+ pytest.param("tutorial014_py39"),
pytest.param("tutorial014_py310", marks=needs_py310),
- "tutorial014_an",
- pytest.param("tutorial014_an_py39", marks=needs_py39),
+ pytest.param("tutorial014_an_py39"),
pytest.param("tutorial014_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
index ae1c40286d..50ebf711f5 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
@@ -5,15 +5,14 @@ from dirty_equals import IsStr
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from ...utils import needs_py39, needs_py310, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial015_an", marks=needs_pydanticv2),
+ pytest.param("tutorial015_an_py39", marks=needs_pydanticv2),
pytest.param("tutorial015_an_py310", marks=(needs_py310, needs_pydanticv2)),
- pytest.param("tutorial015_an_py39", marks=(needs_py39, needs_pydanticv2)),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py
index b069199612..a16d951dc6 100644
--- a/tests/test_tutorial/test_request_files/test_tutorial001.py
+++ b/tests/test_tutorial/test_request_files/test_tutorial001.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_py39",
+ "tutorial001_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py
index 9075a17561..caea0d2e8f 100644
--- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py
+++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py
@@ -5,16 +5,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial001_02",
+ pytest.param("tutorial001_02_py39"),
pytest.param("tutorial001_02_py310", marks=needs_py310),
- "tutorial001_02_an",
- pytest.param("tutorial001_02_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_02_an_py39"),
pytest.param("tutorial001_02_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py
index 9fbe2166c1..53a7a0cf85 100644
--- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py
+++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py
@@ -3,15 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001_03",
- "tutorial001_03_an",
- pytest.param("tutorial001_03_an_py39", marks=needs_py39),
+ "tutorial001_03_py39",
+ "tutorial001_03_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py
index 446a876578..34dbbb985d 100644
--- a/tests/test_tutorial/test_request_files/test_tutorial002.py
+++ b/tests/test_tutorial/test_request_files/test_tutorial002.py
@@ -5,16 +5,12 @@ from dirty_equals import IsDict
from fastapi import FastAPI
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="app",
params=[
- "tutorial002",
- "tutorial002_an",
- pytest.param("tutorial002_py39", marks=needs_py39),
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ "tutorial002_py39",
+ "tutorial002_an_py39",
],
)
def get_app(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py
index 8534ba3e9a..fa4bfd5695 100644
--- a/tests/test_tutorial/test_request_files/test_tutorial003.py
+++ b/tests/test_tutorial/test_request_files/test_tutorial003.py
@@ -4,16 +4,12 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="app",
params=[
- "tutorial003",
- "tutorial003_an",
- pytest.param("tutorial003_py39", marks=needs_py39),
- pytest.param("tutorial003_an_py39", marks=needs_py39),
+ "tutorial003_py39",
+ "tutorial003_an_py39",
],
)
def get_app(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial001.py b/tests/test_tutorial/test_request_form_models/test_tutorial001.py
index 1ca3c96d33..a54df8536c 100644
--- a/tests/test_tutorial/test_request_form_models/test_tutorial001.py
+++ b/tests/test_tutorial/test_request_form_models/test_tutorial001.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_py39",
+ "tutorial001_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002.py b/tests/test_tutorial/test_request_form_models/test_tutorial002.py
index b3f6be63ab..9bb90fa064 100644
--- a/tests/test_tutorial/test_request_form_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_request_form_models/test_tutorial002.py
@@ -3,15 +3,14 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_pydanticv2
+from ...utils import needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial002",
- "tutorial002_an",
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ "tutorial002_py39",
+ "tutorial002_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py b/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
index b503f23a53..41c7833bef 100644
--- a/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
+++ b/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
@@ -3,15 +3,14 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_pydanticv1
+from ...utils import needs_pydanticv1
@pytest.fixture(
name="client",
params=[
- "tutorial002_pv1",
- "tutorial002_pv1_an",
- pytest.param("tutorial002_pv1_an_py39", marks=needs_py39),
+ "tutorial002_pv1_py39",
+ "tutorial002_pv1_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py
index 321f8022b7..da20535cf8 100644
--- a/tests/test_tutorial/test_request_forms/test_tutorial001.py
+++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py
@@ -4,15 +4,12 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_py39",
+ "tutorial001_an_py39",
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py
index d12219245e..f37ffad443 100644
--- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py
+++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py
@@ -5,15 +5,12 @@ from dirty_equals import IsDict
from fastapi import FastAPI
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="app",
params=[
- "tutorial001",
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ "tutorial001_py39",
+ "tutorial001_an_py39",
],
)
def get_app(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py b/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py
index 8ce3dcf1ab..05d5ca619f 100644
--- a/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py
+++ b/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_change_status_code.tutorial001 import app
+from docs_src.response_change_status_code.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_cookies/test_tutorial001.py b/tests/test_tutorial/test_response_cookies/test_tutorial001.py
index eecd1a24c9..6b931c8bda 100644
--- a/tests/test_tutorial/test_response_cookies/test_tutorial001.py
+++ b/tests/test_tutorial/test_response_cookies/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_cookies.tutorial001 import app
+from docs_src.response_cookies.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_cookies/test_tutorial002.py b/tests/test_tutorial/test_response_cookies/test_tutorial002.py
index 3e390025fa..3ee5f500c5 100644
--- a/tests/test_tutorial/test_response_cookies/test_tutorial002.py
+++ b/tests/test_tutorial/test_response_cookies/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_cookies.tutorial002 import app
+from docs_src.response_cookies.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_directly/test_tutorial001.py b/tests/test_tutorial/test_response_directly/test_tutorial001.py
index 2cc4f3b0c1..127f0e4c1d 100644
--- a/tests/test_tutorial/test_response_directly/test_tutorial001.py
+++ b/tests/test_tutorial/test_response_directly/test_tutorial001.py
@@ -9,7 +9,7 @@ from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial001"),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_headers/test_tutorial001.py b/tests/test_tutorial/test_response_headers/test_tutorial001.py
index 1549d6b5b1..6232aad23e 100644
--- a/tests/test_tutorial/test_response_headers/test_tutorial001.py
+++ b/tests/test_tutorial/test_response_headers/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_headers.tutorial001 import app
+from docs_src.response_headers.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_headers/test_tutorial002.py b/tests/test_tutorial/test_response_headers/test_tutorial002.py
index 2826833f84..2ac2226cb1 100644
--- a/tests/test_tutorial/test_response_headers/test_tutorial002.py
+++ b/tests/test_tutorial/test_response_headers/test_tutorial002.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_headers.tutorial002 import app
+from docs_src.response_headers.tutorial002_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py
index 70cfd6e4cc..0f9eac890b 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01.py b/tests/test_tutorial/test_response_model/test_tutorial003_01.py
index 3975856b6c..1a7ce4c7a1 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003_01.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003_01.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003_01",
+ pytest.param("tutorial003_01_py39"),
pytest.param("tutorial003_01_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_02.py b/tests/test_tutorial/test_response_model/test_tutorial003_02.py
index eabd203456..b7507b7110 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003_02.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003_02.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_model.tutorial003_02 import app
+from docs_src.response_model.tutorial003_02_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_03.py b/tests/test_tutorial/test_response_model/test_tutorial003_03.py
index 970ff58450..ea3c733b24 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003_03.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003_03.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.response_model.tutorial003_03 import app
+from docs_src.response_model.tutorial003_03_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_04.py b/tests/test_tutorial/test_response_model/test_tutorial003_04.py
index f32e93ddcb..145af126fd 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003_04.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003_04.py
@@ -9,7 +9,7 @@ from ...utils import needs_py310
@pytest.mark.parametrize(
"module_name",
[
- "tutorial003_04",
+ pytest.param("tutorial003_04_py39"),
pytest.param("tutorial003_04_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05.py b/tests/test_tutorial/test_response_model/test_tutorial003_05.py
index 9500852e15..19a7c601bb 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial003_05.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial003_05.py
@@ -9,7 +9,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003_05",
+ pytest.param("tutorial003_05_py39"),
pytest.param("tutorial003_05_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py
index 449a52b813..19f6998f70 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial004.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial004.py
@@ -4,14 +4,13 @@ import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial004",
- pytest.param("tutorial004_py39", marks=needs_py39),
+ pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py
index a633a3fddd..47d77dc498 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial005.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial005.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial005",
+ pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py
index 863522d1b4..a03aa41e8c 100644
--- a/tests/test_tutorial/test_response_model/test_tutorial006.py
+++ b/tests/test_tutorial/test_response_model/test_tutorial006.py
@@ -10,7 +10,7 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial006",
+ pytest.param("tutorial006_py39"),
pytest.param("tutorial006_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
index c21cbb4bc2..4d1808cf6a 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
@@ -9,7 +9,7 @@ from ...utils import needs_py310, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
index b79f42e642..552bb66970 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
@@ -9,7 +9,7 @@ from ...utils import needs_py310, needs_pydanticv1
@pytest.fixture(
name="client",
params=[
- "tutorial001_pv1",
+ pytest.param("tutorial001_pv1_py39"),
pytest.param("tutorial001_pv1_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py
index 61aefd12a8..47ecb9ba73 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial004",
+ pytest.param("tutorial004_py39"),
pytest.param("tutorial004_py310", marks=needs_py310),
- "tutorial004_an",
- pytest.param("tutorial004_an_py39", marks=needs_py39),
+ pytest.param("tutorial004_an_py39"),
pytest.param("tutorial004_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py
index 12859227b1..1c964f3d15 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial005",
+ pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- "tutorial005_an",
- pytest.param("tutorial005_an_py39", marks=needs_py39),
+ pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_security/test_tutorial001.py b/tests/test_tutorial/test_security/test_tutorial001.py
index f572d6e3e1..cdaa50b191 100644
--- a/tests/test_tutorial/test_security/test_tutorial001.py
+++ b/tests/test_tutorial/test_security/test_tutorial001.py
@@ -3,15 +3,12 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
+ pytest.param("tutorial001_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py
index 6b87351139..000c8b2ac4 100644
--- a/tests/test_tutorial/test_security/test_tutorial003.py
+++ b/tests/test_tutorial/test_security/test_tutorial003.py
@@ -4,16 +4,15 @@ import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- "tutorial003",
+ pytest.param("tutorial003_py39"),
pytest.param("tutorial003_py310", marks=needs_py310),
- "tutorial003_an",
- pytest.param("tutorial003_an_py39", marks=needs_py39),
+ pytest.param("tutorial003_an_py39"),
pytest.param("tutorial003_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py
index ad644d61bb..7953e8e3f6 100644
--- a/tests/test_tutorial/test_security/test_tutorial005.py
+++ b/tests/test_tutorial/test_security/test_tutorial005.py
@@ -5,17 +5,15 @@ import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="mod",
params=[
- "tutorial005",
+ pytest.param("tutorial005_py39"),
pytest.param("tutorial005_py310", marks=needs_py310),
- "tutorial005_an",
- pytest.param("tutorial005_py39", marks=needs_py39),
- pytest.param("tutorial005_an_py39", marks=needs_py39),
+ pytest.param("tutorial005_an_py39"),
pytest.param("tutorial005_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_security/test_tutorial006.py b/tests/test_tutorial/test_security/test_tutorial006.py
index 9587159dc2..a4b3104bbc 100644
--- a/tests/test_tutorial/test_security/test_tutorial006.py
+++ b/tests/test_tutorial/test_security/test_tutorial006.py
@@ -4,15 +4,12 @@ from base64 import b64encode
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="client",
params=[
- "tutorial006",
- "tutorial006_an",
- pytest.param("tutorial006_an_py39", marks=needs_py39),
+ pytest.param("tutorial006_py39"),
+ pytest.param("tutorial006_an_py39"),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
index 059fb889b3..b59d799a31 100644
--- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
+++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
@@ -3,15 +3,14 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- pytest.param("tutorial001_py39", marks=needs_py39),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
index cc9afeab75..61fbacfc34 100644
--- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
+++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
@@ -3,15 +3,14 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39, needs_py310, needs_pydanticv2
+from ...utils import needs_py310, needs_pydanticv2
@pytest.fixture(
name="client",
params=[
- "tutorial002",
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- pytest.param("tutorial002_py39", marks=needs_py39),
],
)
def get_client(request: pytest.FixtureRequest) -> TestClient:
diff --git a/tests/test_tutorial/test_settings/test_app02.py b/tests/test_tutorial/test_settings/test_app02.py
index 5e1232ea01..9cedc5a526 100644
--- a/tests/test_tutorial/test_settings/test_app02.py
+++ b/tests/test_tutorial/test_settings/test_app02.py
@@ -4,15 +4,14 @@ from types import ModuleType
import pytest
from pytest import MonkeyPatch
-from ...utils import needs_py39, needs_pydanticv2
+from ...utils import needs_pydanticv2
@pytest.fixture(
name="mod_path",
params=[
- pytest.param("app02"),
- pytest.param("app02_an"),
- pytest.param("app02_an_py39", marks=needs_py39),
+ pytest.param("app02_py39"),
+ pytest.param("app02_an_py39"),
],
)
def get_mod_path(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_settings/test_app03.py b/tests/test_tutorial/test_settings/test_app03.py
index d9872c15f2..dbaf8f3f90 100644
--- a/tests/test_tutorial/test_settings/test_app03.py
+++ b/tests/test_tutorial/test_settings/test_app03.py
@@ -5,15 +5,14 @@ import pytest
from fastapi.testclient import TestClient
from pytest import MonkeyPatch
-from ...utils import needs_py39, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="mod_path",
params=[
- pytest.param("app03"),
- pytest.param("app03_an"),
- pytest.param("app03_an_py39", marks=needs_py39),
+ pytest.param("app03_py39"),
+ pytest.param("app03_an_py39"),
],
)
def get_mod_path(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_settings/test_tutorial001.py b/tests/test_tutorial/test_settings/test_tutorial001.py
index 92a5782d4d..2c6dce261f 100644
--- a/tests/test_tutorial/test_settings/test_tutorial001.py
+++ b/tests/test_tutorial/test_settings/test_tutorial001.py
@@ -10,8 +10,8 @@ from ...utils import needs_pydanticv1, needs_pydanticv2
@pytest.fixture(
name="app",
params=[
- pytest.param("tutorial001", marks=needs_pydanticv2),
- pytest.param("tutorial001_pv1", marks=needs_pydanticv1),
+ pytest.param("tutorial001_py39", marks=needs_pydanticv2),
+ pytest.param("tutorial001_pv1_py39", marks=needs_pydanticv1),
],
)
def get_app(request: pytest.FixtureRequest, monkeypatch: MonkeyPatch):
diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_sql_databases/test_tutorial001.py
index b45be4884d..e3e6bac128 100644
--- a/tests/test_tutorial/test_sql_databases/test_tutorial001.py
+++ b/tests/test_tutorial/test_sql_databases/test_tutorial001.py
@@ -9,7 +9,7 @@ from sqlalchemy import StaticPool
from sqlmodel import SQLModel, create_engine
from sqlmodel.main import default_registry
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
def clear_sqlmodel():
@@ -22,11 +22,9 @@ def clear_sqlmodel():
@pytest.fixture(
name="client",
params=[
- "tutorial001",
- pytest.param("tutorial001_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial002.py b/tests/test_tutorial/test_sql_databases/test_tutorial002.py
index da0b8b7ce7..e3b8c7f9e4 100644
--- a/tests/test_tutorial/test_sql_databases/test_tutorial002.py
+++ b/tests/test_tutorial/test_sql_databases/test_tutorial002.py
@@ -9,7 +9,7 @@ from sqlalchemy import StaticPool
from sqlmodel import SQLModel, create_engine
from sqlmodel.main import default_registry
-from tests.utils import needs_py39, needs_py310
+from tests.utils import needs_py310
def clear_sqlmodel():
@@ -22,11 +22,9 @@ def clear_sqlmodel():
@pytest.fixture(
name="client",
params=[
- "tutorial002",
- pytest.param("tutorial002_py39", marks=needs_py39),
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- "tutorial002_an",
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_sub_applications/test_tutorial001.py b/tests/test_tutorial/test_sub_applications/test_tutorial001.py
index 0790d207be..ef1f80164b 100644
--- a/tests/test_tutorial/test_sub_applications/test_tutorial001.py
+++ b/tests/test_tutorial/test_sub_applications/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.sub_applications.tutorial001 import app
+from docs_src.sub_applications.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_templates/test_tutorial001.py b/tests/test_tutorial/test_templates/test_tutorial001.py
index 4d4729425e..818508037d 100644
--- a/tests/test_tutorial/test_templates/test_tutorial001.py
+++ b/tests/test_tutorial/test_templates/test_tutorial001.py
@@ -11,7 +11,7 @@ def test_main():
shutil.rmtree("./templates")
shutil.copytree("./docs_src/templates/templates/", "./templates")
shutil.copytree("./docs_src/templates/static/", "./static")
- from docs_src.templates.tutorial001 import app
+ from docs_src.templates.tutorial001_py39 import app
client = TestClient(app)
response = client.get("/items/foo")
diff --git a/tests/test_tutorial/test_testing/test_main.py b/tests/test_tutorial/test_testing/test_main_a.py
similarity index 90%
rename from tests/test_tutorial/test_testing/test_main.py
rename to tests/test_tutorial/test_testing/test_main_a.py
index fe34980813..9b3c796bdc 100644
--- a/tests/test_tutorial/test_testing/test_main.py
+++ b/tests/test_tutorial/test_testing/test_main_a.py
@@ -1,4 +1,4 @@
-from docs_src.app_testing.test_main import client, test_read_main
+from docs_src.app_testing.app_a_py39.test_main import client, test_read_main
def test_main():
diff --git a/tests/test_tutorial/test_testing/test_main_b.py b/tests/test_tutorial/test_testing/test_main_b.py
index aa7f969c6d..3d679cd5a6 100644
--- a/tests/test_tutorial/test_testing/test_main_b.py
+++ b/tests/test_tutorial/test_testing/test_main_b.py
@@ -3,16 +3,15 @@ from types import ModuleType
import pytest
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="test_module",
params=[
- "app_b.test_main",
+ "app_b_py39.test_main",
pytest.param("app_b_py310.test_main", marks=needs_py310),
- "app_b_an.test_main",
- pytest.param("app_b_an_py39.test_main", marks=needs_py39),
+ "app_b_an_py39.test_main",
pytest.param("app_b_an_py310.test_main", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_testing/test_tutorial001.py b/tests/test_tutorial/test_testing/test_tutorial001.py
index 471e896c93..5f6533306e 100644
--- a/tests/test_tutorial/test_testing/test_tutorial001.py
+++ b/tests/test_tutorial/test_testing/test_tutorial001.py
@@ -1,4 +1,4 @@
-from docs_src.app_testing.tutorial001 import client, test_read_main
+from docs_src.app_testing.tutorial001_py39 import client, test_read_main
def test_main():
diff --git a/tests/test_tutorial/test_testing/test_tutorial002.py b/tests/test_tutorial/test_testing/test_tutorial002.py
index ec4f91ee7f..cc9b5ba27c 100644
--- a/tests/test_tutorial/test_testing/test_tutorial002.py
+++ b/tests/test_tutorial/test_testing/test_tutorial002.py
@@ -1,4 +1,4 @@
-from docs_src.app_testing.tutorial002 import test_read_main, test_websocket
+from docs_src.app_testing.tutorial002_py39 import test_read_main, test_websocket
def test_main():
diff --git a/tests/test_tutorial/test_testing/test_tutorial003.py b/tests/test_tutorial/test_testing/test_tutorial003.py
index 2a5d670712..4faa820e98 100644
--- a/tests/test_tutorial/test_testing/test_tutorial003.py
+++ b/tests/test_tutorial/test_testing/test_tutorial003.py
@@ -3,5 +3,5 @@ import pytest
def test_main():
with pytest.warns(DeprecationWarning):
- from docs_src.app_testing.tutorial003 import test_read_items
+ from docs_src.app_testing.tutorial003_py39 import test_read_items
test_read_items()
diff --git a/tests/test_tutorial/test_testing/test_tutorial004.py b/tests/test_tutorial/test_testing/test_tutorial004.py
index 812ee44c1f..c95214ffe3 100644
--- a/tests/test_tutorial/test_testing/test_tutorial004.py
+++ b/tests/test_tutorial/test_testing/test_tutorial004.py
@@ -1,4 +1,4 @@
-from docs_src.app_testing.tutorial004 import test_read_items
+from docs_src.app_testing.tutorial004_py39 import test_read_items
def test_main():
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
index 00ee6ab1ea..6e9656bf55 100644
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
+++ b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
@@ -3,16 +3,15 @@ from types import ModuleType
import pytest
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="test_module",
params=[
- "tutorial001",
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
- "tutorial001_an",
- pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py39"),
pytest.param("tutorial001_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py
index 54c53ae1e3..33e661b164 100644
--- a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py
+++ b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.using_request_directly.tutorial001 import app
+from docs_src.using_request_directly.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_websockets/test_tutorial001.py b/tests/test_tutorial/test_websockets/test_tutorial001.py
index 7dbecb2650..4f8368db28 100644
--- a/tests/test_tutorial/test_websockets/test_tutorial001.py
+++ b/tests/test_tutorial/test_websockets/test_tutorial001.py
@@ -2,7 +2,7 @@ import pytest
from fastapi.testclient import TestClient
from fastapi.websockets import WebSocketDisconnect
-from docs_src.websockets.tutorial001 import app
+from docs_src.websockets.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_tutorial/test_websockets/test_tutorial002.py b/tests/test_tutorial/test_websockets/test_tutorial002.py
index 51aa5752a6..ebf1fc8e81 100644
--- a/tests/test_tutorial/test_websockets/test_tutorial002.py
+++ b/tests/test_tutorial/test_websockets/test_tutorial002.py
@@ -5,16 +5,15 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
from fastapi.websockets import WebSocketDisconnect
-from ...utils import needs_py39, needs_py310
+from ...utils import needs_py310
@pytest.fixture(
name="app",
params=[
- "tutorial002",
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
- "tutorial002_an",
- pytest.param("tutorial002_an_py39", marks=needs_py39),
+ pytest.param("tutorial002_an_py39"),
pytest.param("tutorial002_an_py310", marks=needs_py310),
],
)
diff --git a/tests/test_tutorial/test_websockets/test_tutorial003.py b/tests/test_tutorial/test_websockets/test_tutorial003.py
index 85efc18590..0be1fc81d6 100644
--- a/tests/test_tutorial/test_websockets/test_tutorial003.py
+++ b/tests/test_tutorial/test_websockets/test_tutorial003.py
@@ -4,14 +4,11 @@ from types import ModuleType
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py39
-
@pytest.fixture(
name="mod",
params=[
- pytest.param("tutorial003"),
- pytest.param("tutorial003_py39", marks=needs_py39),
+ pytest.param("tutorial003_py39"),
],
)
def get_mod(request: pytest.FixtureRequest):
@@ -32,17 +29,16 @@ def get_client(mod: ModuleType):
return client
-@needs_py39
def test_get(client: TestClient, html: str):
response = client.get("/")
assert response.text == html
-@needs_py39
def test_websocket_handle_disconnection(client: TestClient):
- with client.websocket_connect("/ws/1234") as connection, client.websocket_connect(
- "/ws/5678"
- ) as connection_two:
+ with (
+ client.websocket_connect("/ws/1234") as connection,
+ client.websocket_connect("/ws/5678") as connection_two,
+ ):
connection.send_text("Hello from 1234")
data1 = connection.receive_text()
assert data1 == "You wrote: Hello from 1234"
diff --git a/tests/test_tutorial/test_wsgi/test_tutorial001.py b/tests/test_tutorial/test_wsgi/test_tutorial001.py
index 4f82252739..9fe8c2a4b8 100644
--- a/tests/test_tutorial/test_wsgi/test_tutorial001.py
+++ b/tests/test_tutorial/test_wsgi/test_tutorial001.py
@@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
-from docs_src.wsgi.tutorial001 import app
+from docs_src.wsgi.tutorial001_py39 import app
client = TestClient(app)
diff --git a/tests/test_union_body_discriminator.py b/tests/test_union_body_discriminator.py
index 6af9e1d226..bf41a72915 100644
--- a/tests/test_union_body_discriminator.py
+++ b/tests/test_union_body_discriminator.py
@@ -1,11 +1,11 @@
-from typing import Any, Dict, Union
+from typing import Annotated, Any, Union
from dirty_equals import IsDict
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, Field
-from typing_extensions import Annotated, Literal
+from typing_extensions import Literal
from .utils import needs_pydanticv2
@@ -32,7 +32,7 @@ def test_discriminator_pydantic_v2() -> None:
@app.post("/items/")
def save_union_body_discriminator(
item: Item, q: Annotated[str, Field(description="Query string")]
- ) -> Dict[str, Any]:
+ ) -> dict[str, Any]:
return {"item": item}
client = TestClient(app)
diff --git a/tests/test_union_body_discriminator_annotated.py b/tests/test_union_body_discriminator_annotated.py
index 14145e6f60..f8108c8df4 100644
--- a/tests/test_union_body_discriminator_annotated.py
+++ b/tests/test_union_body_discriminator_annotated.py
@@ -1,13 +1,12 @@
# Ref: https://github.com/fastapi/fastapi/discussions/14495
-from typing import Union
+from typing import Annotated, Union
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel
-from typing_extensions import Annotated
from .utils import needs_pydanticv2
diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py
index cbe98ea825..018949f0c7 100644
--- a/tests/test_union_forms.py
+++ b/tests/test_union_forms.py
@@ -1,9 +1,8 @@
-from typing import Union
+from typing import Annotated, Union
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_validate_response.py b/tests/test_validate_response.py
index cd97007a44..938d419566 100644
--- a/tests/test_validate_response.py
+++ b/tests/test_validate_response.py
@@ -1,4 +1,4 @@
-from typing import List, Optional, Union
+from typing import Optional, Union
import pytest
from fastapi import FastAPI
@@ -12,7 +12,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: Optional[float] = None
- owner_ids: Optional[List[int]] = None
+ owner_ids: Optional[list[int]] = None
@app.get("/items/invalid", response_model=Item)
@@ -38,7 +38,7 @@ def get_innerinvalid():
return {"name": "double invalid", "price": "foo", "owner_ids": ["foo", "bar"]}
-@app.get("/items/invalidlist", response_model=List[Item])
+@app.get("/items/invalidlist", response_model=list[Item])
def get_invalidlist():
return [
{"name": "foo"},
diff --git a/tests/test_validate_response_dataclass.py b/tests/test_validate_response_dataclass.py
index 0415988a0b..67282bcde1 100644
--- a/tests/test_validate_response_dataclass.py
+++ b/tests/test_validate_response_dataclass.py
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import Optional
import pytest
from fastapi import FastAPI
@@ -13,7 +13,7 @@ app = FastAPI()
class Item:
name: str
price: Optional[float] = None
- owner_ids: Optional[List[int]] = None
+ owner_ids: Optional[list[int]] = None
@app.get("/items/invalid", response_model=Item)
@@ -26,7 +26,7 @@ def get_innerinvalid():
return {"name": "double invalid", "price": "foo", "owner_ids": ["foo", "bar"]}
-@app.get("/items/invalidlist", response_model=List[Item])
+@app.get("/items/invalidlist", response_model=list[Item])
def get_invalidlist():
return [
{"name": "foo"},
diff --git a/tests/test_validate_response_recursive/app.py b/tests/test_validate_response_recursive/app.py
index d23d279808..8f76572ba6 100644
--- a/tests/test_validate_response_recursive/app.py
+++ b/tests/test_validate_response_recursive/app.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi import FastAPI
from fastapi._compat import PYDANTIC_V2
from pydantic import BaseModel
@@ -8,17 +6,17 @@ app = FastAPI()
class RecursiveItem(BaseModel):
- sub_items: List["RecursiveItem"] = []
+ sub_items: list["RecursiveItem"] = []
name: str
class RecursiveSubitemInSubmodel(BaseModel):
- sub_items2: List["RecursiveItemViaSubmodel"] = []
+ sub_items2: list["RecursiveItemViaSubmodel"] = []
name: str
class RecursiveItemViaSubmodel(BaseModel):
- sub_items1: List[RecursiveSubitemInSubmodel] = []
+ sub_items1: list[RecursiveSubitemInSubmodel] = []
name: str
diff --git a/tests/test_webhooks_security.py b/tests/test_webhooks_security.py
index 21a694cb54..982ae1e21d 100644
--- a/tests/test_webhooks_security.py
+++ b/tests/test_webhooks_security.py
@@ -1,10 +1,10 @@
from datetime import datetime
+from typing import Annotated
from fastapi import FastAPI, Security
from fastapi.security import HTTPBearer
from fastapi.testclient import TestClient
from pydantic import BaseModel
-from typing_extensions import Annotated
app = FastAPI()
diff --git a/tests/test_ws_dependencies.py b/tests/test_ws_dependencies.py
index ccb1c4b7da..51b982c00e 100644
--- a/tests/test_ws_dependencies.py
+++ b/tests/test_ws_dependencies.py
@@ -1,16 +1,15 @@
import json
-from typing import List
+from typing import Annotated
from fastapi import APIRouter, Depends, FastAPI, WebSocket
from fastapi.testclient import TestClient
-from typing_extensions import Annotated
-def dependency_list() -> List[str]:
+def dependency_list() -> list[str]:
return []
-DepList = Annotated[List[str], Depends(dependency_list)]
+DepList = Annotated[list[str], Depends(dependency_list)]
def create_dependency(name: str):