Skip to content

Commit

Permalink
Bare Tuple should mean Tuple[Any, ...]. (python#2185)
Browse files Browse the repository at this point in the history
  • Loading branch information
gvanrossum authored Sep 27, 2016
1 parent 2fbf387 commit 0d2c594
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 4 deletions.
5 changes: 4 additions & 1 deletion mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,12 +833,15 @@ def visit_Subscript(self, n: ast35.Subscript) -> Type:
assert isinstance(value, UnboundType)
assert not value.args

empty_tuple_index = False
if isinstance(n.slice.value, ast35.Tuple):
params = self.visit_list(n.slice.value.elts)
if len(n.slice.value.elts) == 0:
empty_tuple_index = True
else:
params = [self.visit(n.slice.value)]

return UnboundType(value.name, params, line=self.line)
return UnboundType(value.name, params, line=self.line, empty_tuple_index=empty_tuple_index)

def visit_Tuple(self, n: ast35.Tuple) -> Type:
return TupleType(self.visit_list(n.elts), None, implicit=True, line=self.line)
Expand Down
3 changes: 3 additions & 0 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def visit_unbound_type(self, t: UnboundType) -> Type:
elif fullname == 'typing.Any':
return AnyType()
elif fullname == 'typing.Tuple':
if len(t.args) == 0 and not t.empty_tuple_index:
# Bare 'Tuple' is same as 'tuple'
return self.builtin_type('builtins.tuple')
if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
# Tuple[T, ...] (uniform, variable-length tuple)
node = self.lookup_fqn_func('builtins.tuple')
Expand Down
6 changes: 5 additions & 1 deletion mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,24 @@ class UnboundType(Type):
optional = False
# is this type a return type?
is_ret_type = False
# special case for X[()]
empty_tuple_index = False

def __init__(self,
name: str,
args: List[Type] = None,
line: int = -1,
column: int = -1,
optional: bool = False,
is_ret_type: bool = False) -> None:
is_ret_type: bool = False,
empty_tuple_index: bool = False) -> None:
if not args:
args = []
self.name = name
self.args = args
self.optional = optional
self.is_ret_type = is_ret_type
self.empty_tuple_index = empty_tuple_index
super().__init__(line, column)

def accept(self, visitor: 'TypeVisitor[T]') -> T:
Expand Down
19 changes: 19 additions & 0 deletions test-data/unit/check-tuples.test
Original file line number Diff line number Diff line change
Expand Up @@ -820,3 +820,22 @@ from typing import List, Tuple
def f() -> Tuple[List[str], ...]:
return ([],)
[builtins fixtures/tuple.pyi]

[case testTupleWithoutArgs]
from typing import Tuple
def f(a: Tuple) -> None: pass
f(())
f((1,))
f(('', ''))
f(0) # E: Argument 1 to "f" has incompatible type "int"; expected Tuple[Any, ...]
[builtins fixtures/tuple.pyi]

[case testTupleSingleton]
# flags: --fast-parser
from typing import Tuple
def f(a: Tuple[()]) -> None: pass
f(())
f((1,)) # E: Argument 1 to "f" has incompatible type "Tuple[int]"; expected "Tuple[]"
f(('', '')) # E: Argument 1 to "f" has incompatible type "Tuple[str, str]"; expected "Tuple[]"
f(0) # E: Argument 1 to "f" has incompatible type "int"; expected "Tuple[]"
[builtins fixtures/tuple.pyi]
2 changes: 0 additions & 2 deletions test-data/unit/fixtures/tuple.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,3 @@ T = TypeVar('T')
class list(Sequence[T], Generic[T]): pass

def sum(iterable: Iterable[T], start: T = None) -> T: pass

True = bool()

0 comments on commit 0d2c594

Please sign in to comment.