-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[flake8-type-checking
] Add exemption for runtime evaluated decorator classes
#15060
base: main
Are you sure you want to change the base?
[flake8-type-checking
] Add exemption for runtime evaluated decorator classes
#15060
Conversation
|
Would this address #13713 ? |
I think so. |
Thank you. I think this makes sense. @Daverball, I'd be interested in your thoughts on this change because you're the most familiar with our type-checking rules. |
4413259
to
3c67b39
Compare
This looks good to me. The flake8 plugin currently does something less clever for FastAPI support, with a toggle that you have to enable if you use FastAPI, which increases false negatives in the rest of your code. This approach seems more balanced and flexible. My only concern is that we probably want to add additional settings to support marker generics like |
I had throught about rolling this option into |
The one thing this currently fails to cover is sharing your instances between modules: from datetime import datetime
from mymodule import app
@app.put("/datetime")
def set_datetime(value: datetime) -> None:
pass The question is if that matters, since red knot presumably will be able to handle that case in the future. But we could also support that use-case by extending [tool.ruff.lint.flake8-type-checking]
runtime-evaluated-decorators = ["mymodule.app"] would match |
I had thought about how to add that possibility, but I could not find a clean way. If this is something you would like to see as you sketched it above, I'd be happy to add it. |
I think that would be enough to cover most FastAPI use-cases, so it seems like a desirable improvement to the semantics of that setting. Although it might require some documentation improvements, so people understand, that this is something they can do. It might also be interesting to investigate whether we can get away with just the original setting with this change, as long as we can match the binding in the module it was defined to the fully qualified name. I.e.
from fastapi import FastAPI as Api
app = Api()
@app.put("/datetime") # matches "mymodule.app" because we're in `mymodule`.
def set_datetime(value: datetime) -> None:
pass |
Actually, the other use-case can already be supported by adding |
Would you like me to add that to this PR or open another PR for that? And do you still want to merge this PR? |
I have no merging power. All I can give is my opinion. I think the feature is fine the way you implemented it, but if we can support this use-case with only the existing setting by slightly changing the semantics, that would be even better, since we wouldn't need to rely on a potentially expensive If you feel like experimenting with the suggested approach in a separate PR, feel free. But please don't feel compelled to invest the time. I'm happy to try it myself, although I definitely won't get around to it today. @MichaReiser Care to chime in, with how you would like this to move forward? |
Summary
This PR makes ruff recognize functions decorated with methods,
like FastAPI uses to specify endpoints.
I've implemented the check by generalizing
ruff_linter::src::rules::fastapi::rules::is_fastapi_route_call
torecognize methods of specific classes used as decorators.
Test Plan
I have added tests by duplicating and adjusting
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_{1..3}.py
.