blob: 85c0d8272976a49153b2df4cc1406290d7a2c5ec [file] [log] [blame] [edit]
"""Script that lints a list of changed files then outputs a list of comments."""
from __future__ import absolute_import
import collections
import logging
import os
import re
import subprocess
# path/to/file.py:27: [E1234(error-name), Text] Error message is here
LINT_WARNING_PATTERN = (r'^(?P<filename>[^:]+):(?P<line_num>\d+): '
r'\[(?P<error_code>\w+)\((?P<error_name>.*)\).*\] '
r'(?P<error_msg>.*)$')
class PylintError(Exception):
"""Error for the pylint module."""
def RunPylint(changed_files, pylintrc_file=None, cwd=None, executor=None):
"""Runs pylint on a list of changed files.
Args:
changed_files: List of files to lint.
pylintrc_file: Path to a pylintrc file to use with pylint (or None to use
the default pylintrc from depot_tools).
cwd: If provided, cwd in which to run pylint.
executor: If provided, object with which to invoke pylint.
Returns:
stdout of the pylint command.
Raises:
PylintError: if pylint cannot be found.
"""
if not changed_files:
return ''
pylint = os.path.expanduser('~/depot_tools/pylint')
if not os.path.exists(pylint):
logging.error('pylint not installed in expected location: %s', pylint)
raise PylintError('Could not find pylint.')
command = [pylint, '--output-format=parseable', '--disable=I']
if pylintrc_file:
command += ['--rcfile={}'.format(pylintrc_file)]
command += changed_files
if executor:
_, stdout, _ = executor.exec_subprocess(command, cwd=cwd)
return stdout
return subprocess.check_output(command, cwd=cwd)
def ParseLint(lines, cwd=None):
"""Reads lines from lint output and inserts them into comments.
Args:
lines: List of lint output lines to parse.
cwd: Base path relative to which parsed paths should be resolved.
Returns:
comments dictionary.
"""
comments = collections.defaultdict(list)
for line in lines:
match = re.match(LINT_WARNING_PATTERN, line)
if match:
warning = {
'line':
match.group('line_num'),
'message':
'{} [{}]'.format(
match.group('error_msg'), match.group('error_name'))
}
if cwd:
filename = os.path.relpath(match.group('filename'), cwd)
else:
filename = match.group('filename')
comments[filename].append(warning)
return comments