def visit_Attribute(self, n: ast3.Attribute) -> Type: before_dot = self.visit(n.value) if isinstance(before_dot, UnboundType) and not before_dot.args: return UnboundType("{}.{}".format(before_dot.name, n.attr), line=self.line) else: self.fail(TYPE_COMMENT_AST_ERROR, self.line, getattr(n, 'col_offset', -1)) return AnyType()
def test_error_type(self): self.assert_join(self.fx.err, self.fx.anyt, self.fx.anyt) # Meet against any type except dynamic results in ErrorType. for t in [self.fx.a, self.fx.o, NoneTyp(), UnboundType('x'), self.fx.void, self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_join(t, self.fx.err, self.fx.err)
def expr_to_unanalyzed_type(expr: Expression) -> Type: """Translate an expression to the corresponding type. The result is not semantically analyzed. It can be UnboundType or TypeList. Raise TypeTranslationError if the expression cannot represent a type. """ if isinstance(expr, NameExpr): name = expr.name return UnboundType(name, line=expr.line, column=expr.column) elif isinstance(expr, MemberExpr): fullname = get_member_expr_fullname(expr) if fullname: return UnboundType(fullname, line=expr.line, column=expr.column) else: raise TypeTranslationError() elif isinstance(expr, IndexExpr): base = expr_to_unanalyzed_type(expr.base) if isinstance(base, UnboundType): if base.args: raise TypeTranslationError() if isinstance(expr.index, TupleExpr): args = expr.index.items else: args = [expr.index] base.args = [expr_to_unanalyzed_type(arg) for arg in args] if not base.args: base.empty_tuple_index = True return base else: raise TypeTranslationError() elif isinstance(expr, ListExpr): return TypeList([expr_to_unanalyzed_type(t) for t in expr.items], line=expr.line, column=expr.column) elif isinstance(expr, (StrExpr, BytesExpr, UnicodeExpr)): # Parse string literal type. try: result = parse_type_comment(expr.value, expr.line, None) except SyntaxError: raise TypeTranslationError() return result elif isinstance(expr, EllipsisExpr): return EllipsisType(expr.line) else: raise TypeTranslationError()
def test_none(self) -> None: self.assert_meet(NoneType(), NoneType(), NoneType()) self.assert_meet(NoneType(), self.fx.anyt, NoneType()) # Any type t joined with None results in None, unless t is Any. for t in [self.fx.a, self.fx.o, UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_meet(t, NoneType(), NoneType())
def test_none(self) -> None: # Any type t joined with None results in t. for t in [ NoneType(), self.fx.a, self.fx.o, UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b), self.fx.anyt ]: self.assert_join(t, NoneType(), t)
def test_any_type(self) -> None: # Join against 'Any' type always results in 'Any'. for t in [ self.fx.anyt, self.fx.a, self.fx.o, NoneType(), UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b) ]: self.assert_join(t, self.fx.anyt, self.fx.anyt)
def test_dynamic_type(self) -> None: # Meet against dynamic type always results in dynamic. for t in [ self.fx.anyt, self.fx.a, self.fx.o, NoneType(), UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b) ]: self.assert_meet(t, self.fx.anyt, t)
def test_void(self): self.assert_meet(self.fx.void, self.fx.void, self.fx.void) self.assert_meet(self.fx.void, self.fx.anyt, self.fx.void) # Meet of any other type against void results in ErrorType, since there # is no meaningful valid result. for t in [self.fx.a, self.fx.o, UnboundType('x'), NoneTyp(), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_meet(t, self.fx.void, self.fx.err)
def test_void(self): self.assert_join(self.fx.void, self.fx.void, self.fx.void) self.assert_join(self.fx.void, self.fx.anyt, self.fx.anyt) # Join of any other type against void results in ErrorType, since there # is no other meaningful result. for t in [self.fx.a, self.fx.o, NoneTyp(), UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_join(t, self.fx.void, self.fx.err)
def anal_type(self, tp: UnboundType) -> Type: tpan = TypeAnalyser(self.api, None, self.plugin, self.options, self.is_typeshed_stub, third_pass=True) res = tp.accept(tpan) self.aliases_used = tpan.aliases_used return res
def anal_type(self, tp: UnboundType) -> Type: tpan = TypeAnalyser(self.lookup_func, self.lookup_fqn_func, None, self.fail, self.note_func, self.plugin, self.options, self.is_typeshed_stub, third_pass=True) return tp.accept(tpan)
def test_unbound_type(self): self.assert_meet(UnboundType('x'), UnboundType('x'), self.fx.anyt) self.assert_meet(UnboundType('x'), UnboundType('y'), self.fx.anyt) self.assert_meet(UnboundType('x'), self.fx.void, self.fx.err) self.assert_meet(UnboundType('x'), self.fx.anyt, UnboundType('x')) # The meet of any type t with an unbound type results in dynamic # (except for void). Unbound type means that there is an error # somewhere in the program, so this does not affect type safety. for t in [self.fx.a, self.fx.o, self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_meet(t, UnboundType('X'), self.fx.anyt)
def test_none(self): self.assert_meet(NoneTyp(), NoneTyp(), NoneTyp()) self.assert_meet(NoneTyp(), self.fx.anyt, self.fx.anyt) self.assert_meet(NoneTyp(), self.fx.void, self.fx.err) # Any type t joined with None results in None, unless t is any or # void. for t in [self.fx.a, self.fx.o, UnboundType('x'), self.fx.t, self.tuple(), self.callable(self.fx.a, self.fx.b)]: self.assert_meet(t, NoneTyp(), NoneTyp())
def generic_class_wrapper(self, tdef: ClassDef) -> ClassDef: """Construct a wrapper class for a generic type.""" # FIX semanal meta-info for nodes + TypeInfo defs = [] # type: List[Node] # Does the type have a superclass, other than builtins.object? base = tdef.info.mro[1] has_proper_superclass = base.fullname() != 'builtins.object' if not has_proper_superclass or self.tf.is_java: # Generate member variables for wrapper object. defs.extend(self.make_generic_wrapper_member_vars(tdef)) for alt in [False, BOUND_VAR]: defs.extend(self.make_tvar_representation(tdef.info, alt)) # Generate constructor. defs.append(self.make_generic_wrapper_init(tdef.info)) # Generate method wrappers. for d in tdef.defs.body: if isinstance(d, FuncDef): if not d.is_constructor(): defs.extend(self.func_tf.generic_method_wrappers(d)) elif isinstance(d, AssignmentStmt): defs.extend(self.generic_accessor_wrappers(d)) elif not isinstance(d, PassStmt): raise RuntimeError( 'Definition {} at line {} not supported'.format( type(d), d.line)) base_type = self.tf.named_type('builtins.object') # type: Type # Inherit superclass wrapper if there is one. if has_proper_superclass: base = self.find_generic_base_class(tdef.info) if base: # TODO bind the type somewhere base_type = UnboundType(base.defn.name + self.tf.wrapper_class_suffix()) # Build the type definition. wrapper = ClassDef(tdef.name + self.tf.wrapper_class_suffix(), Block(defs), None, [base_type]) # FIX fullname self.tf.add_line_mapping(tdef, wrapper) return wrapper
def visit_Subscript(self, n: ast35.Subscript) -> Type: assert isinstance(n.slice, ast35.Index) value = self.visit(n.value) assert isinstance(value, UnboundType) assert not value.args if isinstance(n.slice.value, ast35.Tuple): params = self.visit_list(n.slice.value.elts) else: params = [self.visit(n.slice.value)] return UnboundType(value.name, params, line=self.line)
def visit_Subscript(self, n: ast35.Subscript) -> Type: assert isinstance(n.slice, ast35.Index) value = self.visit(n.value) assert isinstance(value, UnboundType) assert not value.args empty_tuple_index = False if isinstance(n.slice.value, ast35.Tuple): params = self.translate_expr_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, empty_tuple_index=empty_tuple_index)
def visit_Subscript(self, n: ast3.Subscript) -> Type: if not isinstance(n.slice, ast3.Index): self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) return AnyType(TypeOfAny.from_error) empty_tuple_index = False if isinstance(n.slice.value, ast3.Tuple): params = self.translate_expr_list(n.slice.value.elts) if len(n.slice.value.elts) == 0: empty_tuple_index = True else: params = [self.visit(n.slice.value)] value = self.visit(n.value) if isinstance(value, UnboundType) and not value.args: return UnboundType(value.name, params, line=self.line, empty_tuple_index=empty_tuple_index) else: self.fail(TYPE_COMMENT_AST_ERROR, self.line, getattr(n, 'col_offset', -1)) return AnyType(TypeOfAny.from_error)
def visit_Subscript(self, n: ast35.Subscript) -> Type: if not isinstance(n.slice, ast35.Index): raise TypeCommentParseError(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) value = self.visit(n.value) assert isinstance(value, UnboundType) assert not value.args empty_tuple_index = False if isinstance(n.slice.value, ast35.Tuple): params = self.translate_expr_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, empty_tuple_index=empty_tuple_index)
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return make_optional_type(self.visit_unbound_type(t)) sym = self.lookup(t.name, t, suppress_errors=self.third_pass) # type: ignore if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail(errorcode.INTERNAL_ERROR_NODE_IS_NONE(sym.kind), t) return AnyType(TypeOfAny.special_form) fullname = sym.node.fullname() hook = self.plugin.get_type_analyze_hook(fullname) if hook: return hook(AnalyzeTypeContext(t, t, self)) if (fullname in nongen_builtins and t.args and not sym.normalized and not self.allow_unnormalized): self.fail(errorcode.NO_SUBSCRIPT_BUILTIN_ALIAS(fullname), t) if self.tvar_scope: tvar_def = self.tvar_scope.get_binding(sym) else: tvar_def = None if self.warn_bound_tvar and sym.kind == TVAR and tvar_def is not None: self.fail( errorcode. CANNOT_USE_BOUND_TYPE_VAR_TO_DEFINE_GENERIC_ALIAS(t.name), t) return AnyType(TypeOfAny.from_error) elif sym.kind == TVAR and tvar_def is not None: if len(t.args) > 0: self.fail(errorcode.TYPE_VAR_USED_WITH_ARG(t.name), t) return TypeVarType(tvar_def, t.line) elif fullname == 'builtins.None': return NoneTyp() elif fullname == 'typing.Any' or fullname == 'builtins.Any': return AnyType(TypeOfAny.explicit) elif fullname == 'typing.Tuple': if len(t.args) == 0 and not t.empty_tuple_index: # Bare 'Tuple' is same as 'tuple' if self.options.disallow_any_generics and not self.is_typeshed_stub: self.fail(errorcode.BARE_GENERIC(), t) typ = self.named_type('builtins.tuple', line=t.line, column=t.column) typ.from_generic_builtin = True return typ if len(t.args) == 2 and isinstance(t.args[1], EllipsisType): # Tuple[T, ...] (uniform, variable-length tuple) instance = self.named_type('builtins.tuple', [self.anal_type(t.args[0])]) instance.line = t.line return instance return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail(errorcode.OPTIONAL_MUST_HAVE_ONE_ARGUMENT(), t) return AnyType(TypeOfAny.from_error) item = self.anal_type(t.args[0]) return make_optional_type(item) elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: any_type = AnyType(TypeOfAny.from_omitted_generics, line=t.line, column=t.column) return TypeType(any_type, line=t.line, column=t.column) if len(t.args) != 1: self.fail(errorcode.TYPE_MUST_HAVE_EXACTLY_ONE_TYPE(), t) item = self.anal_type(t.args[0]) return TypeType.make_normalized(item, line=t.line) elif fullname == 'typing.ClassVar': if self.nesting_level > 0: self.fail( errorcode.INVALID_TYPE_CLASSVAR_NESTED_INSIDE_TYPE(), t) if len(t.args) == 0: return AnyType(TypeOfAny.from_omitted_generics, line=t.line, column=t.column) if len(t.args) != 1: self.fail( errorcode.CLASS_VAR_MUST_HAVE_AT_MOST_ONE_TYPE_ARG(), t) return AnyType(TypeOfAny.from_error) item = self.anal_type(t.args[0]) if isinstance(item, TypeVarType) or get_type_vars(item): self.fail(errorcode.CLASSVAR_CANNOT_BE_GENERIC(), t) return AnyType(TypeOfAny.from_error) return item elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'): return UninhabitedType(is_noreturn=True) elif sym.kind == TYPE_ALIAS: override = sym.type_override all_vars = sym.alias_tvars assert override is not None an_args = self.anal_array(t.args) if all_vars is not None: exp_len = len(all_vars) else: exp_len = 0 act_len = len(an_args) if exp_len > 0 and act_len == 0: # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...] assert all_vars is not None return set_any_tvars(override, all_vars, t.line, t.column) if exp_len == 0 and act_len == 0: return override if act_len != exp_len: self.fail( errorcode.BAD_NUMBER_ARGUMENT_FOR_TYPEALIAS( exp_len, act_len), t) return set_any_tvars(override, all_vars or [], t.line, t.column, implicit=False) assert all_vars is not None return replace_alias_tvars(override, all_vars, an_args, t.line, t.column) elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance( sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType(TypeOfAny.from_unimported_type) # Allow unbound type variables when defining an alias if not (self.aliasing and sym.kind == TVAR and (not self.tvar_scope or self.tvar_scope.get_binding(sym) is None)): if (not self.third_pass and not self.in_dynamic_func and not (isinstance(sym.node, (FuncDef, Decorator)) or isinstance(sym.node, Var) and sym.node.is_ready) and not (sym.kind == TVAR and tvar_def is None)): if t.args and not self.global_scope: self.fail( errorcode.UNSUPPORTED_FORWARD_REFERENCE( t.name), t) return AnyType(TypeOfAny.from_error) return ForwardRef(t) self.fail(errorcode.INVALID_TYPE_X(name), t) if self.third_pass and sym.kind == TVAR: self.note_func( errorcode.FORWARD_REERENCES_TO_TYPE_VAR_PROHIBITED( ), t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': fallback = Instance(info, [AnyType(TypeOfAny.special_form)], t.line) return TupleType(self.anal_array(t.args), fallback, t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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, t.column) instance.from_generic_builtin = sym.normalized tup = info.tuple_type if tup is not None: # The class has a Tuple[...] base class so it will be # represented as a tuple type. if t.args: self.fail( errorcode.GENERIC_TUPLE_TYPES_NOT_SUPPORTED(), t) return AnyType(TypeOfAny.from_error) return tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) td = info.typeddict_type if td is not None: # The class has a TypedDict[...] base class so it will be # represented as a typeddict type. if t.args: self.fail( errorcode.GENERIC_TYPEDDICT_TYPES_NOT_SUPPORTED(), t) return AnyType(TypeOfAny.from_error) # Create a named TypedDictType return td.copy_modified(item_types=self.anal_array( list(td.items.values())), fallback=instance) return instance else: if self.third_pass: self.fail(errorcode.INVALID_TYPE_X(t.name), t) return AnyType(TypeOfAny.from_error) return AnyType(TypeOfAny.special_form)
def test_generic_unbound_type(self): u = UnboundType('Foo', [UnboundType('T'), AnyType()]) assert_equal(str(u), 'Foo?[T?, Any]')
def visit_NameConstant(self, n: ast35.NameConstant) -> Type: return UnboundType(str(n.value))
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return UnionType.make_simplified_union([self.visit_unbound_type(t), NoneTyp()]) sym = self.lookup(t.name, t) if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail('Internal error (node is None, kind={})'.format(sym.kind), t) return AnyType() fullname = sym.node.fullname() if sym.kind == BOUND_TVAR: if len(t.args) > 0: self.fail('Type variable "{}" used with arguments'.format( t.name), t) assert sym.tvar_def is not None return TypeVarType(sym.tvar_def, t.line) elif fullname == 'builtins.None': if experiments.STRICT_OPTIONAL: return NoneTyp(is_ret_type=t.is_ret_type) else: return Void() elif fullname == 'typing.Any': return AnyType() elif fullname == 'typing.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') tuple_info = cast(TypeInfo, node.node) return Instance(tuple_info, [t.args[0].accept(self)], t.line) return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) items = [item for item in items if not isinstance(item, Void)] return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail('Optional[...] must have exactly one type argument', t) return AnyType() items = self.anal_array(t.args) if experiments.STRICT_OPTIONAL: return UnionType.make_simplified_union([items[0], NoneTyp()]) else: # Without strict Optional checking Optional[t] is just an alias for t. return items[0] elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: return TypeType(AnyType(), line=t.line) if len(t.args) != 1: self.fail('Type[...] must have exactly one type argument', t) items = self.anal_array(t.args) item = items[0] return TypeType(item, line=t.line) elif sym.kind == TYPE_ALIAS: # TODO: Generic type aliases. return sym.type_override elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType() self.fail('Invalid type "{}"'.format(name), t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': return TupleType(self.anal_array(t.args), Instance(info, [AnyType()], t.line), t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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) 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 tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) else: return AnyType()
def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = None) -> ProperType: """Translate an expression to the corresponding type. The result is not semantically analyzed. It can be UnboundType or TypeList. Raise TypeTranslationError if the expression cannot represent a type. """ # The `parent` parameter is used in recursive calls to provide context for # understanding whether an CallableArgument is ok. name = None # type: Optional[str] if isinstance(expr, NameExpr): name = expr.name if name == 'True': return RawExpressionType(True, 'builtins.bool', line=expr.line, column=expr.column) elif name == 'False': return RawExpressionType(False, 'builtins.bool', line=expr.line, column=expr.column) else: return UnboundType(name, line=expr.line, column=expr.column) elif isinstance(expr, MemberExpr): fullname = get_member_expr_fullname(expr) if fullname: return UnboundType(fullname, line=expr.line, column=expr.column) else: raise TypeTranslationError() elif isinstance(expr, IndexExpr): base = expr_to_unanalyzed_type(expr.base, expr) if isinstance(base, UnboundType): if base.args: raise TypeTranslationError() if isinstance(expr.index, TupleExpr): args = expr.index.items else: args = [expr.index] base.args = tuple(expr_to_unanalyzed_type(arg, expr) for arg in args) if not base.args: base.empty_tuple_index = True return base else: raise TypeTranslationError() elif isinstance(expr, CallExpr) and isinstance(_parent, ListExpr): c = expr.callee names = [] # Go through the dotted member expr chain to get the full arg # constructor name to look up while True: if isinstance(c, NameExpr): names.append(c.name) break elif isinstance(c, MemberExpr): names.append(c.name) c = c.expr else: raise TypeTranslationError() arg_const = '.'.join(reversed(names)) # Go through the constructor args to get its name and type. name = None default_type = AnyType(TypeOfAny.unannotated) typ = default_type # type: Type for i, arg in enumerate(expr.args): if expr.arg_names[i] is not None: if expr.arg_names[i] == "name": if name is not None: # Two names raise TypeTranslationError() name = _extract_argument_name(arg) continue elif expr.arg_names[i] == "type": if typ is not default_type: # Two types raise TypeTranslationError() typ = expr_to_unanalyzed_type(arg, expr) continue else: raise TypeTranslationError() elif i == 0: typ = expr_to_unanalyzed_type(arg, expr) elif i == 1: name = _extract_argument_name(arg) else: raise TypeTranslationError() return CallableArgument(typ, name, arg_const, expr.line, expr.column) elif isinstance(expr, ListExpr): return TypeList([expr_to_unanalyzed_type(t, expr) for t in expr.items], line=expr.line, column=expr.column) elif isinstance(expr, StrExpr): return parse_type_string(expr.value, 'builtins.str', expr.line, expr.column, assume_str_is_unicode=expr.from_python_3) elif isinstance(expr, BytesExpr): return parse_type_string(expr.value, 'builtins.bytes', expr.line, expr.column, assume_str_is_unicode=False) elif isinstance(expr, UnicodeExpr): return parse_type_string(expr.value, 'builtins.unicode', expr.line, expr.column, assume_str_is_unicode=True) elif isinstance(expr, UnaryExpr): typ = expr_to_unanalyzed_type(expr.expr) if isinstance(typ, RawExpressionType): if isinstance(typ.literal_value, int) and expr.op == '-': typ.literal_value *= -1 return typ raise TypeTranslationError() elif isinstance(expr, IntExpr): return RawExpressionType(expr.value, 'builtins.int', line=expr.line, column=expr.column) elif isinstance(expr, FloatExpr): # Floats are not valid parameters for RawExpressionType , so we just # pass in 'None' for now. We'll report the appropriate error at a later stage. return RawExpressionType(None, 'builtins.float', line=expr.line, column=expr.column) elif isinstance(expr, ComplexExpr): # Same thing as above with complex numbers. return RawExpressionType(None, 'builtins.complex', line=expr.line, column=expr.column) elif isinstance(expr, EllipsisExpr): return EllipsisType(expr.line) else: raise TypeTranslationError()
def visit_Name(self, n: ast35.Name) -> Type: return UnboundType(n.id, line=self.line)
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return UnionType.make_simplified_union([self.visit_unbound_type(t), NoneTyp()]) sym = self.lookup(t.name, t) if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail('Internal error (node is None, kind={})'.format(sym.kind), t) return AnyType() fullname = sym.node.fullname() if sym.kind == BOUND_TVAR: if len(t.args) > 0: self.fail('Type variable "{}" used with arguments'.format( t.name), t) assert sym.tvar_def is not None return TypeVarType(sym.tvar_def, t.line) elif fullname == 'builtins.None': if experiments.STRICT_OPTIONAL: return NoneTyp(is_ret_type=t.is_ret_type) else: return Void() 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) instance = self.builtin_type('builtins.tuple', [t.args[0].accept(self)]) instance.line = t.line return instance return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) items = [item for item in items if not isinstance(item, Void)] return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail('Optional[...] must have exactly one type argument', t) return AnyType() items = self.anal_array(t.args) if experiments.STRICT_OPTIONAL: return UnionType.make_simplified_union([items[0], NoneTyp()]) else: # Without strict Optional checking Optional[t] is just an alias for t. return items[0] elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: return TypeType(AnyType(), line=t.line) if len(t.args) != 1: self.fail('Type[...] must have exactly one type argument', t) items = self.anal_array(t.args) item = items[0] return TypeType(item, line=t.line) elif sym.kind == TYPE_ALIAS: override = sym.type_override an_args = self.anal_array(t.args) all_vars = self.get_type_var_names(override) exp_len = len(all_vars) act_len = len(an_args) if exp_len > 0 and act_len == 0: # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...] return self.replace_alias_tvars(override, all_vars, [AnyType()] * exp_len, t.line, t.column) if exp_len == 0 and act_len == 0: return override if act_len != exp_len: self.fail('Bad number of arguments for type alias, expected: %s, given: %s' % (exp_len, act_len), t) return t return self.replace_alias_tvars(override, all_vars, an_args, t.line, t.column) elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType() # Allow unbound type variables when defining an alias if not (self.aliasing and sym.kind == UNBOUND_TVAR): self.fail('Invalid type "{}"'.format(name), t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': return TupleType(self.anal_array(t.args), Instance(info, [AnyType()], t.line), t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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, t.column) tup = info.tuple_type if tup is not None: # 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 tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) td = info.typeddict_type if td is not None: # The class has a TypedDict[...] base class so it will be # represented as a typeddict type. if t.args: self.fail('Generic TypedDict types not supported', t) return AnyType() # Create a named TypedDictType return td.copy_modified(item_types=self.anal_array(list(td.items.values())), fallback=instance) return instance else: return AnyType()
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return make_optional_type(self.visit_unbound_type(t)) sym = self.lookup(t.name, t) if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail( 'Internal error (node is None, kind={})'.format( sym.kind), t) return AnyType() fullname = sym.node.fullname() hook = self.plugin.get_type_analyze_hook(fullname) if hook: return hook(AnalyzeTypeContext(t, t, self)) if (fullname in nongen_builtins and t.args and not sym.normalized and not self.allow_unnormalized): self.fail(no_subscript_builtin_alias(fullname), t) tvar_def = self.tvar_scope.get_binding(sym) if sym.kind == TVAR and tvar_def is not None: if len(t.args) > 0: self.fail( 'Type variable "{}" used with arguments'.format( t.name), t) return TypeVarType(tvar_def, t.line) elif fullname == 'builtins.None': return NoneTyp() elif fullname == 'typing.Any' or fullname == 'builtins.Any': return AnyType(explicit=True) elif fullname == 'typing.Tuple': if len(t.args) == 0 and not t.empty_tuple_index: # Bare 'Tuple' is same as 'tuple' if 'generics' in self.options.disallow_any and not self.is_typeshed_stub: self.fail(messages.BARE_GENERIC, t) typ = self.named_type('builtins.tuple', line=t.line, column=t.column) typ.from_generic_builtin = True return typ if len(t.args) == 2 and isinstance(t.args[1], EllipsisType): # Tuple[T, ...] (uniform, variable-length tuple) instance = self.named_type('builtins.tuple', [self.anal_type(t.args[0])]) instance.line = t.line return instance return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail( 'Optional[...] must have exactly one type argument', t) return AnyType() item = self.anal_type(t.args[0]) return make_optional_type(item) elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: any_type = AnyType(from_omitted_generics=True, line=t.line, column=t.column) return TypeType(any_type, line=t.line, column=t.column) if len(t.args) != 1: self.fail('Type[...] must have exactly one type argument', t) item = self.anal_type(t.args[0]) return TypeType.make_normalized(item, line=t.line) elif fullname == 'typing.ClassVar': if self.nesting_level > 0: self.fail( 'Invalid type: ClassVar nested inside other type', t) if len(t.args) == 0: return AnyType(line=t.line) if len(t.args) != 1: self.fail( 'ClassVar[...] must have at most one type argument', t) return AnyType() item = self.anal_type(t.args[0]) if isinstance(item, TypeVarType) or get_type_vars(item): self.fail('Invalid type: ClassVar cannot be generic', t) return AnyType() return item elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'): return UninhabitedType(is_noreturn=True) elif sym.kind == TYPE_ALIAS: override = sym.type_override all_vars = sym.alias_tvars assert override is not None an_args = self.anal_array(t.args) if all_vars is not None: exp_len = len(all_vars) else: exp_len = 0 act_len = len(an_args) if exp_len > 0 and act_len == 0: # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...] assert all_vars is not None return set_any_tvars(override, all_vars, t.line, t.column) if exp_len == 0 and act_len == 0: return override if act_len != exp_len: self.fail( 'Bad number of arguments for type alias, expected: %s, given: %s' % (exp_len, act_len), t) return set_any_tvars(override, all_vars or [], t.line, t.column, implicit=False) assert all_vars is not None return replace_alias_tvars(override, all_vars, an_args, t.line, t.column) elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance( sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType(from_unimported_type=True) # Allow unbound type variables when defining an alias if not (self.aliasing and sym.kind == TVAR and self.tvar_scope.get_binding(sym) is None): self.fail('Invalid type "{}"'.format(name), t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': return TupleType(self.anal_array(t.args), Instance(info, [AnyType()], t.line), t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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, t.column) instance.from_generic_builtin = sym.normalized tup = info.tuple_type if tup is not None: # 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 tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) td = info.typeddict_type if td is not None: # The class has a TypedDict[...] base class so it will be # represented as a typeddict type. if t.args: self.fail('Generic TypedDict types not supported', t) return AnyType() # Create a named TypedDictType return td.copy_modified(item_types=self.anal_array( list(td.items.values())), fallback=instance) return instance else: return AnyType()
def __init__(self): super().__init__() self.x = UnboundType('X') # Helpers self.y = UnboundType('Y') self.fx = TypeFixture() self.function = self.fx.function
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return UnionType.make_simplified_union( [self.visit_unbound_type(t), NoneTyp()]) sym = self.lookup(t.name, t) if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail( 'Internal error (node is None, kind={})'.format( sym.kind), t) return AnyType() fullname = sym.node.fullname() if sym.kind == BOUND_TVAR: if len(t.args) > 0: self.fail( 'Type variable "{}" used with arguments'.format( t.name), t) assert sym.tvar_def is not None return TypeVarType(sym.tvar_def, t.line) elif fullname == 'builtins.None': if experiments.STRICT_OPTIONAL: return NoneTyp(is_ret_type=t.is_ret_type) else: return Void() 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) instance = self.builtin_type('builtins.tuple', [t.args[0].accept(self)]) instance.line = t.line return instance return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) items = [item for item in items if not isinstance(item, Void)] return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail( 'Optional[...] must have exactly one type argument', t) return AnyType() items = self.anal_array(t.args) if experiments.STRICT_OPTIONAL: return UnionType.make_simplified_union( [items[0], NoneTyp()]) else: # Without strict Optional checking Optional[t] is just an alias for t. return items[0] elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: return TypeType(AnyType(), line=t.line) if len(t.args) != 1: self.fail('Type[...] must have exactly one type argument', t) items = self.anal_array(t.args) item = items[0] return TypeType(item, line=t.line) elif sym.kind == TYPE_ALIAS: override = sym.type_override an_args = self.anal_array(t.args) all_vars = self.get_type_var_names(override) exp_len = len(all_vars) act_len = len(an_args) if exp_len > 0 and act_len == 0: # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...] return self.replace_alias_tvars(override, all_vars, [AnyType()] * exp_len, t.line, t.column) if exp_len == 0 and act_len == 0: return override if act_len != exp_len: self.fail( 'Bad number of arguments for type alias, expected: %s, given: %s' % (exp_len, act_len), t) return t return self.replace_alias_tvars(override, all_vars, an_args, t.line, t.column) elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance( sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType() # Allow unbound type variables when defining an alias if not (self.aliasing and sym.kind == UNBOUND_TVAR): self.fail('Invalid type "{}"'.format(name), t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': return TupleType(self.anal_array(t.args), Instance(info, [AnyType()], t.line), t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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, t.column) 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 tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) else: return AnyType()
def test_generic_unbound_type(self) -> None: u = UnboundType('Foo', [UnboundType('T'), AnyType(TypeOfAny.special_form)]) assert_equal(str(u), 'Foo?[T?, Any]')
def test_simple_unbound_type(self) -> None: u = UnboundType('Foo') assert_equal(str(u), 'Foo?')
def setUp(self) -> None: self.x = UnboundType('X') # Helpers self.y = UnboundType('Y') self.fx = TypeFixture() self.function = self.fx.function
def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) -> None: """Perform the first analysis pass. Populate module global table. Resolve the full names of definitions not nested within functions and construct type info structures, but do not resolve inter-definition references such as base classes. Also add implicit definitions such as __name__. In this phase we don't resolve imports. For 'from ... import', we generate dummy symbol table nodes for the imported names, and these will get resolved in later phases of semantic analysis. """ sem = self.sem self.sem.options = options # Needed because we sometimes call into it self.pyversion = options.python_version self.platform = options.platform sem.cur_mod_id = mod_id sem.cur_mod_node = file sem.errors.set_file(fnam, mod_id, scope=sem.scope) sem.globals = SymbolTable() sem.global_decls = [set()] sem.nonlocal_decls = [set()] sem.block_depth = [0] sem.scope.enter_file(mod_id) defs = file.defs with experiments.strict_optional_set(options.strict_optional): # Add implicit definitions of module '__name__' etc. for name, t in implicit_module_attrs.items(): # unicode docstrings should be accepted in Python 2 if name == '__doc__': if self.pyversion >= (3, 0): typ = UnboundType('__builtins__.str') # type: Type else: typ = UnionType([ UnboundType('__builtins__.str'), UnboundType('__builtins__.unicode') ]) else: assert t is not None, 'type should be specified for {}'.format( name) typ = UnboundType(t) v = Var(name, typ) v._fullname = self.sem.qualified_name(name) self.sem.globals[name] = SymbolTableNode(GDEF, v) for d in defs: d.accept(self) # Add implicit definition of literals/keywords to builtins, as we # cannot define a variable with them explicitly. if mod_id == 'builtins': literal_types = [ ('None', NoneTyp()), # reveal_type is a mypy-only function that gives an error with # the type of its arg. ('reveal_type', AnyType(TypeOfAny.special_form)), # reveal_locals is a mypy-only function that gives an error with the types of # locals ('reveal_locals', AnyType(TypeOfAny.special_form)), ] # type: List[Tuple[str, Type]] # TODO(ddfisher): This guard is only needed because mypy defines # fake builtins for its tests which often don't define bool. If # mypy is fast enough that we no longer need those, this # conditional check should be removed. if 'bool' in self.sem.globals: bool_type = self.sem.named_type('bool') literal_types.extend([ ('True', bool_type), ('False', bool_type), ('__debug__', bool_type), ]) else: # We are running tests without 'bool' in builtins. # TODO: Find a permanent solution to this problem. # Maybe add 'bool' to all fixtures? literal_types.append( ('True', AnyType(TypeOfAny.special_form))) for name, typ in literal_types: v = Var(name, typ) v._fullname = self.sem.qualified_name(name) self.sem.globals[name] = SymbolTableNode(GDEF, v) del self.sem.options sem.scope.leave()
def visit_unbound_type(self, t: UnboundType) -> Type: if t.optional: t.optional = False # We don't need to worry about double-wrapping Optionals or # wrapping Anys: Union simplification will take care of that. return make_optional_type(self.visit_unbound_type(t)) sym = self.lookup(t.name, t, suppress_errors=self.third_pass) # type: ignore if sym is not None: if sym.node is None: # UNBOUND_IMPORTED can happen if an unknown name was imported. if sym.kind != UNBOUND_IMPORTED: self.fail('Internal error (node is None, kind={})'.format(sym.kind), t) return AnyType(TypeOfAny.special_form) fullname = sym.node.fullname() hook = self.plugin.get_type_analyze_hook(fullname) if hook: return hook(AnalyzeTypeContext(t, t, self)) if (fullname in nongen_builtins and t.args and not sym.normalized and not self.allow_unnormalized): self.fail(no_subscript_builtin_alias(fullname), t) if self.tvar_scope: tvar_def = self.tvar_scope.get_binding(sym) else: tvar_def = None if self.warn_bound_tvar and sym.kind == TVAR and tvar_def is not None: self.fail('Can\'t use bound type variable "{}"' ' to define generic alias'.format(t.name), t) return AnyType(TypeOfAny.from_error) elif sym.kind == TVAR and tvar_def is not None: if len(t.args) > 0: self.fail('Type variable "{}" used with arguments'.format( t.name), t) return TypeVarType(tvar_def, t.line) elif fullname == 'builtins.None': return NoneTyp() elif fullname == 'typing.Any' or fullname == 'builtins.Any': return AnyType(TypeOfAny.explicit) elif fullname == 'typing.Tuple': if len(t.args) == 0 and not t.empty_tuple_index: # Bare 'Tuple' is same as 'tuple' if self.options.disallow_any_generics and not self.is_typeshed_stub: self.fail(messages.BARE_GENERIC, t) typ = self.named_type('builtins.tuple', line=t.line, column=t.column) typ.from_generic_builtin = True return typ if len(t.args) == 2 and isinstance(t.args[1], EllipsisType): # Tuple[T, ...] (uniform, variable-length tuple) instance = self.named_type('builtins.tuple', [self.anal_type(t.args[0])]) instance.line = t.line return instance return self.tuple_type(self.anal_array(t.args)) elif fullname == 'typing.Union': items = self.anal_array(t.args) return UnionType.make_union(items) elif fullname == 'typing.Optional': if len(t.args) != 1: self.fail('Optional[...] must have exactly one type argument', t) return AnyType(TypeOfAny.from_error) item = self.anal_type(t.args[0]) return make_optional_type(item) elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif fullname == 'typing.Type': if len(t.args) == 0: any_type = AnyType(TypeOfAny.from_omitted_generics, line=t.line, column=t.column) return TypeType(any_type, line=t.line, column=t.column) if len(t.args) != 1: self.fail('Type[...] must have exactly one type argument', t) item = self.anal_type(t.args[0]) return TypeType.make_normalized(item, line=t.line) elif fullname == 'typing.ClassVar': if self.nesting_level > 0: self.fail('Invalid type: ClassVar nested inside other type', t) if len(t.args) == 0: return AnyType(TypeOfAny.from_omitted_generics, line=t.line, column=t.column) if len(t.args) != 1: self.fail('ClassVar[...] must have at most one type argument', t) return AnyType(TypeOfAny.from_error) item = self.anal_type(t.args[0]) if isinstance(item, TypeVarType) or get_type_vars(item): self.fail('Invalid type: ClassVar cannot be generic', t) return AnyType(TypeOfAny.from_error) return item elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'): return UninhabitedType(is_noreturn=True) elif sym.kind == TYPE_ALIAS: override = sym.type_override all_vars = sym.alias_tvars assert override is not None an_args = self.anal_array(t.args) if all_vars is not None: exp_len = len(all_vars) else: exp_len = 0 act_len = len(an_args) if exp_len > 0 and act_len == 0: # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...] assert all_vars is not None return set_any_tvars(override, all_vars, t.line, t.column) if exp_len == 0 and act_len == 0: return override if act_len != exp_len: self.fail('Bad number of arguments for type alias, expected: %s, given: %s' % (exp_len, act_len), t) return set_any_tvars(override, all_vars or [], t.line, t.column, implicit=False) assert all_vars is not None return replace_alias_tvars(override, all_vars, an_args, t.line, t.column) elif not isinstance(sym.node, TypeInfo): name = sym.fullname if name is None: name = sym.node.name() if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType): # Something with an Any type -- make it an alias for Any in a type # context. This is slightly problematic as it allows using the type 'Any' # as a base class -- however, this will fail soon at runtime so the problem # is pretty minor. return AnyType(TypeOfAny.from_unimported_type) # Allow unbound type variables when defining an alias if not (self.aliasing and sym.kind == TVAR and (not self.tvar_scope or self.tvar_scope.get_binding(sym) is None)): if (not self.third_pass and not self.in_dynamic_func and not (isinstance(sym.node, (FuncDef, Decorator)) or isinstance(sym.node, Var) and sym.node.is_ready) and not (sym.kind == TVAR and tvar_def is None)): if t.args and not self.global_scope: self.fail('Unsupported forward reference to "{}"'.format(t.name), t) return AnyType(TypeOfAny.from_error) return ForwardRef(t) self.fail('Invalid type "{}"'.format(name), t) if self.third_pass and sym.kind == TVAR: self.note_func("Forward references to type variables are prohibited", t) return t info = sym.node # type: TypeInfo if len(t.args) > 0 and info.fullname() == 'builtins.tuple': fallback = Instance(info, [AnyType(TypeOfAny.special_form)], t.line) return TupleType(self.anal_array(t.args), fallback, t.line) else: # Analyze arguments and construct Instance type. The # number of type arguments and their values are # checked only later, since we do not always know the # 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, t.column) instance.from_generic_builtin = sym.normalized tup = info.tuple_type if tup is not None: # 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(TypeOfAny.from_error) return tup.copy_modified(items=self.anal_array(tup.items), fallback=instance) td = info.typeddict_type if td is not None: # The class has a TypedDict[...] base class so it will be # represented as a typeddict type. if t.args: self.fail('Generic TypedDict types not supported', t) return AnyType(TypeOfAny.from_error) # Create a named TypedDictType return td.copy_modified(item_types=self.anal_array(list(td.items.values())), fallback=instance) return instance else: if self.third_pass: self.fail('Invalid type "{}"'.format(t.name), t) return AnyType(TypeOfAny.from_error) return AnyType(TypeOfAny.special_form)