gecko-dev/tools/lint/rst/__init__.py

101 строка
2.7 KiB
Python

# 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/.
from __future__ import absolute_import, print_function
import os
import subprocess
from mozlint import result
from mozlint.pathutils import expand_exclusions
from mozlint.util import pip
from mozfile import which
# Error Levels
# (0, 'debug')
# (1, 'info')
# (2, 'warning')
# (3, 'error')
# (4, 'severe')
abspath = os.path.abspath(os.path.dirname(__file__))
rstcheck_requirements_file = os.path.join(abspath, 'requirements.txt')
results = []
RSTCHECK_NOT_FOUND = """
Could not find rstcheck! Install rstcheck and try again.
$ pip install -U --require-hashes -r {}
""".strip().format(rstcheck_requirements_file)
RSTCHECK_INSTALL_ERROR = """
Unable to install required version of rstcheck
Try to install it manually with:
$ pip install -U --require-hashes -r {}
""".strip().format(rstcheck_requirements_file)
def setup(root, **lintargs):
if not pip.reinstall_program(rstcheck_requirements_file):
print(RSTCHECK_INSTALL_ERROR)
return 1
def get_rstcheck_binary():
"""
Returns the path of the first rstcheck binary available
if not found returns None
"""
binary = os.environ.get('RSTCHECK')
if binary:
return binary
return which('rstcheck')
def parse_with_split(errors):
filtered_output = errors.split(":")
filename = filtered_output[0]
lineno = filtered_output[1]
idx = filtered_output[2].index(") ")
level = filtered_output[2][0:idx].split("/")[1]
message = filtered_output[2][idx+2:].split("\n")[0]
return filename, lineno, level, message
def lint(files, config, **lintargs):
config['root'] = lintargs['root']
paths = expand_exclusions(files, config, config['root'])
paths = list(paths)
chunk_size = 50
binary = get_rstcheck_binary()
while paths:
cmdargs = [
binary,
] + paths[:chunk_size]
proc = subprocess.Popen(
cmdargs, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=os.environ
)
all_errors = proc.communicate()[1]
for errors in all_errors.split("\n"):
if len(errors) > 1:
filename, lineno, level, message = parse_with_split(errors)
res = {
'path': filename,
'message': message,
'lineno': lineno,
'level': "error" if int(level) >= 2 else "warning",
}
results.append(result.from_config(config, **res))
paths = paths[chunk_size:]
return results