lintro 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lintro might be problematic. Click here for more details.
- lintro/__init__.py +3 -0
- lintro/__main__.py +6 -0
- lintro/ascii-art/fail.txt +404 -0
- lintro/ascii-art/success.txt +484 -0
- lintro/cli.py +70 -0
- lintro/cli_utils/__init__.py +7 -0
- lintro/cli_utils/commands/__init__.py +7 -0
- lintro/cli_utils/commands/check.py +210 -0
- lintro/cli_utils/commands/format.py +167 -0
- lintro/cli_utils/commands/list_tools.py +114 -0
- lintro/enums/__init__.py +0 -0
- lintro/enums/action.py +29 -0
- lintro/enums/darglint_strictness.py +22 -0
- lintro/enums/group_by.py +31 -0
- lintro/enums/hadolint_enums.py +46 -0
- lintro/enums/output_format.py +40 -0
- lintro/enums/tool_name.py +36 -0
- lintro/enums/tool_type.py +27 -0
- lintro/enums/yamllint_format.py +22 -0
- lintro/exceptions/__init__.py +0 -0
- lintro/exceptions/errors.py +15 -0
- lintro/formatters/__init__.py +0 -0
- lintro/formatters/core/__init__.py +0 -0
- lintro/formatters/core/output_style.py +21 -0
- lintro/formatters/core/table_descriptor.py +24 -0
- lintro/formatters/styles/__init__.py +17 -0
- lintro/formatters/styles/csv.py +41 -0
- lintro/formatters/styles/grid.py +91 -0
- lintro/formatters/styles/html.py +48 -0
- lintro/formatters/styles/json.py +61 -0
- lintro/formatters/styles/markdown.py +41 -0
- lintro/formatters/styles/plain.py +39 -0
- lintro/formatters/tools/__init__.py +35 -0
- lintro/formatters/tools/darglint_formatter.py +72 -0
- lintro/formatters/tools/hadolint_formatter.py +84 -0
- lintro/formatters/tools/prettier_formatter.py +76 -0
- lintro/formatters/tools/ruff_formatter.py +116 -0
- lintro/formatters/tools/yamllint_formatter.py +87 -0
- lintro/models/__init__.py +0 -0
- lintro/models/core/__init__.py +0 -0
- lintro/models/core/tool.py +104 -0
- lintro/models/core/tool_config.py +23 -0
- lintro/models/core/tool_result.py +39 -0
- lintro/parsers/__init__.py +0 -0
- lintro/parsers/darglint/__init__.py +0 -0
- lintro/parsers/darglint/darglint_issue.py +9 -0
- lintro/parsers/darglint/darglint_parser.py +62 -0
- lintro/parsers/hadolint/__init__.py +1 -0
- lintro/parsers/hadolint/hadolint_issue.py +24 -0
- lintro/parsers/hadolint/hadolint_parser.py +65 -0
- lintro/parsers/prettier/__init__.py +0 -0
- lintro/parsers/prettier/prettier_issue.py +10 -0
- lintro/parsers/prettier/prettier_parser.py +60 -0
- lintro/parsers/ruff/__init__.py +1 -0
- lintro/parsers/ruff/ruff_issue.py +43 -0
- lintro/parsers/ruff/ruff_parser.py +89 -0
- lintro/parsers/yamllint/__init__.py +0 -0
- lintro/parsers/yamllint/yamllint_issue.py +24 -0
- lintro/parsers/yamllint/yamllint_parser.py +68 -0
- lintro/tools/__init__.py +40 -0
- lintro/tools/core/__init__.py +0 -0
- lintro/tools/core/tool_base.py +320 -0
- lintro/tools/core/tool_manager.py +167 -0
- lintro/tools/implementations/__init__.py +0 -0
- lintro/tools/implementations/tool_darglint.py +245 -0
- lintro/tools/implementations/tool_hadolint.py +302 -0
- lintro/tools/implementations/tool_prettier.py +270 -0
- lintro/tools/implementations/tool_ruff.py +618 -0
- lintro/tools/implementations/tool_yamllint.py +240 -0
- lintro/tools/tool_enum.py +17 -0
- lintro/utils/__init__.py +0 -0
- lintro/utils/ascii_normalize_cli.py +84 -0
- lintro/utils/config.py +39 -0
- lintro/utils/console_logger.py +783 -0
- lintro/utils/formatting.py +173 -0
- lintro/utils/output_manager.py +301 -0
- lintro/utils/path_utils.py +41 -0
- lintro/utils/tool_executor.py +443 -0
- lintro/utils/tool_utils.py +431 -0
- lintro-0.3.2.dist-info/METADATA +338 -0
- lintro-0.3.2.dist-info/RECORD +85 -0
- lintro-0.3.2.dist-info/WHEEL +5 -0
- lintro-0.3.2.dist-info/entry_points.txt +2 -0
- lintro-0.3.2.dist-info/licenses/LICENSE +21 -0
- lintro-0.3.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Hadolint issue model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class HadolintIssue:
|
|
8
|
+
"""Represents an issue found by hadolint.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
file: File path where the issue was found
|
|
12
|
+
line: Line number where the issue occurs
|
|
13
|
+
column: Column number where the issue occurs (if available)
|
|
14
|
+
level: Severity level (error, warning, info, style)
|
|
15
|
+
code: Rule code (e.g., DL3006, SC2086)
|
|
16
|
+
message: Description of the issue
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
file: str
|
|
20
|
+
line: int
|
|
21
|
+
column: int | None
|
|
22
|
+
level: str
|
|
23
|
+
code: str
|
|
24
|
+
message: str
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Parser for hadolint output."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from lintro.parsers.hadolint.hadolint_issue import HadolintIssue
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_hadolint_output(output: str) -> list[HadolintIssue]:
|
|
9
|
+
"""Parse hadolint output into a list of HadolintIssue objects.
|
|
10
|
+
|
|
11
|
+
Hadolint outputs in the format:
|
|
12
|
+
filename:line code level: message
|
|
13
|
+
|
|
14
|
+
Example outputs:
|
|
15
|
+
Dockerfile:1 DL3006 error: Always tag the version of an image explicitly
|
|
16
|
+
Dockerfile:3 DL3009 warning: Delete the apt-get lists after installing
|
|
17
|
+
something
|
|
18
|
+
Dockerfile:5 DL3015 info: Avoid additional packages by specifying
|
|
19
|
+
`--no-install-recommends`
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
output: The raw output from hadolint
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
List of HadolintIssue objects
|
|
26
|
+
"""
|
|
27
|
+
issues: list[HadolintIssue] = []
|
|
28
|
+
|
|
29
|
+
# Skip empty output
|
|
30
|
+
if not output.strip():
|
|
31
|
+
return issues
|
|
32
|
+
|
|
33
|
+
# Pattern for hadolint output: filename:line code level: message
|
|
34
|
+
pattern: re.Pattern[str] = re.compile(
|
|
35
|
+
r"^(.+?):(\d+)\s+([A-Z]+\d+)\s+(error|warning|info|style):\s+(.+)$"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
lines: list[str] = output.splitlines()
|
|
39
|
+
|
|
40
|
+
for line in lines:
|
|
41
|
+
line = line.strip()
|
|
42
|
+
if not line:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
match: re.Match[str] | None = pattern.match(line)
|
|
46
|
+
if match:
|
|
47
|
+
file: str
|
|
48
|
+
line_num: str
|
|
49
|
+
code: str
|
|
50
|
+
level: str
|
|
51
|
+
message: str
|
|
52
|
+
file, line_num, code, level, message = match.groups()
|
|
53
|
+
|
|
54
|
+
issues.append(
|
|
55
|
+
HadolintIssue(
|
|
56
|
+
file=file,
|
|
57
|
+
line=int(line_num),
|
|
58
|
+
column=None, # hadolint doesn't provide column in this format
|
|
59
|
+
level=level,
|
|
60
|
+
code=code,
|
|
61
|
+
message=message.strip(),
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return issues
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Parser for prettier output.
|
|
2
|
+
|
|
3
|
+
Handles typical Prettier CLI output for --check and --write modes,
|
|
4
|
+
including ANSI-colored lines produced in CI environments.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
from lintro.parsers.prettier.prettier_issue import PrettierIssue
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_prettier_output(output: str) -> list[PrettierIssue]:
|
|
13
|
+
"""Parse prettier output into a list of PrettierIssue objects.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
output: The raw output from prettier
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
List of PrettierIssue objects
|
|
20
|
+
"""
|
|
21
|
+
issues: list[PrettierIssue] = []
|
|
22
|
+
|
|
23
|
+
if not output:
|
|
24
|
+
return issues
|
|
25
|
+
|
|
26
|
+
# Prettier output format when issues are found:
|
|
27
|
+
# "Checking formatting..."
|
|
28
|
+
# "[warn] path/to/file.js"
|
|
29
|
+
# "[warn] Code style issues found in the above file. Run Prettier with --write \
|
|
30
|
+
# to fix."
|
|
31
|
+
# Normalize output by stripping ANSI escape sequences to make matching robust
|
|
32
|
+
# across different terminals and CI runners.
|
|
33
|
+
# Example: "[\x1b[33mwarn\x1b[39m] file.js" -> "[warn] file.js"
|
|
34
|
+
ansi_escape = re.compile(r"\x1b\[[0-9;]*m")
|
|
35
|
+
normalized_output = ansi_escape.sub("", output)
|
|
36
|
+
|
|
37
|
+
lines = normalized_output.splitlines()
|
|
38
|
+
|
|
39
|
+
for i, line in enumerate(lines):
|
|
40
|
+
line = line.strip()
|
|
41
|
+
if not line:
|
|
42
|
+
continue
|
|
43
|
+
|
|
44
|
+
# Look for [warn] lines that contain file paths
|
|
45
|
+
if line.startswith("[warn]") and not line.endswith("fix."):
|
|
46
|
+
# Extract the file path from the [warn] line
|
|
47
|
+
file_path = line[6:].strip() # Remove "[warn] " prefix
|
|
48
|
+
if file_path and not file_path.startswith("Code style issues"):
|
|
49
|
+
# Create a generic issue for the file
|
|
50
|
+
issues.append(
|
|
51
|
+
PrettierIssue(
|
|
52
|
+
file=file_path,
|
|
53
|
+
line=1, # Prettier doesn't provide specific line numbers
|
|
54
|
+
code="FORMAT",
|
|
55
|
+
message="Code style issues found",
|
|
56
|
+
column=1, # Prettier doesn't provide specific column numbers
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return issues
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Ruff parser module."""
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Models for ruff issues."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class RuffIssue:
|
|
8
|
+
"""Represents a ruff linting issue.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
file: File path where the issue was found.
|
|
12
|
+
line: Line number where the issue was found.
|
|
13
|
+
column: Column number where the issue was found.
|
|
14
|
+
code: Ruff error code (e.g., E401, F401).
|
|
15
|
+
message: Human-readable error message.
|
|
16
|
+
url: Optional URL to documentation for this error.
|
|
17
|
+
end_line: End line number for multi-line issues.
|
|
18
|
+
end_column: End column number for multi-line issues.
|
|
19
|
+
fixable: Whether this issue can be auto-fixed.
|
|
20
|
+
fix_applicability: Whether the fix is safe or unsafe (safe, unsafe, or None).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
file: str
|
|
24
|
+
line: int
|
|
25
|
+
column: int
|
|
26
|
+
code: str
|
|
27
|
+
message: str
|
|
28
|
+
url: str | None = None
|
|
29
|
+
end_line: int | None = None
|
|
30
|
+
end_column: int | None = None
|
|
31
|
+
fixable: bool = False
|
|
32
|
+
fix_applicability: str | None = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class RuffFormatIssue:
|
|
37
|
+
"""Represents a ruff formatting issue.
|
|
38
|
+
|
|
39
|
+
Attributes:
|
|
40
|
+
file: File path that would be reformatted.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
file: str
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Parser for ruff output (lint and format).
|
|
2
|
+
|
|
3
|
+
This module provides functions to parse both:
|
|
4
|
+
- ruff check --output-format json (linting issues)
|
|
5
|
+
- ruff format --check (plain text: files needing formatting)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
from lintro.parsers.ruff.ruff_issue import RuffIssue
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def parse_ruff_output(output: str) -> list[RuffIssue]:
|
|
14
|
+
"""Parse ruff JSON output into a list of RuffIssue objects.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
output: The raw JSON output from ruff
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
List of RuffIssue objects
|
|
21
|
+
"""
|
|
22
|
+
issues: list[RuffIssue] = []
|
|
23
|
+
|
|
24
|
+
if not output or output.strip() == "[]":
|
|
25
|
+
return issues
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
# Ruff outputs JSON array of issue objects, but may have warnings
|
|
29
|
+
# after. Find the end of the JSON array by looking for the
|
|
30
|
+
# closing
|
|
31
|
+
# bracket
|
|
32
|
+
json_end = output.rfind("]")
|
|
33
|
+
if json_end == -1:
|
|
34
|
+
# No closing bracket found, try to parse the whole output
|
|
35
|
+
ruff_data = json.loads(output)
|
|
36
|
+
else:
|
|
37
|
+
# Extract just the JSON part (up to and including the closing bracket)
|
|
38
|
+
json_part = output[: json_end + 1]
|
|
39
|
+
ruff_data = json.loads(json_part)
|
|
40
|
+
|
|
41
|
+
for item in ruff_data:
|
|
42
|
+
# Extract fix applicability if available
|
|
43
|
+
fix_applicability = None
|
|
44
|
+
if item.get("fix"):
|
|
45
|
+
fix_applicability = item["fix"].get("applicability")
|
|
46
|
+
|
|
47
|
+
issues.append(
|
|
48
|
+
RuffIssue(
|
|
49
|
+
file=item["filename"],
|
|
50
|
+
line=item["location"]["row"],
|
|
51
|
+
column=item["location"]["column"],
|
|
52
|
+
code=item["code"],
|
|
53
|
+
message=item["message"],
|
|
54
|
+
url=item.get("url"),
|
|
55
|
+
end_line=item["end_location"]["row"],
|
|
56
|
+
end_column=item["end_location"]["column"],
|
|
57
|
+
fixable=bool(item.get("fix")),
|
|
58
|
+
fix_applicability=fix_applicability,
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
except (json.JSONDecodeError, KeyError, TypeError):
|
|
62
|
+
# If JSON parsing fails, return empty list
|
|
63
|
+
# Could also log the error for debugging
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
return issues
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def parse_ruff_format_check_output(output: str) -> list[str]:
|
|
70
|
+
"""Parse the output of `ruff format --check` to get files needing formatting.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
output: The raw output from `ruff format --check`
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
List of file paths that would be reformatted
|
|
77
|
+
"""
|
|
78
|
+
if not output:
|
|
79
|
+
return []
|
|
80
|
+
files = []
|
|
81
|
+
for line in output.splitlines():
|
|
82
|
+
line = line.strip()
|
|
83
|
+
# Ruff format --check output: 'Would reformat: path/to/file.py' or
|
|
84
|
+
# 'Would reformat path/to/file.py'
|
|
85
|
+
if line.startswith("Would reformat: "):
|
|
86
|
+
files.append(line[len("Would reformat: ") :])
|
|
87
|
+
elif line.startswith("Would reformat "):
|
|
88
|
+
files.append(line[len("Would reformat ") :])
|
|
89
|
+
return files
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Yamllint issue model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class YamllintIssue:
|
|
8
|
+
"""Represents an issue found by yamllint.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
file: File path where the issue was found
|
|
12
|
+
line: Line number where the issue occurs
|
|
13
|
+
column: Column number where the issue occurs (if available)
|
|
14
|
+
level: Severity level (error, warning)
|
|
15
|
+
rule: Rule name that was violated (e.g., line-length, trailing-spaces)
|
|
16
|
+
message: Description of the issue
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
file: str
|
|
20
|
+
line: int
|
|
21
|
+
column: int | None
|
|
22
|
+
level: str
|
|
23
|
+
rule: str | None
|
|
24
|
+
message: str
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Parser for yamllint output."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from lintro.parsers.yamllint.yamllint_issue import YamllintIssue
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_yamllint_output(output: str) -> list[YamllintIssue]:
|
|
9
|
+
"""Parse yamllint output into a list of YamllintIssue objects.
|
|
10
|
+
|
|
11
|
+
Yamllint outputs in parsable format as:
|
|
12
|
+
filename:line:column: [level] message (rule)
|
|
13
|
+
|
|
14
|
+
Example outputs:
|
|
15
|
+
test_samples/yaml_violations.yml:3:1: [warning] missing document start
|
|
16
|
+
"---" (document-start)
|
|
17
|
+
test_samples/yaml_violations.yml:6:32: [error] trailing spaces
|
|
18
|
+
(trailing-spaces)
|
|
19
|
+
test_samples/yaml_violations.yml:11:81: [error] line too long (149 > 80
|
|
20
|
+
characters) (line-length)
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
output: The raw output from yamllint
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
List of YamllintIssue objects
|
|
27
|
+
"""
|
|
28
|
+
issues: list[YamllintIssue] = []
|
|
29
|
+
|
|
30
|
+
# Skip empty output
|
|
31
|
+
if not output.strip():
|
|
32
|
+
return issues
|
|
33
|
+
|
|
34
|
+
lines: list[str] = output.splitlines()
|
|
35
|
+
|
|
36
|
+
for line in lines:
|
|
37
|
+
line = line.strip()
|
|
38
|
+
if not line:
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
# Pattern for yamllint parsable format: "filename:line:column: [level]
|
|
42
|
+
# message (rule)"
|
|
43
|
+
pattern: re.Pattern[str] = re.compile(
|
|
44
|
+
r"^([^:]+):(\d+):(\d+):\s*\[(error|warning)\]\s+(.+?)(?:\s+\(([^)]+)\))?$"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
match: re.Match[str] | None = pattern.match(line)
|
|
48
|
+
if match:
|
|
49
|
+
filename: str
|
|
50
|
+
line_num: str
|
|
51
|
+
column: str
|
|
52
|
+
level: str
|
|
53
|
+
message: str
|
|
54
|
+
rule: str | None
|
|
55
|
+
filename, line_num, column, level, message, rule = match.groups()
|
|
56
|
+
|
|
57
|
+
issues.append(
|
|
58
|
+
YamllintIssue(
|
|
59
|
+
file=filename,
|
|
60
|
+
line=int(line_num),
|
|
61
|
+
column=int(column) if column else None,
|
|
62
|
+
level=level,
|
|
63
|
+
rule=rule,
|
|
64
|
+
message=message.strip(),
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return issues
|
lintro/tools/__init__.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Tool implementations for Lintro."""
|
|
2
|
+
|
|
3
|
+
from lintro.enums.tool_type import ToolType
|
|
4
|
+
from lintro.models.core.tool import Tool
|
|
5
|
+
from lintro.models.core.tool_config import ToolConfig
|
|
6
|
+
from lintro.tools.core.tool_manager import ToolManager
|
|
7
|
+
|
|
8
|
+
# Import core implementations after Tool class definition to avoid circular imports
|
|
9
|
+
from lintro.tools.implementations.tool_darglint import DarglintTool
|
|
10
|
+
from lintro.tools.implementations.tool_hadolint import HadolintTool
|
|
11
|
+
from lintro.tools.implementations.tool_prettier import PrettierTool
|
|
12
|
+
from lintro.tools.implementations.tool_ruff import RuffTool
|
|
13
|
+
from lintro.tools.implementations.tool_yamllint import YamllintTool
|
|
14
|
+
from lintro.tools.tool_enum import ToolEnum
|
|
15
|
+
|
|
16
|
+
# Create global core manager instance
|
|
17
|
+
tool_manager = ToolManager()
|
|
18
|
+
|
|
19
|
+
# Register all available tools using ToolEnum
|
|
20
|
+
AVAILABLE_TOOLS = {tool_enum: tool_enum.value for tool_enum in ToolEnum}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
for tool_enum, tool_class in AVAILABLE_TOOLS.items():
|
|
24
|
+
tool_manager.register_tool(tool_class)
|
|
25
|
+
|
|
26
|
+
# Consolidated exports
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Tool",
|
|
29
|
+
"ToolConfig",
|
|
30
|
+
"ToolType",
|
|
31
|
+
"ToolManager",
|
|
32
|
+
"ToolEnum",
|
|
33
|
+
"tool_manager",
|
|
34
|
+
"AVAILABLE_TOOLS",
|
|
35
|
+
"DarglintTool",
|
|
36
|
+
"HadolintTool",
|
|
37
|
+
"PrettierTool",
|
|
38
|
+
"RuffTool",
|
|
39
|
+
"YamllintTool",
|
|
40
|
+
]
|
|
File without changes
|