-
-
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
Customize arguments-differ error messages #4422
Merged
Merged
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
d11a738
Customize output messages for arguments-differ message
ksaketou 4faf101
Modify tests for arguments-differ
ksaketou 9eb140b
Modify the arguments-differ tests for different output messages
ksaketou 5a1c205
Add customization of arguments-differ output messages
ksaketou d127ae7
Resolve merge conflicts
ksaketou e92e510
Ignore arguments-differ messages
ksaketou 745d35f
Improve code formatting
ksaketou b0ab6ec
Merge remote-tracking branch 'upstream/master' into args-differ-msg
ksaketou b3c5f82
Undo functions' parameters changes
ksaketou 33fca2e
Add more details to error messages and adjust code to initial tests
ksaketou 4a5546d
Resolve merge conflict
ksaketou 4599a4e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 836f341
Fix string format
ksaketou 6c0dfa2
Merge branch 'args-differ-msg' of https://github.com/ksaketou/pylint …
ksaketou 0c0b9dd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] e04e2b2
Modify addition to ChangeLog
ksaketou d05d2a1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 60dbe32
Fix parameter typing on function declaration
ksaketou f3b652d
Fix mypy errors
ksaketou 1ba9e1d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -44,6 +44,7 @@ | |||||||||||||||||||
""" | ||||||||||||||||||||
import collections | ||||||||||||||||||||
from itertools import chain, zip_longest | ||||||||||||||||||||
from typing import List, Pattern | ||||||||||||||||||||
|
||||||||||||||||||||
import astroid | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -266,22 +267,56 @@ def _has_different_parameters_default_value(original, overridden): | |||||||||||||||||||
return False | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def _has_different_parameters(original, overridden, dummy_parameter_regex): | ||||||||||||||||||||
def _has_different_parameters( | ||||||||||||||||||||
original: List[astroid.AssignName], | ||||||||||||||||||||
Pierre-Sassoulas marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||
overridden: List[astroid.AssignName], | ||||||||||||||||||||
dummy_parameter_regex: Pattern, | ||||||||||||||||||||
counter: int, | ||||||||||||||||||||
) -> List[str]: | ||||||||||||||||||||
result = [] | ||||||||||||||||||||
zipped = zip_longest(original, overridden) | ||||||||||||||||||||
for original_param, overridden_param in zipped: | ||||||||||||||||||||
params = (original_param, overridden_param) | ||||||||||||||||||||
if not all(params): | ||||||||||||||||||||
return True | ||||||||||||||||||||
|
||||||||||||||||||||
return ["Number of parameters "] | ||||||||||||||||||||
|
||||||||||||||||||||
# check for the arguments' type | ||||||||||||||||||||
original_type = original_param.parent.annotations[counter] | ||||||||||||||||||||
if original_type is not None: | ||||||||||||||||||||
original_type = str(original_param.parent.annotations[counter].name) | ||||||||||||||||||||
|
||||||||||||||||||||
overridden_type = overridden_param.parent.annotations[counter] | ||||||||||||||||||||
if overridden_type is not None: | ||||||||||||||||||||
overridden_type = str(overridden_param.parent.annotations[counter].name) | ||||||||||||||||||||
if original_type != overridden_type: | ||||||||||||||||||||
result.append( | ||||||||||||||||||||
"Parameter '" | ||||||||||||||||||||
+ str(original_param.name) | ||||||||||||||||||||
+ "' was of type '" | ||||||||||||||||||||
+ original_type | ||||||||||||||||||||
+ "' and is now of type '" | ||||||||||||||||||||
+ overridden_type | ||||||||||||||||||||
+ "' in" | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
) | ||||||||||||||||||||
counter += 1 | ||||||||||||||||||||
|
||||||||||||||||||||
# check for the arguments' name | ||||||||||||||||||||
names = [param.name for param in params] | ||||||||||||||||||||
if any(dummy_parameter_regex.match(name) for name in names): | ||||||||||||||||||||
continue | ||||||||||||||||||||
if original_param.name != overridden_param.name: | ||||||||||||||||||||
return True | ||||||||||||||||||||
return False | ||||||||||||||||||||
result.append( | ||||||||||||||||||||
f"Parameter '{original_param.name}' has been renamed to '{overridden_param.name}' in" | ||||||||||||||||||||
) | ||||||||||||||||||||
|
||||||||||||||||||||
return result | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def _different_parameters(original, overridden, dummy_parameter_regex): | ||||||||||||||||||||
def _different_parameters( | ||||||||||||||||||||
original: List[astroid.FunctionDef], | ||||||||||||||||||||
overridden: List[astroid.FunctionDef], | ||||||||||||||||||||
dummy_parameter_regex: Pattern, | ||||||||||||||||||||
) -> List[str]: | ||||||||||||||||||||
"""Determine if the two methods have different parameters | ||||||||||||||||||||
|
||||||||||||||||||||
They are considered to have different parameters if: | ||||||||||||||||||||
|
@@ -293,6 +328,7 @@ def _different_parameters(original, overridden, dummy_parameter_regex): | |||||||||||||||||||
* they have different keyword only parameters. | ||||||||||||||||||||
|
||||||||||||||||||||
""" | ||||||||||||||||||||
output_messages = [] | ||||||||||||||||||||
original_parameters = _positional_parameters(original) | ||||||||||||||||||||
overridden_parameters = _positional_parameters(overridden) | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -315,12 +351,31 @@ def _different_parameters(original, overridden, dummy_parameter_regex): | |||||||||||||||||||
v for v in original.args.kwonlyargs if v.name in overidden_names | ||||||||||||||||||||
] | ||||||||||||||||||||
|
||||||||||||||||||||
arguments = list(original.args.args) | ||||||||||||||||||||
# variable 'count' helps to check if the type of an argument has changed | ||||||||||||||||||||
# at the _has_different_parameters method | ||||||||||||||||||||
if any(arg.name == "self" for arg in arguments) and len(arguments) > 1: | ||||||||||||||||||||
count = 1 | ||||||||||||||||||||
else: | ||||||||||||||||||||
count = 0 | ||||||||||||||||||||
|
||||||||||||||||||||
different_positional = _has_different_parameters( | ||||||||||||||||||||
original_parameters, overridden_parameters, dummy_parameter_regex | ||||||||||||||||||||
original_parameters, overridden_parameters, dummy_parameter_regex, count | ||||||||||||||||||||
) | ||||||||||||||||||||
different_kwonly = _has_different_parameters( | ||||||||||||||||||||
original_kwonlyargs, overridden.args.kwonlyargs, dummy_parameter_regex | ||||||||||||||||||||
original_kwonlyargs, overridden.args.kwonlyargs, dummy_parameter_regex, count | ||||||||||||||||||||
) | ||||||||||||||||||||
if different_kwonly and different_positional: | ||||||||||||||||||||
if "Number " in different_positional[0] and "Number " in different_kwonly[0]: | ||||||||||||||||||||
output_messages.append("Number of parameters ") | ||||||||||||||||||||
output_messages += different_positional[1:] | ||||||||||||||||||||
output_messages += different_kwonly[1:] | ||||||||||||||||||||
else: | ||||||||||||||||||||
if different_positional: | ||||||||||||||||||||
output_messages += different_positional | ||||||||||||||||||||
if different_kwonly: | ||||||||||||||||||||
output_messages += different_kwonly | ||||||||||||||||||||
|
||||||||||||||||||||
if original.name in PYMETHODS: | ||||||||||||||||||||
# Ignore the difference for special methods. If the parameter | ||||||||||||||||||||
# numbers are different, then that is going to be caught by | ||||||||||||||||||||
|
@@ -334,7 +389,10 @@ def _different_parameters(original, overridden, dummy_parameter_regex): | |||||||||||||||||||
kwarg_lost = original.args.kwarg and not overridden.args.kwarg | ||||||||||||||||||||
vararg_lost = original.args.vararg and not overridden.args.vararg | ||||||||||||||||||||
|
||||||||||||||||||||
return any((different_positional, kwarg_lost, vararg_lost, different_kwonly)) | ||||||||||||||||||||
if kwarg_lost or vararg_lost: | ||||||||||||||||||||
output_messages += ["Variadics removed in"] | ||||||||||||||||||||
|
||||||||||||||||||||
return output_messages | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def _is_invalid_base_class(cls): | ||||||||||||||||||||
|
@@ -549,7 +607,7 @@ def _has_same_layout_slots(slots, assigned_value): | |||||||||||||||||||
"be written as a function.", | ||||||||||||||||||||
), | ||||||||||||||||||||
"W0221": ( | ||||||||||||||||||||
"Parameters differ from %s %r method", | ||||||||||||||||||||
"%s %s %r method", | ||||||||||||||||||||
"arguments-differ", | ||||||||||||||||||||
"Used when a method has a different number of arguments than in " | ||||||||||||||||||||
"the implemented interface or in an overridden method.", | ||||||||||||||||||||
|
@@ -1760,12 +1818,47 @@ def _check_signature(self, method1, refmethod, class_type, cls): | |||||||||||||||||||
if is_property_setter(method1): | ||||||||||||||||||||
return | ||||||||||||||||||||
|
||||||||||||||||||||
if _different_parameters( | ||||||||||||||||||||
arg_differ_output = _different_parameters( | ||||||||||||||||||||
refmethod, method1, dummy_parameter_regex=self._dummy_rgx | ||||||||||||||||||||
): | ||||||||||||||||||||
self.add_message( | ||||||||||||||||||||
"arguments-differ", args=(class_type, method1.name), node=method1 | ||||||||||||||||||||
) | ||||||||||||||||||||
) | ||||||||||||||||||||
if len(arg_differ_output) > 0: | ||||||||||||||||||||
for msg in arg_differ_output: | ||||||||||||||||||||
if "Number" in msg: | ||||||||||||||||||||
total_args_method1 = len(method1.args.args) | ||||||||||||||||||||
if method1.args.vararg: | ||||||||||||||||||||
total_args_method1 += 1 | ||||||||||||||||||||
if method1.args.kwarg: | ||||||||||||||||||||
total_args_method1 += 1 | ||||||||||||||||||||
if method1.args.kwonlyargs: | ||||||||||||||||||||
total_args_method1 += len(method1.args.kwonlyargs) | ||||||||||||||||||||
total_args_refmethod = len(refmethod.args.args) | ||||||||||||||||||||
if refmethod.args.vararg: | ||||||||||||||||||||
total_args_refmethod += 1 | ||||||||||||||||||||
if refmethod.args.kwarg: | ||||||||||||||||||||
total_args_refmethod += 1 | ||||||||||||||||||||
if refmethod.args.kwonlyargs: | ||||||||||||||||||||
total_args_refmethod += len(refmethod.args.kwonlyargs) | ||||||||||||||||||||
self.add_message( | ||||||||||||||||||||
"arguments-differ", | ||||||||||||||||||||
args=( | ||||||||||||||||||||
msg | ||||||||||||||||||||
+ f"was {total_args_refmethod} in '{refmethod.parent.name}.{refmethod.name}' and " | ||||||||||||||||||||
f"is now {total_args_method1} in", | ||||||||||||||||||||
class_type, | ||||||||||||||||||||
str(method1.parent.name) + "." + str(method1.name), | ||||||||||||||||||||
), | ||||||||||||||||||||
node=method1, | ||||||||||||||||||||
) | ||||||||||||||||||||
else: | ||||||||||||||||||||
self.add_message( | ||||||||||||||||||||
"arguments-differ", | ||||||||||||||||||||
args=( | ||||||||||||||||||||
msg, | ||||||||||||||||||||
class_type, | ||||||||||||||||||||
str(method1.parent.name) + "." + str(method1.name), | ||||||||||||||||||||
), | ||||||||||||||||||||
node=method1, | ||||||||||||||||||||
) | ||||||||||||||||||||
elif ( | ||||||||||||||||||||
len(method1.args.defaults) < len(refmethod.args.defaults) | ||||||||||||||||||||
and not method1.args.vararg | ||||||||||||||||||||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
arguments-differ:12:4:Child.test:Parameters differ from overridden 'test' method | ||
arguments-differ:23:4:ChildDefaults.test:Parameters differ from overridden 'test' method | ||
arguments-differ:41:4:ClassmethodChild.func:Parameters differ from overridden 'func' method | ||
arguments-differ:68:4:VarargsChild.has_kwargs:Parameters differ from overridden 'has_kwargs' method | ||
arguments-differ:71:4:VarargsChild.no_kwargs:Parameters differ from overridden 'no_kwargs' method | ||
arguments-differ:172:4:SecondChangesArgs.test:Parameters differ from overridden 'test' method | ||
arguments-differ:12:4:Child.test:Number of parameters was 1 in 'Parent.test' and is now 2 in overridden 'Child.test' method | ||
arguments-differ:23:4:ChildDefaults.test:Number of parameters was 3 in 'ParentDefaults.test' and is now 2 in overridden 'ChildDefaults.test' method | ||
arguments-differ:41:4:ClassmethodChild.func:Number of parameters was 2 in 'Classmethod.func' and is now 0 in overridden 'ClassmethodChild.func' method | ||
arguments-differ:68:4:VarargsChild.has_kwargs:Parameter 'arg' was of type 'bool' and is now of type 'int' in overridden 'VarargsChild.has_kwargs' method | ||
arguments-differ:68:4:VarargsChild.has_kwargs:Variadics removed in overridden 'VarargsChild.has_kwargs' method | ||
arguments-differ:71:4:VarargsChild.no_kwargs:Parameter 'args' has been renamed to 'arg' in overridden 'VarargsChild.no_kwargs' method | ||
arguments-differ:172:4:SecondChangesArgs.test:Number of parameters was 2 in 'FirstHasArgs.test' and is now 4 in overridden 'SecondChangesArgs.test' method | ||
arguments-differ:222:4:OverridesSpecialMethod.__getitem__:Parameter 'key' has been renamed to 'cheie' in overridden 'OverridesSpecialMethod.__getitem__' method |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
arguments-differ:25:4:Foo.kwonly_1:Parameters differ from overridden 'kwonly_1' method | ||
arguments-differ:28:4:Foo.kwonly_2:Parameters differ from overridden 'kwonly_2' method | ||
arguments-differ:31:4:Foo.kwonly_3:Parameters differ from overridden 'kwonly_3' method | ||
arguments-differ:34:4:Foo.kwonly_4:Parameters differ from overridden 'kwonly_4' method | ||
arguments-differ:37:4:Foo.kwonly_5:Parameters differ from overridden 'kwonly_5' method | ||
arguments-differ:25:4:Foo.kwonly_1:Number of parameters was 4 in 'AbstractFoo.kwonly_1' and is now 3 in overridden 'Foo.kwonly_1' method | ||
arguments-differ:28:4:Foo.kwonly_2:Number of parameters was 3 in 'AbstractFoo.kwonly_2' and is now 2 in overridden 'Foo.kwonly_2' method | ||
arguments-differ:31:4:Foo.kwonly_3:Number of parameters was 3 in 'AbstractFoo.kwonly_3' and is now 3 in overridden 'Foo.kwonly_3' method | ||
arguments-differ:34:4:Foo.kwonly_4:Number of parameters was 3 in 'AbstractFoo.kwonly_4' and is now 3 in overridden 'Foo.kwonly_4' method | ||
arguments-differ:37:4:Foo.kwonly_5:Variadics removed in overridden 'Foo.kwonly_5' method |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.