diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 91d27f71a5..27d86713a1 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -34,11 +34,41 @@ INVALID_BASE_CLASSES = {'bool', 'range', 'slice', 'memoryview'} -def _get_method_args(method): - args = method.args.args +def _positional_parameters(method): + positional = method.args.args if method.type in ('classmethod', 'method'): - return len(args) - 1 - return len(args) + positional = positional[1:] + return positional + + +def _same_parameter(first, second): + return first.name == second.name + + +def _has_different_parameters(original, overridden): + same_length = len(original) == len(overridden) + if same_length: + return any(not _same_parameter(first, second) + for first, second in zip(original, overridden)) + return True + + +def _different_parameters(original, overridden): + """Determine if the two methods have different parameters + + They are considered to have different parameters if: + + * they have different positional parameters, including different names + + """ + + original_parameters = _positional_parameters(original) + overridden_parameters = _positional_parameters(overridden) + + different_positional = _has_different_parameters(original_parameters, + overridden_parameters) + + return different_positional def _is_invalid_base_class(cls): @@ -926,9 +956,7 @@ def _check_signature(self, method1, refmethod, class_type, cls): # Don't care about functions with unknown argument (builtins). if method1.args.args is None or refmethod.args.args is None: return - # If we use *args, **kwargs, skip the below checks. - if method1.args.vararg or method1.args.kwarg: - return + # Ignore private to class methods. if is_attr_private(method1.name): return @@ -940,9 +968,7 @@ def _check_signature(self, method1, refmethod, class_type, cls): decorator.attrname == 'setter'): return - method1_args = _get_method_args(method1) - refmethod_args = _get_method_args(refmethod) - if method1_args != refmethod_args: + if _different_parameters(refmethod, method1): self.add_message('arguments-differ', args=(class_type, method1.name), node=method1) diff --git a/pylint/test/functional/arguments_differ.py b/pylint/test/functional/arguments_differ.py index d48190438d..5896ea7189 100644 --- a/pylint/test/functional/arguments_differ.py +++ b/pylint/test/functional/arguments_differ.py @@ -134,5 +134,19 @@ def close(self, attr): class StaticmethodChild2(Staticmethod): - def func(self, arg): - super(StaticmethodChild2, self).func(arg) + def func(self, data): + super(StaticmethodChild2, self).func(data) + + +class SuperClass(object): + + @staticmethod + def impl(arg1, arg2): + return arg1 + arg2 + + +class MyClass(SuperClass): + + def impl(self, *args, **kwargs): + + super(MyClass, self).impl(*args, **kwargs) diff --git a/pylint/test/input/func_noerror_overriden_method_varargs.py b/pylint/test/input/func_noerror_overriden_method_varargs.py deleted file mode 100644 index afe30863fa..0000000000 --- a/pylint/test/input/func_noerror_overriden_method_varargs.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=R0201,R0903 -"""docstring""" - -__revision__ = 1 - -class SuperClass(object): - """docstring""" - def impl(self, arg1, arg2): - """docstring""" - return arg1 + arg2 - -class MyClass(SuperClass): - """docstring""" - def impl(self, *args, **kwargs): - """docstring""" - # ...do stuff here... - super(MyClass, self).impl(*args, **kwargs) - -# ...do stuff here...