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.
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?
|
AlexWaygood
left a comment
There was a problem hiding this comment.
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
| // 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.
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.
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 |
…method-argument` and not `invalid-first-argument-name-for-class-method` (`PLW0211`/`N804`) (#16676) ## Summary This PR stabilizes the behavior changes introduced by #13305 that were gated behind preview. The change is that `__new__` methods are now no longer flagged by `invalid-first-argument-name-for-class-method` (`N804`) but instead by `bad-staticmethod-argument` (`PLW0211`) > __new__ methods are technically static methods, with cls as their first argument. However, Ruff currently classifies them as classmethod, which causes two issues: ## Test Plan There have been no new issues or PRs related to `N804` or `PLW0211` since the behavior change was released in Ruff 0.9.7 (about 3 weeks ago). This is a somewhat recent change but I don't think it's necessary to leave this in preview for another 2 months. The main reason why it was in preview is that it is breaking, not because it is a risky change.
…method-argument` and not `invalid-first-argument-name-for-class-method` (`PLW0211`/`N804`) (#16676) ## Summary This PR stabilizes the behavior changes introduced by #13305 that were gated behind preview. The change is that `__new__` methods are now no longer flagged by `invalid-first-argument-name-for-class-method` (`N804`) but instead by `bad-staticmethod-argument` (`PLW0211`) > __new__ methods are technically static methods, with cls as their first argument. However, Ruff currently classifies them as classmethod, which causes two issues: ## Test Plan There have been no new issues or PRs related to `N804` or `PLW0211` since the behavior change was released in Ruff 0.9.7 (about 3 weeks ago). This is a somewhat recent change but I don't think it's necessary to leave this in preview for another 2 months. The main reason why it was in preview is that it is breaking, not because it is a risky change.
…method-argument` and not `invalid-first-argument-name-for-class-method` (`PLW0211`/`N804`) (#16676) ## Summary This PR stabilizes the behavior changes introduced by #13305 that were gated behind preview. The change is that `__new__` methods are now no longer flagged by `invalid-first-argument-name-for-class-method` (`N804`) but instead by `bad-staticmethod-argument` (`PLW0211`) > __new__ methods are technically static methods, with cls as their first argument. However, Ruff currently classifies them as classmethod, which causes two issues: ## Test Plan There have been no new issues or PRs related to `N804` or `PLW0211` since the behavior change was released in Ruff 0.9.7 (about 3 weeks ago). This is a somewhat recent change but I don't think it's necessary to leave this in preview for another 2 months. The main reason why it was in preview is that it is breaking, not because it is a risky change.
Summary
__new__methods are technically static methods, withclsas 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::NewMethodas 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
previeware the following:previewis enabled. Whenpreviewis disabled, the rule is the same but the message has been modified to say "__new__method" instead of "class method".previewis enabled, this now applies to__new__.Closes #13154