def visit_raw_expression_type(self, t: RawExpressionType) -> Type: # We should never see a bare Literal. We synthesize these raw literals # in the earlier stages of semantic analysis, but those # "fake literals" should always be wrapped in an UnboundType # corresponding to 'Literal'. # # Note: if at some point in the distant future, we decide to # make signatures like "foo(x: 20) -> None" legal, we can change # this method so it generates and returns an actual LiteralType # instead. if self.report_invalid_types: if t.base_type_name in ('builtins.int', 'builtins.bool'): # The only time it makes sense to use an int or bool is inside of # a literal type. msg = "Invalid type: try using Literal[{}] instead?".format(repr(t.literal_value)) elif t.base_type_name in ('builtins.float', 'builtins.complex'): # We special-case warnings for floats and complex numbers. msg = "Invalid type: {} literals cannot be used as a type".format(t.simple_name()) else: # And in all other cases, we default to a generic error message. # Note: the reason why we use a generic error message for strings # but not ints or bools is because whenever we see an out-of-place # string, it's unclear if the user meant to construct a literal type # or just misspelled a regular type. So we avoid guessing. msg = 'Invalid type comment or annotation' self.fail(msg, t) if t.note is not None: self.note_func(t.note, t) return AnyType(TypeOfAny.from_error, line=t.line, column=t.column)
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()