From 2461effedca7a7b8eaecad90c76f74d22edaa6be Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Wed, 15 Jan 2025 21:38:29 +0100 Subject: [PATCH 01/11] PEP 702 (@deprecated): "normal" overloaded methods Fixes #18474 It seems I covered overloaded functions, descriptors, and special methods so far but completely forgot about "normal" methods (thanks to @sobolevn for pointing this out). This addition should do the trick. --- mypy/checkexpr.py | 9 ++++++- test-data/unit/check-deprecated.test | 39 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b6618109bb44..9ec4c84d32ab 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1485,7 +1485,14 @@ def check_call_expr_with_callee_type( ) proper_callee = get_proper_type(callee_type) if isinstance(e.callee, (NameExpr, MemberExpr)): - self.chk.warn_deprecated_overload_item(e.callee.node, e, target=callee_type) + node = e.callee.node + if (node is None) and (member is not None) and isinstance(object_type, Instance) and ( + (symbol := object_type.type.names.get(member)) is not None + ): + node = symbol.node + self.chk.warn_deprecated_overload_item( + node, e, target=callee_type, selftype=object_type + ) if isinstance(e.callee, RefExpr) and isinstance(proper_callee, CallableType): # Cache it for find_isinstance_check() if proper_callee.type_guard is not None: diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index 362d8725f183..875efbac45a7 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -377,6 +377,45 @@ for i in a: # E: function __main__.A.__iter__ is deprecated: no iteration [builtins fixtures/tuple.pyi] +[case testDeprecatedOverloadedMethods] +# flags: --enable-error-code=deprecated + +from typing import Iterator, Union +from typing_extensions import deprecated, overload + +class A: + @overload + @deprecated("pass `str` instead") + def f(self, v: int) -> None: ... + @overload + def f(self, v: str) -> None: ... + def f(self, v: Union[int, str]) -> None: ... + + @overload + def g(self, v: int) -> None: ... + @overload + @deprecated("pass `int` instead") + def g(self, v: str) -> None: ... + def g(self, v: Union[int, str]) -> None: ... + + @overload + def h(self, v: int) -> A: ... + @overload + def h(self, v: str) -> A: ... + @deprecated("use `h2` instead") + def h(self, v: Union[int, str]) -> A: ... + +a = A() +a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +a.f("x") +a.g(1) +a.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + +[builtins fixtures/tuple.pyi] + + [case testDeprecatedOverloadedSpecialMethods] # flags: --enable-error-code=deprecated From 1ba5cf17f55cebbb21bb13c5c0e6f98f28d9ea23 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:41:53 +0000 Subject: [PATCH 02/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/checkexpr.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 9ec4c84d32ab..033faee96a6b 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1486,8 +1486,11 @@ def check_call_expr_with_callee_type( proper_callee = get_proper_type(callee_type) if isinstance(e.callee, (NameExpr, MemberExpr)): node = e.callee.node - if (node is None) and (member is not None) and isinstance(object_type, Instance) and ( - (symbol := object_type.type.names.get(member)) is not None + if ( + (node is None) + and (member is not None) + and isinstance(object_type, Instance) + and ((symbol := object_type.type.names.get(member)) is not None) ): node = symbol.node self.chk.warn_deprecated_overload_item( From 7f3d73cdf349ac01960598f893163fd241e78663 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Fri, 17 Jan 2025 18:08:18 +0100 Subject: [PATCH 03/11] fix inheritance --- mypy/checkexpr.py | 9 +++++---- test-data/unit/check-deprecated.test | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 9ec4c84d32ab..da0e81ad09d7 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1486,10 +1486,11 @@ def check_call_expr_with_callee_type( proper_callee = get_proper_type(callee_type) if isinstance(e.callee, (NameExpr, MemberExpr)): node = e.callee.node - if (node is None) and (member is not None) and isinstance(object_type, Instance) and ( - (symbol := object_type.type.names.get(member)) is not None - ): - node = symbol.node + if (node is None) and (member is not None) and isinstance(object_type, Instance): + for base in object_type.type.mro: + if (symbol := base.names.get(member)) is not None: + node = symbol.node + break self.chk.warn_deprecated_overload_item( node, e, target=callee_type, selftype=object_type ) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index 875efbac45a7..05ccf861a4c6 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -405,6 +405,8 @@ class A: @deprecated("use `h2` instead") def h(self, v: Union[int, str]) -> A: ... +class B(A): ... + a = A() a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.f("x") @@ -413,6 +415,14 @@ a.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __ma a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead +b = B() +b.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +b.f("x") +b.g(1) +b.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + [builtins fixtures/tuple.pyi] From a0fcf3167b42f112df37fb41c80d56b04f83a50a Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Fri, 17 Jan 2025 18:28:10 +0100 Subject: [PATCH 04/11] Add tests for class methods and static methods and fix `warn_deprecated_overload_item` for static methods --- mypy/checker.py | 2 +- test-data/unit/check-deprecated.test | 118 ++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 47b08b683e36..3b14452fdc84 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -7746,7 +7746,7 @@ def warn_deprecated_overload_item( if isinstance(item, Decorator) and isinstance( candidate := item.func.type, CallableType ): - if selftype is not None: + if (selftype is not None) and (not node.is_static): candidate = bind_self(candidate, selftype) if candidate == target: self.warn_deprecated(item.func, context) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index 05ccf861a4c6..60663d8d849f 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -377,7 +377,7 @@ for i in a: # E: function __main__.A.__iter__ is deprecated: no iteration [builtins fixtures/tuple.pyi] -[case testDeprecatedOverloadedMethods] +[case testDeprecatedOverloadedInstanceMethods] # flags: --enable-error-code=deprecated from typing import Iterator, Union @@ -426,6 +426,122 @@ b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead [builtins fixtures/tuple.pyi] +[case testDeprecatedOverloadedClassMethods] +# flags: --enable-error-code=deprecated + +from typing import Iterator, Union +from typing_extensions import deprecated, overload + +class A: + @overload + @classmethod + @deprecated("pass `str` instead") + def f(self, v: int) -> None: ... + @overload + @classmethod + def f(self, v: str) -> None: ... + @classmethod + def f(self, v: Union[int, str]) -> None: ... + + @overload + @classmethod + def g(self, v: int) -> None: ... + @overload + @classmethod + @deprecated("pass `int` instead") + def g(self, v: str) -> None: ... + @classmethod + def g(self, v: Union[int, str]) -> None: ... + + @overload + @classmethod + def h(self, v: int) -> A: ... + @overload + @classmethod + def h(self, v: str) -> A: ... + @deprecated("use `h2` instead") + @classmethod + def h(self, v: Union[int, str]) -> A: ... + +class B(A): ... + +a = A() +a.f(1) # E: overload def (self: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +a.f("x") +a.g(1) +a.g("x") # E: overload def (self: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + +b = B() +b.f(1) # E: overload def (self: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +b.f("x") +b.g(1) +b.g("x") # E: overload def (self: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + +[builtins fixtures/tuple.pyi] + + +[case testDeprecatedOverloadedStaticMethods] +# flags: --enable-error-code=deprecated + +from typing import Iterator, Union +from typing_extensions import deprecated, overload + +class A: + @overload + @staticmethod + @deprecated("pass `str` instead") + def f(v: int) -> None: ... + @overload + @staticmethod + def f(v: str) -> None: ... + @staticmethod + def f(v: Union[int, str]) -> None: ... + + @overload + @staticmethod + def g(v: int) -> None: ... + @overload + @staticmethod + @deprecated("pass `int` instead") + def g(v: str) -> None: ... + @staticmethod + def g(v: Union[int, str]) -> None: ... + + @overload + @staticmethod + def h(v: int) -> A: ... + @overload + @staticmethod + def h(v: str) -> A: ... + @deprecated("use `h2` instead") + @staticmethod + def h(v: Union[int, str]) -> A: ... + +class B(A): ... + +a = A() +a.f(1) # E: overload def (v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +a.f("x") +a.g(1) +a.g("x") # E: overload def (v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + +b = B() +b.f(1) # E: overload def (v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +b.f("x") +b.g(1) +b.g("x") # E: overload def (v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead + +[builtins fixtures/classmethod.pyi] + + [case testDeprecatedOverloadedSpecialMethods] # flags: --enable-error-code=deprecated From b4a9cd3995028fe9fc40754b33c262d62721f4d6 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Fri, 17 Jan 2025 19:07:22 +0100 Subject: [PATCH 05/11] `self` --> `cls` for class methods --- test-data/unit/check-deprecated.test | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index 60663d8d849f..bd05025e88b3 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -436,48 +436,48 @@ class A: @overload @classmethod @deprecated("pass `str` instead") - def f(self, v: int) -> None: ... + def f(cls, v: int) -> None: ... @overload @classmethod - def f(self, v: str) -> None: ... + def f(cls, v: str) -> None: ... @classmethod - def f(self, v: Union[int, str]) -> None: ... + def f(cls, v: Union[int, str]) -> None: ... @overload @classmethod - def g(self, v: int) -> None: ... + def g(cls, v: int) -> None: ... @overload @classmethod @deprecated("pass `int` instead") - def g(self, v: str) -> None: ... + def g(cls, v: str) -> None: ... @classmethod - def g(self, v: Union[int, str]) -> None: ... + def g(cls, v: Union[int, str]) -> None: ... @overload @classmethod - def h(self, v: int) -> A: ... + def h(cls, v: int) -> A: ... @overload @classmethod - def h(self, v: str) -> A: ... + def h(cls, v: str) -> A: ... @deprecated("use `h2` instead") @classmethod - def h(self, v: Union[int, str]) -> A: ... + def h(cls, v: Union[int, str]) -> A: ... class B(A): ... a = A() -a.f(1) # E: overload def (self: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +a.f(1) # E: overload def (cls: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.f("x") a.g(1) -a.g("x") # E: overload def (self: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +a.g("x") # E: overload def (cls: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead b = B() -b.f(1) # E: overload def (self: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead +b.f(1) # E: overload def (cls: type[__main__.A], v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead b.f("x") b.g(1) -b.g("x") # E: overload def (self: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +b.g("x") # E: overload def (cls: type[__main__.A], v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead From 2ff8cf15d98215f538e509cf70d3fdea7ff12a9c Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Sun, 19 Jan 2025 21:40:59 +0100 Subject: [PATCH 06/11] less brackets Co-authored-by: sobolevn --- mypy/checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 3b14452fdc84..1ffe3588a968 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -7746,7 +7746,7 @@ def warn_deprecated_overload_item( if isinstance(item, Decorator) and isinstance( candidate := item.func.type, CallableType ): - if (selftype is not None) and (not node.is_static): + if selftype is not None and not node.is_static: candidate = bind_self(candidate, selftype) if candidate == target: self.warn_deprecated(item.func, context) From 67573912a90722322c304d261f3fcd8072d3a3a5 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Sun, 19 Jan 2025 21:44:31 +0100 Subject: [PATCH 07/11] less brackets --- mypy/checkexpr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index da0e81ad09d7..0fa924bbe8ea 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1486,7 +1486,7 @@ def check_call_expr_with_callee_type( proper_callee = get_proper_type(callee_type) if isinstance(e.callee, (NameExpr, MemberExpr)): node = e.callee.node - if (node is None) and (member is not None) and isinstance(object_type, Instance): + if node is None and member is not None and isinstance(object_type, Instance): for base in object_type.type.mro: if (symbol := base.names.get(member)) is not None: node = symbol.node From cc7a9150dfcad4b6c8a309060b36bcb0c6273a51 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Sun, 19 Jan 2025 21:46:26 +0100 Subject: [PATCH 08/11] additional test Co-authored-by: sobolevn --- test-data/unit/check-deprecated.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index bd05025e88b3..a307a90124a3 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -410,6 +410,9 @@ class B(A): ... a = A() a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.f("x") + +int_or_str: Union[int, str] +a.f(int_or_str) a.g(1) a.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead From c95f93678317430e83c256fdd52d578b207eb065 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Sun, 19 Jan 2025 22:29:05 +0100 Subject: [PATCH 09/11] execute `check_deprecated` before `warn_deprecated_overload_item` when analysing "normal" methods (like we do when in other cases). --- mypy/checkexpr.py | 1 + test-data/unit/check-deprecated.test | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 0fa924bbe8ea..d61c07bd2628 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1491,6 +1491,7 @@ def check_call_expr_with_callee_type( if (symbol := base.names.get(member)) is not None: node = symbol.node break + self.chk.check_deprecated(node, e) self.chk.warn_deprecated_overload_item( node, e, target=callee_type, selftype=object_type ) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index a307a90124a3..07b58158744c 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -402,29 +402,34 @@ class A: def h(self, v: int) -> A: ... @overload def h(self, v: str) -> A: ... - @deprecated("use `h2` instead") + @deprecated("use `h2` instead") def h(self, v: Union[int, str]) -> A: ... class B(A): ... +int_or_str: Union[int, str] + a = A() a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.f("x") - -int_or_str: Union[int, str] -a.f(int_or_str) +a.f(int_or_str) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.g(1) a.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead -a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead -a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead +a.g(int_or_str) # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead +a.h(int_or_str) # E: function __main__.A.h is deprecated: use `h2` instead b = B() b.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead b.f("x") +b.f(int_or_str) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead b.g(1) b.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead -b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead -b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead +b.g(int_or_str) # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead +b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead +b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead +b.h(int_or_str) # E: function __main__.A.h is deprecated: use `h2` instead [builtins fixtures/tuple.pyi] From 7522cb8f095c782b771a5badf94d9f4ef1330763 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Mon, 27 Jan 2025 19:30:07 +0100 Subject: [PATCH 10/11] remove `int_or_str` tests --- test-data/unit/check-deprecated.test | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test-data/unit/check-deprecated.test b/test-data/unit/check-deprecated.test index 07b58158744c..df9695332a5b 100644 --- a/test-data/unit/check-deprecated.test +++ b/test-data/unit/check-deprecated.test @@ -407,29 +407,21 @@ class A: class B(A): ... -int_or_str: Union[int, str] - a = A() a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.f("x") -a.f(int_or_str) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead a.g(1) a.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead -a.g(int_or_str) # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead a.h(1) # E: function __main__.A.h is deprecated: use `h2` instead a.h("x") # E: function __main__.A.h is deprecated: use `h2` instead -a.h(int_or_str) # E: function __main__.A.h is deprecated: use `h2` instead b = B() b.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead b.f("x") -b.f(int_or_str) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead b.g(1) b.g("x") # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead -b.g(int_or_str) # E: overload def (self: __main__.A, v: builtins.str) of function __main__.A.g is deprecated: pass `int` instead b.h(1) # E: function __main__.A.h is deprecated: use `h2` instead b.h("x") # E: function __main__.A.h is deprecated: use `h2` instead -b.h(int_or_str) # E: function __main__.A.h is deprecated: use `h2` instead [builtins fixtures/tuple.pyi] From c75892246646e97bcfb04e8ef5a03fc76eb9d4b5 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Tue, 28 Jan 2025 07:26:29 +0100 Subject: [PATCH 11/11] refactor: `type.get` instead of loop --- mypy/checkexpr.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index d61c07bd2628..da38947ec69c 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1487,10 +1487,8 @@ def check_call_expr_with_callee_type( if isinstance(e.callee, (NameExpr, MemberExpr)): node = e.callee.node if node is None and member is not None and isinstance(object_type, Instance): - for base in object_type.type.mro: - if (symbol := base.names.get(member)) is not None: - node = symbol.node - break + if (symbol := object_type.type.get(member)) is not None: + node = symbol.node self.chk.check_deprecated(node, e) self.chk.warn_deprecated_overload_item( node, e, target=callee_type, selftype=object_type