def test_false_only_tuple(self) -> None: with strict_optional_set(False): fo = false_only(self.tuple(self.fx.a)) assert_equal(fo, NoneType()) with strict_optional_set(True): fo = false_only(self.tuple(self.fx.a)) assert_equal(fo, UninhabitedType())
def get_suggestion(self, function: str) -> str: """Compute a suggestion for a function. Return the type and whether the first argument should be ignored. """ graph = self.graph mod, _, node = self.find_node(function) callsites, orig_errors = self.get_callsites(node) # FIXME: what about static and class methods? is_method = bool(node.info) with strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( is_method, self.get_trivial_type(node), self.get_default_arg_types(graph[mod], node), callsites) best = self.find_best(node, guesses) # Now try to find the return type! self.try_type(node, best) returns = get_return_types(self.manager.all_types, node) with strict_optional_set(graph[mod].options.strict_optional): if returns: ret_types = generate_type_combinations(returns) else: ret_types = [NoneTyp()] guesses = [best.copy_modified(ret_type=t) for t in ret_types] best = self.find_best(node, guesses) return format_callable(is_method, best)
def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: """Compute a suggestion for a function. Return the type and whether the first argument should be ignored. """ graph = self.graph callsites, orig_errors = self.get_callsites(node) uses = get_arg_uses(self.manager.all_types, node) if self.no_errors and orig_errors: raise SuggestionFailure("Function does not typecheck.") is_method = bool(node.info) and not node.is_static if len(node.arg_names) >= 10: raise SuggestionFailure("Too many arguments") with strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( is_method, self.get_starting_type(node), self.get_default_arg_types(graph[mod], node), callsites, uses, ) guesses = self.filter_options(guesses, is_method) if len(guesses) > self.max_guesses: raise SuggestionFailure("Too many possibilities!") best, _ = self.find_best(node, guesses) # Now try to find the return type! self.try_type(node, best) returns = get_return_types(self.manager.all_types, node) with strict_optional_set(graph[mod].options.strict_optional): if returns: ret_types = generate_type_combinations(returns) else: ret_types = [NoneType()] guesses = [ best.copy_modified(ret_type=refine_type(best.ret_type, t)) for t in ret_types ] guesses = self.filter_options(guesses, is_method) best, errors = self.find_best(node, guesses) if self.no_errors and errors: raise SuggestionFailure("No annotation without errors") return self.pyannotate_signature(mod, is_method, best)
def refine_union(t: UnionType, s: ProperType) -> Type: """Refine a union type based on another type. This is done by refining every component of the union against the right hand side type (or every component of its union if it is one). If an element of the union is successfully refined, we drop it from the union in favor of the refined versions. """ # Don't try to do any union refining if the types are already the # same. This prevents things like refining Optional[Any] against # itself and producing None. if t == s: return t rhs_items = s.items if isinstance(s, UnionType) else [s] new_items = [] for lhs in t.items: refined = False for rhs in rhs_items: new = refine_type(lhs, rhs) if new != lhs: new_items.append(new) refined = True if not refined: new_items.append(lhs) # Turn strict optional on when simplifying the union since we # don't want to drop Nones. with strict_optional_set(True): return make_simplified_union(new_items)
def get_suggestion(self, function: str) -> str: """Compute a suggestion for a function. Return the type and whether the first argument should be ignored. """ graph = self.graph mod, _, node = self.find_node(function) callsites, orig_errors = self.get_callsites(node) if self.no_errors and orig_errors: raise SuggestionFailure("Function does not typecheck.") # FIXME: what about static and class methods? is_method = bool(node.info) if len(node.arg_names) >= 10: raise SuggestionFailure("Too many arguments") with strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( is_method, self.get_trivial_type(node), self.get_default_arg_types(graph[mod], node), callsites) guesses = self.filter_options(guesses) if len(guesses) > self.max_guesses: raise SuggestionFailure("Too many possibilities!") best, _ = self.find_best(node, guesses) # Now try to find the return type! self.try_type(node, best) returns = get_return_types(self.manager.all_types, node) with strict_optional_set(graph[mod].options.strict_optional): if returns: ret_types = generate_type_combinations(returns) else: ret_types = [NoneType()] guesses = [best.copy_modified(ret_type=t) for t in ret_types] guesses = self.filter_options(guesses) best, errors = self.find_best(node, guesses) if self.no_errors and errors: raise SuggestionFailure("No annotation without errors") return self.format_callable(mod, is_method, best)
def check_type_arguments(graph: 'Graph', scc: List[str], errors: Errors) -> None: for module in scc: state = graph[module] assert state.tree analyzer = TypeArgumentAnalyzer(errors) with state.wrap_context(): with strict_optional_set(state.options.strict_optional): state.tree.accept(analyzer)
def get_suggestion(self, function: str) -> str: """Compute a suggestion for a function. Return the type and whether the first argument should be ignored. """ graph = self.graph mod, _, node = self.find_node(function) callsites, orig_errors = self.get_callsites(node) if self.no_errors and orig_errors: raise SuggestionFailure("Function does not typecheck.") # FIXME: what about static and class methods? is_method = bool(node.info) with strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( is_method, self.get_trivial_type(node), self.get_default_arg_types(graph[mod], node), callsites) guesses = self.filter_options(guesses) if len(guesses) > self.max_guesses: raise SuggestionFailure("Too many possibilities!") best, _ = self.find_best(node, guesses) # Now try to find the return type! self.try_type(node, best) returns = get_return_types(self.manager.all_types, node) with strict_optional_set(graph[mod].options.strict_optional): if returns: ret_types = generate_type_combinations(returns) else: ret_types = [NoneType()] guesses = [best.copy_modified(ret_type=t) for t in ret_types] guesses = self.filter_options(guesses) best, errors = self.find_best(node, guesses) if self.no_errors and errors: raise SuggestionFailure("No annotation without errors") return self.format_callable(mod, is_method, best)
def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], state: 'State', errors: Errors) -> None: """Check type arguments against type variable bounds and restrictions. This mirrors the logic in check_type_arguments() except that we process only some targets. This is used in fine grained incremental mode. """ analyzer = TypeArgumentAnalyzer(errors) with state.wrap_context(): with strict_optional_set(state.options.strict_optional): for target in targets: analyzer.recurse_into_functions = not isinstance(target.node, MypyFile) target.node.accept(analyzer)
def test_false_only_of_union(self) -> None: with strict_optional_set(True): tup_type = self.tuple() # Union of something that is unknown, something that is always true, something # that is always false union_type = UnionType([self.fx.a, self.tuple(AnyType(TypeOfAny.special_form)), tup_type]) assert_equal(len(union_type.items), 3) fo = false_only(union_type) assert isinstance(fo, UnionType) assert_equal(len(fo.items), 2) assert_false(fo.items[0].can_be_true) assert_true(fo.items[0].can_be_false) assert_true(fo.items[1] is tup_type)
def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], state: 'State', errors: Errors) -> None: """Check type arguments against type variable bounds and restrictions. This mirrors the logic in check_type_arguments() except that we process only some targets. This is used in fine grained incremental mode. """ analyzer = TypeArgumentAnalyzer(errors) with state.wrap_context(): with strict_optional_set(state.options.strict_optional): for target in targets: analyzer.recurse_into_functions = not isinstance( target.node, MypyFile) target.node.accept(analyzer)
def visit_file(self, file_node: MypyFile, fnam: str, options: Options, patches: List[Tuple[int, Callable[[], None]]]) -> None: self.recurse_into_functions = True self.errors.set_file(fnam, file_node.fullname(), scope=self.scope) self.options = options self.sem.options = options self.patches = patches self.is_typeshed_file = self.errors.is_typeshed_file(fnam) self.sem.cur_mod_id = file_node.fullname() self.cur_mod_node = file_node self.sem.globals = file_node.names with state.strict_optional_set(options.strict_optional): self.scope.enter_file(file_node.fullname()) self.update_imported_vars() self.accept(file_node) self.analyze_symbol_table(file_node.names) self.scope.leave() del self.cur_mod_node self.patches = []
def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], state: 'State', errors: Errors) -> None: """Check type arguments against type variable bounds and restrictions. This mirrors the logic in check_type_arguments() except that we process only some targets. This is used in fine grained incremental mode. """ analyzer = TypeArgumentAnalyzer(errors, state.options, errors.is_typeshed_file(state.path or '')) with state.wrap_context(): with strict_optional_set(state.options.strict_optional): for target in targets: func = None # type: Optional[Union[FuncDef, OverloadedFuncDef]] if isinstance(target.node, (FuncDef, OverloadedFuncDef)): func = target.node saved = (state.id, target.active_typeinfo, func) # module, class, function with errors.scope.saved_scope(saved) if errors.scope else nothing(): analyzer.recurse_into_functions = func is not None target.node.accept(analyzer)
def assert_meet_uninhabited(self, s: Type, t: Type) -> None: with strict_optional_set(False): self.assert_meet(s, t, self.fx.nonet) with strict_optional_set(True): self.assert_meet(s, t, self.fx.uninhabited)
def test_false_only_of_true_type_is_uninhabited(self) -> None: with strict_optional_set(True): fo = false_only(self.tuple(AnyType(TypeOfAny.special_form))) assert_type(UninhabitedType, fo)
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. """ if options.allow_redefinition: # Perform renaming across the AST to allow variable redefinitions file.accept(VariableRenameVisitor()) 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 state.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 i, d in enumerate(defs): d.accept(self) if isinstance(d, AssertStmt) and assert_will_always_fail( d, options): # We've encountered an assert that's always false, # e.g. assert sys.platform == 'lol'. Truncate the # list of statements. This mutates file.defs too. del defs[i + 1:] break # 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()
from mypyc.errors import Errors from mypyc.options import CompilerOptions from mypyc.ir.rtypes import none_rprimitive from mypyc.ir.module_ir import ModuleIR, ModuleIRs from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature from mypyc.irbuild.prebuildvisitor import PreBuildVisitor from mypyc.irbuild.vtable import compute_vtable from mypyc.irbuild.prepare import build_type_map from mypyc.irbuild.builder import IRBuilder from mypyc.irbuild.visitor import IRBuilderVisitor from mypyc.irbuild.mapper import Mapper # The stubs for callable contextmanagers are busted so cast it to the # right type... F = TypeVar('F', bound=Callable[..., Any]) strict_optional_dec = cast(Callable[[F], F], strict_optional_set(True)) @strict_optional_dec # Turn on strict optional for any type manipulations we do def build_ir(modules: List[MypyFile], graph: Graph, types: Dict[Expression, Type], mapper: 'Mapper', options: CompilerOptions, errors: Errors) -> ModuleIRs: build_type_map(mapper, modules, graph, types, options, errors) result = OrderedDict() # type: ModuleIRs # Generate IR for all modules. class_irs = [] for module in modules:
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. """ if options.allow_redefinition: # Perform renaming across the AST to allow variable redefinitions file.accept(VariableRenameVisitor()) 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 state.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 i, d in enumerate(defs): d.accept(self) if isinstance(d, AssertStmt) and assert_will_always_fail(d, options): # We've encountered an assert that's always false, # e.g. assert sys.platform == 'lol'. Truncate the # list of statements. This mutates file.defs too. del defs[i + 1:] break # 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()