forked from conan-io/hooks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
recipe_linter.py
82 lines (69 loc) · 3.32 KB
/
recipe_linter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# coding=utf-8
import json
import os
import platform
import subprocess
import sys
import re
from conans.errors import ConanException
from conans.tools import logger
try:
import astroid # Conan 'pylint_plugin.py' uses astroid
from pylint import epylint as lint
except ImportError as e:
sys.stderr.write("Install pylint to use 'recipe_linter' hook: 'pip install pylint astroid'")
sys.exit(1)
CONAN_HOOK_PYLINT_RCFILE = "CONAN_PYLINTRC"
CONAN_HOOK_PYLINT_WERR = "CONAN_PYLINT_WERR"
CONAN_HOOK_PYLINT_RECIPE_PLUGINS = "CONAN_PYLINT_RECIPE_PLUGINS"
def pre_export(output, conanfile_path, *args, **kwargs):
output.info("Lint recipe '{}'".format(conanfile_path))
conanfile_dirname = os.path.dirname(conanfile_path)
lint_args = ['--output-format=json', # JSON output fails in Windows (parsing)
'--py3k',
'--enable=all',
'--reports=no',
'--disable=no-absolute-import',
'--persistent=no',
# These were disabled in linter that was inside Conan
# '--disable=W0702', # No exception type(s) specified (bare-except)
# '--disable=W0703', # Catching too general exception Exception (broad-except)
'--init-hook="import sys;sys.path.extend([\'{}\',])"'.format(conanfile_dirname.replace('\\', '/'))
]
pylint_plugins = os.getenv(CONAN_HOOK_PYLINT_RECIPE_PLUGINS, 'conans.pylint_plugin')
if pylint_plugins:
lint_args += ['--load-plugins={}'.format(pylint_plugins)]
rc_file = os.getenv(CONAN_HOOK_PYLINT_RCFILE)
if rc_file:
lint_args += ['--rcfile', rc_file.replace('\\', '/')]
try:
command = ['pylint'] + lint_args + ['"{}"'.format(conanfile_path).replace('\\', '/')]
command = " ".join(command)
shell = bool(platform.system() != "Windows")
p = subprocess.Popen(command, shell=shell, bufsize=10,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pylint_stdout, pylint_stderr = p.communicate()
# Remove ANSI escape sequences from Pylint output (fails in Windows)
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
pylint_stdout = ansi_escape.sub('', pylint_stdout.decode('utf-8'))
except Exception as exc:
output.error("Unexpected error running linter: {}".format(exc))
else:
try:
messages = json.loads(pylint_stdout)
except Exception as exc:
output.error("Error parsing JSON output: {}".format(exc))
logger.error(
"Error parsing linter output for recipe '{}': {}".format(conanfile_path, exc))
logger.error(" - linter arguments: {}".format(lint_args))
logger.error(" - output: {}".format(pylint_stdout.getvalue()))
logger.error(" - stderr: {}".format(pylint_stderr.getvalue()))
else:
errors = 0
for msg in messages:
line = "{path}:{line}:{column}: {message-id}: {message} ({symbol})".format(**msg)
output.info(line)
errors += int(msg["type"] == "error")
output.info("Linter detected '{}' errors".format(errors))
if os.getenv(CONAN_HOOK_PYLINT_WERR) and errors:
raise ConanException("Package recipe has linter errors. Please fix them.")