Failed Conditions
Pull Request — master (#1109)
by Abdeali
02:35
created

coalib.bearlib.abstractions.Lint.process_output()   A

Complexity

Conditions 3

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 7
rs 9.4286
1
import subprocess
2
import tempfile
3
import re
4
import sys
5
6
from coalib.misc.Shell import escape_path_argument
7
from coalib.results.Result import Result
8
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY
9
10
11
class Lint():
12
    """
13
    :param executable:   The executable to run the linter.
14
    :param arguments:    The arguments to supply to the linter, such
15
                         that the file name to be analyzed can be
16
                         appended to the end.
17
    :param output_regex: The regex which will match the output of the linter to
18
                         get results. Thie regex should give out the following
19
                         variables:
20
                          line - The line where the issue starts.
21
                          column - The column where the issue starts.
22
                          end_line - The line where the issue ends.
23
                          end_column - The column where the issue ends.
24
                          severity - The severity of the issue.
25
                          message - The message of the result.
26
    """
27
    executable = None
28
    arguments = ""
29
    output_regex = re.compile(r'(?P<line>\d+)\.(?P<column>\d+)\|'
30
                              r'(?P<severity>\d+): (?P<message>.*)')
31
32
    def lint(self, filename):
33
        """
34
        Takes a file and lints it using the linter variables defined apriori.
35
36
        :param filename: The name of the file to execute.
37
        """
38
        command = (self.executable + ' ' + self.arguments + ' '
39
                   + escape_path_argument(filename))
40
        stderr_file = tempfile.TemporaryFile()
41
        stdout_file = tempfile.TemporaryFile()
42
        process = subprocess.Popen(
43
            command,
44
            shell=True,
45
            stdout=stdout_file,
46
            stderr=stderr_file,
47
            universal_newlines=True)
48
        process.wait()
49
        stdout_file.seek(0)
50
        output = stdout_file.read().decode(sys.stdout.encoding,
51
                                           errors="replace")
52
        stdout_file.close()
53
        stderr_file.close()
54
        return self.process_output(output, filename)
55
56
    def process_output(self, output, filename):
57
        regex = self.output_regex
58
        if isinstance(regex, str):
59
            regex = regex % {"file_name": filename}
60
61
        for match in re.finditer(regex, output):
62
            yield self.match_to_result(match, filename)
63
64
    def _get_groupdict(self, match):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
65
        groups = match.groupdict()
66
        # Attempt to convert all values from string to int as regex only
67
        # matches strings.
68
        for key, value in groups.items():
69
            try:
70
                value = int(value)
71
                groups[key] = value
72
            except (TypeError, ValueError):
73
                pass
74
        return groups
75
76
    def match_to_result(self, match, filename):
77
        """
78
        Converts a regex match's groups into a result.
79
80
        :param match:    The match got from regex parsing.
81
        :param filename: The name of the file from which this match is got.
82
        """
83
        groups = self._get_groupdict(match)
84
85
        return Result.from_values(
86
            origin=self,
87
            message=groups.get("message", ""),
88
            file=filename,
89
            severity=groups.get("severity", RESULT_SEVERITY.NORMAL),
90
            line=groups.get("line"),
91
            column=groups.get("column", 0),
92
            end_line=groups.get("end_line", None),
93
            end_column=groups.get("end_column", None))
94