pylama_mypy.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. """MyPy support.
  2. TODO: Error codes
  3. """
  4. from __future__ import annotations
  5. from mypy import api
  6. from pylama.context import RunContext
  7. from pylama.lint import LinterV2 as Abstract
  8. class Linter(Abstract):
  9. """MyPy runner."""
  10. name = "mypy"
  11. def run_check(self, ctx: RunContext):
  12. """Check code with mypy."""
  13. # Support stdin
  14. args = [ctx.temp_filename, "--follow-imports=skip", "--show-column-numbers"]
  15. stdout, _, _ = api.run(args) # noqa
  16. for line in stdout.splitlines():
  17. if not line:
  18. continue
  19. message = _MyPyMessage(line)
  20. if message.valid:
  21. ctx.push(
  22. source="mypy",
  23. lnum=message.line_num,
  24. col=message.column,
  25. text=message.text,
  26. type=message.types.get(message.message_type.strip(), "W"),
  27. )
  28. class _MyPyMessage:
  29. """Parser for a single MyPy output line."""
  30. types = {"error": "E", "warning": "W", "note": "N"}
  31. valid = False
  32. def __init__(self, line):
  33. self.filename = None
  34. self.line_num = None
  35. self.column = None
  36. try:
  37. result = line.split(":", maxsplit=4)
  38. self.filename, line_num_txt, column_txt, self.message_type, text = result
  39. except ValueError:
  40. return
  41. try:
  42. self.line_num = int(line_num_txt.strip())
  43. self.column = int(column_txt.strip())
  44. except ValueError:
  45. return
  46. self.text = text.strip()
  47. self.valid = True