-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Consider __new__
methods as special function type for enforcing class method or static method rules
#13305
Consider __new__
methods as special function type for enforcing class method or static method rules
#13305
Conversation
|
code | total | + violation | - violation | + fix | - fix |
---|---|---|---|---|---|
ARG004 | 2 | 2 | 0 | 0 | 0 |
ARG003 | 2 | 0 | 2 | 0 | 0 |
Linter (preview)
ℹ️ ecosystem check detected linter changes. (+2 -2 violations, +0 -0 fixes in 1 projects; 54 projects unchanged)
latchbio/latch (+2 -2 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview
- src/latch_cli/centromere/utils.py:67:34: ARG003 Unused class method argument: `args` + src/latch_cli/centromere/utils.py:67:34: ARG004 Unused static method argument: `args` - src/latch_cli/centromere/utils.py:67:42: ARG003 Unused class method argument: `kwargs` + src/latch_cli/centromere/utils.py:67:42: ARG004 Unused static method argument: `kwargs`
Changes by rule (2 rules affected)
code | total | + violation | - violation | + fix | - fix |
---|---|---|---|---|---|
ARG004 | 2 | 2 | 0 | 0 | 0 |
ARG003 | 2 | 0 | 2 | 0 | 0 |
I'm sure there are other breaking changes besides the ruff-ecosystem results |
Affected Rules
ARG003, ARG004ARG003 ( PLW0642
N804, PLW0211N804 ( PLR0913, PLR0917PLR0913 ( ExampleYou can view an example of how these rules are applied here: class ClassDunderNew:
@classmethod
def __new__(
cls,
x, # ARG003: Unused class method argument: `x`
):
cls = 1 # PLW0642: Reassigned `cls` variable in class method
@classmethod
def __new__( # PLR0913: Too many arguments in function definition (6 > 5) # PLR0917: Too many positional arguments (6/5)
self, # N804: First argument of a class method should be named `cls`
a1, a2, a3, a4, a5,
a6,
):
...
class StaticDunderNew:
@staticmethod
def __new__(
cls,
x, # ARG004: Unused static method argument: `x`
):
cls = 1
@staticmethod
def __new__( # PLR0913: Too many arguments in function definition (6 > 5) # PLR0917: Too many positional arguments (6/5)
self, # PLW0211: First argument of a static method should not be named `self`
a1, a2, a3, a4, a5,
):
... |
I reviewed all the code affected by Please check if these affected rules are acceptable. :) |
1865ecb
to
0e23922
Compare
…ified as `staticmethod`
0e23922
to
b7931ce
Compare
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 so much!
I think this is pretty much good to go - had to tweak some things to rebase, and I decided we should special case the counting of arguments for the "too-many-(positional-)arguments" rules to treat __new__
like a classmethod, since it seems more intuitive there. Also added more test fixtures to track changes if we decide to further modify the treatment of __new__
later.
My only hesitation on merging is whether this should be considered breaking and wait until the next minor release - thoughts @AlexWaygood / @MichaReiser ?
Also to Alex: It'd be great if you could spot check the conflict resolution for PYI019 to make sure it's in line with what you had in mind for the recent changes to that rule. https://github.com/astral-sh/ruff/pull/13305/files#diff-bfce927fd2c71368a7fc9c045c1f51f03f4ac25e398ed8b3a571caf01f4efe06
I'd prefer if this is a preview only change just because of the scope of it. It's definitely a breaking change otherwise |
I don't think making the change preview only makes sense in many cases, since I consider the old behavior a bug/incorrect. Here's what I ended up doing. Even though this is a long list, there are actually not so many behavior changes, so I wouldn't consider this breaking, personally. What do you think?
|
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.
This looks excellent! Thanks @cake-monotone for the PR, and thanks @dylwil3 for driving it over the line!
crates/ruff_linter/src/rules/flake8_unused_arguments/rules/unused_arguments.rs
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pep8_naming/rules/invalid_first_argument_name.rs
Show resolved
Hide resolved
Co-authored-by: Alex Waygood <[email protected]>
Co-authored-by: Alex Waygood <[email protected]>
Co-authored-by: Alex Waygood <[email protected]>
__new__
methods are now classified as staticmethod
__new__
methods as special function type for enforcing class method or static method rules
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.
argh sorry, a couple of tiny nits I missed pre-merge that might be good to address as a followup
// In preview, this violation is caught by `PLW0211` instead | ||
function_type::FunctionType::NewMethod if checker.settings.preview.is_enabled() => { | ||
return; | ||
} |
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.
Oh, I guess it might be good to add a note about this to the rule's docs?
&& !visibility::is_overload(decorator_list, checker.semantic()) | ||
{ | ||
// we use `method()` here rather than `function()`, as although `__new__` is | ||
// an implicit staticmethod, `__new__` methods must always have >= parameter |
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.
Ah shoot, my previous suggestion had a typo -- it should have been this :-(
// an implicit staticmethod, `__new__` methods must always have >= parameter | |
// an implicit staticmethod, `__new__` methods must always have >=1 parameters |
Summary
__new__
methods are technically static methods, withcls
as their first argument. However, Ruff currently classifies them as classmethod, which causes two issues:__new__
is explicitly treated as a classmethod.Motivated by this, the current PR makes the following adjustments:
Introduces
FunctionType::NewMethod
as an enum variant, since, for the purposes of lint rules,__new__
sometimes behaves like a static method and other times like a class method. This is an internal change.The following rule behaviors and messages are totally unchanged:
The following rule behaviors are unchanged, but the messages have been changed for correctness to use "
__new__
method" instead of "class method":The following rules are changed unconditionally (not gated behind preview) because their current behavior is an honest bug: it just isn't true that
__new__
is a class method, and it is true that__new__
is a static method:__new__
__new__
The only changes which differ based on
preview
are the following:preview
is enabled. Whenpreview
is disabled, the rule is the same but the message has been modified to say "__new__
method" instead of "class method".preview
is enabled, this now applies to__new__
.Closes #13154