-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[fastapi] Implement FAST001 (fastapi-redundant-response-model) and FAST002 (fastapi-non-annotated-dependency)
#11579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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