summaryrefslogtreecommitdiffstats
path: root/tools/lint/python/pylint.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lint/python/pylint.py')
-rw-r--r--tools/lint/python/pylint.py137
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/lint/python/pylint.py b/tools/lint/python/pylint.py
new file mode 100644
index 0000000000..ba95be1f0b
--- /dev/null
+++ b/tools/lint/python/pylint.py
@@ -0,0 +1,137 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+import os
+import subprocess
+
+import signal
+
+from mozprocess import ProcessHandler
+
+from mozlint import result
+from mozlint.pathutils import expand_exclusions
+
+here = os.path.abspath(os.path.dirname(__file__))
+PYLINT_REQUIREMENTS_PATH = os.path.join(here, "pylint_requirements.txt")
+
+PYLINT_NOT_FOUND = """
+Could not find pylint! Install pylint and try again.
+
+ $ pip install -U --require-hashes -r {}
+""".strip().format(
+ PYLINT_REQUIREMENTS_PATH
+)
+
+
+PYLINT_INSTALL_ERROR = """
+Unable to install correct version of pylint
+Try to install it manually with:
+ $ pip install -U --require-hashes -r {}
+""".strip().format(
+ PYLINT_REQUIREMENTS_PATH
+)
+
+
+class PylintProcess(ProcessHandler):
+ def __init__(self, config, *args, **kwargs):
+ self.config = config
+ kwargs["stream"] = False
+ kwargs["universal_newlines"] = True
+ ProcessHandler.__init__(self, *args, **kwargs)
+
+ def run(self, *args, **kwargs):
+ orig = signal.signal(signal.SIGINT, signal.SIG_IGN)
+ ProcessHandler.run(self, *args, **kwargs)
+ signal.signal(signal.SIGINT, orig)
+
+
+def setup(root, **lintargs):
+ virtualenv_manager = lintargs["virtualenv_manager"]
+ try:
+ virtualenv_manager.install_pip_requirements(
+ PYLINT_REQUIREMENTS_PATH,
+ quiet=True,
+ # The defined versions of astroid and lazy-object-proxy conflict and fail to
+ # install with the new 2020 pip resolver (bug 1682959)
+ legacy_resolver=True,
+ )
+ except subprocess.CalledProcessError:
+ print(PYLINT_INSTALL_ERROR)
+ return 1
+
+
+def get_pylint_binary():
+ return "pylint"
+
+
+def run_process(config, cmd):
+ proc = PylintProcess(config, cmd)
+ proc.run()
+ try:
+ proc.wait()
+ except KeyboardInterrupt:
+ proc.kill()
+
+ return proc.output
+
+
+def parse_issues(log, config, issues_json, path):
+ results = []
+
+ try:
+ issues = json.loads(issues_json)
+ except json.decoder.JSONDecodeError:
+ log.debug("Could not parse the output:")
+ log.debug("pylint output: {}".format(issues_json))
+ return []
+
+ for issue in issues:
+ res = {
+ "path": issue["path"],
+ "level": issue["type"],
+ "lineno": issue["line"],
+ "column": issue["column"],
+ "message": issue["message"],
+ "rule": issue["message-id"],
+ }
+ results.append(result.from_config(config, **res))
+ return results
+
+
+def get_pylint_version(binary):
+ return subprocess.check_output(
+ [binary, "--version"],
+ universal_newlines=True,
+ stderr=subprocess.STDOUT,
+ )
+
+
+def lint(paths, config, **lintargs):
+ log = lintargs["log"]
+
+ binary = get_pylint_binary()
+
+ log = lintargs["log"]
+ paths = list(expand_exclusions(paths, config, lintargs["root"]))
+
+ cmd_args = [binary]
+ results = []
+
+ # list from https://code.visualstudio.com/docs/python/linting#_pylint
+ # And ignore a bit more elements
+ cmd_args += [
+ "-fjson",
+ "--disable=all",
+ "--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode,no-else-return", # NOQA: E501
+ "--disable=import-error,no-member",
+ ]
+
+ base_command = cmd_args + paths
+ log.debug("Command: {}".format(" ".join(cmd_args)))
+ log.debug("pylint version: {}".format(get_pylint_version(binary)))
+ output = " ".join(run_process(config, base_command))
+ results = parse_issues(log, config, str(output), [])
+
+ return results