committed by
GitHub
144 changed files with 1661 additions and 17103 deletions
@ -0,0 +1,52 @@ |
|||
name: FastAPI People Sponsors |
|||
|
|||
on: |
|||
schedule: |
|||
- cron: "0 6 1 * *" |
|||
workflow_dispatch: |
|||
inputs: |
|||
debug_enabled: |
|||
description: "Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)" |
|||
required: false |
|||
default: "false" |
|||
|
|||
env: |
|||
UV_SYSTEM_PYTHON: 1 |
|||
|
|||
jobs: |
|||
job: |
|||
if: github.repository_owner == 'fastapi' |
|||
runs-on: ubuntu-latest |
|||
permissions: |
|||
contents: write |
|||
steps: |
|||
- name: Dump GitHub context |
|||
env: |
|||
GITHUB_CONTEXT: ${{ toJson(github) }} |
|||
run: echo "$GITHUB_CONTEXT" |
|||
- uses: actions/checkout@v4 |
|||
- name: Set up Python |
|||
uses: actions/setup-python@v5 |
|||
with: |
|||
python-version: "3.11" |
|||
- name: Setup uv |
|||
uses: astral-sh/setup-uv@v5 |
|||
with: |
|||
version: "0.4.15" |
|||
enable-cache: true |
|||
cache-dependency-glob: | |
|||
requirements**.txt |
|||
pyproject.toml |
|||
- name: Install Dependencies |
|||
run: uv pip install -r requirements-github-actions.txt |
|||
# Allow debugging with tmate |
|||
- name: Setup tmate session |
|||
uses: mxschmitt/action-tmate@v3 |
|||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} |
|||
with: |
|||
limit-access-to-actor: true |
|||
- name: FastAPI People Sponsors |
|||
run: python ./scripts/sponsors.py |
|||
env: |
|||
SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }} |
|||
PR_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} |
@ -8,7 +8,7 @@ Por isso é comum prover essas configurações como variáveis de ambiente que s |
|||
|
|||
## Variáveis de Ambiente |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Se você já sabe o que são variáveis de ambiente e como utilizá-las, sinta-se livre para avançar para o próximo tópico. |
|||
|
|||
@ -67,7 +67,7 @@ name = os.getenv("MY_NAME", "World") |
|||
print(f"Hello {name} from Python") |
|||
``` |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
O segundo parâmetro em <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> é o valor padrão para o retorno. |
|||
|
|||
@ -124,7 +124,7 @@ Hello World from Python |
|||
|
|||
</div> |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Você pode ler mais sobre isso em: <a href="https://12factor.net/pt_br/config" class="external-link" target="_blank">The Twelve-Factor App: Configurações</a>. |
|||
|
|||
@ -196,7 +196,7 @@ Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo |
|||
|
|||
//// |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Se você quiser algo pronto para copiar e colar na sua aplicação, não use esse exemplo, mas sim o exemplo abaixo. |
|||
|
|||
@ -226,7 +226,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
</div> |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Para definir múltiplas variáveis de ambiente para um único comando basta separá-las utilizando espaços, e incluir todas elas antes do comando. |
|||
|
|||
@ -250,7 +250,7 @@ E utilizar essa configuração em `main.py`: |
|||
|
|||
{* ../../docs_src/settings/app01/main.py hl[3,11:13] *} |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Você também precisa incluir um arquivo `__init__.py` como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}. |
|||
|
|||
@ -276,7 +276,7 @@ Agora criamos a dependência que retorna um novo objeto `config.Settings()`. |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Vamos discutir sobre `@lru_cache` logo mais. |
|||
|
|||
@ -304,7 +304,7 @@ Se você tiver muitas configurações que variem bastante, talvez em ambientes d |
|||
|
|||
Essa prática é tão comum que possui um nome, essas variáveis de ambiente normalmente são colocadas em um arquivo `.env`, e esse arquivo é chamado de "dotenv". |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Um arquivo iniciando com um ponto final (`.`) é um arquivo oculto em sistemas baseados em Unix, como Linux e MacOS. |
|||
|
|||
@ -314,7 +314,7 @@ Mas um arquivo dotenv não precisa ter esse nome exato. |
|||
|
|||
Pydantic suporta a leitura desses tipos de arquivos utilizando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>. |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
Para que isso funcione você precisa executar `pip install python-dotenv`. |
|||
|
|||
@ -337,7 +337,7 @@ E então adicionar o seguinte código em `config.py`: |
|||
|
|||
{* ../../docs_src/settings/app03_an/config.py hl[9] *} |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
@ -349,7 +349,7 @@ O atributo `model_config` é usado apenas para configuração do Pydantic. Você |
|||
|
|||
{* ../../docs_src/settings/app03_an/config_pv1.py hl[9:10] *} |
|||
|
|||
/// dica |
|||
/// tip | Dica |
|||
|
|||
A classe `Config` é usada apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
|
@ -0,0 +1,274 @@ |
|||
# OAuth2 com Senha (e hashing), Bearer com tokens JWT |
|||
|
|||
Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens <abbr title="JSON Web Tokens">JWT</abbr> e hashing de senhas seguras. |
|||
|
|||
Este código é algo que você pode realmente usar na sua aplicação, salvar os hashes das senhas no seu banco de dados, etc. |
|||
|
|||
Vamos começar de onde paramos no capítulo anterior e incrementá-lo. |
|||
|
|||
## Sobre o JWT |
|||
|
|||
JWT significa "JSON Web Tokens". |
|||
|
|||
É um padrão para codificar um objeto JSON em uma string longa e densa sem espaços. Ele se parece com isso: |
|||
|
|||
``` |
|||
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
|||
``` |
|||
|
|||
Ele não é criptografado, então qualquer pessoa pode recuperar as informações do seu conteúdo. |
|||
|
|||
Mas ele é assinado. Assim, quando você recebe um token que você emitiu, você pode verificar que foi realmente você quem o emitiu. |
|||
|
|||
Dessa forma, você pode criar um token com um prazo de expiração, digamos, de 1 semana. E então, quando o usuário voltar no dia seguinte com o token, você sabe que ele ainda está logado no seu sistema. |
|||
|
|||
Depois de uma semana, o token expirará e o usuário não estará autorizado, precisando fazer login novamente para obter um novo token. E se o usuário (ou uma terceira parte) tentar modificar o token para alterar a expiração, você seria capaz de descobrir isso, pois as assinaturas não iriam corresponder. |
|||
|
|||
Se você quiser brincar com tokens JWT e ver como eles funcionam, visite <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>. |
|||
|
|||
## Instalar `PyJWT` |
|||
|
|||
Nós precisamos instalar o `PyJWT` para criar e verificar os tokens JWT em Python. |
|||
|
|||
Certifique-se de criar um [ambiente virtual](../../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o `pyjwt`: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install pyjwt |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
/// info | Informação |
|||
|
|||
Se você pretente utilizar algoritmos de assinatura digital como o RSA ou o ECDSA, você deve instalar a dependência da biblioteca de criptografia `pyjwt[crypto]`. |
|||
|
|||
Você pode ler mais sobre isso na <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">documentação de instalação do PyJWT</a>. |
|||
|
|||
/// |
|||
|
|||
## Hashing de senhas |
|||
|
|||
"Hashing" significa converter algum conteúdo (uma senha neste caso) em uma sequência de bytes (apenas uma string) que parece um monte de caracteres sem sentido. |
|||
|
|||
Sempre que você passar exatamente o mesmo conteúdo (exatamente a mesma senha), você obterá exatamente o mesmo resultado. |
|||
|
|||
Mas não é possível converter os caracteres sem sentido de volta para a senha original. |
|||
|
|||
### Por que usar hashing de senhas |
|||
|
|||
Se o seu banco de dados for roubado, o invasor não terá as senhas em texto puro dos seus usuários, apenas os hashes. |
|||
|
|||
Então, o invasor não poderá tentar usar essas senhas em outro sistema (como muitos usuários utilizam a mesma senha em vários lugares, isso seria perigoso). |
|||
|
|||
## Instalar o `passlib` |
|||
|
|||
O PassLib é uma excelente biblioteca Python para lidar com hashes de senhas. |
|||
|
|||
Ele suporta muitos algoritmos de hashing seguros e utilitários para trabalhar com eles. |
|||
|
|||
O algoritmo recomendado é o "Bcrypt". |
|||
|
|||
Certifique-se de criar um [ambiente virtual](../../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o PassLib com Bcrypt: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install "passlib[bcrypt]" |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
/// tip | Dica |
|||
|
|||
Com o `passlib`, você poderia até configurá-lo para ser capaz de ler senhas criadas pelo **Django**, um plug-in de segurança do **Flask** ou muitos outros. |
|||
|
|||
Assim, você poderia, por exemplo, compartilhar os mesmos dados de um aplicativo Django em um banco de dados com um aplicativo FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados. |
|||
|
|||
E seus usuários poderiam fazer login tanto pela sua aplicação Django quanto pela sua aplicação **FastAPI**, ao mesmo tempo. |
|||
|
|||
/// |
|||
|
|||
## Criar o hash e verificar as senhas |
|||
|
|||
Importe as ferramentas que nós precisamos de `passlib`. |
|||
|
|||
Crie um "contexto" do PassLib. Este será usado para criar o hash e verificar as senhas. |
|||
|
|||
/// tip | Dica |
|||
|
|||
O contexto do PassLib também possui funcionalidades para usar diferentes algoritmos de hashing, incluindo algoritmos antigos que estão obsoletos, apenas para permitir verificá-los, etc. |
|||
|
|||
Por exemplo, você poderia usá-lo para ler e verificar senhas geradas por outro sistema (como Django), mas criar o hash de novas senhas com um algoritmo diferente, como o Bcrypt. |
|||
|
|||
E ser compatível com todos eles ao mesmo tempo. |
|||
|
|||
/// |
|||
|
|||
Crie uma função utilitária para criar o hash de uma senha fornecida pelo usuário. |
|||
|
|||
E outra função utilitária para verificar se uma senha recebida corresponde ao hash armazenado. |
|||
|
|||
E outra para autenticar e retornar um usuário. |
|||
|
|||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} |
|||
|
|||
/// note | Nota |
|||
|
|||
Se você verificar o novo banco de dados (falso) `fake_users_db`, você verá como o hash da senha se parece agora: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`. |
|||
|
|||
/// |
|||
|
|||
## Manipular tokens JWT |
|||
|
|||
Importe os módulos instalados. |
|||
|
|||
Crie uma chave secreta aleatória que será usada para assinar os tokens JWT. |
|||
|
|||
Para gerar uma chave secreta aleatória e segura, use o comando: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ openssl rand -hex 32 |
|||
|
|||
09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
E copie a saída para a variável `SECRET_KEY` (não use a do exemplo). |
|||
|
|||
Crie uma variável `ALGORITHM` com o algoritmo usado para assinar o token JWT e defina como `"HS256"`. |
|||
|
|||
Crie uma variável para a expiração do token. |
|||
|
|||
Defina um modelo Pydantic que será usado no endpoint de token para a resposta. |
|||
|
|||
Crie uma função utilitária para gerar um novo token de acesso. |
|||
|
|||
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} |
|||
|
|||
## Atualize as dependências |
|||
|
|||
Atualize `get_current_user` para receber o mesmo token de antes, mas desta vez, usando tokens JWT. |
|||
|
|||
Decodifique o token recebido, verifique-o e retorne o usuário atual. |
|||
|
|||
Se o token for inválido, retorne um erro HTTP imediatamente. |
|||
|
|||
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} |
|||
|
|||
## Atualize a *operação de rota* `/token` |
|||
|
|||
Crie um `timedelta` com o tempo de expiração do token. |
|||
|
|||
Crie um token de acesso JWT real e o retorne. |
|||
|
|||
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} |
|||
|
|||
### Detalhes técnicos sobre o "sujeito" `sub` do JWT |
|||
|
|||
A especificação JWT diz que existe uma chave `sub`, com o sujeito do token. |
|||
|
|||
É opcional usá-la, mas é onde você colocaria a identificação do usuário, então nós estamos usando aqui. |
|||
|
|||
O JWT pode ser usado para outras coisas além de identificar um usuário e permitir que ele execute operações diretamente na sua API. |
|||
|
|||
Por exemplo, você poderia identificar um "carro" ou uma "postagem de blog". |
|||
|
|||
Depois, você poderia adicionar permissões sobre essa entidade, como "dirigir" (para o carro) ou "editar" (para o blog). |
|||
|
|||
E então, poderia dar esse token JWT para um usuário (ou bot), e ele poderia usá-lo para realizar essas ações (dirigir o carro ou editar o blog) sem sequer precisar ter uma conta, apenas com o token JWT que sua API gerou para isso. |
|||
|
|||
Usando essas ideias, o JWT pode ser usado para cenários muito mais sofisticados. |
|||
|
|||
Nesses casos, várias dessas entidades poderiam ter o mesmo ID, digamos `foo` (um usuário `foo`, um carro `foo` e uma postagem de blog `foo`). |
|||
|
|||
Então, para evitar colisões de ID, ao criar o token JWT para o usuário, você poderia prefixar o valor da chave `sub`, por exemplo, com `username:`. Assim, neste exemplo, o valor de `sub` poderia ser: `username:johndoe`. |
|||
|
|||
O importante a se lembrar é que a chave `sub` deve ter um identificador único em toda a aplicação e deve ser uma string. |
|||
|
|||
## Testando |
|||
|
|||
Execute o servidor e vá para a documentação: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. |
|||
|
|||
Você verá a interface de usuário assim: |
|||
|
|||
<img src="/img/tutorial/security/image07.png"> |
|||
|
|||
Autorize a aplicação da mesma maneira que antes. |
|||
|
|||
Usando as credenciais: |
|||
|
|||
Username: `johndoe` |
|||
Password: `secret` |
|||
|
|||
/// check | Verifique |
|||
|
|||
Observe que em nenhuma parte do código está a senha em texto puro "`secret`", nós temos apenas o hash. |
|||
|
|||
/// |
|||
|
|||
<img src="/img/tutorial/security/image08.png"> |
|||
|
|||
Chame o endpoint `/users/me/`, você receberá o retorno como: |
|||
|
|||
```JSON |
|||
{ |
|||
"username": "johndoe", |
|||
"email": "[email protected]", |
|||
"full_name": "John Doe", |
|||
"disabled": false |
|||
} |
|||
``` |
|||
|
|||
<img src="/img/tutorial/security/image09.png"> |
|||
|
|||
Se você abrir as ferramentas de desenvolvedor, poderá ver que os dados enviados incluem apenas o token. A senha é enviada apenas na primeira requisição para autenticar o usuário e obter o token de acesso, mas não é enviada nas próximas requisições: |
|||
|
|||
<img src="/img/tutorial/security/image10.png"> |
|||
|
|||
/// note | Nota |
|||
|
|||
Perceba que o cabeçalho `Authorization`, com o valor que começa com `Bearer `. |
|||
|
|||
/// |
|||
|
|||
## Uso avançado com `scopes` |
|||
|
|||
O OAuth2 tem a noção de "scopes" (escopos). |
|||
|
|||
Você pode usá-los para adicionar um conjunto específico de permissões a um token JWT. |
|||
|
|||
Então, você pode dar este token diretamente a um usuário ou a uma terceira parte para interagir com sua API com um conjunto de restrições. |
|||
|
|||
Você pode aprender como usá-los e como eles são integrados ao **FastAPI** mais adiante no **Guia Avançado do Usuário**. |
|||
|
|||
|
|||
## Recapitulação |
|||
|
|||
Com o que você viu até agora, você pode configurar uma aplicação **FastAPI** segura usando padrões como OAuth2 e JWT. |
|||
|
|||
Em quase qualquer framework, lidar com a segurança se torna rapidamente um assunto bastante complexo. |
|||
|
|||
Muitos pacotes que simplificam bastante isso precisam fazer muitas concessões com o modelo de dados, o banco de dados e os recursos disponíveis. E alguns desses pacotes que simplificam demais na verdade têm falhas de segurança subjacentes. |
|||
|
|||
--- |
|||
|
|||
O **FastAPI** não faz nenhuma concessão com nenhum banco de dados, modelo de dados ou ferramenta. |
|||
|
|||
Ele oferece toda a flexibilidade para você escolher as opções que melhor se ajustam ao seu projeto. |
|||
|
|||
E você pode usar diretamente muitos pacotes bem mantidos e amplamente utilizados, como `passlib` e `PyJWT`, porque o **FastAPI** não exige mecanismos complexos para integrar pacotes externos. |
|||
|
|||
Mas ele fornece as ferramentas para simplificar o processo o máximo possível, sem comprometer a flexibilidade, robustez ou segurança. |
|||
|
|||
E você pode usar e implementar protocolos padrão seguros, como o OAuth2, de uma maneira relativamente simples. |
|||
|
|||
Você pode aprender mais no **Guia Avançado do Usuário** sobre como usar os "scopes" do OAuth2 para um sistema de permissões mais refinado, seguindo esses mesmos padrões. O OAuth2 com scopes é o mecanismo usado por muitos provedores grandes de autenticação, como o Facebook, Google, GitHub, Microsoft, Twitter, etc. para autorizar aplicativos de terceiros a interagir com suas APIs em nome de seus usuários. |
@ -0,0 +1,221 @@ |
|||
import logging |
|||
import secrets |
|||
import subprocess |
|||
from collections import defaultdict |
|||
from pathlib import Path |
|||
from typing import Any |
|||
|
|||
import httpx |
|||
import yaml |
|||
from github import Github |
|||
from pydantic import BaseModel, SecretStr |
|||
from pydantic_settings import BaseSettings |
|||
|
|||
github_graphql_url = "https://api.github.com/graphql" |
|||
|
|||
|
|||
sponsors_query = """ |
|||
query Q($after: String) { |
|||
user(login: "tiangolo") { |
|||
sponsorshipsAsMaintainer(first: 100, after: $after) { |
|||
edges { |
|||
cursor |
|||
node { |
|||
sponsorEntity { |
|||
... on Organization { |
|||
login |
|||
avatarUrl |
|||
url |
|||
} |
|||
... on User { |
|||
login |
|||
avatarUrl |
|||
url |
|||
} |
|||
} |
|||
tier { |
|||
name |
|||
monthlyPriceInDollars |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
""" |
|||
|
|||
|
|||
class SponsorEntity(BaseModel): |
|||
login: str |
|||
avatarUrl: str |
|||
url: str |
|||
|
|||
|
|||
class Tier(BaseModel): |
|||
name: str |
|||
monthlyPriceInDollars: float |
|||
|
|||
|
|||
class SponsorshipAsMaintainerNode(BaseModel): |
|||
sponsorEntity: SponsorEntity |
|||
tier: Tier |
|||
|
|||
|
|||
class SponsorshipAsMaintainerEdge(BaseModel): |
|||
cursor: str |
|||
node: SponsorshipAsMaintainerNode |
|||
|
|||
|
|||
class SponsorshipAsMaintainer(BaseModel): |
|||
edges: list[SponsorshipAsMaintainerEdge] |
|||
|
|||
|
|||
class SponsorsUser(BaseModel): |
|||
sponsorshipsAsMaintainer: SponsorshipAsMaintainer |
|||
|
|||
|
|||
class SponsorsResponseData(BaseModel): |
|||
user: SponsorsUser |
|||
|
|||
|
|||
class SponsorsResponse(BaseModel): |
|||
data: SponsorsResponseData |
|||
|
|||
|
|||
class Settings(BaseSettings): |
|||
sponsors_token: SecretStr |
|||
pr_token: SecretStr |
|||
github_repository: str |
|||
httpx_timeout: int = 30 |
|||
|
|||
|
|||
def get_graphql_response( |
|||
*, |
|||
settings: Settings, |
|||
query: str, |
|||
after: str | None = None, |
|||
) -> dict[str, Any]: |
|||
headers = {"Authorization": f"token {settings.sponsors_token.get_secret_value()}"} |
|||
variables = {"after": after} |
|||
response = httpx.post( |
|||
github_graphql_url, |
|||
headers=headers, |
|||
timeout=settings.httpx_timeout, |
|||
json={"query": query, "variables": variables, "operationName": "Q"}, |
|||
) |
|||
if response.status_code != 200: |
|||
logging.error(f"Response was not 200, after: {after}") |
|||
logging.error(response.text) |
|||
raise RuntimeError(response.text) |
|||
data = response.json() |
|||
if "errors" in data: |
|||
logging.error(f"Errors in response, after: {after}") |
|||
logging.error(data["errors"]) |
|||
logging.error(response.text) |
|||
raise RuntimeError(response.text) |
|||
return data |
|||
|
|||
|
|||
def get_graphql_sponsor_edges( |
|||
*, settings: Settings, after: str | None = None |
|||
) -> list[SponsorshipAsMaintainerEdge]: |
|||
data = get_graphql_response(settings=settings, query=sponsors_query, after=after) |
|||
graphql_response = SponsorsResponse.model_validate(data) |
|||
return graphql_response.data.user.sponsorshipsAsMaintainer.edges |
|||
|
|||
|
|||
def get_individual_sponsors( |
|||
settings: Settings, |
|||
) -> defaultdict[float, dict[str, SponsorEntity]]: |
|||
nodes: list[SponsorshipAsMaintainerNode] = [] |
|||
edges = get_graphql_sponsor_edges(settings=settings) |
|||
|
|||
while edges: |
|||
for edge in edges: |
|||
nodes.append(edge.node) |
|||
last_edge = edges[-1] |
|||
edges = get_graphql_sponsor_edges(settings=settings, after=last_edge.cursor) |
|||
|
|||
tiers: defaultdict[float, dict[str, SponsorEntity]] = defaultdict(dict) |
|||
for node in nodes: |
|||
tiers[node.tier.monthlyPriceInDollars][node.sponsorEntity.login] = ( |
|||
node.sponsorEntity |
|||
) |
|||
return tiers |
|||
|
|||
|
|||
def update_content(*, content_path: Path, new_content: Any) -> bool: |
|||
old_content = content_path.read_text(encoding="utf-8") |
|||
|
|||
new_content = yaml.dump(new_content, sort_keys=False, width=200, allow_unicode=True) |
|||
if old_content == new_content: |
|||
logging.info(f"The content hasn't changed for {content_path}") |
|||
return False |
|||
content_path.write_text(new_content, encoding="utf-8") |
|||
logging.info(f"Updated {content_path}") |
|||
return True |
|||
|
|||
|
|||
def main() -> None: |
|||
logging.basicConfig(level=logging.INFO) |
|||
settings = Settings() |
|||
logging.info(f"Using config: {settings.model_dump_json()}") |
|||
g = Github(settings.pr_token.get_secret_value()) |
|||
repo = g.get_repo(settings.github_repository) |
|||
|
|||
tiers = get_individual_sponsors(settings=settings) |
|||
keys = list(tiers.keys()) |
|||
keys.sort(reverse=True) |
|||
sponsors = [] |
|||
for key in keys: |
|||
sponsor_group = [] |
|||
for login, sponsor in tiers[key].items(): |
|||
sponsor_group.append( |
|||
{"login": login, "avatarUrl": sponsor.avatarUrl, "url": sponsor.url} |
|||
) |
|||
sponsors.append(sponsor_group) |
|||
github_sponsors = { |
|||
"sponsors": sponsors, |
|||
} |
|||
|
|||
# For local development |
|||
# github_sponsors_path = Path("../docs/en/data/github_sponsors.yml") |
|||
github_sponsors_path = Path("./docs/en/data/github_sponsors.yml") |
|||
updated = update_content( |
|||
content_path=github_sponsors_path, new_content=github_sponsors |
|||
) |
|||
|
|||
if not updated: |
|||
logging.info("The data hasn't changed, finishing.") |
|||
return |
|||
|
|||
logging.info("Setting up GitHub Actions git user") |
|||
subprocess.run(["git", "config", "user.name", "github-actions"], check=True) |
|||
subprocess.run( |
|||
["git", "config", "user.email", "[email protected]"], check=True |
|||
) |
|||
branch_name = f"fastapi-people-sponsors-{secrets.token_hex(4)}" |
|||
logging.info(f"Creating a new branch {branch_name}") |
|||
subprocess.run(["git", "checkout", "-b", branch_name], check=True) |
|||
logging.info("Adding updated file") |
|||
subprocess.run( |
|||
[ |
|||
"git", |
|||
"add", |
|||
str(github_sponsors_path), |
|||
], |
|||
check=True, |
|||
) |
|||
logging.info("Committing updated file") |
|||
message = "👥 Update FastAPI People - Sponsors" |
|||
subprocess.run(["git", "commit", "-m", message], check=True) |
|||
logging.info("Pushing branch") |
|||
subprocess.run(["git", "push", "origin", branch_name], check=True) |
|||
logging.info("Creating PR") |
|||
pr = repo.create_pull(title=message, body=message, base="master", head=branch_name) |
|||
logging.info(f"Created PR: {pr.number}") |
|||
logging.info("Finished") |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
main() |
@ -1,206 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_multiple_params.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_post_body_q_bar_content(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json={"name": "Foo", "price": 50.5}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"item_id": 5, |
|||
"item": { |
|||
"name": "Foo", |
|||
"price": 50.5, |
|||
"description": None, |
|||
"tax": None, |
|||
}, |
|||
"q": "bar", |
|||
} |
|||
|
|||
|
|||
def test_post_no_body_q_bar(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5, "q": "bar"} |
|||
|
|||
|
|||
def test_post_no_body(client: TestClient): |
|||
response = client.put("/items/5", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5} |
|||
|
|||
|
|||
def test_post_id_foo(client: TestClient): |
|||
response = client.put("/items/foo", json=None) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["path", "item_id"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "foo", |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["path", "item_id"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "The ID of the item to get", |
|||
"maximum": 1000.0, |
|||
"minimum": 0.0, |
|||
"type": "integer", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [ |
|||
{"$ref": "#/components/schemas/Item"}, |
|||
{"type": "null"}, |
|||
], |
|||
"title": "Item", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"$ref": "#/components/schemas/Item"} |
|||
) |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": IsDict( |
|||
{ |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Tax", "type": "number"} |
|||
), |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,213 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_multiple_params.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_body_q_bar_content(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json={"name": "Foo", "price": 50.5}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"item_id": 5, |
|||
"item": { |
|||
"name": "Foo", |
|||
"price": 50.5, |
|||
"description": None, |
|||
"tax": None, |
|||
}, |
|||
"q": "bar", |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_no_body_q_bar(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5, "q": "bar"} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_no_body(client: TestClient): |
|||
response = client.put("/items/5", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_id_foo(client: TestClient): |
|||
response = client.put("/items/foo", json=None) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["path", "item_id"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "foo", |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["path", "item_id"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "The ID of the item to get", |
|||
"maximum": 1000.0, |
|||
"minimum": 0.0, |
|||
"type": "integer", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [ |
|||
{"$ref": "#/components/schemas/Item"}, |
|||
{"type": "null"}, |
|||
], |
|||
"title": "Item", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"$ref": "#/components/schemas/Item"} |
|||
) |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": IsDict( |
|||
{ |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Tax", "type": "number"} |
|||
), |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,213 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_multiple_params.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_q_bar_content(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json={"name": "Foo", "price": 50.5}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"item_id": 5, |
|||
"item": { |
|||
"name": "Foo", |
|||
"price": 50.5, |
|||
"description": None, |
|||
"tax": None, |
|||
}, |
|||
"q": "bar", |
|||
} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_no_body_q_bar(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5, "q": "bar"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_no_body(client: TestClient): |
|||
response = client.put("/items/5", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_id_foo(client: TestClient): |
|||
response = client.put("/items/foo", json=None) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["path", "item_id"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "foo", |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["path", "item_id"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "The ID of the item to get", |
|||
"maximum": 1000.0, |
|||
"minimum": 0.0, |
|||
"type": "integer", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [ |
|||
{"$ref": "#/components/schemas/Item"}, |
|||
{"type": "null"}, |
|||
], |
|||
"title": "Item", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"$ref": "#/components/schemas/Item"} |
|||
) |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": IsDict( |
|||
{ |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Tax", "type": "number"} |
|||
), |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,213 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_multiple_params.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_body_q_bar_content(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json={"name": "Foo", "price": 50.5}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"item_id": 5, |
|||
"item": { |
|||
"name": "Foo", |
|||
"price": 50.5, |
|||
"description": None, |
|||
"tax": None, |
|||
}, |
|||
"q": "bar", |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_no_body_q_bar(client: TestClient): |
|||
response = client.put("/items/5?q=bar", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5, "q": "bar"} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_no_body(client: TestClient): |
|||
response = client.put("/items/5", json=None) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"item_id": 5} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_id_foo(client: TestClient): |
|||
response = client.put("/items/foo", json=None) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["path", "item_id"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "foo", |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["path", "item_id"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "The ID of the item to get", |
|||
"maximum": 1000.0, |
|||
"minimum": 0.0, |
|||
"type": "integer", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [ |
|||
{"$ref": "#/components/schemas/Item"}, |
|||
{"type": "null"}, |
|||
], |
|||
"title": "Item", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"$ref": "#/components/schemas/Item"} |
|||
) |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": IsDict( |
|||
{ |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Tax", "type": "number"} |
|||
), |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,128 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_nested_models.tutorial009_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body(client: TestClient): |
|||
data = {"2": 2.2, "3": 3.3} |
|||
response = client.post("/index-weights/", json=data) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == data |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_invalid_body(client: TestClient): |
|||
data = {"foo": 2.2, "3": 3.3} |
|||
response = client.post("/index-weights/", json=data) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["body", "foo", "[key]"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "foo", |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "__key__"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/index-weights/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create Index Weights", |
|||
"operationId": "create_index_weights_index_weights__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"title": "Weights", |
|||
"type": "object", |
|||
"additionalProperties": {"type": "number"}, |
|||
} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,317 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_updates.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/baz") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"name": "Baz", |
|||
"description": None, |
|||
"price": 50.2, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_put(client: TestClient): |
|||
response = client.put( |
|||
"/items/bar", json={"name": "Barz", "price": 3, "description": None} |
|||
) |
|||
assert response.json() == { |
|||
"name": "Barz", |
|||
"description": None, |
|||
"price": 3, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
}, |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"type": "object", |
|||
"title": "Item", |
|||
"properties": { |
|||
"name": { |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Name", |
|||
}, |
|||
"description": { |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Description", |
|||
}, |
|||
"price": { |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
"title": "Price", |
|||
}, |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_py310 |
|||
@needs_pydanticv1 |
|||
def test_openapi_schema_pv1(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
}, |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,317 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39, needs_pydanticv1, needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.body_updates.tutorial001_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/baz") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"name": "Baz", |
|||
"description": None, |
|||
"price": 50.2, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_put(client: TestClient): |
|||
response = client.put( |
|||
"/items/bar", json={"name": "Barz", "price": 3, "description": None} |
|||
) |
|||
assert response.json() == { |
|||
"name": "Barz", |
|||
"description": None, |
|||
"price": 3, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py39 |
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
}, |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"type": "object", |
|||
"title": "Item", |
|||
"properties": { |
|||
"name": { |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Name", |
|||
}, |
|||
"description": { |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Description", |
|||
}, |
|||
"price": { |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
"title": "Price", |
|||
}, |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_py39 |
|||
@needs_pydanticv1 |
|||
def test_openapi_schema_pv1(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
}, |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Update Item", |
|||
"operationId": "update_item_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,108 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.cookie_params.tutorial001_an import app |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,cookies,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"ads_id": None}), |
|||
("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), |
|||
( |
|||
"/items", |
|||
{"ads_id": "ads_track", "session": "cookiesession"}, |
|||
200, |
|||
{"ads_id": "ads_track"}, |
|||
), |
|||
("/items", {"session": "cookiesession"}, 200, {"ads_id": None}), |
|||
], |
|||
) |
|||
def test(path, cookies, expected_status, expected_response): |
|||
client = TestClient(app, cookies=cookies) |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Ads Id", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Ads Id", "type": "string"} |
|||
), |
|||
"name": "ads_id", |
|||
"in": "cookie", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,114 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,cookies,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"ads_id": None}), |
|||
("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), |
|||
( |
|||
"/items", |
|||
{"ads_id": "ads_track", "session": "cookiesession"}, |
|||
200, |
|||
{"ads_id": "ads_track"}, |
|||
), |
|||
("/items", {"session": "cookiesession"}, 200, {"ads_id": None}), |
|||
], |
|||
) |
|||
def test(path, cookies, expected_status, expected_response): |
|||
from docs_src.cookie_params.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app, cookies=cookies) |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(): |
|||
from docs_src.cookie_params.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Ads Id", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Ads Id", "type": "string"} |
|||
), |
|||
"name": "ads_id", |
|||
"in": "cookie", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,114 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"path,cookies,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"ads_id": None}), |
|||
("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), |
|||
( |
|||
"/items", |
|||
{"ads_id": "ads_track", "session": "cookiesession"}, |
|||
200, |
|||
{"ads_id": "ads_track"}, |
|||
), |
|||
("/items", {"session": "cookiesession"}, 200, {"ads_id": None}), |
|||
], |
|||
) |
|||
def test(path, cookies, expected_status, expected_response): |
|||
from docs_src.cookie_params.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app, cookies=cookies) |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(): |
|||
from docs_src.cookie_params.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Ads Id", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Ads Id", "type": "string"} |
|||
), |
|||
"name": "ads_id", |
|||
"in": "cookie", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,114 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,cookies,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"ads_id": None}), |
|||
("/items", {"ads_id": "ads_track"}, 200, {"ads_id": "ads_track"}), |
|||
( |
|||
"/items", |
|||
{"ads_id": "ads_track", "session": "cookiesession"}, |
|||
200, |
|||
{"ads_id": "ads_track"}, |
|||
), |
|||
("/items", {"session": "cookiesession"}, 200, {"ads_id": None}), |
|||
], |
|||
) |
|||
def test(path, cookies, expected_status, expected_response): |
|||
from docs_src.cookie_params.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app, cookies=cookies) |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(): |
|||
from docs_src.cookie_params.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Ads Id", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Ads Id", "type": "string"} |
|||
), |
|||
"name": "ads_id", |
|||
"in": "cookie", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,183 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
("/items", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}), |
|||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), |
|||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), |
|||
("/users", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,191 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
("/items", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}), |
|||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), |
|||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), |
|||
("/users", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,191 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
("/items", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}), |
|||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), |
|||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), |
|||
("/users", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,191 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
("/items", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}), |
|||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}), |
|||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}), |
|||
("/users", 200, {"q": None, "skip": 0, "limit": 100}), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,162 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial004_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
( |
|||
"/items", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
] |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
], |
|||
"q": "foo", |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}, {"item_name": "Baz"}], "q": "foo"}, |
|||
), |
|||
( |
|||
"/items?q=bar&limit=2", |
|||
200, |
|||
{"items": [{"item_name": "Foo"}, {"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?q=bar&skip=1&limit=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?limit=1&q=bar&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,170 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial004_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
( |
|||
"/items", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
] |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
], |
|||
"q": "foo", |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}, {"item_name": "Baz"}], "q": "foo"}, |
|||
), |
|||
( |
|||
"/items?q=bar&limit=2", |
|||
200, |
|||
{"items": [{"item_name": "Foo"}, {"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?q=bar&skip=1&limit=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?limit=1&q=bar&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,170 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial004_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
( |
|||
"/items", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
] |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
], |
|||
"q": "foo", |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}, {"item_name": "Baz"}], "q": "foo"}, |
|||
), |
|||
( |
|||
"/items?q=bar&limit=2", |
|||
200, |
|||
{"items": [{"item_name": "Foo"}, {"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?q=bar&skip=1&limit=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?limit=1&q=bar&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,170 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial004_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,expected_status,expected_response", |
|||
[ |
|||
( |
|||
"/items", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
] |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo", |
|||
200, |
|||
{ |
|||
"items": [ |
|||
{"item_name": "Foo"}, |
|||
{"item_name": "Bar"}, |
|||
{"item_name": "Baz"}, |
|||
], |
|||
"q": "foo", |
|||
}, |
|||
), |
|||
( |
|||
"/items?q=foo&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}, {"item_name": "Baz"}], "q": "foo"}, |
|||
), |
|||
( |
|||
"/items?q=bar&limit=2", |
|||
200, |
|||
{"items": [{"item_name": "Foo"}, {"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?q=bar&skip=1&limit=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
( |
|||
"/items?limit=1&q=bar&skip=1", |
|||
200, |
|||
{"items": [{"item_name": "Bar"}], "q": "bar"}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(path, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Q", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Q", "type": "string"} |
|||
), |
|||
"name": "q", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Limit", |
|||
"type": "integer", |
|||
"default": 100, |
|||
}, |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,149 +0,0 @@ |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial006_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_get_no_headers(): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_get_invalid_one_header(): |
|||
response = client.get("/items/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
def test_get_invalid_second_header(): |
|||
response = client.get( |
|||
"/items/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
def test_get_valid_headers(): |
|||
response = client.get( |
|||
"/items/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"item": "Foo"}, {"item": "Bar"}] |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,161 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial006_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_headers(client: TestClient): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_one_header(client: TestClient): |
|||
response = client.get("/items/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_second_header(client: TestClient): |
|||
response = client.get( |
|||
"/items/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_valid_headers(client: TestClient): |
|||
response = client.get( |
|||
"/items/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"item": "Foo"}, {"item": "Bar"}] |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,23 +1,39 @@ |
|||
import importlib |
|||
|
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial008b import app |
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture( |
|||
name="client", |
|||
params=[ |
|||
"tutorial008b", |
|||
"tutorial008b_an", |
|||
pytest.param("tutorial008b_an_py39", marks=needs_py39), |
|||
], |
|||
) |
|||
def get_client(request: pytest.FixtureRequest): |
|||
mod = importlib.import_module(f"docs_src.dependencies.{request.param}") |
|||
|
|||
client = TestClient(app) |
|||
client = TestClient(mod.app) |
|||
return client |
|||
|
|||
|
|||
def test_get_no_item(): |
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found"} |
|||
|
|||
|
|||
def test_owner_error(): |
|||
def test_owner_error(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "Owner error: Rick"} |
|||
|
|||
|
|||
def test_get_item(): |
|||
def test_get_item(client: TestClient): |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"} |
|||
|
@ -1,23 +0,0 @@ |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial008b_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_get_no_item(): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found"} |
|||
|
|||
|
|||
def test_owner_error(): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "Owner error: Rick"} |
|||
|
|||
|
|||
def test_get_item(): |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"} |
@ -1,33 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008b_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_owner_error(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "Owner error: Rick"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_item(client: TestClient): |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"} |
@ -1,38 +1,50 @@ |
|||
import importlib |
|||
from types import ModuleType |
|||
|
|||
import pytest |
|||
from fastapi.exceptions import FastAPIError |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008c import app |
|||
@pytest.fixture( |
|||
name="mod", |
|||
params=[ |
|||
"tutorial008c", |
|||
"tutorial008c_an", |
|||
pytest.param("tutorial008c_an_py39", marks=needs_py39), |
|||
], |
|||
) |
|||
def get_mod(request: pytest.FixtureRequest): |
|||
mod = importlib.import_module(f"docs_src.dependencies.{request.param}") |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
return mod |
|||
|
|||
|
|||
def test_get_no_item(client: TestClient): |
|||
def test_get_no_item(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
def test_get(client: TestClient): |
|||
def test_get(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
def test_fastapi_error(client: TestClient): |
|||
def test_fastapi_error(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
with pytest.raises(FastAPIError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert "No response object was returned" in exc_info.value.args[0] |
|||
|
|||
|
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008c import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
def test_internal_server_error(mod: ModuleType): |
|||
client = TestClient(mod.app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
|||
|
@ -1,38 +0,0 @@ |
|||
import pytest |
|||
from fastapi.exceptions import FastAPIError |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008c_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
def test_fastapi_error(client: TestClient): |
|||
with pytest.raises(FastAPIError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert "No response object was returned" in exc_info.value.args[0] |
|||
|
|||
|
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008c_an import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
@ -1,44 +0,0 @@ |
|||
import pytest |
|||
from fastapi.exceptions import FastAPIError |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008c_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_fastapi_error(client: TestClient): |
|||
with pytest.raises(FastAPIError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert "No response object was returned" in exc_info.value.args[0] |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008c_an_py39 import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
@ -1,41 +1,51 @@ |
|||
import importlib |
|||
from types import ModuleType |
|||
|
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008d import app |
|||
@pytest.fixture( |
|||
name="mod", |
|||
params=[ |
|||
"tutorial008d", |
|||
"tutorial008d_an", |
|||
pytest.param("tutorial008d_an_py39", marks=needs_py39), |
|||
], |
|||
) |
|||
def get_mod(request: pytest.FixtureRequest): |
|||
mod = importlib.import_module(f"docs_src.dependencies.{request.param}") |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
return mod |
|||
|
|||
|
|||
def test_get_no_item(client: TestClient): |
|||
def test_get_no_item(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
def test_get(client: TestClient): |
|||
def test_get(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
def test_internal_error(client: TestClient): |
|||
from docs_src.dependencies.tutorial008d import InternalError |
|||
|
|||
with pytest.raises(InternalError) as exc_info: |
|||
def test_internal_error(mod: ModuleType): |
|||
client = TestClient(mod.app) |
|||
with pytest.raises(mod.InternalError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert ( |
|||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick" |
|||
) |
|||
|
|||
|
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008d import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
def test_internal_server_error(mod: ModuleType): |
|||
client = TestClient(mod.app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
|||
|
@ -1,41 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008d_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
def test_internal_error(client: TestClient): |
|||
from docs_src.dependencies.tutorial008d_an import InternalError |
|||
|
|||
with pytest.raises(InternalError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert ( |
|||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick" |
|||
) |
|||
|
|||
|
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008d_an import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
@ -1,47 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial008d_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_item(client: TestClient): |
|||
response = client.get("/items/foo") |
|||
assert response.status_code == 404, response.text |
|||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get(client: TestClient): |
|||
response = client.get("/items/plumbus") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == "plumbus" |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_internal_error(client: TestClient): |
|||
from docs_src.dependencies.tutorial008d_an_py39 import InternalError |
|||
|
|||
with pytest.raises(InternalError) as exc_info: |
|||
client.get("/items/portal-gun") |
|||
assert ( |
|||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick" |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_internal_server_error(): |
|||
from docs_src.dependencies.tutorial008d_an_py39 import app |
|||
|
|||
client = TestClient(app, raise_server_exceptions=False) |
|||
response = client.get("/items/portal-gun") |
|||
assert response.status_code == 500, response.text |
|||
assert response.text == "Internal Server Error" |
@ -1,250 +0,0 @@ |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.dependencies.tutorial012_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_get_no_headers_items(): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_get_no_headers_users(): |
|||
response = client.get("/users/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_get_invalid_one_header_items(): |
|||
response = client.get("/items/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
def test_get_invalid_one_users(): |
|||
response = client.get("/users/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
def test_get_invalid_second_header_items(): |
|||
response = client.get( |
|||
"/items/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
def test_get_invalid_second_header_users(): |
|||
response = client.get( |
|||
"/users/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
def test_get_valid_headers_items(): |
|||
response = client.get( |
|||
"/items/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"item": "Portal Gun"}, {"item": "Plumbus"}] |
|||
|
|||
|
|||
def test_get_valid_headers_users(): |
|||
response = client.get( |
|||
"/users/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,266 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.dependencies.tutorial012_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_headers_items(client: TestClient): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_no_headers_users(client: TestClient): |
|||
response = client.get("/users/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["header", "x-key"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["header", "x-token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["header", "x-key"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_one_header_items(client: TestClient): |
|||
response = client.get("/items/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_one_users(client: TestClient): |
|||
response = client.get("/users/", headers={"X-Token": "invalid"}) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Token header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_second_header_items(client: TestClient): |
|||
response = client.get( |
|||
"/items/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_invalid_second_header_users(client: TestClient): |
|||
response = client.get( |
|||
"/users/", headers={"X-Token": "fake-super-secret-token", "X-Key": "invalid"} |
|||
) |
|||
assert response.status_code == 400, response.text |
|||
assert response.json() == {"detail": "X-Key header invalid"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_valid_headers_items(client: TestClient): |
|||
response = client.get( |
|||
"/items/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"item": "Portal Gun"}, {"item": "Plumbus"}] |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_valid_headers_users(client: TestClient): |
|||
response = client.get( |
|||
"/users/", |
|||
headers={ |
|||
"X-Token": "fake-super-secret-token", |
|||
"X-Key": "fake-super-secret-key", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
"/users/": { |
|||
"get": { |
|||
"summary": "Read Users", |
|||
"operationId": "read_users_users__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Token", "type": "string"}, |
|||
"name": "x-token", |
|||
"in": "header", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "X-Key", "type": "string"}, |
|||
"name": "x-key", |
|||
"in": "header", |
|||
}, |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,175 +0,0 @@ |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.extra_data_types.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_extra_types(): |
|||
item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" |
|||
data = { |
|||
"start_datetime": "2018-12-22T14:00:00+00:00", |
|||
"end_datetime": "2018-12-24T15:00:00+00:00", |
|||
"repeat_at": "15:30:00", |
|||
"process_after": 300, |
|||
} |
|||
expected_response = data.copy() |
|||
expected_response.update( |
|||
{ |
|||
"start_process": "2018-12-22T14:05:00+00:00", |
|||
"duration": 176_100, |
|||
"item_id": item_id, |
|||
} |
|||
) |
|||
response = client.put(f"/items/{item_id}", json=data) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "Item Id", |
|||
"type": "string", |
|||
"format": "uuid", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"required": True, |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"allOf": [ |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
], |
|||
"title": "Body", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
) |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_read_items_items__item_id__put": { |
|||
"title": "Body_read_items_items__item_id__put", |
|||
"type": "object", |
|||
"properties": { |
|||
"start_datetime": { |
|||
"title": "Start Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"end_datetime": { |
|||
"title": "End Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"repeat_at": IsDict( |
|||
{ |
|||
"title": "Repeat At", |
|||
"anyOf": [ |
|||
{"type": "string", "format": "time"}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Repeat At", |
|||
"type": "string", |
|||
"format": "time", |
|||
} |
|||
), |
|||
"process_after": IsDict( |
|||
{ |
|||
"title": "Process After", |
|||
"type": "string", |
|||
"format": "duration", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Process After", |
|||
"type": "number", |
|||
"format": "time-delta", |
|||
} |
|||
), |
|||
}, |
|||
"required": ["start_datetime", "end_datetime", "process_after"], |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,184 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_data_types.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_extra_types(client: TestClient): |
|||
item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" |
|||
data = { |
|||
"start_datetime": "2018-12-22T14:00:00+00:00", |
|||
"end_datetime": "2018-12-24T15:00:00+00:00", |
|||
"repeat_at": "15:30:00", |
|||
"process_after": 300, |
|||
} |
|||
expected_response = data.copy() |
|||
expected_response.update( |
|||
{ |
|||
"start_process": "2018-12-22T14:05:00+00:00", |
|||
"duration": 176_100, |
|||
"item_id": item_id, |
|||
} |
|||
) |
|||
response = client.put(f"/items/{item_id}", json=data) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "Item Id", |
|||
"type": "string", |
|||
"format": "uuid", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"required": True, |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"allOf": [ |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
], |
|||
"title": "Body", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
) |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_read_items_items__item_id__put": { |
|||
"title": "Body_read_items_items__item_id__put", |
|||
"type": "object", |
|||
"properties": { |
|||
"start_datetime": { |
|||
"title": "Start Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"end_datetime": { |
|||
"title": "End Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"repeat_at": IsDict( |
|||
{ |
|||
"title": "Repeat At", |
|||
"anyOf": [ |
|||
{"type": "string", "format": "time"}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Repeat At", |
|||
"type": "string", |
|||
"format": "time", |
|||
} |
|||
), |
|||
"process_after": IsDict( |
|||
{ |
|||
"title": "Process After", |
|||
"type": "string", |
|||
"format": "duration", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Process After", |
|||
"type": "number", |
|||
"format": "time-delta", |
|||
} |
|||
), |
|||
}, |
|||
"required": ["start_datetime", "end_datetime", "process_after"], |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,184 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_data_types.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_extra_types(client: TestClient): |
|||
item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" |
|||
data = { |
|||
"start_datetime": "2018-12-22T14:00:00+00:00", |
|||
"end_datetime": "2018-12-24T15:00:00+00:00", |
|||
"repeat_at": "15:30:00", |
|||
"process_after": 300, |
|||
} |
|||
expected_response = data.copy() |
|||
expected_response.update( |
|||
{ |
|||
"start_process": "2018-12-22T14:05:00+00:00", |
|||
"duration": 176_100, |
|||
"item_id": item_id, |
|||
} |
|||
) |
|||
response = client.put(f"/items/{item_id}", json=data) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "Item Id", |
|||
"type": "string", |
|||
"format": "uuid", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"required": True, |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"allOf": [ |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
], |
|||
"title": "Body", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
) |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_read_items_items__item_id__put": { |
|||
"title": "Body_read_items_items__item_id__put", |
|||
"type": "object", |
|||
"properties": { |
|||
"start_datetime": { |
|||
"title": "Start Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"end_datetime": { |
|||
"title": "End Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"repeat_at": IsDict( |
|||
{ |
|||
"title": "Repeat At", |
|||
"anyOf": [ |
|||
{"type": "string", "format": "time"}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Repeat At", |
|||
"type": "string", |
|||
"format": "time", |
|||
} |
|||
), |
|||
"process_after": IsDict( |
|||
{ |
|||
"title": "Process After", |
|||
"type": "string", |
|||
"format": "duration", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Process After", |
|||
"type": "number", |
|||
"format": "time-delta", |
|||
} |
|||
), |
|||
}, |
|||
"required": ["start_datetime", "end_datetime", "process_after"], |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,184 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_data_types.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_extra_types(client: TestClient): |
|||
item_id = "ff97dd87-a4a5-4a12-b412-cde99f33e00e" |
|||
data = { |
|||
"start_datetime": "2018-12-22T14:00:00+00:00", |
|||
"end_datetime": "2018-12-24T15:00:00+00:00", |
|||
"repeat_at": "15:30:00", |
|||
"process_after": 300, |
|||
} |
|||
expected_response = data.copy() |
|||
expected_response.update( |
|||
{ |
|||
"start_process": "2018-12-22T14:05:00+00:00", |
|||
"duration": 176_100, |
|||
"item_id": item_id, |
|||
} |
|||
) |
|||
response = client.put(f"/items/{item_id}", json=data) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"put": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__item_id__put", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": { |
|||
"title": "Item Id", |
|||
"type": "string", |
|||
"format": "uuid", |
|||
}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
"requestBody": { |
|||
"required": True, |
|||
"content": { |
|||
"application/json": { |
|||
"schema": IsDict( |
|||
{ |
|||
"allOf": [ |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
], |
|||
"title": "Body", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put" |
|||
} |
|||
) |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_read_items_items__item_id__put": { |
|||
"title": "Body_read_items_items__item_id__put", |
|||
"type": "object", |
|||
"properties": { |
|||
"start_datetime": { |
|||
"title": "Start Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"end_datetime": { |
|||
"title": "End Datetime", |
|||
"type": "string", |
|||
"format": "date-time", |
|||
}, |
|||
"repeat_at": IsDict( |
|||
{ |
|||
"title": "Repeat At", |
|||
"anyOf": [ |
|||
{"type": "string", "format": "time"}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Repeat At", |
|||
"type": "string", |
|||
"format": "time", |
|||
} |
|||
), |
|||
"process_after": IsDict( |
|||
{ |
|||
"title": "Process After", |
|||
"type": "string", |
|||
"format": "duration", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "Process After", |
|||
"type": "number", |
|||
"format": "time-delta", |
|||
} |
|||
), |
|||
}, |
|||
"required": ["start_datetime", "end_datetime", "process_after"], |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,144 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsOneOf |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_models.tutorial003_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_get_car(client: TestClient): |
|||
response = client.get("/items/item1") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"description": "All my friends drive a low rider", |
|||
"type": "car", |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_get_plane(client: TestClient): |
|||
response = client.get("/items/item2") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"description": "Music is my aeroplane, it's my aeroplane", |
|||
"type": "plane", |
|||
"size": 5, |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"title": "Response Read Item Items Item Id Get", |
|||
"anyOf": [ |
|||
{"$ref": "#/components/schemas/PlaneItem"}, |
|||
{"$ref": "#/components/schemas/CarItem"}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"PlaneItem": { |
|||
"title": "PlaneItem", |
|||
"required": IsOneOf( |
|||
["description", "type", "size"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["description", "size"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"type": {"title": "Type", "type": "string", "default": "plane"}, |
|||
"size": {"title": "Size", "type": "integer"}, |
|||
}, |
|||
}, |
|||
"CarItem": { |
|||
"title": "CarItem", |
|||
"required": IsOneOf( |
|||
["description", "type"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["description"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"type": {"title": "Type", "type": "string", "default": "car"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,67 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_models.tutorial004_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_items(client: TestClient): |
|||
response = client.get("/items/") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == [ |
|||
{"name": "Foo", "description": "There comes my hero"}, |
|||
{"name": "Red", "description": "It's my aeroplane"}, |
|||
] |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"title": "Response Read Items Items Get", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/Item"}, |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "description"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": {"title": "Description", "type": "string"}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
} |
@ -1,51 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.extra_models.tutorial005_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_get_items(client: TestClient): |
|||
response = client.get("/keyword-weights/") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"foo": 2.3, "bar": 3.4} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/keyword-weights/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"title": "Response Read Keyword Weights Keyword Weights Get", |
|||
"type": "object", |
|||
"additionalProperties": {"type": "number"}, |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
"summary": "Read Keyword Weights", |
|||
"operationId": "read_keyword_weights_keyword_weights__get", |
|||
} |
|||
} |
|||
}, |
|||
} |
@ -1,102 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.header_params.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "User-Agent", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "User-Agent", "type": "string"} |
|||
), |
|||
"name": "user-agent", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,110 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial001_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "User-Agent", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "User-Agent", "type": "string"} |
|||
), |
|||
"name": "user-agent", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,110 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial001_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"User-Agent": "testclient"}), |
|||
("/items", {"User-Agent": "FastAPI test"}, 200, {"User-Agent": "FastAPI test"}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "User-Agent", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "User-Agent", "type": "string"} |
|||
), |
|||
"name": "user-agent", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,113 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.header_params.tutorial002_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"strange_header": None}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), |
|||
( |
|||
"/items", |
|||
{"strange_header": "FastAPI test"}, |
|||
200, |
|||
{"strange_header": "FastAPI test"}, |
|||
), |
|||
( |
|||
"/items", |
|||
{"strange-header": "Not really underscore"}, |
|||
200, |
|||
{"strange_header": None}, |
|||
), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Strange Header", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Strange Header", "type": "string"} |
|||
), |
|||
"name": "strange_header", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,121 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial002_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"strange_header": None}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), |
|||
( |
|||
"/items", |
|||
{"strange_header": "FastAPI test"}, |
|||
200, |
|||
{"strange_header": "FastAPI test"}, |
|||
), |
|||
( |
|||
"/items", |
|||
{"strange-header": "Not really underscore"}, |
|||
200, |
|||
{"strange_header": None}, |
|||
), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Strange Header", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Strange Header", "type": "string"} |
|||
), |
|||
"name": "strange_header", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,124 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial002_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"strange_header": None}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), |
|||
( |
|||
"/items", |
|||
{"strange_header": "FastAPI test"}, |
|||
200, |
|||
{"strange_header": "FastAPI test"}, |
|||
), |
|||
( |
|||
"/items", |
|||
{"strange-header": "Not really underscore"}, |
|||
200, |
|||
{"strange_header": None}, |
|||
), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(): |
|||
from docs_src.header_params.tutorial002_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Strange Header", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Strange Header", "type": "string"} |
|||
), |
|||
"name": "strange_header", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,124 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial002_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"strange_header": None}), |
|||
("/items", {"X-Header": "notvalid"}, 200, {"strange_header": None}), |
|||
( |
|||
"/items", |
|||
{"strange_header": "FastAPI test"}, |
|||
200, |
|||
{"strange_header": "FastAPI test"}, |
|||
), |
|||
( |
|||
"/items", |
|||
{"strange-header": "Not really underscore"}, |
|||
200, |
|||
{"strange_header": None}, |
|||
), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(): |
|||
from docs_src.header_params.tutorial002_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
"title": "Strange Header", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Strange Header", "type": "string"} |
|||
), |
|||
"name": "strange_header", |
|||
"in": "header", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,110 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from docs_src.header_params.tutorial003_an import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"X-Token values": None}), |
|||
("/items", {"x-token": "foo"}, 200, {"X-Token values": ["foo"]}), |
|||
# TODO: fix this, is it a bug? |
|||
# ("/items", [("x-token", "foo"), ("x-token", "bar")], 200, {"X-Token values": ["foo", "bar"]}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"title": "X-Token", |
|||
"anyOf": [ |
|||
{"type": "array", "items": {"type": "string"}}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "X-Token", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
} |
|||
), |
|||
"name": "x-token", |
|||
"in": "header", |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,118 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial003_an_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"X-Token values": None}), |
|||
("/items", {"x-token": "foo"}, 200, {"X-Token values": ["foo"]}), |
|||
# TODO: fix this, is it a bug? |
|||
# ("/items", [("x-token", "foo"), ("x-token", "bar")], 200, {"X-Token values": ["foo", "bar"]}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"title": "X-Token", |
|||
"anyOf": [ |
|||
{"type": "array", "items": {"type": "string"}}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "X-Token", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
} |
|||
), |
|||
"name": "x-token", |
|||
"in": "header", |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,118 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial003_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"X-Token values": None}), |
|||
("/items", {"x-token": "foo"}, 200, {"X-Token values": ["foo"]}), |
|||
# TODO: fix this, is it a bug? |
|||
# ("/items", [("x-token", "foo"), ("x-token", "bar")], 200, {"X-Token values": ["foo", "bar"]}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"title": "X-Token", |
|||
"anyOf": [ |
|||
{"type": "array", "items": {"type": "string"}}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "X-Token", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
} |
|||
), |
|||
"name": "x-token", |
|||
"in": "header", |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,118 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.header_params.tutorial003_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"path,headers,expected_status,expected_response", |
|||
[ |
|||
("/items", None, 200, {"X-Token values": None}), |
|||
("/items", {"x-token": "foo"}, 200, {"X-Token values": ["foo"]}), |
|||
# TODO: fix this, is it a bug? |
|||
# ("/items", [("x-token", "foo"), ("x-token", "bar")], 200, {"X-Token values": ["foo", "bar"]}), |
|||
], |
|||
) |
|||
def test(path, headers, expected_status, expected_response, client: TestClient): |
|||
response = client.get(path, headers=headers) |
|||
assert response.status_code == expected_status |
|||
assert response.json() == expected_response |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"summary": "Read Items", |
|||
"operationId": "read_items_items__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"title": "X-Token", |
|||
"anyOf": [ |
|||
{"type": "array", "items": {"type": "string"}}, |
|||
{"type": "null"}, |
|||
], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"title": "X-Token", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
} |
|||
), |
|||
"name": "x-token", |
|||
"in": "header", |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,226 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.path_operation_configuration.tutorial005_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_query_params_str_validations(client: TestClient): |
|||
response = client.post("/items/", json={"name": "Foo", "price": 42}) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"name": "Foo", |
|||
"price": 42, |
|||
"description": None, |
|||
"tax": None, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "The created item", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create an item", |
|||
"description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", |
|||
"operationId": "create_item_items__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": { |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": { |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"uniqueItems": True, |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_py310 |
|||
@needs_pydanticv1 |
|||
def test_openapi_schema_pv1(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "The created item", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create an item", |
|||
"description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", |
|||
"operationId": "create_item_items__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": {"title": "Tax", "type": "number"}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"uniqueItems": True, |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,226 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39, needs_pydanticv1, needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.path_operation_configuration.tutorial005_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_query_params_str_validations(client: TestClient): |
|||
response = client.post("/items/", json={"name": "Foo", "price": 42}) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"name": "Foo", |
|||
"price": 42, |
|||
"description": None, |
|||
"tax": None, |
|||
"tags": [], |
|||
} |
|||
|
|||
|
|||
@needs_py39 |
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "The created item", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create an item", |
|||
"description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", |
|||
"operationId": "create_item_items__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": { |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": { |
|||
"title": "Tax", |
|||
"anyOf": [{"type": "number"}, {"type": "null"}], |
|||
}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"uniqueItems": True, |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_py39 |
|||
@needs_pydanticv1 |
|||
def test_openapi_schema_pv1(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "The created item", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create an item", |
|||
"description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", |
|||
"operationId": "create_item_items__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": ["name", "price"], |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"description": {"title": "Description", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"tax": {"title": "Tax", "type": "number"}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"uniqueItems": True, |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,180 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.query_params.tutorial006_py310 import app |
|||
|
|||
c = TestClient(app) |
|||
return c |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_foo_needy_very(client: TestClient): |
|||
response = client.get("/items/foo?needy=very") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"item_id": "foo", |
|||
"needy": "very", |
|||
"skip": 0, |
|||
"limit": None, |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_foo_no_needy(client: TestClient): |
|||
response = client.get("/items/foo?skip=a&limit=b") |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["query", "needy"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["query", "skip"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "a", |
|||
}, |
|||
{ |
|||
"type": "int_parsing", |
|||
"loc": ["query", "limit"], |
|||
"msg": "Input should be a valid integer, unable to parse string as an integer", |
|||
"input": "b", |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["query", "needy"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["query", "skip"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
}, |
|||
{ |
|||
"loc": ["query", "limit"], |
|||
"msg": "value is not a valid integer", |
|||
"type": "type_error.integer", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200 |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read User Item", |
|||
"operationId": "read_user_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
}, |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Needy", "type": "string"}, |
|||
"name": "needy", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Skip", |
|||
"type": "integer", |
|||
"default": 0, |
|||
}, |
|||
"name": "skip", |
|||
"in": "query", |
|||
}, |
|||
{ |
|||
"required": False, |
|||
"schema": IsDict( |
|||
{ |
|||
"anyOf": [{"type": "integer"}, {"type": "null"}], |
|||
"title": "Limit", |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Limit", "type": "integer"} |
|||
), |
|||
"name": "limit", |
|||
"in": "query", |
|||
}, |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,232 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {"username": "Foo"}, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {"password": "secret"}, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,240 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from tests.utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {"username": "Foo"}, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {"password": "secret"}, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,196 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from tests.utils import needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial002_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_extra_form(client: TestClient): |
|||
response = client.post( |
|||
"/login/", data={"username": "Foo", "password": "secret", "extra": "extra"} |
|||
) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "extra_forbidden", |
|||
"loc": ["body", "extra"], |
|||
"msg": "Extra inputs are not permitted", |
|||
"input": "extra", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {"username": "Foo"}, |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {"password": "secret"}, |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"additionalProperties": False, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,203 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from tests.utils import needs_py39, needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial002_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_extra_form(client: TestClient): |
|||
response = client.post( |
|||
"/login/", data={"username": "Foo", "password": "secret", "extra": "extra"} |
|||
) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "extra_forbidden", |
|||
"loc": ["body", "extra"], |
|||
"msg": "Extra inputs are not permitted", |
|||
"input": "extra", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {"username": "Foo"}, |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {"password": "secret"}, |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": {}, |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"additionalProperties": False, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,196 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from tests.utils import needs_pydanticv1 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial002_pv1_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_extra_form(client: TestClient): |
|||
response = client.post( |
|||
"/login/", data={"username": "Foo", "password": "secret", "extra": "extra"} |
|||
) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.extra", |
|||
"loc": ["body", "extra"], |
|||
"msg": "extra fields not permitted", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
}, |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
}, |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"additionalProperties": False, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,203 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from tests.utils import needs_py39, needs_pydanticv1 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_form_models.tutorial002_pv1_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo", "password": "secret"} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_extra_form(client: TestClient): |
|||
response = client.post( |
|||
"/login/", data={"username": "Foo", "password": "secret", "extra": "extra"} |
|||
) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.extra", |
|||
"loc": ["body", "extra"], |
|||
"msg": "extra fields not permitted", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
} |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
}, |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == { |
|||
"detail": [ |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
}, |
|||
{ |
|||
"type": "value_error.missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
}, |
|||
] |
|||
} |
|||
|
|||
|
|||
# TODO: remove when deprecating Pydantic v1 |
|||
@needs_pydanticv1 |
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": {"$ref": "#/components/schemas/FormData"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"FormData": { |
|||
"properties": { |
|||
"username": {"type": "string", "title": "Username"}, |
|||
"password": {"type": "string", "title": "Password"}, |
|||
}, |
|||
"additionalProperties": False, |
|||
"type": "object", |
|||
"required": ["username", "password"], |
|||
"title": "FormData", |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,234 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_forms.tutorial001_an import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo"} |
|||
|
|||
|
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Body_login_login__post" |
|||
} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_login_login__post": { |
|||
"title": "Body_login_login__post", |
|||
"required": ["username", "password"], |
|||
"type": "object", |
|||
"properties": { |
|||
"username": {"title": "Username", "type": "string"}, |
|||
"password": {"title": "Password", "type": "string"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,242 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.request_forms.tutorial001_an_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 200 |
|||
assert response.json() == {"username": "Foo"} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_password(client: TestClient): |
|||
response = client.post("/login/", data={"username": "Foo"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_username(client: TestClient): |
|||
response = client.post("/login/", data={"password": "secret"}) |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
} |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
} |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_form_no_data(client: TestClient): |
|||
response = client.post("/login/") |
|||
assert response.status_code == 422 |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "username"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "password"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "username"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "password"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/login/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Login", |
|||
"operationId": "login_login__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/x-www-form-urlencoded": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Body_login_login__post" |
|||
} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_login_login__post": { |
|||
"title": "Body_login_login__post", |
|||
"required": ["username", "password"], |
|||
"type": "object", |
|||
"properties": { |
|||
"username": {"title": "Username", "type": "string"}, |
|||
"password": {"title": "Password", "type": "string"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,309 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi import FastAPI |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="app") |
|||
def get_app(): |
|||
from docs_src.request_forms_and_files.tutorial001_an import app |
|||
|
|||
return app |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(app: FastAPI): |
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
def test_post_form_no_body(client: TestClient): |
|||
response = client.post("/files/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_form_no_file(client: TestClient): |
|||
response = client.post("/files/", data={"token": "foo"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/files/", json={"file": "Foo", "token": "Bar"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_file_no_token(tmp_path, app: FastAPI): |
|||
path = tmp_path / "test.txt" |
|||
path.write_bytes(b"<file content>") |
|||
|
|||
client = TestClient(app) |
|||
with path.open("rb") as file: |
|||
response = client.post("/files/", files={"file": file}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
def test_post_files_and_token(tmp_path, app: FastAPI): |
|||
patha = tmp_path / "test.txt" |
|||
pathb = tmp_path / "testb.txt" |
|||
patha.write_text("<file content>") |
|||
pathb.write_text("<file b content>") |
|||
|
|||
client = TestClient(app) |
|||
with patha.open("rb") as filea, pathb.open("rb") as fileb: |
|||
response = client.post( |
|||
"/files/", |
|||
data={"token": "foo"}, |
|||
files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"file_size": 14, |
|||
"token": "foo", |
|||
"fileb_content_type": "text/plain", |
|||
} |
|||
|
|||
|
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/files/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create File", |
|||
"operationId": "create_file_files__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"multipart/form-data": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Body_create_file_files__post" |
|||
} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_create_file_files__post": { |
|||
"title": "Body_create_file_files__post", |
|||
"required": ["file", "fileb", "token"], |
|||
"type": "object", |
|||
"properties": { |
|||
"file": {"title": "File", "type": "string", "format": "binary"}, |
|||
"fileb": { |
|||
"title": "Fileb", |
|||
"type": "string", |
|||
"format": "binary", |
|||
}, |
|||
"token": {"title": "Token", "type": "string"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,317 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict |
|||
from fastapi import FastAPI |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="app") |
|||
def get_app(): |
|||
from docs_src.request_forms_and_files.tutorial001_an_py39 import app |
|||
|
|||
return app |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(app: FastAPI): |
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_form_no_body(client: TestClient): |
|||
response = client.post("/files/") |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_form_no_file(client: TestClient): |
|||
response = client.post("/files/", data={"token": "foo"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_body_json(client: TestClient): |
|||
response = client.post("/files/", json={"file": "Foo", "token": "Bar"}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "file"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "file"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_file_no_token(tmp_path, app: FastAPI): |
|||
path = tmp_path / "test.txt" |
|||
path.write_bytes(b"<file content>") |
|||
|
|||
client = TestClient(app) |
|||
with path.open("rb") as file: |
|||
response = client.post("/files/", files={"file": file}) |
|||
assert response.status_code == 422, response.text |
|||
assert response.json() == IsDict( |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "fileb"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
{ |
|||
"type": "missing", |
|||
"loc": ["body", "token"], |
|||
"msg": "Field required", |
|||
"input": None, |
|||
}, |
|||
] |
|||
} |
|||
) | IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{ |
|||
"detail": [ |
|||
{ |
|||
"loc": ["body", "fileb"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
{ |
|||
"loc": ["body", "token"], |
|||
"msg": "field required", |
|||
"type": "value_error.missing", |
|||
}, |
|||
] |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_post_files_and_token(tmp_path, app: FastAPI): |
|||
patha = tmp_path / "test.txt" |
|||
pathb = tmp_path / "testb.txt" |
|||
patha.write_text("<file content>") |
|||
pathb.write_text("<file b content>") |
|||
|
|||
client = TestClient(app) |
|||
with patha.open("rb") as filea, pathb.open("rb") as fileb: |
|||
response = client.post( |
|||
"/files/", |
|||
data={"token": "foo"}, |
|||
files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"file_size": 14, |
|||
"token": "foo", |
|||
"fileb_content_type": "text/plain", |
|||
} |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/files/": { |
|||
"post": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Create File", |
|||
"operationId": "create_file_files__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"multipart/form-data": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Body_create_file_files__post" |
|||
} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Body_create_file_files__post": { |
|||
"title": "Body_create_file_files__post", |
|||
"required": ["file", "fileb", "token"], |
|||
"type": "object", |
|||
"properties": { |
|||
"file": {"title": "File", "type": "string", "format": "binary"}, |
|||
"fileb": { |
|||
"title": "Fileb", |
|||
"type": "string", |
|||
"format": "binary", |
|||
}, |
|||
"token": {"title": "Token", "type": "string"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,160 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict, IsOneOf |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.response_model.tutorial003_01_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_post_user(client: TestClient): |
|||
response = client.post( |
|||
"/user/", |
|||
json={ |
|||
"username": "foo", |
|||
"password": "fighter", |
|||
"email": "[email protected]", |
|||
"full_name": "Grave Dohl", |
|||
}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"username": "foo", |
|||
"email": "[email protected]", |
|||
"full_name": "Grave Dohl", |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/user/": { |
|||
"post": { |
|||
"summary": "Create User", |
|||
"operationId": "create_user_user__post", |
|||
"requestBody": { |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/UserIn"} |
|||
} |
|||
}, |
|||
"required": True, |
|||
}, |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/BaseUser"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"BaseUser": { |
|||
"title": "BaseUser", |
|||
"required": IsOneOf( |
|||
["username", "email", "full_name"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["username", "email"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"username": {"title": "Username", "type": "string"}, |
|||
"email": { |
|||
"title": "Email", |
|||
"type": "string", |
|||
"format": "email", |
|||
}, |
|||
"full_name": IsDict( |
|||
{ |
|||
"title": "Full Name", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Full Name", "type": "string"} |
|||
), |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"UserIn": { |
|||
"title": "UserIn", |
|||
"required": ["username", "email", "password"], |
|||
"type": "object", |
|||
"properties": { |
|||
"username": {"title": "Username", "type": "string"}, |
|||
"email": { |
|||
"title": "Email", |
|||
"type": "string", |
|||
"format": "email", |
|||
}, |
|||
"full_name": IsDict( |
|||
{ |
|||
"title": "Full Name", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Full Name", "type": "string"} |
|||
), |
|||
"password": {"title": "Password", "type": "string"}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,103 +0,0 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.response_model.tutorial003_05_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_get_portal(client: TestClient): |
|||
response = client.get("/portal") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"message": "Here's your interdimensional portal."} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_get_redirect(client: TestClient): |
|||
response = client.get("/portal", params={"teleport": True}, follow_redirects=False) |
|||
assert response.status_code == 307, response.text |
|||
assert response.headers["location"] == "https://www.youtube.com/watch?v=dQw4w9WgXcQ" |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/portal": { |
|||
"get": { |
|||
"summary": "Get Portal", |
|||
"operationId": "get_portal_portal_get", |
|||
"parameters": [ |
|||
{ |
|||
"required": False, |
|||
"schema": { |
|||
"title": "Teleport", |
|||
"type": "boolean", |
|||
"default": False, |
|||
}, |
|||
"name": "teleport", |
|||
"in": "query", |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": {"application/json": {"schema": {}}}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,147 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict, IsOneOf |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.response_model.tutorial004_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
@pytest.mark.parametrize( |
|||
"url,data", |
|||
[ |
|||
("/items/foo", {"name": "Foo", "price": 50.2}), |
|||
( |
|||
"/items/bar", |
|||
{"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, |
|||
), |
|||
( |
|||
"/items/baz", |
|||
{ |
|||
"name": "Baz", |
|||
"description": None, |
|||
"price": 50.2, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(url, data, client: TestClient): |
|||
response = client.get(url) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == data |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": IsOneOf( |
|||
["name", "description", "price", "tax", "tags"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["name", "price"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,147 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict, IsOneOf |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py39 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.response_model.tutorial004_py39 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py39 |
|||
@pytest.mark.parametrize( |
|||
"url,data", |
|||
[ |
|||
("/items/foo", {"name": "Foo", "price": 50.2}), |
|||
( |
|||
"/items/bar", |
|||
{"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, |
|||
), |
|||
( |
|||
"/items/baz", |
|||
{ |
|||
"name": "Baz", |
|||
"description": None, |
|||
"price": 50.2, |
|||
"tax": 10.5, |
|||
"tags": [], |
|||
}, |
|||
), |
|||
], |
|||
) |
|||
def test_get(url, data, client: TestClient): |
|||
response = client.get(url) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == data |
|||
|
|||
|
|||
@needs_py39 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item", |
|||
"operationId": "read_item_items__item_id__get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": IsOneOf( |
|||
["name", "description", "price", "tax", "tags"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["name", "price"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
"tags": { |
|||
"title": "Tags", |
|||
"type": "array", |
|||
"items": {"type": "string"}, |
|||
"default": [], |
|||
}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
@ -1,166 +0,0 @@ |
|||
import pytest |
|||
from dirty_equals import IsDict, IsOneOf |
|||
from fastapi.testclient import TestClient |
|||
|
|||
from ...utils import needs_py310 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from docs_src.response_model.tutorial005_py310 import app |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_read_item_name(client: TestClient): |
|||
response = client.get("/items/bar/name") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"name": "Bar", "description": "The Bar fighters"} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_read_item_public_data(client: TestClient): |
|||
response = client.get("/items/bar/public") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"name": "Bar", |
|||
"description": "The Bar fighters", |
|||
"price": 62, |
|||
} |
|||
|
|||
|
|||
@needs_py310 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/items/{item_id}/name": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item Name", |
|||
"operationId": "read_item_name_items__item_id__name_get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
} |
|||
}, |
|||
"/items/{item_id}/public": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": {"$ref": "#/components/schemas/Item"} |
|||
} |
|||
}, |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
}, |
|||
}, |
|||
}, |
|||
"summary": "Read Item Public Data", |
|||
"operationId": "read_item_public_data_items__item_id__public_get", |
|||
"parameters": [ |
|||
{ |
|||
"required": True, |
|||
"schema": {"title": "Item Id", "type": "string"}, |
|||
"name": "item_id", |
|||
"in": "path", |
|||
} |
|||
], |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": IsOneOf( |
|||
["name", "description", "price", "tax"], |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
["name", "price"], |
|||
), |
|||
"type": "object", |
|||
"properties": { |
|||
"name": {"title": "Name", "type": "string"}, |
|||
"price": {"title": "Price", "type": "number"}, |
|||
"description": IsDict( |
|||
{ |
|||
"title": "Description", |
|||
"anyOf": [{"type": "string"}, {"type": "null"}], |
|||
} |
|||
) |
|||
| IsDict( |
|||
# TODO: remove when deprecating Pydantic v1 |
|||
{"title": "Description", "type": "string"} |
|||
), |
|||
"tax": {"title": "Tax", "type": "number", "default": 10.5}, |
|||
}, |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": ["loc", "msg", "type"], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|||
}, |
|||
}, |
|||
"msg": {"title": "Message", "type": "string"}, |
|||
"type": {"title": "Error Type", "type": "string"}, |
|||
}, |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|||
} |
|||
}, |
|||
}, |
|||
} |
|||
}, |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue