Skip to content

Commit b96d4d0

Browse files
authored
[suggest] Use the type of a method in a parent class as a guess (python#7980)
1 parent c39335a commit b96d4d0

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

mypy/suggestions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,23 @@ def find_best(self, func: FuncDef, guesses: List[CallableType]) -> Tuple[Callabl
408408
key=lambda s: (count_errors(errors[s]), self.score_callable(s)))
409409
return best, count_errors(errors[best])
410410

411+
def get_guesses_from_parent(self, node: FuncDef) -> List[CallableType]:
412+
"""Try to get a guess of a method type from a parent class."""
413+
if not node.info:
414+
return []
415+
416+
for parent in node.info.mro[1:]:
417+
pnode = parent.names.get(node.name)
418+
if pnode and isinstance(pnode.node, (FuncDef, Decorator)):
419+
typ = get_proper_type(pnode.node.type)
420+
# FIXME: Doesn't work right with generic tyeps
421+
if isinstance(typ, CallableType) and len(typ.arg_types) == len(node.arguments):
422+
# Return the first thing we find, since it probably doesn't make sense
423+
# to grab things further up in the chain if an earlier parent has it.
424+
return [typ]
425+
426+
return []
427+
411428
def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature:
412429
"""Compute a suggestion for a function.
413430
@@ -430,6 +447,7 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature:
430447
callsites,
431448
uses,
432449
)
450+
guesses += self.get_guesses_from_parent(node)
433451
guesses = self.filter_options(guesses, is_method, ignore_return=True)
434452
best, _ = self.find_best(node, guesses)
435453

test-data/unit/fine-grained-suggest.test

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,42 @@ def baz():
790790
() -> str
791791
==
792792

793+
[case testSuggestParent]
794+
# suggest: foo.B.foo
795+
# suggest: foo.B.bar
796+
# suggest: foo.C.foo
797+
[file foo.py]
798+
from typing import TypeVar, Callable, Any
799+
F = TypeVar('F', bound=Callable[..., Any])
800+
def deco(f: F) -> F: ...
801+
802+
class A:
803+
def foo(self, x: int) -> float:
804+
return 0.0
805+
806+
@deco
807+
def bar(self, x: int) -> float:
808+
return 0.0
809+
810+
811+
class B(A):
812+
def foo(self, x):
813+
return 0.0
814+
815+
@deco
816+
def bar(self, x):
817+
return 0.0
818+
819+
class C(B):
820+
def foo(self, x):
821+
return 0.0
822+
823+
[out]
824+
(int) -> float
825+
(int) -> float
826+
(int) -> float
827+
==
828+
793829
[case testSuggestColonBadLocation]
794830
# suggest: tmp/foo.py:7:8:9
795831
[file foo.py]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy