Пример #1
0
 def test_error_pos_is_correctly_passed_to_warning(
         self, src_pos: 'Optional[Pos]') -> None:
     for op in ['truediv', 'floordiv', 'mod']:
         TypeCheckLogger.clean_sing()
         getattr(pv.float(1.0), op)(pv.float(0.0), src_pos)
         assert len(TypeCheckLogger().warnings) == 1
         assert TypeCheckLogger().warnings[-1][2] == src_pos
Пример #2
0
    def test_fail_and_success_in_examples(self, filepath: str,
                                          capsys: Any) -> None:
        # Cleaning type errors
        TypeCheckLogger.clean_sing()
        assert len(TypeCheckLogger().warnings) == 0

        # Getting expected values running Pytropos
        expected_output, expected_exitcode, expected_store = \
            self._find_output_file_and_store(filepath)

        # Executing Pytropos
        file = open(filepath)
        exit_exitcode, exit_store = main.run_pytropos(file.read(), file.name)
        out, err = capsys.readouterr()

        # Checking validity of execution
        assert out == expected_output
        assert exit_exitcode == expected_exitcode

        if expected_exitcode != 2:
            assert exit_store is not None
            assert expected_store is not None
            assert exit_store._global_scope == expected_store
        else:
            assert exit_store is None
            assert expected_store is None

        # there shouldn't be any trash after the generated code is executed,
        # everything should be encapsuled
        # (Note: this is an assertion to prevent a bug to be reintroduced)
        assert len(TypeCheckLogger().warnings) == 0
Пример #3
0
def run_transformed_type_checking_code(
        newast_comp: 'CodeType',
        pt_globals: 'Optional[Dict[str, Any]]') -> 'Tuple[int, None[Store]]':
    if pt_globals is None:
        pt_globals = {}

    # from pytropos.internals.tools import NonImplementedPT
    try:
        # at the module level, locals and globals are the same
        # see: https://stackoverflow.com/questions/2904274/globals-and-locals-in-python-exec
        exec(newast_comp, pt_globals)
    except Exception:
        derror(
            "Error: An error inside pytropos has occurred, please open an issue in:"
        )
        derror("  ", metadata.url)
        derror("Please run the code again with `-vvv` parameter")

        derror("\nType checking errors found:", verb=2)
        derror(TypeCheckLogger(), verb=2)

        derror("\nValue of variables at the moment of the failure:",
               metadata.url,
               verb=2)
        derror(pt_globals['st'], end='\n\n', verb=2)

        traceback.print_exc()
        return (2, None)

    store = pt_globals['st']

    if debug_print.verbosity == 2:
        derror("\nLast computed variables values (Store):", verb=2)
        derror(store, end='\n\n', verb=2)

    if debug_print.verbosity == 3:
        derror("\nLast computed variables values (Store):", verb=3)
        derror("Store({", verb=3)
        for i, v in store.items():
            derror(f"  {i!r}: PythonValue({v.val}),", verb=3)
        derror("})\n", verb=3)

    if len(TypeCheckLogger().warnings) > 0:
        derror(TypeCheckLogger())
        return (1, store)
    else:
        dprint('No type checking error found.', verb=1)
        dprint(
            'I wasn\'t able to find any error in the code, though there may be some (sorry)',
            verb=2)
    return (0, store)
Пример #4
0
    def test_shifts_with_some_values(self, i: PythonValue,
                                     j: Optional[int]) -> None:
        TypeCheckLogger.clean_sing()

        new_val1 = i.lshift(pv.int(j))
        new_val2 = i.rshift(pv.int(j))

        assert not i.is_top()
        assert isinstance(i.val, AbstractValue)
        assert isinstance(new_val1.val, AbstractValue)
        assert isinstance(new_val2.val, AbstractValue)

        if i.val.is_top() or j is None:
            assert new_val1.val.is_top()
            assert new_val2.val.is_top()
            assert len(TypeCheckLogger().warnings) == 0
            return

        if new_val1.val.is_top():
            with raises(ValueError):
                ops.lshift(i.val.val, j)  # type: ignore
            assert len(TypeCheckLogger().warnings) > 0
            assert valueError.match(TypeCheckLogger().warnings[0][1])
        else:
            assert ops.lshift(i.val.val, j) == new_val1.val.val  # type: ignore

        if new_val2.val.is_top():
            with raises(ValueError):
                ops.rshift(i.val.val, j)  # type: ignore
            assert len(TypeCheckLogger().warnings) > 0
            assert valueError.match(TypeCheckLogger().warnings[-1][1])
        else:
            assert ops.rshift(i.val.val, j) == new_val2.val.val  # type: ignore
Пример #5
0
    def test_float_and_ints_comform_to_baseline_python_divs(
            self, i: int, j: float) -> None:
        for op in ['truediv', 'floordiv', 'mod']:
            TypeCheckLogger.clean_sing()

            if j == 0.0:
                with raises(ZeroDivisionError):
                    getattr(ops, op)(i, j)
                newval = getattr(pv.int(i), op)(pv.float(j))
                assert isinstance(newval.val, (Int, Float))
                assert newval.val.is_top()

                assert len(TypeCheckLogger().warnings) == 1
                assert zeroDivisionError.match(
                    TypeCheckLogger().warnings[0][1])
            else:
                assert check_float_equality(
                    getattr(ops, op)(i, j),
                    getattr(pv.int(i), op)(pv.float(j)).val.val)
                assert len(TypeCheckLogger().warnings) == 0

            if i == 0:
                with raises(ZeroDivisionError):
                    getattr(ops, op)(j, i)
                newval = getattr(pv.float(j), op)(pv.int(i))
                assert isinstance(newval.val, (Int, Float))
                assert newval.val.is_top()

                assert len(TypeCheckLogger().warnings) > 0
                assert zeroDivisionError.match(
                    TypeCheckLogger().warnings[-1][1])
            else:
                assert check_float_equality(
                    getattr(ops, op)(j, i),
                    getattr(pv.float(j), op)(pv.int(i)).val.val)
