pylama_pylint.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. """Pylint integration to Pylama."""
  2. import logging
  3. from argparse import ArgumentParser
  4. from os import environ
  5. from pathlib import Path
  6. from typing import Dict
  7. from pylint.interfaces import CONFIDENCE_LEVELS
  8. from pylint.lint import Run
  9. from pylint.reporters import BaseReporter
  10. from pylama.context import RunContext
  11. from pylama.lint import LinterV2 as BaseLinter
  12. HOME_RCFILE = Path(environ.get("HOME", "")) / ".pylintrc"
  13. logger = logging.getLogger("pylama")
  14. class Linter(BaseLinter):
  15. """Check code with Pylint."""
  16. name = "pylint"
  17. @classmethod
  18. def add_args(cls, parser: ArgumentParser):
  19. """Add --max-complexity option."""
  20. parser.add_argument(
  21. "--pylint-confidence",
  22. choices=[cc.name for cc in CONFIDENCE_LEVELS],
  23. help="Only show warnings with the listed confidence levels.",
  24. )
  25. def run_check(self, ctx: RunContext):
  26. """Pylint code checking."""
  27. logger.debug("Start pylint")
  28. params = ctx.get_params("pylint")
  29. options = ctx.options
  30. if options:
  31. params.setdefault("max_line_length", options.max_line_length)
  32. params.setdefault("confidence", options.pylint_confidence)
  33. params.setdefault("enable", ctx.select | ctx.get_filter("pylint", "select"))
  34. params.setdefault("disable", ctx.ignore | ctx.get_filter("pylint", "ignore"))
  35. # if params.get("disable"):
  36. # params["disable"].add("W0012")
  37. class Reporter(BaseReporter):
  38. """Handle messages."""
  39. def _display(self, _):
  40. pass
  41. def handle_message(self, msg):
  42. msg_id = msg.msg_id
  43. ctx.push(
  44. filtrate=False,
  45. col=msg.column + 1,
  46. lnum=msg.line,
  47. number=msg_id,
  48. text=msg.msg,
  49. type=msg_id[0],
  50. source="pylint",
  51. )
  52. logger.debug(params)
  53. reporter = Reporter()
  54. args = _Params(params).to_attrs()
  55. Run([ctx.temp_filename] + args, reporter=reporter, exit=False)
  56. class _Params:
  57. """Store pylint params."""
  58. def __init__(self, params: Dict):
  59. attrs = {
  60. name.replace("_", "-"): self.prepare_value(value)
  61. for name, value in params.items()
  62. if value
  63. }
  64. if HOME_RCFILE.exists():
  65. attrs["rcfile"] = HOME_RCFILE.as_posix()
  66. if attrs.get("disable"):
  67. attrs["disable"] += ",W0012"
  68. else:
  69. attrs["disable"] = "W0012"
  70. self.attrs = attrs
  71. @staticmethod
  72. def prepare_value(value):
  73. """Prepare value to pylint."""
  74. if isinstance(value, (list, tuple, set)):
  75. return ",".join(value)
  76. if isinstance(value, bool):
  77. return "y" if value else "n"
  78. return str(value)
  79. def to_attrs(self):
  80. """Convert to argument list."""
  81. return [f"--{key}={value}" for key, value in self.attrs.items()] # noqa
  82. def __str__(self):
  83. return " ".join(self.to_attrs())
  84. def __repr__(self):
  85. return f"<Pylint {self}>"
  86. # pylama:ignore=W0403