1
|
|
|
from subprocess import Popen, PIPE |
2
|
|
|
|
3
|
|
|
from coalib.bears.LocalBear import LocalBear |
4
|
|
|
from coalib.results.Diff import Diff |
5
|
|
|
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY |
6
|
|
|
from coalib.results.Result import Result |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
class CorrectionBasedBear(LocalBear): |
10
|
|
|
SEVERITY = RESULT_SEVERITY.NORMAL |
11
|
|
|
GET_REPLACEMENT = (lambda self, file, cli_options: |
12
|
|
|
self.__run_process(file, cli_options)) |
13
|
|
|
|
14
|
|
|
def __run_process(self, file, cli_options): |
15
|
|
|
process = Popen(self.BINARY + ' ' + cli_options, |
16
|
|
|
shell=True, |
17
|
|
|
stdin=PIPE, |
18
|
|
|
stdout=PIPE, |
19
|
|
|
stderr=PIPE, |
20
|
|
|
universal_newlines=True) |
21
|
|
|
process.stdin.writelines(file) |
22
|
|
|
process.stdin.close() |
23
|
|
|
process.wait() |
24
|
|
|
|
25
|
|
|
corrected = process.stdout.readlines() |
26
|
|
|
errors = process.stderr.readlines() |
27
|
|
|
|
28
|
|
|
process.stdout.close() |
29
|
|
|
process.stderr.close() |
30
|
|
|
|
31
|
|
|
return corrected, errors |
32
|
|
|
|
33
|
|
|
@staticmethod |
34
|
|
|
def __yield_diffs(file, new_file): |
35
|
|
|
if new_file != file: |
36
|
|
|
wholediff = Diff.from_string_arrays(file, new_file) |
37
|
|
|
|
38
|
|
|
for diff in wholediff.split_diff(): |
39
|
|
|
yield diff |
40
|
|
|
|
41
|
|
|
def __print_errors(self, errors): |
42
|
|
|
for line in filter(lambda error: bool(error.strip()), errors): |
43
|
|
|
self.warn(line) |
44
|
|
|
|
45
|
|
|
def retrieve_results(self, filename, file, **kwargs): |
46
|
|
|
""" |
47
|
|
|
Yields results using the self.GET_REPLACEMENT function. |
48
|
|
|
|
49
|
|
|
:param filename: The filename, just pass it over as you got it! |
50
|
|
|
:param file: The file, just pass it over as you got it! |
51
|
|
|
:param kwargs: Any keyword arguments that will be passed to the |
52
|
|
|
GET_REPLACEMENT function. Please provide cli_options |
53
|
|
|
if you don't override the default. |
54
|
|
|
""" |
55
|
|
|
new_file, errors = self.GET_REPLACEMENT(file=file, **kwargs) |
56
|
|
|
self.__print_errors(errors) |
57
|
|
|
|
58
|
|
|
for diff in self.__yield_diffs(file, new_file): |
59
|
|
|
yield Result( |
60
|
|
|
self, |
61
|
|
|
self.RESULT_MESSAGE, |
62
|
|
|
affected_code=(diff.range(filename),), |
63
|
|
|
diffs={filename: diff}, |
64
|
|
|
severity=self.SEVERITY) |
65
|
|
|
|
66
|
|
|
@classmethod |
67
|
|
|
def check_prerequisites(cls): |
68
|
|
|
try: |
69
|
|
|
bin_args = getattr(cls, "BINARY_CHECK_ARGUMENTS", "--version") |
70
|
|
|
Popen([cls.BINARY, bin_args], stdout=PIPE, stderr=PIPE) |
71
|
|
|
return True |
72
|
|
|
except OSError: |
73
|
|
|
return repr(cls.BINARY) + " is not installed." |
74
|
|
|
except AttributeError: |
75
|
|
|
# Happens when `BINARY` does not exist in `cls`. |
76
|
|
|
return True |
77
|
|
|
|