Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for namedtuple methods (issue #1076) #1810

Merged
merged 85 commits into from
Sep 2, 2016
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
ecca142
namedtuple: add (shaky) support for _replace, _asdict + naive test
elazarg Jul 6, 2016
8ef445f
namedtuple: add tests and refine types
elazarg Jul 6, 2016
5e429cd
minor cleanup
elazarg Jul 6, 2016
0214e3c
minor cleanup
elazarg Jul 6, 2016
fbb75c3
flake8-ing
elazarg Jul 6, 2016
17d7f8b
fix type errors
elazarg Jul 6, 2016
6dd370c
fix type errors
elazarg Jul 6, 2016
1370fbf
Merge branch 'namedtuple' of https://github.com/elazarg/mypy into nam…
elazarg Jul 6, 2016
560eb3e
_fields will not be supported
elazarg Jul 6, 2016
2627511
slight refactoring
elazarg Jul 6, 2016
46475d4
restore tests for _replace and _asdict
elazarg Jul 6, 2016
c1dc1c7
NamedTupleTypeInfo
elazarg Jul 9, 2016
763e0c0
run both Replace and AsTuple
elazarg Jul 10, 2016
4b10a35
fix most of the tests
elazarg Jul 10, 2016
ee047f8
complete support for _replace
elazarg Jul 10, 2016
725d53c
flake8-ing
elazarg Jul 10, 2016
044e640
Add partial support for calling '_replace' statically
elazarg Jul 12, 2016
eb6534e
fix method name
elazarg Aug 11, 2016
aa0d5da
namedtuple tests pass. list has problems
elazarg Aug 14, 2016
e12bd01
tests pass. OrderedDict unsupported. cleanup still required
elazarg Aug 14, 2016
dc9d8da
fix line endings
elazarg Aug 14, 2016
158b068
flake8-ing
elazarg Aug 14, 2016
90ffb08
s/self_type/with_fallback. Fix visitor type
elazarg Aug 14, 2016
9a6e6cd
uniform copy_with. typechecks.
elazarg Aug 14, 2016
76d709e
uniform copy_with. typechecks.
elazarg Aug 14, 2016
20bf222
rename tests to startwith NamedTuple
elazarg Aug 15, 2016
a2696c2
Read-only attributes. Can't set new attributes in subclasses yet
elazarg Aug 15, 2016
9e1b866
update semantic namedtuple repr name
elazarg Aug 15, 2016
f7b531f
support _fields
elazarg Aug 15, 2016
67bdafe
support _source. test for unit namedtuple
elazarg Aug 15, 2016
39bce74
support _asdict()->OrderedDict as an UnboundType
elazarg Aug 15, 2016
a2db6a0
minor cleanup
elazarg Aug 15, 2016
8784ce0
support _make and _field_types
elazarg Aug 16, 2016
191de7c
namedtuple: add (shaky) support for _replace, _asdict + naive test
elazarg Jul 6, 2016
6d2d6d1
namedtuple: add tests and refine types
elazarg Jul 6, 2016
8819af9
minor cleanup
elazarg Jul 6, 2016
9fb5137
flake8-ing
elazarg Jul 6, 2016
35c30a2
fix type errors
elazarg Jul 6, 2016
a642a7f
_fields will not be supported
elazarg Jul 6, 2016
c505cbc
slight refactoring
elazarg Jul 6, 2016
9f96ca7
restore tests for _replace and _asdict
elazarg Jul 6, 2016
5c2d3ac
NamedTupleTypeInfo
elazarg Jul 9, 2016
41ed075
run both Replace and AsTuple
elazarg Jul 10, 2016
6dd568f
fix most of the tests
elazarg Jul 10, 2016
b18fc25
complete support for _replace
elazarg Jul 10, 2016
d7dbd3f
flake8-ing
elazarg Jul 10, 2016
2b67380
Add partial support for calling '_replace' statically
elazarg Jul 12, 2016
525c081
fix method name
elazarg Aug 11, 2016
15acfe0
namedtuple tests pass. list has problems
elazarg Aug 14, 2016
fb9ba7f
tests pass. OrderedDict unsupported. cleanup still required
elazarg Aug 14, 2016
99635c5
fix line endings
elazarg Aug 14, 2016
8f61c13
flake8-ing
elazarg Aug 14, 2016
ff21b0c
s/self_type/with_fallback. Fix visitor type
elazarg Aug 14, 2016
4c1bfe4
uniform copy_with. typechecks.
elazarg Aug 14, 2016
b0d78ba
uniform copy_with. typechecks.
elazarg Aug 14, 2016
87c804c
rename tests to startwith NamedTuple
elazarg Aug 15, 2016
6adc2f9
Read-only attributes. Can't set new attributes in subclasses yet
elazarg Aug 15, 2016
7ed7b0e
update semantic namedtuple repr name
elazarg Aug 15, 2016
c7dc9a7
support _fields
elazarg Aug 15, 2016
b39925b
support _source. test for unit namedtuple
elazarg Aug 15, 2016
030307e
support _asdict()->OrderedDict as an UnboundType
elazarg Aug 15, 2016
12d3407
minor cleanup
elazarg Aug 15, 2016
1f944fc
support _make and _field_types
elazarg Aug 16, 2016
7825f79
Merge branch 'namedtuple'
elazarg Aug 16, 2016
8a0ce40
merge upstream
elazarg Aug 16, 2016
7978357
merge fix except Awaitable lookup
elazarg Aug 16, 2016
badc3f9
merge fix
elazarg Aug 16, 2016
c051f3f
Merge remote
elazarg Aug 17, 2016
44c124b
Merge branch 'master' into namedtuple
elazarg Aug 17, 2016
d067c9e
fix syntax error
elazarg Aug 17, 2016
42342de
Merge branch 'master' into namedtuple
elazarg Aug 18, 2016
a5ccc50
join/meet namedtuples as namedtuple only if attrs are equal
elazarg Aug 20, 2016
eaf4b99
join/meet namedtuples as namedtuple only if attrs are equal. add tests.
elazarg Aug 20, 2016
9829b25
Fix conflicts:
elazarg Aug 21, 2016
b1988f8
Merge branch 'master' into namedtuple
elazarg Aug 28, 2016
8ced59e
Merge remote-tracking branch 'upstream/master' into namedtuple
elazarg Aug 28, 2016
053ee56
remove NamedTupleType
elazarg Aug 30, 2016
94bb8d0
Merge remote-tracking branch 'upstream/master' into namedtuple
elazarg Aug 30, 2016
71f0d78
restore semanal test
elazarg Aug 30, 2016
66a77fb
fix signatures
elazarg Sep 1, 2016
922dd91
_asdict() -> Dict
elazarg Sep 1, 2016
6460839
_asdict() -> OrderedDict
elazarg Sep 1, 2016
cd5b933
use buitlins.dict; rearrange build_namedtuple_typeinfo
elazarg Sep 1, 2016
4b93761
Merge remote-tracking branch 'upstream/master' into namedtuple
elazarg Sep 1, 2016
500a847
remove unneeded 'class dict' from proprty.pyi
elazarg Sep 1, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,9 @@ def visit_class_def(self, defn: ClassDef) -> Type:
with self.binder.frame_context():
self.accept(defn.defs)
self.binder = old_binder
self.check_multiple_inheritance(typ)
if not defn.has_incompatible_baseclass:
# Otherwise we've already found errors; more errors are not useful
self.check_multiple_inheritance(typ)
self.leave_partial_types()
self.errors.pop_type()

Expand Down
3 changes: 1 addition & 2 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,8 +1296,7 @@ def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Typ
slic.stride)
return AnyType()

