From 51d5062e66c6b73de63f244d2390fae36e187767 Mon Sep 17 00:00:00 2001 From: Christian Bundy Date: Thu, 4 May 2023 12:16:17 -0700 Subject: [PATCH 1/3] Add `warn_name_override` --- docs/source/config_file.rst | 8 ++++++++ mypy/checker.py | 4 +++- mypy/main.py | 7 +++++++ mypy/options.py | 5 +++++ test-data/unit/check-functions.test | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 3b96e6bd7a5a..01067ddb3e2d 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -592,6 +592,14 @@ section of the command line docs. Shows a warning when encountering any code inferred to be unreachable or redundant after performing type analysis. +.. confval:: warn_name_override + + :type: boolean + :default: False + + Shows a warning when an argument could be used as either a positional or + keyword argument, but it has a different name than the parent argument. + Suppressing errors ****************** diff --git a/mypy/checker.py b/mypy/checker.py index f81cb7a1fd32..232d81df3f92 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2051,7 +2051,9 @@ def check_override( # Use boolean variable to clarify code. fail = False op_method_wider_note = False - if not is_subtype(override, original, ignore_pos_arg_names=True): + if not is_subtype( + override, original, ignore_pos_arg_names=not self.options.warn_name_override + ): fail = True elif isinstance(override, Overloaded) and self.is_forward_op_method(name): # Operator method overrides cannot extend the domain, as diff --git a/mypy/main.py b/mypy/main.py index bf1c3648ff45..a762b5b37202 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -781,6 +781,13 @@ def add_invertible_flag( help="Warn about statements or expressions inferred to be unreachable", group=lint_group, ) + add_invertible_flag( + "--warn-name-override", + default=False, + strict_flag=False, + help="Warn about overridden positional argument names that could be used as keywords", + group=lint_group, + ) # Note: this group is intentionally added here even though we don't add # --strict to this group near the end. diff --git a/mypy/options.py b/mypy/options.py index 45591597ba69..2c2fdbaa0e7c 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -55,6 +55,7 @@ class BuildType: "warn_return_any", "warn_unreachable", "warn_unused_ignores", + "warn_name_override", } OPTIONS_AFFECTING_CACHE: Final = ( @@ -203,6 +204,10 @@ def __init__(self) -> None: # Make arguments prepended via Concatenate be truly positional-only. self.strict_concatenate = False + # Warn about methods that override the name of an argument that could be used + # either positionally or as a keyword argument. + self.warn_name_override = False + # Report an error for any branches inferred to be unreachable as a result of # type analysis. self.warn_unreachable = False diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index b76abd31e3dc..cca8d25bdb5e 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -60,6 +60,27 @@ class B(A): class C(A): def f(self, foo: int, bar: str) -> None: pass +[case testPositionalOverridingArgumentNameSensitivityWithWarnNameOverride] +# flags: --warn-name-override +import typing + +class A(object): + def f(self, a: int, b: str) -> None: pass + +class B(A): + def f(self, b: str, a: int) -> None: pass # E: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "int" \ + # N: This violates the Liskov substitution principle \ + # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides \ + # E: Argument 2 of "f" is incompatible with supertype "A"; supertype defines the argument type as "str" + +class C(A): + def f(self, foo: int, bar: str) -> None: pass # E: Signature of "f" incompatible with supertype "A" \ + # N: Superclass: \ + # N: def f(self, a: int, b: str) -> None \ + # N: Subclass: \ + # N: def f(self, foo: int, bar: str) -> None + + [case testPositionalOverridingArgumentNamesCheckedWhenMismatchingPos] import typing From 1153541ee9250368506bd3b9a15dad9f36a210bd Mon Sep 17 00:00:00 2001 From: Christian Bundy Date: Fri, 5 May 2023 07:29:29 -0700 Subject: [PATCH 2/3] Enable by default --- docs/source/config_file.rst | 2 +- mypy/main.py | 2 +- mypy/options.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 01067ddb3e2d..2e163ffacfb2 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -595,7 +595,7 @@ section of the command line docs. .. confval:: warn_name_override :type: boolean - :default: False + :default: True Shows a warning when an argument could be used as either a positional or keyword argument, but it has a different name than the parent argument. diff --git a/mypy/main.py b/mypy/main.py index a762b5b37202..bd8126acf171 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -783,7 +783,7 @@ def add_invertible_flag( ) add_invertible_flag( "--warn-name-override", - default=False, + default=True, strict_flag=False, help="Warn about overridden positional argument names that could be used as keywords", group=lint_group, diff --git a/mypy/options.py b/mypy/options.py index 2c2fdbaa0e7c..712e89b2333f 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -206,7 +206,7 @@ def __init__(self) -> None: # Warn about methods that override the name of an argument that could be used # either positionally or as a keyword argument. - self.warn_name_override = False + self.warn_name_override = True # Report an error for any branches inferred to be unreachable as a result of # type analysis. From 0be9d5cfbc403377dcc37e23c77b303771f220dd Mon Sep 17 00:00:00 2001 From: Christian Bundy Date: Fri, 5 May 2023 14:41:20 -0700 Subject: [PATCH 3/3] Revert "Enable by default" This reverts commit 1153541ee9250368506bd3b9a15dad9f36a210bd. --- docs/source/config_file.rst | 2 +- mypy/main.py | 2 +- mypy/options.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 2e163ffacfb2..01067ddb3e2d 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -595,7 +595,7 @@ section of the command line docs. .. confval:: warn_name_override :type: boolean - :default: True + :default: False Shows a warning when an argument could be used as either a positional or keyword argument, but it has a different name than the parent argument. diff --git a/mypy/main.py b/mypy/main.py index bd8126acf171..a762b5b37202 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -783,7 +783,7 @@ def add_invertible_flag( ) add_invertible_flag( "--warn-name-override", - default=True, + default=False, strict_flag=False, help="Warn about overridden positional argument names that could be used as keywords", group=lint_group, diff --git a/mypy/options.py b/mypy/options.py index 712e89b2333f..2c2fdbaa0e7c 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -206,7 +206,7 @@ def __init__(self) -> None: # Warn about methods that override the name of an argument that could be used # either positionally or as a keyword argument. - self.warn_name_override = True + self.warn_name_override = False # Report an error for any branches inferred to be unreachable as a result of # type analysis.