-
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
RUF012 triggers many false positives (are they really? they are correct) in some projects #5243
Comments
For what it's worth, the Django project is against adding type hints, at least in the near future. You can read more in this PR and a technical board statement. This might be why it doesn't recommend the For balance, however, the typed-django project also hasn't gone all-in with Is it perhaps worth resolving a balance of only flagging a violation when type annotations are already used to annotate a variable? |
Yep, but I wonder why a RUF rule should really be forcing type hints at all. |
Thanks for this! I’m a little busy this morning but I’ll get back to it later today and share my perspective :) |
Adding to the false positives, this is also flagging pydantic models which function similar to dataclasses in how they are defined but actually create new instances of objects when instantiating the class. from pydantic import BaseModel
class MyExample(BaseModel):
foo: dict[str, str] = {} In this example, |
Thank you for all the feedback here :) A couple misc. reactions, from reading through the thread:
|
(To be clear: I'm looking for more feedback here, including on the questions above. Thanks all!) |
I also wanted to ask here, when you have a class variable as an "immutable" constant for that class, what should you do? Should you still annotate with this? Is there some other annotation here, as you probably don't want to have mutable class variables in most cases? |
To me, it makes sense that a typing rule should be suggesting typing.ClassVar, while a bugbear-like rule should be suggesting inmutable data structures (even if Django uses mutable ones extensively). There is no way for ruff (or any other tool) to automatically decide what you meant, and so this would be two rules, or one rule with two possible fixes. As my final 2c, the problem to me is not that the rule is pedantic per se, it is that it’s basically a typing rule, when many projects use typing as an opt-in thing (or not at all). When and if ruff re-classifies its rules, it might become more clear. As it stands the RUF set of rules are basically whatever, so it makes sense that rules like this one end up there. Disabling is a perfectly OK workaround. Thanks a lot for giving it a thought! |
One of my use cases is the following: from typing import ClassVar
class SomeAbstractBaseClass:
some_attribute: ClassVar[dict[str, str]]
class SomeConcreteNewClass(SomeAbstractBaseClass):
some_attribute = {"1": "2"} This triggers |
I've just had this fire on an Ansible plugin module which does not have any type annotations. For now I'll disable RUF012 and hope that #5275 resolves it. |
I'd suggest a setting that lets you whitelist certain ancestor classes, with maybe default set to I am not sure if this is possible yet, but it might be with the new import resolver. |
Yeah makes sense. Also happy to add other libs to the exemption if it’d be helpful. |
Related suggestion, have you considered a new category for "Ruff Warnings" ( |
In the Django and its (database) model case it's not valid, as there's class descriptors doing a bit of magic there. As such the |
I found Django migrations are an area where Sample 1class Migration(migrations.Migration):
dependencies = [...]
operations = [...]
Sample 2class Migration(migrations.Migration):
dependencies: ClassVar[list[tuple[str, str]]] = [...]
operations: ClassVar[list[Operation]] = [...]
Sample 3class Migration(migrations.Migration):
dependencies: list[tuple[str, str]] = [...]
operations: list[Operation] = [...]
|
How does Mypy behave if you use |
@charliermarsh it behaves as desired. I hadn't considered |
@alexei - No prob! I should probably add this to the rule docs. |
@charliermarsh, I appreciate the fix in #5274 to omit pydantic models however, it does not omit classes that subclass user defined models. from pydantic import BaseModel
class MyBaseModel(BaseModel):
def __bool__(self) -> bool:
"""pydantic.BaseModel does not implement __bool__."""
return bool(self.model_dump(exclude_unset=True))
class MyExample(MyBaseModel):
subclass_field: dict[str, str] = {} # RUF012 If this is not something that ruff can determine on it's own, an option like |
@ITProKyle -- We can definitely detect this for subclasses defined in the same file, and I'll make that change now. Unfortunately we can't yet support it for classes defined across files. |
Every usage I have are in different file and even different python packages all together so it sounds like a combination of both detection and a config setting would be needed in my case. |
Only applies to subclasses defined within the same file, as elsewhere. See: #5243 (comment).
It would be nice if we could somehow reuse an existing setting here. It's not quite identical to |
I ran into this for a
So I think for now, i will need to add in a |
I find a similiar observation for: some_attribute = ClassVar[dict[str, str]]
class MyExample:
subclass_field: some_attribute = {} here is class MyExample2:
subclass_field: some_attribute = {}
class MyExample3:
subclass_field: some_attribute = {} |
I think this might be because it uses type alias. |
Yes, but is it bad to use
|
No, it's not bad but just a limitation of Ruff which will be resolved with the ongoing red knot project. |
Hello 👋🏽
In this PR RUF012 was extended to apply to non-dataclass classes.
This has the (maybe desirable, maybe not, but was surprising to me) effect of forcing typing for a RUF rule, in places where you would not necessarily use typing (if you did not want to).
For instance, in Django Rest Framework (from their docs):
Or in Django itself:
You could argue that's good, but at least to me, it's different from dataclasses, since in there you are required to use typing to even use them, so they are opt-in even before you use ruff. You could also argue both Django and Django Rest Framework should be recommending tuples instead.
Isn't this too trigger happy for a RUF rule? Does it make sense to split it from the dataclass one?
EDIT: Actually, it is a separated code already 🤦🏽
In any case, feel free to close if this is just what it is! Ignoring the rule is easy for these kind of projects.
The text was updated successfully, but these errors were encountered: