Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / tools / lint / rst / __init__.py
blob6b819c5af23efea2371f4361f75297fccf6d51f9
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 import os
6 import re
7 import subprocess
9 from mozfile import which
10 from mozlint import result
11 from mozlint.pathutils import expand_exclusions
13 # Error Levels
14 # (0, 'debug')
15 # (1, 'info')
16 # (2, 'warning')
17 # (3, 'error')
18 # (4, 'severe')
20 abspath = os.path.abspath(os.path.dirname(__file__))
21 rstcheck_requirements_file = os.path.join(abspath, "requirements.txt")
23 results = []
25 RSTCHECK_NOT_FOUND = """
26 Could not find rstcheck! Install rstcheck and try again.
28 $ pip install -U --require-hashes -r {}
29 """.strip().format(
30 rstcheck_requirements_file
33 RSTCHECK_INSTALL_ERROR = """
34 Unable to install required version of rstcheck
35 Try to install it manually with:
36 $ pip install -U --require-hashes -r {}
37 """.strip().format(
38 rstcheck_requirements_file
41 RSTCHECK_FORMAT_REGEX = re.compile(r"(.*):(.*): \(.*/([0-9]*)\) (.*)$")
44 def get_rstcheck_binary():
45 """
46 Returns the path of the first rstcheck binary available
47 if not found returns None
48 """
49 binary = os.environ.get("RSTCHECK")
50 if binary:
51 return binary
53 return which("rstcheck")
56 def parse_with_split(errors):
57 match = RSTCHECK_FORMAT_REGEX.match(errors)
58 if not match:
59 return None
60 filename, lineno, level, message = match.groups()
62 return filename, lineno, level, message
65 def lint(files, config, **lintargs):
66 log = lintargs["log"]
67 config["root"] = lintargs["root"]
68 paths = expand_exclusions(files, config, config["root"])
69 paths = list(paths)
70 chunk_size = 50
71 binary = get_rstcheck_binary()
73 while paths:
74 # Config for rstcheck is stored in `/.rstcheck.cfg`.
75 cmdargs = [which("python"), binary] + paths[:chunk_size]
76 log.debug("Command: {}".format(" ".join(cmdargs)))
78 proc = subprocess.Popen(
79 cmdargs,
80 stdout=subprocess.PIPE,
81 stderr=subprocess.PIPE,
82 env=os.environ,
83 universal_newlines=True,
85 all_errors = proc.communicate()[1]
86 for errors in all_errors.split("\n"):
87 if len(errors) > 1:
88 split_result = parse_with_split(errors)
89 if split_result:
90 filename, lineno, level, message = split_result
91 res = {
92 "path": filename,
93 "message": message,
94 "lineno": lineno,
95 "level": "error" if int(level) >= 2 else "warning",
97 results.append(result.from_config(config, **res))
98 paths = paths[chunk_size:]
100 return results