Runs Mypy in a subprocess. If this passes without errors, executes the script again with a given Python version.
(testcase: DataDrivenTestCase, cache_dir: str)
| 39 | |
| 40 | |
| 41 | def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None: |
| 42 | """Runs Mypy in a subprocess. |
| 43 | |
| 44 | If this passes without errors, executes the script again with a given Python |
| 45 | version. |
| 46 | """ |
| 47 | assert testcase.old_cwd is not None, "test was not properly set up" |
| 48 | # We must enable site packages to get access to installed stubs. |
| 49 | mypy_cmdline = [ |
| 50 | "--show-traceback", |
| 51 | "--no-silence-site-packages", |
| 52 | "--no-error-summary", |
| 53 | "--hide-error-codes", |
| 54 | "--allow-empty-bodies", |
| 55 | "--test-env", # Speeds up some checks |
| 56 | ] |
| 57 | interpreter = python3_path |
| 58 | mypy_cmdline.append(f"--python-version={'.'.join(map(str, PYTHON3_VERSION))}") |
| 59 | |
| 60 | m = re.search("# flags: (.*)$", "\n".join(testcase.input), re.MULTILINE) |
| 61 | if m: |
| 62 | additional_flags = m.group(1).split() |
| 63 | for flag in additional_flags: |
| 64 | if flag.startswith("--python-version="): |
| 65 | targeted_python_version = flag.split("=")[1] |
| 66 | targeted_major, targeted_minor = targeted_python_version.split(".") |
| 67 | if (int(targeted_major), int(targeted_minor)) > ( |
| 68 | sys.version_info.major, |
| 69 | sys.version_info.minor, |
| 70 | ): |
| 71 | return |
| 72 | mypy_cmdline.extend(additional_flags) |
| 73 | |
| 74 | # Write the program to a file. |
| 75 | program = "_" + testcase.name + ".py" |
| 76 | program_path = os.path.join(test_temp_dir, program) |
| 77 | mypy_cmdline.append(program_path) |
| 78 | with open(program_path, "w", encoding="utf8") as file: |
| 79 | for s in testcase.input: |
| 80 | file.write(f"{s}\n") |
| 81 | mypy_cmdline.append(f"--cache-dir={cache_dir}") |
| 82 | output = [] |
| 83 | # Type check the program. |
| 84 | out, err, returncode = api.run(mypy_cmdline) |
| 85 | # split lines, remove newlines, and remove directory of test case |
| 86 | for line in (out + err).splitlines(): |
| 87 | if line.startswith(test_temp_dir + os.sep): |
| 88 | output.append(line[len(test_temp_dir + os.sep) :].rstrip("\r\n")) |
| 89 | else: |
| 90 | # Normalize paths so that the output is the same on Windows and Linux/macOS. |
| 91 | line = line.replace(test_temp_dir + os.sep, test_temp_dir + "/") |
| 92 | output.append(line.rstrip("\r\n")) |
| 93 | if returncode > 1 and not testcase.output: |
| 94 | # Either api.run() doesn't work well in case of a crash, or pytest interferes with it. |
| 95 | # Tweak output to prevent tests with empty expected output to pass in case of a crash. |
| 96 | output.append("!!! Mypy crashed !!!") |
| 97 | if returncode == 0 and not output: |
| 98 | # Execute the program. |
no test coverage detected
searching dependent graphs…