Пример #6
0
    def test_op_float(self, i: float, j: float) -> None:
        """
        This test basically checks that doing something like this:
        Float(3) + Float(5) == Float(8)
        for all operations (+*/...) and Values
        """
        for op in ['add', 'sub', 'mul', 'truediv', 'floordiv', 'mod']:
            TypeCheckLogger.clean_sing()

            pt_val = getattr(pv.float(i), op)(pv.float(j))
            assert isinstance(pt_val.val, Float)
            if pt_val.val.is_top():
                with raises(ZeroDivisionError):
                    getattr(ops, op)(i, j)
                assert len(TypeCheckLogger().warnings) == 1
                assert zeroDivisionError.match(
                    TypeCheckLogger().warnings[0][1])
            else:
                assert check_float_equality(
                    getattr(ops, op)(i, j), pt_val.val.val)  # type: ignore
                assert len(TypeCheckLogger().warnings) == 0
Пример #7
0
    def test_div_int(self, i: int, j: int) -> None:
        """
        Checks correctness of division between integers.
        int(3).truediv(int(5)) == int(3/5)
        for division operations
        """
        for op in ['truediv', 'floordiv', 'mod']:
            TypeCheckLogger.clean_sing()

            pt_val = getattr(pv.int(i), op)(pv.int(j))
            if pt_val.is_top():
                with raises(ZeroDivisionError):
                    getattr(ops, op)(i, j)
                assert len(TypeCheckLogger().warnings) == 1
                assert zeroDivisionError.match(
                    TypeCheckLogger().warnings[0][1])
            else:
                assert isinstance(pt_val.val, (Float, Int))
                py_val = getattr(ops, op)(i, j)
                assert py_val == pt_val.val.val
                assert type(py_val) is type(pt_val.val.val)  # noqa: E721
                assert len(TypeCheckLogger().warnings) == 0
Пример #8
0
 def test_bool_returns_always_a_Bool(self, val: PythonValue) -> None:
     TypeCheckLogger.clean_sing()
     bool_val = val.bool()
     assert isinstance(bool_val.val, Bool)
     assert len(TypeCheckLogger().warnings) == 0
Пример #9
0
def run_pytropos(  # noqa: C901
    file: str,
    filename: str,
    cursorline: 'Optional[int]' = None,
    console: bool = False,
    pt_globals: 'Optional[Dict[str, Any]]' = None
) -> 'Tuple[int, Optional[Store]]':
    dprint("Starting pytropos", verb=1)

    dprint(
        "Parsing and un-parsing a python file (it should preserve all type comments)",
        verb=2)

    if debug_print.verbosity > 1:
        try:
            from typed_astunparse import unparse
        except ModuleNotFoundError:
            print(
                "Sorry! You need to install `typed_astunparse` for bigger verbosity levels.\n"
                "Note: If you are using python 3.7 we recommend you to install \n"
                "      `typed_astunparse` with `pip install -r git_requirements.txt` \n"
                "      (you can find `git_requirements.txt` in {})\n".format(
                    metadata.url),
                file=sys.stderr)
            exit(1)

    # Parsing file
    ast_: ast3.Module
    try:
        ast_ = ast3.parse(file, filename=filename)  # type: ignore
    except SyntaxError as msg:
        derror(
            f"{msg.filename}:{msg.lineno}:{msg.offset-1}: {type(msg).__name__}: {msg.msg}"
        )
        return (2, None)
    except (OverflowError, ValueError) as msg:
        derror(f"{filename}::: {type(msg).__name__}")
        return (2, None)

    if debug_print.verbosity > 1:
        dprint("Original file:", verb=2)
        dprint("AST dump of original file:", ast3.dump(ast_), verb=3)
        dprint(unparse(ast_), verb=2)

    # Converting AST (code) into Pytropos representation
    newast: ast3.Module
    try:
        newast = PytroposTransformer(  # type: ignore
            filename, cursorline=cursorline, console=console).visit(ast_)
    except AstTransformerError:
        derror(
            "Sorry it seems Pytropos cannot run the file. Pytropos doesn't support "
            "some Python characteristic it uses right now. Sorry :(")
        traceback.print_exc()
        # derror(msg)
        return (2, None)

    if debug_print.verbosity > 1:
        dprint("Modified file:", verb=2)
        dprint("AST dump of modified file:", ast3.dump(newast), verb=3)
        dprint(unparse(newast), verb=2)

    newast_py = ast.fix_missing_locations(typed_ast3_to_ast(newast))

    # TODO(helq): add these lines of code for optional debugging
    # import astpretty
    # astpretty.pprint(newast_py)
    try:
        newast_comp = compile(newast_py, '<generated type checking ast>',
                              'exec')  # type: ignore
    except (ValueError, TypeError):
        derror(
            "PYTROPOS INTERNAL ERROR. Sorry, it seems something unexpected happened. "
            "Please report this issue: run pytropos again with the same input and "
            "the flag -vvv")
        traceback.print_exc()
        # derror(msg)
        return (2, None)

    exitvalues = run_transformed_type_checking_code(newast_comp, pt_globals)
    TypeCheckLogger.clean_sing()

    dprint("Closing pytropos", verb=1)

    return exitvalues