return TupleType(left_type.items[begin:end:stride], left_type.fallback,
left_type.line, left_type.implicit)
return left_type.slice(begin, stride, end)

def _get_value(self, index: Node) -> Optional[int]:
if isinstance(index, IntExpr):
Expand Down
4 changes: 3 additions & 1 deletion mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ def analyze_member_var_access(name: str, itype: Instance, info: TypeInfo,
if isinstance(vv, Decorator):
# The associated Var node of a decorator contains the type.
v = vv.var

if isinstance(v, Var):
return analyze_var(name, v, itype, info, node, is_lvalue, msg, not_ready_callback)
elif isinstance(v, FuncDef):
Expand Down Expand Up @@ -217,6 +216,9 @@ def analyze_var(name: str, var: Var, itype: Instance, info: TypeInfo, node: Cont
if isinstance(typ, PartialType):
return handle_partial_attribute_type(typ, is_lvalue, msg, var)
t = expand_type_by_instance(typ, itype)
if is_lvalue and var.is_property and not var.is_settable_property:
# TODO allow setting attributes in subclass (although it is probably an error)
msg.read_only_property(name, info, node)
if var.is_initialized_in_class and isinstance(t, FunctionLike):
if is_lvalue:
if var.is_property:
Expand Down
2 changes: 1 addition & 1 deletion mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def visit_overloaded(self, t: Overloaded) -> Type:
return Overloaded(items)

def visit_tuple_type(self, t: TupleType) -> Type:
return TupleType(self.expand_types(t.items), t.fallback, t.line)
return t.copy_modified(items=self.expand_types(t.items))

def visit_union_type(self, t: UnionType) -> Type:
# After substituting for type variables in t.items,
Expand Down
2 changes: 1 addition & 1 deletion mypy/join.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Calculation of the least upper bound types (joins)."""

from typing import cast, List
from typing import List

from mypy.types import (
Type, AnyType, NoneTyp, Void, TypeVisitor, Instance, UnboundType,
Expand Down
11 changes: 11 additions & 0 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ class ClassDef(Statement):
decorators = None # type: List[Expression]
# Built-in/extension class? (single implementation inheritance only)
is_builtinclass = False
has_incompatible_baseclass = False

def __init__(self,
name: str,
Expand Down Expand Up @@ -1191,6 +1192,7 @@ def __init__(self, callee: Expression, args: List[Expression], arg_kinds: List[i
arg_names: List[str] = None, analyzed: Expression = None) -> None:
if not arg_names:
arg_names = [None] * len(args)

self.callee = callee
self.args = args
self.arg_kinds = arg_kinds
Expand Down Expand Up @@ -2025,6 +2027,15 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo':
return ti


def namedtuple_type_info(tup: 'mypy.types.TupleType', *args) -> TypeInfo:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*args won't be type checked. It would be nice if the arguments would be spelled out -- alternatively, add an explicit Any annotation.

info = TypeInfo(*args)
info.tuple_type = tup
info.bases = [tup.fallback]
info.is_named_tuple = True
info.mro = [info] + tup.fallback.type.mro
return info


class SymbolTableNode:
# Kind of node. Possible values:
# - LDEF: local definition (of any kind)
Expand Down
133 changes: 83 additions & 50 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@
traverse the entire AST.
"""

from functools import partial

import sys
from typing import (
List, Dict, Set, Tuple, cast, Any, overload, TypeVar, Union, Optional, Callable
List, Dict, Set, Tuple, cast, Any, TypeVar, Union, Optional, Callable
)

from mypy.nodes import (
Expand All @@ -60,29 +62,27 @@
SymbolTableNode, BOUND_TVAR, UNBOUND_TVAR, ListComprehension, GeneratorExpr,
FuncExpr, MDEF, FuncBase, Decorator, SetExpr, TypeVarExpr, NewTypeExpr,
StrExpr, BytesExpr, PrintStmt, ConditionalExpr, PromoteExpr,
ComparisonExpr, StarExpr, ARG_POS, ARG_NAMED, MroError, type_aliases,
ComparisonExpr, StarExpr, ARG_POS, ARG_NAMED, ARG_OPT, MroError, type_aliases,
YieldFromExpr, NamedTupleExpr, NonlocalDecl,
SetComprehension, DictionaryComprehension, TYPE_ALIAS, TypeAliasExpr,
YieldExpr, ExecStmt, Argument, BackquoteExpr, ImportBase, AwaitExpr,
IntExpr, FloatExpr, UnicodeExpr,
Expression, EllipsisExpr, namedtuple_type_info,
COVARIANT, CONTRAVARIANT, INVARIANT, UNBOUND_IMPORTED, LITERAL_YES,
)
from mypy.visitor import NodeVisitor
from mypy.traverser import TraverserVisitor
from mypy.errors import Errors, report_internal_error
from mypy.types import (
NoneTyp, CallableType, Overloaded, Instance, Type, TypeVarType, AnyType,
FunctionLike, UnboundType, TypeList, ErrorType, TypeVarDef, Void,
FunctionLike, UnboundType, TypeList, TypeVarDef, Void,
replace_leading_arg_type, TupleType, UnionType, StarType, EllipsisType
)
from mypy.nodes import function_type, implicit_module_attrs
from mypy.typeanal import TypeAnalyser, TypeAnalyserPass3, analyze_type_alias
from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError
from mypy.lex import lex
from mypy.parsetype import parse_type
from mypy.sametypes import is_same_type
from mypy.erasetype import erase_typevars
from mypy import defaults
from mypy.options import Options


Expand Down Expand Up @@ -751,38 +751,40 @@ def analyze_base_classes(self, defn: ClassDef) -> None:
"""

base_types = [] # type: List[Instance]
info = defn.info
for base_expr in defn.base_type_exprs:
try:
base = self.expr_to_analyzed_type(base_expr)
except TypeTranslationError:
self.fail('Invalid base class', base_expr)
defn.info.fallback_to_any = True
info.fallback_to_any = True
continue

if isinstance(base, TupleType):
if defn.info.tuple_type:
if info.tuple_type:
self.fail("Class has two incompatible bases derived from tuple", defn)
defn.has_incompatible_baseclass = True
if (not self.is_stub_file
and not defn.info.is_named_tuple
and not info.is_named_tuple
and base.fallback.type.fullname() == 'builtins.tuple'):
self.fail("Tuple[...] not supported as a base class outside a stub file", defn)
defn.info.tuple_type = base
info.tuple_type = base
base_types.append(base.fallback)
elif isinstance(base, Instance):
if base.type.is_newtype:
self.fail("Cannot subclass NewType", defn)
base_types.append(base)
elif isinstance(base, AnyType):
defn.info.fallback_to_any = True
info.fallback_to_any = True
else:
self.fail('Invalid base class', base_expr)
defn.info.fallback_to_any = True
info.fallback_to_any = True

# Add 'object' as implicit base if there is no other base class.
if (not base_types and defn.fullname != 'builtins.object'):
base_types.append(self.object_type())

defn.info.bases = base_types
info.bases = base_types

# Calculate the MRO. It might be incomplete at this point if
# the bases of defn include classes imported from other
Expand All @@ -794,8 +796,8 @@ def analyze_base_classes(self, defn: ClassDef) -> None:
calculate_class_mro(defn, self.fail_blocker)
# If there are cyclic imports, we may be missing 'object' in
# the MRO. Fix MRO if needed.
if defn.info.mro and defn.info.mro[-1].fullname() != 'builtins.object':
defn.info.mro.append(self.object_type().type)
if info.mro and info.mro[-1].fullname() != 'builtins.object':
info.mro.append(self.object_type().type)

def expr_to_analyzed_type(self, expr: Node) -> Type:
if isinstance(expr, CallExpr):
Expand Down Expand Up @@ -1627,6 +1629,7 @@ def parse_namedtuple_args(self, call: CallExpr,
if len(args) < 2:
return self.fail_namedtuple_arg("Too few arguments for namedtuple()", call)
if len(args) > 2:
# FIX incorrect. There are two additional parameters
return self.fail_namedtuple_arg("Too many arguments for namedtuple()", call)
if call.arg_kinds != [ARG_POS, ARG_POS]:
return self.fail_namedtuple_arg("Unexpected arguments to namedtuple()", call)
Expand Down Expand Up @@ -1690,46 +1693,77 @@ def fail_namedtuple_arg(self, message: str,
def build_namedtuple_typeinfo(self, name: str, items: List[str],
types: List[Type]) -> TypeInfo:
symbols = SymbolTable()
tup = TupleType(types, self.named_type('__builtins__.tuple', types))
class_def = ClassDef(name, Block([]))
class_def.fullname = self.qualified_name(name)
info = TypeInfo(symbols, class_def)
# Add named tuple items as attributes.
# TODO: Make them read-only.
for item, typ in zip(items, types):
var = Var(item)
var.info = info
var.type = typ
symbols[item] = SymbolTableNode(MDEF, var)
# Add a __init__ method.
init = self.make_namedtuple_init(info, items, types)
symbols['__init__'] = SymbolTableNode(MDEF, init)
info.tuple_type = TupleType(types, self.named_type('__builtins__.tuple', [AnyType()]))
info.is_named_tuple = True
info.mro = [info] + info.tuple_type.fallback.type.mro
info.bases = [info.tuple_type.fallback]
return info

def make_argument(self, name: str, type: Type) -> Argument:
return Argument(Var(name), type, None, ARG_POS)
info = namedtuple_type_info(tup, symbols, class_def)

vars = [Var(item, typ) for item, typ in zip(items, types)]
this_type = self_type(info)
add_field = partial(self.add_namedtuple_field, symbols, info)
strtype = self.named_type('__builtins__.str')

for var in vars:
add_field(var, is_property=True)

tuple_of_strings = TupleType([strtype for _ in items],
self.named_type('__builtins__.tuple', [AnyType()]))
add_field(Var('_fields', tuple_of_strings),
is_initialized_in_class=True)
add_field(Var('_field_types', UnboundType('Dict', [strtype, AnyType()])),
is_initialized_in_class=True)
add_field(Var('_source', strtype),
is_initialized_in_class=True)

add_method = partial(self.add_namedtuple_method, symbols, info, this_type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calls to partial can't be fully type checked. Maybe consider using a nested function instead? It will only add a few lines of code.

add_method('_replace', ret=this_type,
args=self.factory_args(vars, ARG_NAMED, initializer=EllipsisExpr()))
add_method('__init__', ret=NoneTyp(),
args=self.factory_args(vars, ARG_POS), name=info.name())
# TODO: refine to OrderedDict[str, Union[types]]
add_method('_asdict', ret=UnboundType('collections.OrderedDict', is_ret_type=True),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm UnboundType is not what we want here? I'd rather use just Dict[str, Any] (i.e., as Instance type). The union of types is not desirable since dictionaries are invariant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.named_type finds __builting__.dict only if I add a fixture declaration to every test. It's a bit awkward.

args=[])

# TODO: refine signature
union = UnboundType('Iterable', [UnionType(types)])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The union could be problematic, as union types are not generally produced by type inference. For example, the type of x is List[object], for better or worse:

x = [1, 'xx']

I'd suggest using Iterable[Any] instead and adding a note about this. Again, I'm not sure if UnboundType works here -- I wonder it gets semantically analyzed, and what if Iterable is not in scope. You may have to use self.named_type or something.

add_method('_make', ret=this_type, is_classmethod=True,
args=[Argument(Var('iterable', union), union, None, ARG_POS),
Argument(Var('new'), AnyType(), EllipsisExpr(), ARG_NAMED),
Argument(Var('len'), AnyType(), EllipsisExpr(), ARG_NAMED)])
return info

def make_namedtuple_init(self, info: TypeInfo, items: List[str],
types: List[Type]) -> FuncDef:
args = [self.make_argument(item, type) for item, type in zip(items, types)]
# TODO: Make sure that the self argument name is not visible?
args = [Argument(Var('__self'), NoneTyp(), None, ARG_POS)] + args
def add_namedtuple_field(self, symbols: SymbolTable, info: TypeInfo, var: Var,
is_initialized_in_class: bool = False,
is_property: bool = False) -> None:
var.info = info
var.is_initialized_in_class = is_initialized_in_class
var.is_property = is_property
symbols[var.name()] = SymbolTableNode(MDEF, var)

def factory_args(self, vars: List[Var], kind: int,
initializer: Expression = None) -> List[Argument]:
return [Argument(var, var.type, initializer, kind) for var in vars]

def add_namedtuple_method(self, symbols: SymbolTable, info: TypeInfo, this_type: Type,
funcname: str, ret: Type, args: List[Argument], name=None,
is_classmethod=False) -> None:
if not is_classmethod:
args = [Argument(Var('self'), this_type, None, ARG_POS)] + args
types = [arg.type_annotation for arg in args]
items = [arg.variable.name() for arg in args]
arg_kinds = [arg.kind for arg in args]
signature = CallableType([cast(Type, None)] + types,
arg_kinds,
['__self'] + items,
NoneTyp(),
signature = CallableType(types, arg_kinds, items, ret,
self.named_type('__builtins__.function'),
name=info.name())
func = FuncDef('__init__',
args,
Block([]),
typ=signature)
name=name or info.name() + '.' + funcname)
signature.is_classmethod_class = is_classmethod
func = FuncDef(funcname, args, Block([]), typ=signature)
func.info = info
return func
func.is_class = is_classmethod
symbols[funcname] = SymbolTableNode(MDEF, func)

def make_argument(self, name: str, type: Type) -> Argument:
return Argument(Var(name), type, None, ARG_POS)

def analyze_types(self, items: List[Node]) -> List[Type]:
result = [] # type: List[Type]
Expand Down Expand Up @@ -2832,8 +2866,7 @@ def self_type(typ: TypeInfo) -> Union[Instance, TupleType]:
inst = Instance(typ, tv)
if typ.tuple_type is None:
return inst
else:
return TupleType(typ.tuple_type.items, inst)
return typ.tuple_type.copy_modified(fallback=inst)


def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike:
Expand Down
8 changes: 4 additions & 4 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from mypy.types import (
Type, AnyType, UnboundType, TypeVisitor, ErrorType, Void, NoneTyp,
Instance, TypeVarType, CallableType, TupleType, UnionType, Overloaded, ErasedType, TypeList,
PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance
Instance, TypeVarType, CallableType, TupleType, UnionType, Overloaded,
ErasedType, TypeList, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance
)
import mypy.applytype
import mypy.constraints
Expand Down Expand Up @@ -181,8 +181,8 @@ def visit_tuple_type(self, left: TupleType) -> bool:
elif isinstance(right, TupleType):
if len(left.items) != len(right.items):
return False
for i in range(len(left.items)):
if not is_subtype(left.items[i], right.items[i], self.check_type_parameter):
for l, r in zip(left.items, right.items):
if not is_subtype(l, r, self.check_type_parameter):
return False
if not is_subtype(left.fallback, right.fallback, self.check_type_parameter):
return False
Expand Down
18 changes: 9 additions & 9 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"""Semantic analysis of types"""

from typing import Callable, cast, List, Tuple
from typing import Callable, cast, List

from mypy.types import (
Type, UnboundType, TypeVarType, TupleType, UnionType, Instance, AnyType, CallableType,
Void, NoneTyp, DeletedType, TypeList, TypeVarDef, TypeVisitor, StarType, PartialType,
EllipsisType, UninhabitedType, TypeType
Type, UnboundType, TypeVarType, TupleType, UnionType, Instance,
AnyType, CallableType, Void, NoneTyp, DeletedType, TypeList, TypeVarDef, TypeVisitor,
StarType, PartialType, EllipsisType, UninhabitedType, TypeType
)
from mypy.nodes import (
BOUND_TVAR, TYPE_ALIAS, UNBOUND_IMPORTED,
TypeInfo, Context, SymbolTableNode, TypeVarExpr, Var, Node,
TypeInfo, Context, SymbolTableNode, Var, Node,
IndexExpr, RefExpr
)
from mypy.sametypes import is_same_type
Expand Down Expand Up @@ -164,17 +164,17 @@ def visit_unbound_type(self, t: UnboundType) -> Type:
# valid count at this point. Thus we may construct an
# Instance with an invalid number of type arguments.
instance = Instance(info, self.anal_array(t.args), t.line)
if info.tuple_type is None:
tup = info.tuple_type
if tup is None:
return instance
else:
# The class has a Tuple[...] base class so it will be
# represented as a tuple type.
if t.args:
self.fail('Generic tuple types not supported', t)
return AnyType()
return TupleType(self.anal_array(info.tuple_type.items),
fallback=instance,
line=t.line)
return tup.copy_modified(items=self.anal_array(tup.items),
fallback=instance)
else:
return AnyType()

Expand Down
Loading