| """Test cases for invoking mypyc on the command line. | |
| These are slow -- do not add test cases unless you have a very good reason to do so. | |
| """ | |
| from __future__ import annotations | |
| import glob | |
| import os | |
| import os.path | |
| import re | |
| import subprocess | |
| import sys | |
| from mypy.test.config import test_temp_dir | |
| from mypy.test.data import DataDrivenTestCase | |
| from mypy.test.helpers import normalize_error_messages | |
| from mypyc.test.testutil import MypycDataSuite, assert_test_output | |
| files = ["commandline.test"] | |
| base_path = os.path.join(os.path.dirname(__file__), "..", "..") | |
| python3_path = sys.executable | |
| class TestCommandLine(MypycDataSuite): | |
| files = files | |
| base_path = test_temp_dir | |
| optional_out = True | |
| def run_case(self, testcase: DataDrivenTestCase) -> None: | |
| # Parse options from test case description (arguments must not have spaces) | |
| text = "\n".join(testcase.input) | |
| m = re.search(r"# *cmd: *(.*)", text) | |
| assert m is not None, 'Test case missing "# cmd: <files>" section' | |
| args = m.group(1).split() | |
| # Write main program to run (not compiled) | |
| program = "_%s.py" % testcase.name | |
| program_path = os.path.join(test_temp_dir, program) | |
| with open(program_path, "w") as f: | |
| f.write(text) | |
| env = os.environ.copy() | |
| env["PYTHONPATH"] = base_path | |
| out = b"" | |
| try: | |
| # Compile program | |
| cmd = subprocess.run( | |
| [sys.executable, "-m", "mypyc", *args], | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.STDOUT, | |
| cwd="tmp", | |
| env=env, | |
| ) | |
| if "ErrorOutput" in testcase.name or cmd.returncode != 0: | |
| out += cmd.stdout | |
| elif "WarningOutput" in testcase.name: | |
| # Strip out setuptools build related output since we're only | |
| # interested in the messages emitted during compilation. | |
| messages, _, _ = cmd.stdout.partition(b"running build_ext") | |
| out += messages | |
| if cmd.returncode == 0: | |
| # Run main program | |
| out += subprocess.check_output([python3_path, program], cwd="tmp") | |
| finally: | |
| suffix = "pyd" if sys.platform == "win32" else "so" | |
| so_paths = glob.glob(f"tmp/**/*.{suffix}", recursive=True) | |
| for path in so_paths: | |
| os.remove(path) | |
| # Strip out 'tmp/' from error message paths in the testcase output, | |
| # due to a mismatch between this test and mypy's test suite. | |
| expected = [x.replace("tmp/", "") for x in testcase.output] | |
| # Verify output | |
| actual = normalize_error_messages(out.decode().splitlines()) | |
| assert_test_output(testcase, actual, "Invalid output", expected=expected) |