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
lintro/cli.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Command-line interface for Lintro."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from lintro import __version__
|
|
6
|
+
from lintro.cli_utils.commands.check import check_command
|
|
7
|
+
from lintro.cli_utils.commands.format import format_code
|
|
8
|
+
from lintro.cli_utils.commands.list_tools import list_tools_command
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LintroGroup(click.Group):
|
|
12
|
+
def format_commands(
|
|
13
|
+
self,
|
|
14
|
+
ctx: click.Context,
|
|
15
|
+
formatter: click.HelpFormatter,
|
|
16
|
+
) -> None:
|
|
17
|
+
"""Render command list with aliases in the help output.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
ctx: click.Context: The Click context.
|
|
21
|
+
formatter: click.HelpFormatter: The help formatter to write to.
|
|
22
|
+
"""
|
|
23
|
+
# Group commands by canonical name and aliases
|
|
24
|
+
commands = self.list_commands(ctx)
|
|
25
|
+
# Map canonical name to (command, [aliases])
|
|
26
|
+
canonical_map = {}
|
|
27
|
+
for name in commands:
|
|
28
|
+
cmd = self.get_command(ctx, name)
|
|
29
|
+
if not hasattr(cmd, "_canonical_name"):
|
|
30
|
+
cmd._canonical_name = name
|
|
31
|
+
canonical = cmd._canonical_name
|
|
32
|
+
if canonical not in canonical_map:
|
|
33
|
+
canonical_map[canonical] = (cmd, [])
|
|
34
|
+
if name != canonical:
|
|
35
|
+
canonical_map[canonical][1].append(name)
|
|
36
|
+
rows = []
|
|
37
|
+
for canonical, (cmd, aliases) in canonical_map.items():
|
|
38
|
+
names = [canonical] + aliases
|
|
39
|
+
name_str = " / ".join(names)
|
|
40
|
+
rows.append((name_str, cmd.get_short_help_str()))
|
|
41
|
+
if rows:
|
|
42
|
+
with formatter.section("Commands"):
|
|
43
|
+
formatter.write_dl(rows)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@click.group(cls=LintroGroup, invoke_without_command=True)
|
|
47
|
+
@click.version_option(version=__version__)
|
|
48
|
+
def cli() -> None:
|
|
49
|
+
"""Lintro: Unified CLI for code formatting, linting, and quality assurance."""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Register canonical commands and set _canonical_name for help
|
|
54
|
+
check_command._canonical_name = "check"
|
|
55
|
+
format_code._canonical_name = "format"
|
|
56
|
+
list_tools_command._canonical_name = "list-tools"
|
|
57
|
+
|
|
58
|
+
cli.add_command(check_command, name="check")
|
|
59
|
+
cli.add_command(format_code, name="format")
|
|
60
|
+
cli.add_command(list_tools_command, name="list-tools")
|
|
61
|
+
|
|
62
|
+
# Register aliases
|
|
63
|
+
cli.add_command(check_command, name="chk")
|
|
64
|
+
cli.add_command(format_code, name="fmt")
|
|
65
|
+
cli.add_command(list_tools_command, name="ls")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def main() -> None:
|
|
69
|
+
"""Entry point for the CLI."""
|
|
70
|
+
cli()
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""Check command implementation for lintro CLI.
|
|
2
|
+
|
|
3
|
+
This module provides the core logic for the 'check' command.
|
|
4
|
+
|
|
5
|
+
Functions:
|
|
6
|
+
check_command: CLI command for checking files with various tools.
|
|
7
|
+
check: Programmatic function for backward compatibility.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
from click.testing import CliRunner
|
|
14
|
+
|
|
15
|
+
from lintro.utils.tool_executor import run_lint_tools_simple
|
|
16
|
+
|
|
17
|
+
# Constants
|
|
18
|
+
DEFAULT_PATHS: list[str] = ["."]
|
|
19
|
+
DEFAULT_EXIT_CODE: int = 0
|
|
20
|
+
DEFAULT_ACTION: str = "check"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@click.command("check")
|
|
24
|
+
@click.argument("paths", nargs=-1, type=click.Path(exists=True))
|
|
25
|
+
@click.option(
|
|
26
|
+
"--tools",
|
|
27
|
+
type=str,
|
|
28
|
+
help='Comma-separated list of tools to run. Use "all" to run all available tools.',
|
|
29
|
+
)
|
|
30
|
+
@click.option(
|
|
31
|
+
"--tool-options",
|
|
32
|
+
type=str,
|
|
33
|
+
help="Tool-specific options in the format tool:option=value,tool:option=value",
|
|
34
|
+
)
|
|
35
|
+
@click.option(
|
|
36
|
+
"--exclude",
|
|
37
|
+
type=str,
|
|
38
|
+
help="Comma-separated list of patterns to exclude from processing",
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"--include-venv",
|
|
42
|
+
is_flag=True,
|
|
43
|
+
help="Include virtual environment directories in processing",
|
|
44
|
+
)
|
|
45
|
+
@click.option(
|
|
46
|
+
"--output",
|
|
47
|
+
type=click.Path(),
|
|
48
|
+
help="Output file path for writing results",
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
"--output-format",
|
|
52
|
+
type=click.Choice(["plain", "grid", "markdown", "html", "json", "csv"]),
|
|
53
|
+
default="grid",
|
|
54
|
+
help="Output format for displaying results",
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--group-by",
|
|
58
|
+
type=click.Choice(["file", "code", "none", "auto"]),
|
|
59
|
+
default="file",
|
|
60
|
+
help="How to group issues in the output",
|
|
61
|
+
)
|
|
62
|
+
@click.option(
|
|
63
|
+
"--ignore-conflicts",
|
|
64
|
+
is_flag=True,
|
|
65
|
+
help="Ignore potential conflicts between tools",
|
|
66
|
+
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"--verbose",
|
|
69
|
+
is_flag=True,
|
|
70
|
+
help="Show verbose output",
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
"--no-log",
|
|
74
|
+
is_flag=True,
|
|
75
|
+
help="Disable logging to file",
|
|
76
|
+
)
|
|
77
|
+
@click.option(
|
|
78
|
+
"--raw-output",
|
|
79
|
+
is_flag=True,
|
|
80
|
+
help="Show raw tool output instead of formatted output",
|
|
81
|
+
)
|
|
82
|
+
def check_command(
|
|
83
|
+
paths,
|
|
84
|
+
tools,
|
|
85
|
+
tool_options,
|
|
86
|
+
exclude,
|
|
87
|
+
include_venv,
|
|
88
|
+
output,
|
|
89
|
+
output_format,
|
|
90
|
+
group_by,
|
|
91
|
+
ignore_conflicts,
|
|
92
|
+
verbose,
|
|
93
|
+
no_log,
|
|
94
|
+
raw_output,
|
|
95
|
+
) -> None:
|
|
96
|
+
"""Check files for issues using the specified tools.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
paths: tuple: List of file/directory paths to check.
|
|
100
|
+
tools: str | None: Comma-separated list of tool names to run.
|
|
101
|
+
tool_options: str | None: Tool-specific configuration options.
|
|
102
|
+
exclude: str | None: Comma-separated patterns of files/dirs to exclude.
|
|
103
|
+
include_venv: bool: Whether to include virtual environment directories.
|
|
104
|
+
output: str | None: Path to output file for results.
|
|
105
|
+
output_format: str: Format for displaying results (table, json, etc).
|
|
106
|
+
group_by: str: How to group issues in output (tool, file, etc).
|
|
107
|
+
ignore_conflicts: bool: Whether to ignore tool configuration conflicts.
|
|
108
|
+
verbose: bool: Whether to show verbose output during execution.
|
|
109
|
+
no_log: bool: Whether to disable logging to file.
|
|
110
|
+
raw_output: bool: Whether to show raw tool output instead of formatted output.
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
SystemExit: Process exit with the aggregated exit code from tools.
|
|
114
|
+
"""
|
|
115
|
+
# Add default paths if none provided
|
|
116
|
+
if not paths:
|
|
117
|
+
paths = DEFAULT_PATHS
|
|
118
|
+
|
|
119
|
+
# Build tool-specific options string
|
|
120
|
+
tool_option_parts: list[str] = []
|
|
121
|
+
if tool_options:
|
|
122
|
+
tool_option_parts.append(tool_options)
|
|
123
|
+
|
|
124
|
+
# Removed darglint_timeout and prettier_timeout handling
|
|
125
|
+
combined_tool_options: str | None = (
|
|
126
|
+
",".join(tool_option_parts) if tool_option_parts else None
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Run with simplified approach
|
|
130
|
+
exit_code: int = run_lint_tools_simple(
|
|
131
|
+
action=DEFAULT_ACTION,
|
|
132
|
+
paths=list(paths),
|
|
133
|
+
tools=tools,
|
|
134
|
+
tool_options=combined_tool_options,
|
|
135
|
+
exclude=exclude,
|
|
136
|
+
include_venv=include_venv,
|
|
137
|
+
group_by=group_by,
|
|
138
|
+
output_format=output_format,
|
|
139
|
+
verbose=verbose,
|
|
140
|
+
raw_output=raw_output,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Exit with code only; CLI uses this as process exit code and avoids any
|
|
144
|
+
# additional trailing output after the logger's ASCII art.
|
|
145
|
+
raise SystemExit(exit_code)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def check(
|
|
149
|
+
paths,
|
|
150
|
+
tools,
|
|
151
|
+
tool_options,
|
|
152
|
+
exclude,
|
|
153
|
+
include_venv,
|
|
154
|
+
output,
|
|
155
|
+
output_format,
|
|
156
|
+
group_by,
|
|
157
|
+
ignore_conflicts,
|
|
158
|
+
verbose,
|
|
159
|
+
no_log,
|
|
160
|
+
) -> None:
|
|
161
|
+
"""Programmatic check function for backward compatibility.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
paths: tuple: List of file/directory paths to check.
|
|
165
|
+
tools: str | None: Comma-separated list of tool names to run.
|
|
166
|
+
tool_options: str | None: Tool-specific configuration options.
|
|
167
|
+
exclude: str | None: Comma-separated patterns of files/dirs to exclude.
|
|
168
|
+
include_venv: bool: Whether to include virtual environment directories.
|
|
169
|
+
output: str | None: Path to output file for results.
|
|
170
|
+
output_format: str: Format for displaying results (table, json, etc).
|
|
171
|
+
group_by: str: How to group issues in output (tool, file, etc).
|
|
172
|
+
ignore_conflicts: bool: Whether to ignore tool configuration conflicts.
|
|
173
|
+
verbose: bool: Whether to show verbose output during execution.
|
|
174
|
+
no_log: bool: Whether to disable logging to file.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
None: This function does not return a value.
|
|
178
|
+
"""
|
|
179
|
+
# Build arguments for the click command
|
|
180
|
+
args: list[str] = []
|
|
181
|
+
if paths:
|
|
182
|
+
args.extend(paths)
|
|
183
|
+
if tools:
|
|
184
|
+
args.extend(["--tools", tools])
|
|
185
|
+
if tool_options:
|
|
186
|
+
args.extend(["--tool-options", tool_options])
|
|
187
|
+
if exclude:
|
|
188
|
+
args.extend(["--exclude", exclude])
|
|
189
|
+
if include_venv:
|
|
190
|
+
args.append("--include-venv")
|
|
191
|
+
if output:
|
|
192
|
+
args.extend(["--output", output])
|
|
193
|
+
if output_format:
|
|
194
|
+
args.extend(["--output-format", output_format])
|
|
195
|
+
if group_by:
|
|
196
|
+
args.extend(["--group-by", group_by])
|
|
197
|
+
if ignore_conflicts:
|
|
198
|
+
args.append("--ignore-conflicts")
|
|
199
|
+
# Removed darglint_timeout and prettier_timeout handling
|
|
200
|
+
if verbose:
|
|
201
|
+
args.append("--verbose")
|
|
202
|
+
if no_log:
|
|
203
|
+
args.append("--no-log")
|
|
204
|
+
|
|
205
|
+
runner = CliRunner()
|
|
206
|
+
result = runner.invoke(check_command, args)
|
|
207
|
+
|
|
208
|
+
if result.exit_code != DEFAULT_EXIT_CODE:
|
|
209
|
+
sys.exit(result.exit_code)
|
|
210
|
+
return None
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Format command implementation using simplified Loguru-based approach."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from click.testing import CliRunner
|
|
5
|
+
|
|
6
|
+
from lintro.utils.tool_executor import run_lint_tools_simple
|
|
7
|
+
|
|
8
|
+
# Constants
|
|
9
|
+
DEFAULT_PATHS: list[str] = ["."]
|
|
10
|
+
DEFAULT_EXIT_CODE: int = 0
|
|
11
|
+
DEFAULT_ACTION: str = "fmt"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.command()
|
|
15
|
+
@click.argument("paths", nargs=-1, type=click.Path(exists=True))
|
|
16
|
+
@click.option(
|
|
17
|
+
"--tools",
|
|
18
|
+
default=None,
|
|
19
|
+
help="Comma-separated list of tools to run (e.g., ruff,prettier) or 'all'.",
|
|
20
|
+
)
|
|
21
|
+
@click.option(
|
|
22
|
+
"--tool-options",
|
|
23
|
+
default=None,
|
|
24
|
+
help="Tool-specific options in format tool:option=value,tool2:option=value.",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"--exclude",
|
|
28
|
+
default=None,
|
|
29
|
+
help="Comma-separated patterns to exclude from formatting.",
|
|
30
|
+
)
|
|
31
|
+
@click.option(
|
|
32
|
+
"--include-venv",
|
|
33
|
+
is_flag=True,
|
|
34
|
+
default=False,
|
|
35
|
+
help="Include virtual environment directories in formatting.",
|
|
36
|
+
)
|
|
37
|
+
@click.option(
|
|
38
|
+
"--group-by",
|
|
39
|
+
default="auto",
|
|
40
|
+
type=click.Choice(["file", "code", "none", "auto"]),
|
|
41
|
+
help="How to group issues in output.",
|
|
42
|
+
)
|
|
43
|
+
@click.option(
|
|
44
|
+
"--output-format",
|
|
45
|
+
default="grid",
|
|
46
|
+
type=click.Choice(["plain", "grid", "markdown", "html", "json", "csv"]),
|
|
47
|
+
help="Output format for displaying results.",
|
|
48
|
+
)
|
|
49
|
+
@click.option(
|
|
50
|
+
"--verbose",
|
|
51
|
+
"-v",
|
|
52
|
+
is_flag=True,
|
|
53
|
+
default=False,
|
|
54
|
+
help="Enable verbose output with debug information.",
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--raw-output",
|
|
58
|
+
is_flag=True,
|
|
59
|
+
default=False,
|
|
60
|
+
help="Show raw tool output instead of formatted output.",
|
|
61
|
+
)
|
|
62
|
+
def format_code(
|
|
63
|
+
paths: tuple[str, ...],
|
|
64
|
+
tools: str | None,
|
|
65
|
+
tool_options: str | None,
|
|
66
|
+
exclude: str | None,
|
|
67
|
+
include_venv: bool,
|
|
68
|
+
group_by: str,
|
|
69
|
+
output_format: str,
|
|
70
|
+
verbose: bool,
|
|
71
|
+
raw_output: bool,
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Format code using configured formatting tools.
|
|
74
|
+
|
|
75
|
+
Runs code formatting tools on the specified paths to automatically fix style issues.
|
|
76
|
+
Uses simplified Loguru-based logging for clean output and proper file logging.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
paths: tuple[str, ...]:
|
|
80
|
+
Paths to format (defaults to current directory if none provided).
|
|
81
|
+
tools: str | None: Specific tools to run, or 'all' for all available tools.
|
|
82
|
+
tool_options: str | None: Tool-specific configuration options.
|
|
83
|
+
exclude: str | None: Patterns to exclude from formatting.
|
|
84
|
+
include_venv: bool: Whether to include virtual environment directories.
|
|
85
|
+
group_by: str: How to group issues in the output display.
|
|
86
|
+
output_format: str: Format for displaying results.
|
|
87
|
+
verbose: bool: Enable detailed debug output.
|
|
88
|
+
raw_output: bool:
|
|
89
|
+
Show raw tool output instead of formatted output.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
ClickException: If issues are found during formatting.
|
|
93
|
+
"""
|
|
94
|
+
# Default to current directory if no paths provided
|
|
95
|
+
if not paths:
|
|
96
|
+
paths = DEFAULT_PATHS
|
|
97
|
+
|
|
98
|
+
# Run with simplified approach
|
|
99
|
+
exit_code: int = run_lint_tools_simple(
|
|
100
|
+
action=DEFAULT_ACTION,
|
|
101
|
+
paths=list(paths),
|
|
102
|
+
tools=tools,
|
|
103
|
+
tool_options=tool_options,
|
|
104
|
+
exclude=exclude,
|
|
105
|
+
include_venv=include_venv,
|
|
106
|
+
group_by=group_by,
|
|
107
|
+
output_format=output_format,
|
|
108
|
+
verbose=verbose,
|
|
109
|
+
raw_output=raw_output,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Exit with appropriate code
|
|
113
|
+
if exit_code != DEFAULT_EXIT_CODE:
|
|
114
|
+
raise click.ClickException("Format found issues")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def format_code_legacy(
|
|
118
|
+
paths: list[str] | None = None,
|
|
119
|
+
tools: str | None = None,
|
|
120
|
+
tool_options: str | None = None,
|
|
121
|
+
exclude: str | None = None,
|
|
122
|
+
include_venv: bool = False,
|
|
123
|
+
group_by: str = "auto",
|
|
124
|
+
output_format: str = "grid",
|
|
125
|
+
verbose: bool = False,
|
|
126
|
+
) -> None:
|
|
127
|
+
"""Programmatic format function for backward compatibility.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
paths: list[str] | None: List of file/directory paths to format.
|
|
131
|
+
tools: str | None: Comma-separated list of tool names to run.
|
|
132
|
+
tool_options: str | None: Tool-specific configuration options.
|
|
133
|
+
exclude: str | None: Comma-separated patterns of files/dirs to exclude.
|
|
134
|
+
include_venv: bool: Whether to include virtual environment directories.
|
|
135
|
+
group_by: str: How to group issues in output (tool, file, etc).
|
|
136
|
+
output_format: str: Format for displaying results (table, json, etc).
|
|
137
|
+
verbose: bool: Whether to show verbose output during execution.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
None: This function does not return a value.
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
Exception: If format fails for any reason.
|
|
144
|
+
"""
|
|
145
|
+
args: list[str] = []
|
|
146
|
+
if paths:
|
|
147
|
+
args.extend(paths)
|
|
148
|
+
if tools:
|
|
149
|
+
args.extend(["--tools", tools])
|
|
150
|
+
if tool_options:
|
|
151
|
+
args.extend(["--tool-options", tool_options])
|
|
152
|
+
if exclude:
|
|
153
|
+
args.extend(["--exclude", exclude])
|
|
154
|
+
if include_venv:
|
|
155
|
+
args.append("--include-venv")
|
|
156
|
+
if group_by:
|
|
157
|
+
args.extend(["--group-by", group_by])
|
|
158
|
+
if output_format:
|
|
159
|
+
args.extend(["--output-format", output_format])
|
|
160
|
+
if verbose:
|
|
161
|
+
args.append("--verbose")
|
|
162
|
+
|
|
163
|
+
runner = CliRunner()
|
|
164
|
+
result = runner.invoke(format_code, args)
|
|
165
|
+
if result.exit_code != DEFAULT_EXIT_CODE:
|
|
166
|
+
raise Exception(f"Format failed: {result.output}")
|
|
167
|
+
return None
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""List tools command implementation for lintro CLI.
|
|
2
|
+
|
|
3
|
+
This module provides the core logic for the 'list_tools' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from lintro.enums.action import Action
|
|
9
|
+
from lintro.tools import tool_manager
|
|
10
|
+
from lintro.utils.console_logger import get_tool_emoji
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.command("list-tools")
|
|
14
|
+
@click.option(
|
|
15
|
+
"--output",
|
|
16
|
+
type=click.Path(),
|
|
17
|
+
help="Output file path for writing results",
|
|
18
|
+
)
|
|
19
|
+
@click.option(
|
|
20
|
+
"--show-conflicts",
|
|
21
|
+
is_flag=True,
|
|
22
|
+
help="Show potential conflicts between tools",
|
|
23
|
+
)
|
|
24
|
+
def list_tools_command(
|
|
25
|
+
output,
|
|
26
|
+
show_conflicts,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""List all available tools and their configurations.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
output: Path to output file for writing results.
|
|
32
|
+
show_conflicts: Whether to show potential conflicts between tools.
|
|
33
|
+
"""
|
|
34
|
+
list_tools(output=output, show_conflicts=show_conflicts)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def list_tools(
|
|
38
|
+
output: str | None,
|
|
39
|
+
show_conflicts: bool,
|
|
40
|
+
) -> None:
|
|
41
|
+
"""List all available tools.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
output: Output file path.
|
|
45
|
+
show_conflicts: Whether to show potential conflicts between tools.
|
|
46
|
+
"""
|
|
47
|
+
available_tools = tool_manager.get_available_tools()
|
|
48
|
+
check_tools = tool_manager.get_check_tools()
|
|
49
|
+
fix_tools = tool_manager.get_fix_tools()
|
|
50
|
+
|
|
51
|
+
output_lines = []
|
|
52
|
+
|
|
53
|
+
# Create header with emojis
|
|
54
|
+
border = "=" * 70
|
|
55
|
+
header_title = "🔧 Available Tools"
|
|
56
|
+
emojis = "🔧 🔧 🔧 🔧 🔧"
|
|
57
|
+
output_lines.append(f"{border}")
|
|
58
|
+
output_lines.append(f"{header_title} {emojis}")
|
|
59
|
+
output_lines.append(f"{border}")
|
|
60
|
+
output_lines.append("")
|
|
61
|
+
|
|
62
|
+
for tool_enum, tool in available_tools.items():
|
|
63
|
+
tool_name = tool_enum.name.lower()
|
|
64
|
+
tool_description = getattr(tool.config, "description", tool.__class__.__name__)
|
|
65
|
+
emoji = get_tool_emoji(tool_name)
|
|
66
|
+
|
|
67
|
+
capabilities: list[str] = []
|
|
68
|
+
if tool_enum in check_tools:
|
|
69
|
+
capabilities.append(Action.CHECK.value)
|
|
70
|
+
if tool_enum in fix_tools:
|
|
71
|
+
capabilities.append(Action.FIX.value)
|
|
72
|
+
|
|
73
|
+
output_lines.append(f"{emoji} {tool_name}: {tool_description}")
|
|
74
|
+
output_lines.append(f" Capabilities: {', '.join(capabilities)}")
|
|
75
|
+
|
|
76
|
+
if (
|
|
77
|
+
show_conflicts
|
|
78
|
+
and hasattr(tool.config, "conflicts_with")
|
|
79
|
+
and tool.config.conflicts_with
|
|
80
|
+
):
|
|
81
|
+
conflicts = [
|
|
82
|
+
conflict.name.lower()
|
|
83
|
+
for conflict in tool.config.conflicts_with
|
|
84
|
+
if conflict in available_tools
|
|
85
|
+
]
|
|
86
|
+
if conflicts:
|
|
87
|
+
output_lines.append(f" Conflicts with: {', '.join(conflicts)}")
|
|
88
|
+
|
|
89
|
+
output_lines.append("")
|
|
90
|
+
|
|
91
|
+
# Add summary footer
|
|
92
|
+
summary_border = "-" * 70
|
|
93
|
+
output_lines.append(summary_border)
|
|
94
|
+
output_lines.append(f"📊 Total tools: {len(available_tools)}")
|
|
95
|
+
output_lines.append(f"🔍 Check tools: {len(check_tools)}")
|
|
96
|
+
output_lines.append(f"🔧 Fix tools: {len(fix_tools)}")
|
|
97
|
+
output_lines.append(summary_border)
|
|
98
|
+
|
|
99
|
+
# Format output
|
|
100
|
+
output_text = "\n".join(output_lines)
|
|
101
|
+
|
|
102
|
+
# Print to console using click.echo for consistency
|
|
103
|
+
click.echo(output_text)
|
|
104
|
+
|
|
105
|
+
# Write to file if specified
|
|
106
|
+
if output:
|
|
107
|
+
try:
|
|
108
|
+
with open(output, "w", encoding="utf-8") as f:
|
|
109
|
+
f.write(output_text + "\n")
|
|
110
|
+
success_msg = f"Output written to: {output}"
|
|
111
|
+
click.echo(success_msg)
|
|
112
|
+
except IOError as e:
|
|
113
|
+
error_msg = f"Error writing to file {output}: {e}"
|
|
114
|
+
click.echo(error_msg, err=True)
|
lintro/enums/__init__.py
ADDED
|
File without changes
|
lintro/enums/action.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Action/capability enum for tools (check vs. fix)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Action(StrEnum):
|
|
9
|
+
"""Supported actions a tool can perform."""
|
|
10
|
+
|
|
11
|
+
CHECK = "check"
|
|
12
|
+
FIX = "fix"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def normalize_action(value: str | Action) -> Action:
|
|
16
|
+
"""Normalize a raw value to an Action enum.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
value: str or Action to normalize.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Action: Normalized enum value.
|
|
23
|
+
"""
|
|
24
|
+
if isinstance(value, Action):
|
|
25
|
+
return value
|
|
26
|
+
try:
|
|
27
|
+
return Action(value.lower())
|
|
28
|
+
except Exception:
|
|
29
|
+
return Action.CHECK
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Darglint strictness levels."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import StrEnum, auto
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DarglintStrictness(StrEnum):
|
|
9
|
+
SHORT = auto()
|
|
10
|
+
LONG = auto()
|
|
11
|
+
FULL = auto()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def normalize_darglint_strictness(
|
|
15
|
+
value: str | DarglintStrictness,
|
|
16
|
+
) -> DarglintStrictness:
|
|
17
|
+
if isinstance(value, DarglintStrictness):
|
|
18
|
+
return value
|
|
19
|
+
try:
|
|
20
|
+
return DarglintStrictness[value.upper()]
|
|
21
|
+
except Exception:
|
|
22
|
+
return DarglintStrictness.FULL
|
lintro/enums/group_by.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Grouping strategy enum definitions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import StrEnum, auto
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class GroupBy(StrEnum):
|
|
9
|
+
"""Supported grouping strategies for presenting issues."""
|
|
10
|
+
|
|
11
|
+
FILE = auto()
|
|
12
|
+
CODE = auto()
|
|
13
|
+
NONE = auto()
|
|
14
|
+
AUTO = auto()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def normalize_group_by(value: str | GroupBy) -> GroupBy:
|
|
18
|
+
"""Normalize a raw value to GroupBy enum.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
value: str or GroupBy to normalize.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
GroupBy: Normalized enum value.
|
|
25
|
+
"""
|
|
26
|
+
if isinstance(value, GroupBy):
|
|
27
|
+
return value
|
|
28
|
+
try:
|
|
29
|
+
return GroupBy[value.upper()]
|
|
30
|
+
except Exception:
|
|
31
|
+
return GroupBy.FILE
|