Example #1
0
    def run_case_inner(self, testcase: DataDrivenTestCase) -> None:
        if not os.path.isdir(WORKDIR):  # (one test puts something in build...)
            os.mkdir(WORKDIR)

        text = '\n'.join(testcase.input)

        with open('native.py', 'w', encoding='utf-8') as f:
            f.write(text)
        with open('interpreted.py', 'w', encoding='utf-8') as f:
            f.write(text)

        shutil.copyfile(TESTUTIL_PATH, 'testutil.py')

        step = 1
        self.run_case_step(testcase, step)

        steps = testcase.find_steps()
        if steps == [[]]:
            steps = []

        for operations in steps:
            # To make sure that any new changes get picked up as being
            # new by distutils, shift the mtime of all of the
            # generated artifacts back by a second.
            fudge_dir_mtimes(WORKDIR, -1)

            step += 1
            with chdir_manager('..'):
                perform_file_operations(operations)
            self.run_case_step(testcase, step)
Example #2
0
    def perform_step(
        self, operations: List[Union[UpdateFile, DeleteFile]], server: Server,
        options: Options, build_options: Options, testcase: DataDrivenTestCase,
        main_src: str, step: int, num_regular_incremental_steps: int
    ) -> Tuple[List[str], List[List[str]]]:
        """Perform one fine-grained incremental build step (after some file updates/deletions).

        Return (mypy output, triggered targets).
        """
        perform_file_operations(operations)
        sources = self.parse_sources(main_src, step, options)

        if step <= num_regular_incremental_steps:
            new_messages = self.build(build_options, sources)
        else:
            new_messages = self.run_check(server, sources)

        updated: List[str] = []
        changed: List[str] = []
        targets: List[str] = []
        triggered = []
        if server.fine_grained_manager:
            if CHECK_CONSISTENCY:
                check_consistency(server.fine_grained_manager)
            triggered.append(server.fine_grained_manager.triggered)

            updated = server.fine_grained_manager.updated_modules
            changed = [
                mod
                for mod, file in server.fine_grained_manager.changed_modules
            ]
            targets = server.fine_grained_manager.processed_targets

        expected_stale = testcase.expected_stale_modules.get(step - 1)
        if expected_stale is not None:
            assert_module_equivalence('stale' + str(step - 1), expected_stale,
                                      changed)

        expected_rechecked = testcase.expected_rechecked_modules.get(step - 1)
        if expected_rechecked is not None:
            assert_module_equivalence('rechecked' + str(step - 1),
                                      expected_rechecked, updated)

        expected = testcase.expected_fine_grained_targets.get(step)
        if expected:
            assert_target_equivalence('targets' + str(step), expected, targets)

        new_messages = normalize_messages(new_messages)

        a = new_messages
        assert testcase.tmpdir
        a.extend(
            self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))

        return a, triggered
Example #3
0
def test_pep561(testcase: DataDrivenTestCase) -> None:
    """Test running mypy on files that depend on PEP 561 packages."""
    assert testcase.old_cwd is not None, "test was not properly set up"
    if 'python2' in testcase.name.lower():
        python = try_find_python2_interpreter()
        if python is None:
            pytest.skip()
    else:
        python = sys.executable

    assert python is not None, "Should be impossible"
    pkgs, pip_args = parse_pkgs(testcase.input[0])
    mypy_args = parse_mypy_args(testcase.input[1])
    use_pip = True
    editable = False
    for arg in pip_args:
        if arg == 'no-pip':
            use_pip = False
        elif arg == 'editable':
            editable = True
    assert pkgs != [], "No packages to install for PEP 561 test?"
    with virtualenv(python) as venv:
        venv_dir, python_executable = venv
        for pkg in pkgs:
            install_package(pkg, python_executable, use_pip, editable)

        cmd_line = list(mypy_args)
        has_program = not ('-p' in cmd_line or '--package' in cmd_line)
        if has_program:
            program = testcase.name + '.py'
            with open(program, 'w', encoding='utf-8') as f:
                for s in testcase.input:
                    f.write(f'{s}\n')
            cmd_line.append(program)

        cmd_line.extend(['--no-error-summary'])
        if python_executable != sys.executable:
            cmd_line.append(f'--python-executable={python_executable}')

        steps = testcase.find_steps()
        if steps != [[]]:
            steps = [[]] + steps  # type: ignore[operator,assignment]

        for i, operations in enumerate(steps):
            perform_file_operations(operations)

            output = []
            # Type check the module
            out, err, returncode = mypy.api.run(cmd_line)

            # split lines, remove newlines, and remove directory of test case
            for line in (out + err).splitlines():
                if line.startswith(test_temp_dir + os.sep):
                    output.append(line[len(test_temp_dir +
                                           os.sep):].rstrip("\r\n"))
                else:
                    # Normalize paths so that the output is the same on Windows and Linux/macOS.
                    line = line.replace(test_temp_dir + os.sep,
                                        test_temp_dir + '/')
                    output.append(line.rstrip("\r\n"))
            iter_count = '' if i == 0 else f' on iteration {i + 1}'
            expected = testcase.output if i == 0 else testcase.output2.get(
                i + 1, [])

            assert_string_arrays_equal(
                expected, output, 'Invalid output ({}, line {}){}'.format(
                    testcase.file, testcase.line, iter_count))

        if has_program:
            os.remove(program)
