|
|
@ -1,4 +1,5 @@ |
|
|
import sys |
|
|
import sys |
|
|
|
|
|
import warnings |
|
|
from typing import Optional |
|
|
from typing import Optional |
|
|
|
|
|
|
|
|
import pytest |
|
|
import pytest |
|
|
@ -33,89 +34,85 @@ class Item(BaseModel): |
|
|
|
|
|
|
|
|
app = FastAPI() |
|
|
app = FastAPI() |
|
|
|
|
|
|
|
|
|
|
|
with warnings.catch_warnings(record=True): |
|
|
|
|
|
warnings.simplefilter("always") |
|
|
|
|
|
|
|
|
@app.get("/items/{item_id}") |
|
|
@app.get("/items/{item_id}") |
|
|
def get_item_with_path( |
|
|
def get_item_with_path( |
|
|
item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)], |
|
|
item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)], |
|
|
): |
|
|
): |
|
|
return {"item_id": item_id} |
|
|
return {"item_id": item_id} |
|
|
|
|
|
|
|
|
|
|
|
@app.get("/items/") |
|
|
@app.get("/items/") |
|
|
def get_items_with_query( |
|
|
def get_items_with_query( |
|
|
|
|
|
q: Annotated[ |
|
|
q: Annotated[ |
|
|
Optional[str], Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$") |
|
|
Optional[str], |
|
|
|
|
|
Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$"), |
|
|
] = None, |
|
|
] = None, |
|
|
skip: Annotated[int, Query(ge=0)] = 0, |
|
|
skip: Annotated[int, Query(ge=0)] = 0, |
|
|
limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10, |
|
|
limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10, |
|
|
): |
|
|
): |
|
|
return {"q": q, "skip": skip, "limit": limit} |
|
|
return {"q": q, "skip": skip, "limit": limit} |
|
|
|
|
|
|
|
|
|
|
|
@app.get("/users/") |
|
|
@app.get("/users/") |
|
|
def get_user_with_header( |
|
|
def get_user_with_header( |
|
|
|
|
|
x_custom: Annotated[Optional[str], Header()] = None, |
|
|
x_custom: Annotated[Optional[str], Header()] = None, |
|
|
x_token: Annotated[Optional[str], Header(convert_underscores=True)] = None, |
|
|
x_token: Annotated[Optional[str], Header(convert_underscores=True)] = None, |
|
|
): |
|
|
): |
|
|
return {"x_custom": x_custom, "x_token": x_token} |
|
|
return {"x_custom": x_custom, "x_token": x_token} |
|
|
|
|
|
|
|
|
|
|
|
@app.get("/cookies/") |
|
|
@app.get("/cookies/") |
|
|
def get_cookies( |
|
|
def get_cookies( |
|
|
|
|
|
session_id: Annotated[Optional[str], Cookie()] = None, |
|
|
session_id: Annotated[Optional[str], Cookie()] = None, |
|
|
tracking_id: Annotated[Optional[str], Cookie(min_length=10)] = None, |
|
|
tracking_id: Annotated[Optional[str], Cookie(min_length=10)] = None, |
|
|
): |
|
|
): |
|
|
return {"session_id": session_id, "tracking_id": tracking_id} |
|
|
return {"session_id": session_id, "tracking_id": tracking_id} |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/items/") |
|
|
@app.post("/items/") |
|
|
def create_item( |
|
|
def create_item( |
|
|
|
|
|
item: Annotated[ |
|
|
item: Annotated[ |
|
|
Item, |
|
|
Item, |
|
|
Body(examples=[{"name": "Foo", "price": 35.4, "description": "The Foo item"}]), |
|
|
Body( |
|
|
|
|
|
examples=[{"name": "Foo", "price": 35.4, "description": "The Foo item"}] |
|
|
|
|
|
), |
|
|
], |
|
|
], |
|
|
): |
|
|
): |
|
|
return {"item": item} |
|
|
return {"item": item} |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/items-embed/") |
|
|
@app.post("/items-embed/") |
|
|
def create_item_embed( |
|
|
def create_item_embed( |
|
|
|
|
|
item: Annotated[Item, Body(embed=True)], |
|
|
item: Annotated[Item, Body(embed=True)], |
|
|
): |
|
|
): |
|
|
return {"item": item} |
|
|
return {"item": item} |
|
|
|
|
|
|
|
|
|
|
|
@app.put("/items/{item_id}") |
|
|
@app.put("/items/{item_id}") |
|
|
def update_item( |
|
|
def update_item( |
|
|
|
|
|
item_id: Annotated[int, Path(ge=1)], |
|
|
item_id: Annotated[int, Path(ge=1)], |
|
|
item: Annotated[Item, Body()], |
|
|
item: Annotated[Item, Body()], |
|
|
importance: Annotated[int, Body(gt=0, le=10)], |
|
|
importance: Annotated[int, Body(gt=0, le=10)], |
|
|
): |
|
|
): |
|
|
return {"item": item, "importance": importance} |
|
|
return {"item": item, "importance": importance} |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/form-data/") |
|
|
@app.post("/form-data/") |
|
|
def submit_form( |
|
|
def submit_form( |
|
|
|
|
|
username: Annotated[str, Form(min_length=3, max_length=50)], |
|
|
username: Annotated[str, Form(min_length=3, max_length=50)], |
|
|
password: Annotated[str, Form(min_length=8)], |
|
|
password: Annotated[str, Form(min_length=8)], |
|
|
email: Annotated[Optional[str], Form()] = None, |
|
|
email: Annotated[Optional[str], Form()] = None, |
|
|
): |
|
|
): |
|
|
return {"username": username, "password": password, "email": email} |
|
|
return {"username": username, "password": password, "email": email} |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/upload/") |
|
|
@app.post("/upload/") |
|
|
def upload_file( |
|
|
def upload_file( |
|
|
|
|
|
file: Annotated[bytes, File()], |
|
|
file: Annotated[bytes, File()], |
|
|
description: Annotated[Optional[str], Form()] = None, |
|
|
description: Annotated[Optional[str], Form()] = None, |
|
|
): |
|
|
): |
|
|
return {"file_size": len(file), "description": description} |
|
|
return {"file_size": len(file), "description": description} |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/upload-multiple/") |
|
|
@app.post("/upload-multiple/") |
|
|
def upload_multiple_files( |
|
|
def upload_multiple_files( |
|
|
|
|
|
files: Annotated[list[bytes], File()], |
|
|
files: Annotated[list[bytes], File()], |
|
|
note: Annotated[str, Form()] = "", |
|
|
note: Annotated[str, Form()] = "", |
|
|
): |
|
|
): |
|
|
return { |
|
|
return { |
|
|
"file_count": len(files), |
|
|
"file_count": len(files), |
|
|
"total_size": sum(len(f) for f in files), |
|
|
"total_size": sum(len(f) for f in files), |
|
|
@ -211,10 +208,10 @@ def test_header_params_none(): |
|
|
|
|
|
|
|
|
# Cookie parameter tests |
|
|
# Cookie parameter tests |
|
|
def test_cookie_params(): |
|
|
def test_cookie_params(): |
|
|
with TestClient(app) as client: |
|
|
with TestClient(app) as test_client: |
|
|
client.cookies.set("session_id", "abc123") |
|
|
test_client.cookies.set("session_id", "abc123") |
|
|
client.cookies.set("tracking_id", "1234567890abcdef") |
|
|
test_client.cookies.set("tracking_id", "1234567890abcdef") |
|
|
response = client.get("/cookies/") |
|
|
response = test_client.get("/cookies/") |
|
|
assert response.status_code == 200 |
|
|
assert response.status_code == 200 |
|
|
assert response.json() == { |
|
|
assert response.json() == { |
|
|
"session_id": "abc123", |
|
|
"session_id": "abc123", |
|
|
@ -223,9 +220,9 @@ def test_cookie_params(): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_cookie_tracking_id_too_short(): |
|
|
def test_cookie_tracking_id_too_short(): |
|
|
with TestClient(app) as client: |
|
|
with TestClient(app) as test_client: |
|
|
client.cookies.set("tracking_id", "short") |
|
|
test_client.cookies.set("tracking_id", "short") |
|
|
response = client.get("/cookies/") |
|
|
response = test_client.get("/cookies/") |
|
|
assert response.status_code == 422 |
|
|
assert response.status_code == 422 |
|
|
assert response.json() == snapshot( |
|
|
assert response.json() == snapshot( |
|
|
{ |
|
|
{ |
|
|
|