/
primer_tool.py
139 lines (117 loc) · 5.1 KB
/
primer_tool.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
from __future__ import annotations
import argparse
import json
from io import StringIO
from pathlib import Path
import git
from pylint.lint import Run
from pylint.reporters import JSONReporter
from pylint.testutils.primer import PackageToLint
TESTS_DIR = Path(__file__).parent.parent
PRIMER_DIRECTORY = TESTS_DIR / ".pylint_primer_tests/"
PACKAGES_TO_PRIME_PATH = Path(__file__).parent / "packages_to_prime.json"
class Primer:
"""Main class to handle priming of packages."""
def __init__(self, json_path: Path) -> None:
# Preparing arguments
self._argument_parser = argparse.ArgumentParser(prog="Pylint Primer")
self._subparsers = self._argument_parser.add_subparsers(dest="command")
# All arguments for the prepare parser
prepare_parser = self._subparsers.add_parser("prepare")
prepare_parser.add_argument(
"--clone", help="Clone all packages.", action="store_true", default=False
)
prepare_parser.add_argument(
"--check",
help="Check consistencies and commits of all packages.",
action="store_true",
default=False,
)
prepare_parser.add_argument(
"--make-commit-string",
help="Get latest commit string.",
action="store_true",
default=False,
)
prepare_parser.add_argument(
"--read-commit-string",
help="Print latest commit string.",
action="store_true",
default=False,
)
# All arguments for the run parser
run_parser = self._subparsers.add_parser("run")
run_parser.add_argument(
"--type", choices=["main", "pr"], required=True, help="Type of primer run."
)
# Storing arguments
self.config = self._argument_parser.parse_args()
self.packages = self._get_packages_to_lint_from_json(json_path)
"""All packages to prime."""
def run(self) -> None:
if self.config.command == "prepare":
self._handle_prepare_command()
if self.config.command == "run":
self._handle_run_command()
def _handle_prepare_command(self) -> None:
commit_string = ""
if self.config.clone:
for package, data in self.packages.items():
local_commit = data.lazy_clone()
print(f"Cloned '{package}' at commit '{local_commit}'.")
commit_string += local_commit + "_"
elif self.config.check:
for package, data in self.packages.items():
local_commit = git.Repo(data.clone_directory).head.object.hexsha
print(f"Found '{package}' at commit '{local_commit}'.")
commit_string += local_commit + "_"
elif self.config.make_commit_string:
for package, data in self.packages.items():
remote_sha1_commit = (
git.cmd.Git().ls_remote(data.url, data.branch).split("\t")[0]
)
print(f"'{package}' remote is at commit '{remote_sha1_commit}'.")
commit_string += remote_sha1_commit + "_"
elif self.config.read_commit_string:
with open(PRIMER_DIRECTORY / "commit_string.txt", encoding="utf-8") as f:
print(f.read())
if commit_string:
with open(
PRIMER_DIRECTORY / "commit_string.txt", "w", encoding="utf-8"
) as f:
f.write(commit_string)
def _handle_run_command(self) -> None:
packages: dict[str, list[dict[str, str | int]]] = {}
for package, data in self.packages.items():
output = self._lint_package(data)
packages[package] = output
print(f"Successfully primed {package}.")
with open(
PRIMER_DIRECTORY / f"output_{self.config.type}.txt", "w", encoding="utf-8"
) as f:
json.dump(packages, f)
def _lint_package(self, data: PackageToLint) -> list[dict[str, str | int]]:
# We want to test all the code we can
enables = ["--enable-all-extensions", "--enable=all"]
# Duplicate code takes too long and is relatively safe
disables = ["--disable=duplicate-code"]
arguments = data.pylint_args + enables + disables
if data.pylintrc_relpath:
arguments += [f"--rcfile={data.pylintrc_relpath}"]
output = StringIO()
reporter = JSONReporter(output)
Run(arguments, reporter=reporter, do_exit=False)
return json.loads(output.getvalue())
@staticmethod
def _get_packages_to_lint_from_json(json_path: Path) -> dict[str, PackageToLint]:
with open(json_path, encoding="utf8") as f:
return {
name: PackageToLint(**package_data)
for name, package_data in json.load(f).items()
}
if __name__ == "__main__":
primer = Primer(PACKAGES_TO_PRIME_PATH)
primer.run()