Example #4
0
    def run_case_once(self,
                      testcase: DataDrivenTestCase,
                      operations: List[FileOperation] = [],
                      incremental_step: int = 0) -> None:
        original_program_text = '\n'.join(testcase.input)
        module_data = self.parse_module(original_program_text,
                                        incremental_step)

        # Unload already loaded plugins, they may be updated.
        for file, _ in testcase.files:
            module = module_from_path(file)
            if module.endswith('_plugin') and module in sys.modules:
                del sys.modules[module]
        if incremental_step == 0 or incremental_step == 1:
            # In run 1, copy program text to program file.
            for module_name, program_path, program_text in module_data:
                if module_name == '__main__':
                    with open(program_path, 'w', encoding='utf8') as f:
                        f.write(program_text)
                    break
        elif incremental_step > 1:
            # In runs 2+, copy *.[num] files to * files.
            perform_file_operations(operations)

        # Parse options after moving files (in case mypy.ini is being moved).
        options = parse_options(original_program_text, testcase,
                                incremental_step)
        options.use_builtins_fixtures = True
        options.show_traceback = True

        # Enable some options automatically based on test file name.
        if 'optional' in testcase.file:
            options.strict_optional = True
        if 'columns' in testcase.file:
            options.show_column_numbers = True
        if 'errorcodes' in testcase.file:
            options.show_error_codes = True

        if incremental_step and options.incremental:
            # Don't overwrite # flags: --no-incremental in incremental test cases
            options.incremental = True
        else:
            options.incremental = False
            # Don't waste time writing cache unless we are specifically looking for it
            if not testcase.writescache:
                options.cache_dir = os.devnull

        sources = []
        for module_name, program_path, program_text in module_data:
            # Always set to none so we're forced to reread the module in incremental mode
            sources.append(
                BuildSource(program_path, module_name,
                            None if incremental_step else program_text))

        plugin_dir = os.path.join(test_data_prefix, 'plugins')
        sys.path.insert(0, plugin_dir)

        res = None
        try:
            res = build.build(sources=sources,
                              options=options,
                              alt_lib_path=test_temp_dir)
            a = res.errors
        except CompileError as e:
            a = e.messages
        finally:
            assert sys.path[0] == plugin_dir
            del sys.path[0]

        if testcase.normalize_output:
            a = normalize_error_messages(a)

        # Make sure error messages match
        if incremental_step == 0:
            # Not incremental
            msg = 'Unexpected type checker output ({}, line {})'
            output = testcase.output
        elif incremental_step == 1:
            msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})'
            output = testcase.output
        elif incremental_step > 1:
            msg = ('Unexpected type checker output in incremental, run {}'.
                   format(incremental_step) + ' ({}, line {})')
            output = testcase.output2.get(incremental_step, [])
        else:
            raise AssertionError()

        if output != a and testcase.config.getoption('--update-data', False):
            update_testcase_output(testcase, a)
        assert_string_arrays_equal(output, a,
                                   msg.format(testcase.file, testcase.line))

        if res:
            if options.cache_dir != os.devnull:
                self.verify_cache(module_data, res.errors, res.manager,
                                  res.graph)

            name = 'targets'
            if incremental_step:
                name += str(incremental_step + 1)
            expected = testcase.expected_fine_grained_targets.get(
                incremental_step + 1)
            actual = res.manager.processed_targets
            # Skip the initial builtin cycle.
            actual = [
                t for t in actual if not any(
                    t.startswith(mod)
                    for mod in core_modules + ['mypy_extensions'])
            ]
            if expected is not None:
                assert_target_equivalence(name, expected, actual)
            if incremental_step > 1:
                suffix = '' if incremental_step == 2 else str(
                    incremental_step - 1)
                expected_rechecked = testcase.expected_rechecked_modules.get(
                    incremental_step - 1)
                if expected_rechecked is not None:
                    assert_module_equivalence('rechecked' + suffix,
                                              expected_rechecked,
                                              res.manager.rechecked_modules)
                expected_stale = testcase.expected_stale_modules.get(
                    incremental_step - 1)
                if expected_stale is not None:
                    assert_module_equivalence('stale' + suffix, expected_stale,
                                              res.manager.stale_modules)

        if testcase.output_files:
            check_test_output_files(testcase,
                                    incremental_step,
                                    strip_prefix='tmp/')