[fastapi] Implement FAST001 (fastapi-redundant-response-model) and FAST002 (fastapi-non-annotated-dependency)#11579
Conversation
|
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| RUF102 | 3 | 3 | 0 | 0 | 0 |
CodSpeed Performance ReportMerging #11579 will not alter performanceComparing Summary
|
b55718e to
b6da4d7
Compare
|
Thank you for this! Two reactions, which I'd in-turn like your reaction on:
|
|
@charliermarsh Thanks for your comments.
|
|
@charliermarsh Any chance you could provide feedback on my previous message when you have a moment? |
|
Thanks @TomerBin for emailing me! This looks great. And recommending Additionally, if there was a way to auto-fix code that uses the old style to now use An old dependency and @app.get("/items/")
def get_items(
current_user: User = Depends(get_current_user),
some_security_param: str = Security(get_oauth2_user),
):
# do stuff
passThat would be ideally transformed into: @app.get("/items/")
def get_items(
current_user: Annotated[User, Depends(get_current_user)],
some_security_param: Annotated[str, Security(get_oauth2_user)],
):
# do stuff
passAdditionally, the same transformation would apply to other types of parameters, like The only caveat is that if one of those has a @app.post("/stuff/")
def do_stuff(
some_query_param: str | None = Query(default=None),
some_path_param: str = Path(),
some_body_param: str = Body("foo"),
some_cookie_param: str = Cookie(),
some_header_param: int = Header(default=5),
some_file_param: UploadFile = File(),
some_form_param: str = Form(),
):
# do stuff
passwould ideally be transformed into: @app.post("/stuff/")
def do_stuff(
some_query_param: Annotated[str | None, Query()] = None,
some_path_param: Annotated[str, Path()],
some_body_param: Annotated[str, Body()] = "foo",
some_cookie_param: Annotated[str, Cookie()],
some_header_param: Annotated[int, Header()] = 5,
some_file_param: Annotated[UploadFile, File()],
some_form_param: Annotated[str, Form()],
):
# do stuff
passNote: please keep pinging me on email if I miss a GitHub notification around this, I miss most GitHub notifications as I still have around 10k unread. 😅 |
b6da4d7 to
c19547f
Compare
ruff] Implement RUF102 (fastapi-redundant-response-model)fastapi] Implement FAST001 (fastapi-redundant-response-model) and FAST002 (fastapi-non-annotated-dependency)
charliermarsh
left a comment
There was a problem hiding this comment.
Thanks. I decided to move these to a dedicated FastAPI category. There's precedence for it with NumPy (NPY), and I think I'd prefer to keep the Ruff rules framework-agnostic.
|
@TomerBin, thanks for your work on this! Is this rule intended to apply only to route functions? I ask because at my company, we have a pretty comprehensive set of free functions that are used as dependency providers, for example:
Currently, this rule only detects and fixes the route function, and not the provider function in |
## Summary Part of #15584 This PR adds a fix safety section to [fast-api-non-annotated-dependency (FAST002)](https://docs.astral.sh/ruff/rules/fast-api-non-annotated-dependency/#fast-api-non-annotated-dependency-fast002). It also re-words the availability section since I found it confusing. The lint/fix was added in #11579 as always unsafe. No reasoning is given in the original PR/code as to why this was chosen. Example of why the fix is unsafe: https://play.ruff.rs/3bd0566e-1ef6-4cec-ae34-3b07cd308155 ```py from fastapi import Depends, FastAPI, Query app = FastAPI() # Fix will remove the parameter default value @app.get("/items/") async def read_items(commons: dict = Depends(common_parameters)): return commons # Fix will delete comment and change default parameter value @app.get("/items/") async def read_items_1(q: str = Query( # This comment will be deleted default="rick")): return q ``` After fixing both instances of `FAST002`: ```py from fastapi import Depends, FastAPI, Query from typing import Annotated app = FastAPI() # Fix will remove the parameter default value @app.get("/items/") async def read_items(commons: Annotated[dict, Depends(common_parameters)]): return commons # Fix will delete comment and change default parameter value @app.get("/items/") async def read_items_1(q: Annotated[str, Query()] = "rick"): return q ```
Summary
Implements ruff specific role for fastapi routes, and its autofix.
Test Plan
cargo test/cargo insta review