Skip to content

Commit

Permalink
Support per-argument type comment syntax (#1738)
Browse files Browse the repository at this point in the history
This adds support for the (Python 2) per-argument type comment syntax now that python/typed_ast#5 has landed. It only works when using `--fast-parser`; without that these comments will be ignore.

The code works by converting Python 2.7 per-argument type comments to Python 3 annotations in the typed_ast's conversion module -- this allows them to be mixed with the # type: (...) -> None syntax.

Fixes #1102.
  • Loading branch information
ddfisher authored and gvanrossum committed Jun 23, 2016
1 parent 4889c0c commit ad9024d
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 3 deletions.
3 changes: 2 additions & 1 deletion mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ def visit_FunctionDef(self, n: ast35.FunctionDef) -> Node:
# for ellipsis arg
if (len(func_type_ast.argtypes) == 1 and
isinstance(func_type_ast.argtypes[0], ast35.Ellipsis)):
arg_types = [AnyType() for a in args]
arg_types = [a.type_annotation if a.type_annotation is not None else AnyType()
for a in args]
else:
arg_types = [a if a is not None else AnyType() for
a in TypeConverter(line=n.lineno).visit_list(func_type_ast.argtypes)]
Expand Down
112 changes: 112 additions & 0 deletions test-data/unit/check-fastparse.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,115 @@ class C:
@x.setter
def x(self, value: str) -> None: pass
[builtins fixtures/property.py]

[case testFastParsePerArgumentAnnotations]
# flags: fast-parser
class A: pass
class B: pass
class C: pass
class D: pass
class E: pass
class F: pass
def f(a, # type: A
b = None, # type: B
*args, # type: C
d = None, # type: D
e, # type: E
**kwargs # type: F
):
reveal_type(a) # E: Revealed type is '__main__.A'
reveal_type(b) # E: Revealed type is '__main__.B'
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
reveal_type(d) # E: Revealed type is '__main__.D'
reveal_type(e) # E: Revealed type is '__main__.E'
reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]'
[builtins fixtures/dict.py]
[out]
main: note: In function "f":

[case testFastParsePerArgumentAnnotationsWithReturn]
# flags: fast-parser
class A: pass
class B: pass
class C: pass
class D: pass
class E: pass
class F: pass
def f(a, # type: A
b = None, # type: B
*args, # type: C
d = None, # type: D
e, # type: E
**kwargs # type: F
):
# type: (...) -> int
reveal_type(a) # E: Revealed type is '__main__.A'
reveal_type(b) # E: Revealed type is '__main__.B'
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
reveal_type(d) # E: Revealed type is '__main__.D'
reveal_type(e) # E: Revealed type is '__main__.E'
reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]'
return "not an int" # E: Incompatible return value type (got "str", expected "int")
[builtins fixtures/dict.py]
[out]
main: note: In function "f":

[case testFastParsePerArgumentAnnotationsWithAnnotatedBareStar]
# flags: fast-parser
def f(*, # type: int # E: bare * has associated type comment
x # type: str
):
# type: (...) -> int
pass
[builtins fixtures/dict.py]
[out]

[case testFastParsePerArgumentAnnotationsWithReturnAndBareStar]
# flags: fast-parser
def f(*,
x # type: str
):
# type: (...) -> int
reveal_type(x) # E: Revealed type is 'builtins.str'
return "not an int" # E: Incompatible return value type (got "str", expected "int")
[builtins fixtures/dict.py]
[out]
main: note: In function "f":

[case testFastParsePerArgumentAnnotations_python2]
# flags: fast-parser
class A: pass
class B: pass
class C: pass
class D: pass
def f(a, # type: A
b = None, # type: B
*args # type: C
# kwargs not tested due to lack of 2.7 dict fixtures
):
reveal_type(a) # E: Revealed type is '__main__.A'
reveal_type(b) # E: Revealed type is '__main__.B'
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
[builtins fixtures/dict.py]
[out]
main: note: In function "f":

[case testFastParsePerArgumentAnnotationsWithReturn_python2]
# flags: fast-parser
class A: pass
class B: pass
class C: pass
class D: pass
def f(a, # type: A
b = None, # type: B
*args # type: C
# kwargs not tested due to lack of 2.7 dict fixtures
):
# type: (...) -> int
reveal_type(a) # E: Revealed type is '__main__.A'
reveal_type(b) # E: Revealed type is '__main__.B'
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
return "not an int" # E: Incompatible return value type (got "str", expected "int")
[builtins fixtures/dict.py]
[out]
main: note: In function "f":
10 changes: 8 additions & 2 deletions test-data/unit/lib-stub/__builtin__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
class Any: pass

class object:
def __init__(self) -> None: pass
def __init__(self):
# type: () -> None
pass

class type:
def __init__(self, x) -> None: pass
def __init__(self, x):
# type: (Any) -> None
pass

# These are provided here for convenience.
class int: pass
Expand Down

0 comments on commit ad9024d

Please sign in to comment.