Ejemplo n.º 1
0
 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())
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
 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)
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
 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 = []
Ejemplo n.º 14
0
 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 = []
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
 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)
Ejemplo n.º 17
0
 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)
Ejemplo n.º 18
0
 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)
Ejemplo n.º 19
0
    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()
Ejemplo n.º 20
0
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:
Ejemplo n.º 21
0
    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()