Browse Source

🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

pull/14182/head
pre-commit-ci[bot] 9 months ago
parent
commit
dd3820c62d
  1. 6
      add_query_method.patch
  2. 9
      fastapi/routing.py
  3. 15
      query_method_patch.py
  4. 14
      test_query_method.py
  5. 32
      tests/test_query_method.py

6
add_query_method.patch

@ -3,7 +3,7 @@
@@ -2581,6 +2581,89 @@ class APIRouter: @@ -2581,6 +2581,89 @@ class APIRouter:
generate_unique_id_function=generate_unique_id_function, generate_unique_id_function=generate_unique_id_function,
) )
+ def query( + def query(
+ self, + self,
+ path: Annotated[ + path: Annotated[
@ -80,10 +80,10 @@
+ ) -> Callable[[DecoratedCallable], DecoratedCallable]: + ) -> Callable[[DecoratedCallable], DecoratedCallable]:
+ """ + """
+ Add a *path operation* using an HTTP QUERY operation. + Add a *path operation* using an HTTP QUERY operation.
+ +
+ The QUERY method is a safe HTTP method that allows request bodies, + The QUERY method is a safe HTTP method that allows request bodies,
+ useful for complex queries that exceed URL length limits. + useful for complex queries that exceed URL length limits.
+ +
+ See: https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html + See: https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html
+ """ + """
+ return self.api_route( + return self.api_route(

9
fastapi/routing.py

@ -2629,8 +2629,10 @@ class APIRouter(routing.Router):
""" """
), ),
] = Default(None), ] = Default(None),
status_code: Annotated[Optional[int], Doc( status_code: Annotated[
""" Optional[int],
Doc(
"""
The default status code to be used for the response. The default status code to be used for the response.
You could override the status code by returning a response directly. You could override the status code by returning a response directly.
@ -2638,7 +2640,8 @@ class APIRouter(routing.Router):
Read more about it in the Read more about it in the
[FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/).
""" """
)] = None, ),
] = None,
tags: Annotated[ tags: Annotated[
Optional[List[Union[str, Enum]]], Optional[List[Union[str, Enum]]],
Doc( Doc(

15
query_method_patch.py

@ -2,6 +2,7 @@
# This is the method to add to the FastAPI class in applications.py after the post method # This is the method to add to the FastAPI class in applications.py after the post method
def query( def query(
self, self,
path: str, path: str,
@ -27,21 +28,23 @@ def query(
name: Optional[str] = None, name: Optional[str] = None,
callbacks: Optional[List[BaseRoute]] = None, callbacks: Optional[List[BaseRoute]] = None,
openapi_extra: Optional[Dict[str, Any]] = None, openapi_extra: Optional[Dict[str, Any]] = None,
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(generate_unique_id), generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
generate_unique_id
),
) -> Callable[[DecoratedCallable], DecoratedCallable]: ) -> Callable[[DecoratedCallable], DecoratedCallable]:
""" """
Add a *path operation* using an HTTP QUERY operation. Add a *path operation* using an HTTP QUERY operation.
The QUERY method is a safe HTTP method that allows request bodies, The QUERY method is a safe HTTP method that allows request bodies,
useful for complex queries that exceed URL length limits. useful for complex queries that exceed URL length limits.
## Example ## Example
```python ```python
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@app.query("/search/") @app.query("/search/")
def search_items(query: SearchQuery): def search_items(query: SearchQuery):
return {"results": [...]} return {"results": [...]}

14
test_query_method.py

@ -3,40 +3,46 @@
Test script for the new QUERY method in FastAPI Test script for the new QUERY method in FastAPI
""" """
from typing import Any, Dict, List
from fastapi import FastAPI from fastapi import FastAPI
from pydantic import BaseModel from pydantic import BaseModel
from typing import List, Dict, Any
app = FastAPI() app = FastAPI()
class SearchQuery(BaseModel): class SearchQuery(BaseModel):
terms: List[str] terms: List[str]
filters: Dict[str, Any] = {} filters: Dict[str, Any] = {}
limit: int = 10 limit: int = 10
@app.query("/search/") @app.query("/search/")
def search_items(query: SearchQuery): def search_items(query: SearchQuery):
""" """
Search for items using the QUERY method. Search for items using the QUERY method.
This demonstrates the new QUERY HTTP method that allows This demonstrates the new QUERY HTTP method that allows
complex request bodies for search operations. complex request bodies for search operations.
""" """
return { return {
"results": [ "results": [
{"id": 1, "name": "Item 1", "matches": query.terms}, {"id": 1, "name": "Item 1", "matches": query.terms},
{"id": 2, "name": "Item 2", "matches": query.terms} {"id": 2, "name": "Item 2", "matches": query.terms},
], ],
"query": query.dict(), "query": query.dict(),
"total": 2 "total": 2,
} }
@app.get("/") @app.get("/")
def read_root(): def read_root():
return {"message": "FastAPI with QUERY method support"} return {"message": "FastAPI with QUERY method support"}
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
print("Testing FastAPI QUERY method implementation...") print("Testing FastAPI QUERY method implementation...")
print("Visit http://localhost:8000/docs to see the QUERY endpoint in action!") print("Visit http://localhost:8000/docs to see the QUERY endpoint in action!")
uvicorn.run(app, host="0.0.0.0", port=8000) uvicorn.run(app, host="0.0.0.0", port=8000)

32
tests/test_query_method.py

@ -2,11 +2,11 @@
Tests for the QUERY HTTP method implementation in FastAPI Tests for the QUERY HTTP method implementation in FastAPI
""" """
import pytest from typing import Any, Dict, List
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
from typing import List, Dict, Any
class SearchQuery(BaseModel): class SearchQuery(BaseModel):
@ -21,10 +21,7 @@ def test_query_method_basic():
@app.query("/search/") @app.query("/search/")
def search_items(query: SearchQuery): def search_items(query: SearchQuery):
return { return {"results": [{"id": 1, "name": "test"}], "query": query.dict()}
"results": [{"id": 1, "name": "test"}],
"query": query.dict()
}
client = TestClient(app) client = TestClient(app)
@ -35,8 +32,8 @@ def test_query_method_basic():
json={ json={
"terms": ["test", "search"], "terms": ["test", "search"],
"filters": {"category": "books"}, "filters": {"category": "books"},
"limit": 5 "limit": 5,
} },
) )
assert response.status_code == 200 assert response.status_code == 200
@ -65,7 +62,7 @@ def test_query_method_validation():
json={ json={
"filters": {"category": "books"} "filters": {"category": "books"}
# Missing required 'terms' field # Missing required 'terms' field
} },
) )
assert response.status_code == 422 # Validation error assert response.status_code == 422 # Validation error
@ -111,11 +108,7 @@ def test_query_method_with_dependencies():
client = TestClient(app) client = TestClient(app)
response = client.request( response = client.request("QUERY", "/search/", json={"terms": ["test"]})
"QUERY",
"/search/",
json={"terms": ["test"]}
)
assert response.status_code == 200 assert response.status_code == 200
@ -130,18 +123,11 @@ def test_query_method_response_model():
@app.query("/search/", response_model=SearchResponse) @app.query("/search/", response_model=SearchResponse)
def search_items(query: SearchQuery): def search_items(query: SearchQuery):
return { return {"results": [{"id": 1, "name": "test"}], "total": 1}
"results": [{"id": 1, "name": "test"}],
"total": 1
}
client = TestClient(app) client = TestClient(app)
response = client.request( response = client.request("QUERY", "/search/", json={"terms": ["test"]})
"QUERY",
"/search/",
json={"terms": ["test"]}
)
assert response.status_code == 200 assert response.status_code == 200
data = response.json() data = response.json()

Loading…
Cancel
Save