| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- """End-to-end test cases for the daemon (dmypy).
- These are special because they run multiple shell commands.
- This also includes some unit tests.
- """
- from __future__ import annotations
- import os
- import subprocess
- import sys
- import tempfile
- import unittest
- from mypy.dmypy_server import filter_out_missing_top_level_packages
- from mypy.fscache import FileSystemCache
- from mypy.modulefinder import SearchPaths
- from mypy.test.config import PREFIX, test_temp_dir
- from mypy.test.data import DataDrivenTestCase, DataSuite
- from mypy.test.helpers import assert_string_arrays_equal, normalize_error_messages
- # Files containing test cases descriptions.
- daemon_files = ["daemon.test"]
- class DaemonSuite(DataSuite):
- files = daemon_files
- def run_case(self, testcase: DataDrivenTestCase) -> None:
- try:
- test_daemon(testcase)
- finally:
- # Kill the daemon if it's still running.
- run_cmd("dmypy kill")
- def test_daemon(testcase: DataDrivenTestCase) -> None:
- assert testcase.old_cwd is not None, "test was not properly set up"
- for i, step in enumerate(parse_script(testcase.input)):
- cmd = step[0]
- expected_lines = step[1:]
- assert cmd.startswith("$")
- cmd = cmd[1:].strip()
- cmd = cmd.replace("{python}", sys.executable)
- sts, output = run_cmd(cmd)
- output_lines = output.splitlines()
- output_lines = normalize_error_messages(output_lines)
- if sts:
- output_lines.append("== Return code: %d" % sts)
- assert_string_arrays_equal(
- expected_lines,
- output_lines,
- "Command %d (%s) did not give expected output" % (i + 1, cmd),
- )
- def parse_script(input: list[str]) -> list[list[str]]:
- """Parse testcase.input into steps.
- Each command starts with a line starting with '$'.
- The first line (less '$') is sent to the shell.
- The remaining lines are expected output.
- """
- steps = []
- step: list[str] = []
- for line in input:
- if line.startswith("$"):
- if step:
- assert step[0].startswith("$")
- steps.append(step)
- step = []
- step.append(line)
- if step:
- steps.append(step)
- return steps
- def run_cmd(input: str) -> tuple[int, str]:
- if input[1:].startswith("mypy run --") and "--show-error-codes" not in input:
- input += " --hide-error-codes"
- if input.startswith("dmypy "):
- input = sys.executable + " -m mypy." + input
- if input.startswith("mypy "):
- input = sys.executable + " -m" + input
- env = os.environ.copy()
- env["PYTHONPATH"] = PREFIX
- try:
- output = subprocess.check_output(
- input, shell=True, stderr=subprocess.STDOUT, text=True, cwd=test_temp_dir, env=env
- )
- return 0, output
- except subprocess.CalledProcessError as err:
- return err.returncode, err.output
- class DaemonUtilitySuite(unittest.TestCase):
- """Unit tests for helpers"""
- def test_filter_out_missing_top_level_packages(self) -> None:
- with tempfile.TemporaryDirectory() as td:
- self.make_file(td, "base/a/")
- self.make_file(td, "base/b.py")
- self.make_file(td, "base/c.pyi")
- self.make_file(td, "base/missing.txt")
- self.make_file(td, "typeshed/d.pyi")
- self.make_file(td, "typeshed/@python2/e") # outdated
- self.make_file(td, "pkg1/f-stubs")
- self.make_file(td, "pkg2/g-python2-stubs") # outdated
- self.make_file(td, "mpath/sub/long_name/")
- def makepath(p: str) -> str:
- return os.path.join(td, p)
- search = SearchPaths(
- python_path=(makepath("base"),),
- mypy_path=(makepath("mpath/sub"),),
- package_path=(makepath("pkg1"), makepath("pkg2")),
- typeshed_path=(makepath("typeshed"),),
- )
- fscache = FileSystemCache()
- res = filter_out_missing_top_level_packages(
- {"a", "b", "c", "d", "e", "f", "g", "long_name", "ff", "missing"}, search, fscache
- )
- assert res == {"a", "b", "c", "d", "f", "long_name"}
- def make_file(self, base: str, path: str) -> None:
- fullpath = os.path.join(base, path)
- os.makedirs(os.path.dirname(fullpath), exist_ok=True)
- if not path.endswith("/"):
- with open(fullpath, "w") as f:
- f.write("# test file")
|