Skip to content

Commit

Permalink
Support FIXME names for unknown types in dmypy suggest (#7679)
Browse files Browse the repository at this point in the history
This PR adds an option to `dmypy suggest` to replace `Any` in suggested signatures with a dummy name like `FIXME` or `UNKNOWN`. The main question here is whether we should replace only the top-level `Any`s , or also nested one. I am leaning towards the former, but this is not a strong opinion.
  • Loading branch information
ilevkivskyi committed Oct 10, 2019
1 parent 40f4d66 commit 263ba7f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 4 deletions.
5 changes: 4 additions & 1 deletion mypy/dmypy/client.py
Expand Up @@ -114,6 +114,8 @@ def __init__(self, prog: str) -> None:
help="Try using unicode wherever str is inferred")
p.add_argument('--callsites', action='store_true',
help="Find callsites instead of suggesting a type")
p.add_argument('--use-fixme', metavar='NAME', type=str,
help="A dummy name to use instead of Any for types that can't be inferred")

hang_parser = p = subparsers.add_parser('hang', help="Hang for 100 seconds")

Expand Down Expand Up @@ -367,7 +369,8 @@ def do_suggest(args: argparse.Namespace) -> None:
"""
response = request(args.status_file, 'suggest', function=args.function,
json=args.json, callsites=args.callsites, no_errors=args.no_errors,
no_any=args.no_any, flex_any=args.flex_any, try_text=args.try_text)
no_any=args.no_any, flex_any=args.flex_any, try_text=args.try_text,
use_fixme=args.use_fixme)
check_output(response, verbose=False, junit_xml=None, perf_stats_file=None)


Expand Down
2 changes: 1 addition & 1 deletion mypy/semanal.py
Expand Up @@ -50,7 +50,7 @@
from contextlib import contextmanager

from typing import (
List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable,
List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable
)
from typing_extensions import Final

Expand Down
6 changes: 5 additions & 1 deletion mypy/suggestions.py
Expand Up @@ -160,7 +160,8 @@ def __init__(self, fgmanager: FineGrainedBuildManager,
no_errors: bool = False,
no_any: bool = False,
try_text: bool = False,
flex_any: Optional[float] = None) -> None:
flex_any: Optional[float] = None,
use_fixme: Optional[str] = None) -> None:
self.fgmanager = fgmanager
self.manager = fgmanager.manager
self.plugin = self.manager.plugin
Expand All @@ -175,6 +176,7 @@ def __init__(self, fgmanager: FineGrainedBuildManager,
self.flex_any = 1.0

self.max_guesses = 16
self.use_fixme = use_fixme

def suggest(self, function: str) -> str:
"""Suggest an inferred type for function."""
Expand Down Expand Up @@ -592,6 +594,8 @@ def format_signature(self, sig: PyAnnotateSignature) -> str:
)

def format_type(self, cur_module: Optional[str], typ: Type) -> str:
if self.use_fixme and isinstance(get_proper_type(typ), AnyType):
return self.use_fixme
return typ.accept(TypeFormatter(cur_module, self.graph))

def score_type(self, t: Type, arg_pos: bool) -> int:
Expand Down
4 changes: 3 additions & 1 deletion mypy/test/testfinegrained.py
Expand Up @@ -281,10 +281,12 @@ def maybe_suggest(self, step: int, server: Server, src: str, tmp_dir: str) -> Li
try_text = '--try-text' in flags
m = re.match('--flex-any=([0-9.]+)', flags)
flex_any = float(m.group(1)) if m else None
m = re.match(r'--use-fixme=(\w+)', flags)
use_fixme = m.group(1) if m else None
res = cast(Dict[str, Any],
server.cmd_suggest(
target.strip(), json=json, no_any=no_any, no_errors=no_errors,
try_text=try_text, flex_any=flex_any,
try_text=try_text, flex_any=flex_any, use_fixme=use_fixme,
callsites=callsites))
val = res['error'] if 'error' in res else res['out'] + res['err']
if json:
Expand Down
35 changes: 35 additions & 0 deletions test-data/unit/fine-grained-suggest.test
Expand Up @@ -733,3 +733,38 @@ func('test')
[out]
(str) -> int
==

[case testSuggestUseFixmeBasic]
# suggest: --use-fixme=UNKNOWN foo.foo
# suggest: --use-fixme=UNKNOWN foo.bar
[file foo.py]

def foo():
return g()

def bar(x):
return None

def g(): ...
x = bar(g())
[out]
() -> UNKNOWN
(UNKNOWN) -> None
==

[case testSuggestUseFixmeNoNested]
# suggest: --use-fixme=UNKNOWN foo.foo
[file foo.py]
from typing import List, Any

def foo(x, y):
return x, y

def f() -> List[Any]: ...
def g(): ...

z = foo(f(), g())
[builtins fixtures/isinstancelist.pyi]
[out]
(foo.List[Any], UNKNOWN) -> Tuple[foo.List[Any], Any]
==

0 comments on commit 263ba7f

Please sign in to comment.