lintro 0.6.2__py3-none-any.whl → 0.17.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.
- lintro/__init__.py +1 -1
- lintro/cli.py +230 -14
- lintro/cli_utils/commands/__init__.py +8 -1
- lintro/cli_utils/commands/check.py +1 -0
- lintro/cli_utils/commands/config.py +325 -0
- lintro/cli_utils/commands/format.py +2 -2
- lintro/cli_utils/commands/init.py +361 -0
- lintro/cli_utils/commands/list_tools.py +180 -42
- lintro/cli_utils/commands/test.py +316 -0
- lintro/cli_utils/commands/versions.py +81 -0
- lintro/config/__init__.py +62 -0
- lintro/config/config_loader.py +420 -0
- lintro/config/lintro_config.py +189 -0
- lintro/config/tool_config_generator.py +403 -0
- lintro/enums/__init__.py +1 -0
- lintro/enums/darglint_strictness.py +10 -0
- lintro/enums/hadolint_enums.py +22 -0
- lintro/enums/tool_name.py +2 -0
- lintro/enums/tool_type.py +2 -0
- lintro/enums/yamllint_format.py +11 -0
- lintro/exceptions/__init__.py +1 -0
- lintro/formatters/__init__.py +1 -0
- lintro/formatters/core/__init__.py +1 -0
- lintro/formatters/core/output_style.py +11 -0
- lintro/formatters/core/table_descriptor.py +8 -0
- lintro/formatters/styles/csv.py +2 -0
- lintro/formatters/styles/grid.py +2 -0
- lintro/formatters/styles/html.py +2 -0
- lintro/formatters/styles/json.py +2 -0
- lintro/formatters/styles/markdown.py +2 -0
- lintro/formatters/styles/plain.py +2 -0
- lintro/formatters/tools/__init__.py +12 -0
- lintro/formatters/tools/black_formatter.py +27 -5
- lintro/formatters/tools/darglint_formatter.py +16 -1
- lintro/formatters/tools/eslint_formatter.py +108 -0
- lintro/formatters/tools/hadolint_formatter.py +13 -0
- lintro/formatters/tools/markdownlint_formatter.py +88 -0
- lintro/formatters/tools/prettier_formatter.py +15 -0
- lintro/formatters/tools/pytest_formatter.py +201 -0
- lintro/formatters/tools/ruff_formatter.py +26 -5
- lintro/formatters/tools/yamllint_formatter.py +14 -1
- lintro/models/__init__.py +1 -0
- lintro/models/core/__init__.py +1 -0
- lintro/models/core/tool_config.py +11 -7
- lintro/parsers/__init__.py +69 -9
- lintro/parsers/actionlint/actionlint_parser.py +1 -1
- lintro/parsers/bandit/__init__.py +6 -0
- lintro/parsers/bandit/bandit_issue.py +49 -0
- lintro/parsers/bandit/bandit_parser.py +99 -0
- lintro/parsers/black/black_issue.py +4 -0
- lintro/parsers/darglint/__init__.py +1 -0
- lintro/parsers/darglint/darglint_issue.py +11 -0
- lintro/parsers/eslint/__init__.py +6 -0
- lintro/parsers/eslint/eslint_issue.py +26 -0
- lintro/parsers/eslint/eslint_parser.py +63 -0
- lintro/parsers/markdownlint/__init__.py +6 -0
- lintro/parsers/markdownlint/markdownlint_issue.py +22 -0
- lintro/parsers/markdownlint/markdownlint_parser.py +113 -0
- lintro/parsers/prettier/__init__.py +1 -0
- lintro/parsers/prettier/prettier_issue.py +12 -0
- lintro/parsers/prettier/prettier_parser.py +1 -1
- lintro/parsers/pytest/__init__.py +21 -0
- lintro/parsers/pytest/pytest_issue.py +28 -0
- lintro/parsers/pytest/pytest_parser.py +483 -0
- lintro/parsers/ruff/ruff_parser.py +6 -2
- lintro/parsers/yamllint/__init__.py +1 -0
- lintro/tools/__init__.py +3 -1
- lintro/tools/core/__init__.py +1 -0
- lintro/tools/core/timeout_utils.py +112 -0
- lintro/tools/core/tool_base.py +286 -50
- lintro/tools/core/tool_manager.py +77 -24
- lintro/tools/core/version_requirements.py +482 -0
- lintro/tools/implementations/__init__.py +1 -0
- lintro/tools/implementations/pytest/pytest_command_builder.py +311 -0
- lintro/tools/implementations/pytest/pytest_config.py +200 -0
- lintro/tools/implementations/pytest/pytest_error_handler.py +128 -0
- lintro/tools/implementations/pytest/pytest_executor.py +122 -0
- lintro/tools/implementations/pytest/pytest_handlers.py +375 -0
- lintro/tools/implementations/pytest/pytest_option_validators.py +212 -0
- lintro/tools/implementations/pytest/pytest_output_processor.py +408 -0
- lintro/tools/implementations/pytest/pytest_result_processor.py +113 -0
- lintro/tools/implementations/pytest/pytest_utils.py +697 -0
- lintro/tools/implementations/tool_actionlint.py +106 -16
- lintro/tools/implementations/tool_bandit.py +34 -29
- lintro/tools/implementations/tool_black.py +236 -29
- lintro/tools/implementations/tool_darglint.py +183 -22
- lintro/tools/implementations/tool_eslint.py +374 -0
- lintro/tools/implementations/tool_hadolint.py +94 -25
- lintro/tools/implementations/tool_markdownlint.py +354 -0
- lintro/tools/implementations/tool_prettier.py +317 -24
- lintro/tools/implementations/tool_pytest.py +327 -0
- lintro/tools/implementations/tool_ruff.py +278 -84
- lintro/tools/implementations/tool_yamllint.py +448 -34
- lintro/tools/tool_enum.py +8 -0
- lintro/utils/__init__.py +1 -0
- lintro/utils/ascii_normalize_cli.py +5 -0
- lintro/utils/config.py +41 -18
- lintro/utils/console_logger.py +211 -25
- lintro/utils/path_utils.py +42 -0
- lintro/utils/tool_executor.py +339 -45
- lintro/utils/tool_utils.py +51 -24
- lintro/utils/unified_config.py +926 -0
- {lintro-0.6.2.dist-info → lintro-0.17.2.dist-info}/METADATA +172 -30
- lintro-0.17.2.dist-info/RECORD +134 -0
- lintro-0.6.2.dist-info/RECORD +0 -96
- {lintro-0.6.2.dist-info → lintro-0.17.2.dist-info}/WHEEL +0 -0
- {lintro-0.6.2.dist-info → lintro-0.17.2.dist-info}/entry_points.txt +0 -0
- {lintro-0.6.2.dist-info → lintro-0.17.2.dist-info}/licenses/LICENSE +0 -0
- {lintro-0.6.2.dist-info → lintro-0.17.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"""Tool configuration generator for Lintro.
|
|
2
|
+
|
|
3
|
+
This module provides CLI argument injection for enforced settings and
|
|
4
|
+
default config generation for tools without native configs.
|
|
5
|
+
|
|
6
|
+
The tiered configuration model:
|
|
7
|
+
1. EXECUTION: What tools run and how
|
|
8
|
+
2. ENFORCE: Cross-cutting settings injected via CLI flags
|
|
9
|
+
3. DEFAULTS: Fallback config when no native config exists
|
|
10
|
+
4. TOOLS: Per-tool enable/disable and config source
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import atexit
|
|
16
|
+
import json
|
|
17
|
+
import os
|
|
18
|
+
import tempfile
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from loguru import logger
|
|
23
|
+
|
|
24
|
+
from lintro.config.lintro_config import LintroConfig
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
import yaml
|
|
28
|
+
except ImportError:
|
|
29
|
+
yaml = None # type: ignore[assignment]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# CLI flags for enforced settings: setting -> {tool: flag}
|
|
33
|
+
ENFORCE_CLI_FLAGS: dict[str, dict[str, str]] = {
|
|
34
|
+
"line_length": {
|
|
35
|
+
"ruff": "--line-length",
|
|
36
|
+
"black": "--line-length",
|
|
37
|
+
"prettier": "--print-width",
|
|
38
|
+
},
|
|
39
|
+
"target_python": {
|
|
40
|
+
"ruff": "--target-version",
|
|
41
|
+
"black": "--target-version",
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Tool config format for defaults generation
|
|
46
|
+
TOOL_CONFIG_FORMATS: dict[str, str] = {
|
|
47
|
+
"prettier": "json",
|
|
48
|
+
"yamllint": "yaml",
|
|
49
|
+
"markdownlint": "json",
|
|
50
|
+
"hadolint": "yaml",
|
|
51
|
+
"bandit": "yaml",
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Native config file patterns for checking if tool has native config
|
|
55
|
+
NATIVE_CONFIG_PATTERNS: dict[str, list[str]] = {
|
|
56
|
+
"prettier": [
|
|
57
|
+
".prettierrc",
|
|
58
|
+
".prettierrc.json",
|
|
59
|
+
".prettierrc.yaml",
|
|
60
|
+
".prettierrc.yml",
|
|
61
|
+
".prettierrc.js",
|
|
62
|
+
".prettierrc.cjs",
|
|
63
|
+
".prettierrc.toml",
|
|
64
|
+
"prettier.config.js",
|
|
65
|
+
"prettier.config.cjs",
|
|
66
|
+
],
|
|
67
|
+
"markdownlint": [
|
|
68
|
+
".markdownlint-cli2.jsonc",
|
|
69
|
+
".markdownlint-cli2.yaml",
|
|
70
|
+
".markdownlint-cli2.cjs",
|
|
71
|
+
".markdownlint.jsonc",
|
|
72
|
+
".markdownlint.json",
|
|
73
|
+
".markdownlint.yaml",
|
|
74
|
+
".markdownlint.yml",
|
|
75
|
+
".markdownlint.cjs",
|
|
76
|
+
],
|
|
77
|
+
"yamllint": [
|
|
78
|
+
".yamllint",
|
|
79
|
+
".yamllint.yaml",
|
|
80
|
+
".yamllint.yml",
|
|
81
|
+
],
|
|
82
|
+
"hadolint": [
|
|
83
|
+
".hadolint.yaml",
|
|
84
|
+
".hadolint.yml",
|
|
85
|
+
],
|
|
86
|
+
"bandit": [
|
|
87
|
+
".bandit",
|
|
88
|
+
".bandit.yaml",
|
|
89
|
+
".bandit.yml",
|
|
90
|
+
"bandit.yaml",
|
|
91
|
+
"bandit.yml",
|
|
92
|
+
],
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Track temporary files for cleanup
|
|
96
|
+
_temp_files: list[Path] = []
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _cleanup_temp_files() -> None:
|
|
100
|
+
"""Clean up temporary config files on exit."""
|
|
101
|
+
for temp_file in _temp_files:
|
|
102
|
+
try:
|
|
103
|
+
if temp_file.exists():
|
|
104
|
+
temp_file.unlink()
|
|
105
|
+
logger.debug(f"Cleaned up temp config: {temp_file}")
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.debug(f"Failed to clean up {temp_file}: {e}")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# Register cleanup on exit
|
|
111
|
+
atexit.register(_cleanup_temp_files)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_enforce_cli_args(
|
|
115
|
+
tool_name: str,
|
|
116
|
+
lintro_config: LintroConfig,
|
|
117
|
+
) -> list[str]:
|
|
118
|
+
"""Get CLI arguments for enforced settings.
|
|
119
|
+
|
|
120
|
+
These settings override native tool configs to ensure consistency
|
|
121
|
+
across different tools for shared concerns like line length.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
tool_name: Name of the tool (e.g., "ruff", "prettier").
|
|
125
|
+
lintro_config: Lintro configuration.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
list[str]: CLI arguments to inject (e.g., ["--line-length", "88"]).
|
|
129
|
+
"""
|
|
130
|
+
args: list[str] = []
|
|
131
|
+
tool_lower = tool_name.lower()
|
|
132
|
+
enforce = lintro_config.enforce
|
|
133
|
+
|
|
134
|
+
# Inject line_length if set
|
|
135
|
+
if enforce.line_length is not None:
|
|
136
|
+
flag = ENFORCE_CLI_FLAGS.get("line_length", {}).get(tool_lower)
|
|
137
|
+
if flag:
|
|
138
|
+
args.extend([flag, str(enforce.line_length)])
|
|
139
|
+
logger.debug(
|
|
140
|
+
f"Injecting enforce.line_length={enforce.line_length} "
|
|
141
|
+
f"to {tool_name} as {flag}",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Inject target_python if set
|
|
145
|
+
if enforce.target_python is not None:
|
|
146
|
+
flag = ENFORCE_CLI_FLAGS.get("target_python", {}).get(tool_lower)
|
|
147
|
+
if flag:
|
|
148
|
+
args.extend([flag, enforce.target_python])
|
|
149
|
+
logger.debug(
|
|
150
|
+
f"Injecting enforce.target_python={enforce.target_python} "
|
|
151
|
+
f"to {tool_name} as {flag}",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return args
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def has_native_config(tool_name: str) -> bool:
|
|
158
|
+
"""Check if a tool has a native config file in the project.
|
|
159
|
+
|
|
160
|
+
Searches for known native config file patterns starting from the
|
|
161
|
+
current working directory and moving upward to find the project root.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
tool_name: Name of the tool (e.g., "prettier", "markdownlint").
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
bool: True if a native config file exists.
|
|
168
|
+
"""
|
|
169
|
+
tool_lower = tool_name.lower()
|
|
170
|
+
patterns = NATIVE_CONFIG_PATTERNS.get(tool_lower, [])
|
|
171
|
+
|
|
172
|
+
if not patterns:
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
# Search from current directory upward
|
|
176
|
+
current = Path.cwd().resolve()
|
|
177
|
+
|
|
178
|
+
while True:
|
|
179
|
+
for pattern in patterns:
|
|
180
|
+
config_path = current / pattern
|
|
181
|
+
if config_path.exists():
|
|
182
|
+
logger.debug(
|
|
183
|
+
f"Found native config for {tool_name}: {config_path}",
|
|
184
|
+
)
|
|
185
|
+
return True
|
|
186
|
+
|
|
187
|
+
# Move up one directory
|
|
188
|
+
parent = current.parent
|
|
189
|
+
if parent == current:
|
|
190
|
+
# Reached filesystem root
|
|
191
|
+
break
|
|
192
|
+
current = parent
|
|
193
|
+
|
|
194
|
+
return False
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def generate_defaults_config(
|
|
198
|
+
tool_name: str,
|
|
199
|
+
lintro_config: LintroConfig,
|
|
200
|
+
) -> Path | None:
|
|
201
|
+
"""Generate a temporary config file from defaults.
|
|
202
|
+
|
|
203
|
+
Only used when a tool has no native config file and defaults
|
|
204
|
+
are specified in the Lintro config.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
tool_name: Name of the tool.
|
|
208
|
+
lintro_config: Lintro configuration.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Path | None: Path to generated config file, or None if not needed.
|
|
212
|
+
"""
|
|
213
|
+
tool_lower = tool_name.lower()
|
|
214
|
+
|
|
215
|
+
# Check if tool has native config - if so, don't generate defaults
|
|
216
|
+
if has_native_config(tool_lower):
|
|
217
|
+
logger.debug(
|
|
218
|
+
f"Tool {tool_name} has native config, skipping defaults generation",
|
|
219
|
+
)
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
# Get defaults for this tool
|
|
223
|
+
defaults = lintro_config.get_tool_defaults(tool_lower)
|
|
224
|
+
if not defaults:
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
# Get config format for this tool
|
|
228
|
+
config_format = TOOL_CONFIG_FORMATS.get(tool_lower, "json")
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
return _write_defaults_config(
|
|
232
|
+
defaults=defaults,
|
|
233
|
+
tool_name=tool_lower,
|
|
234
|
+
config_format=config_format,
|
|
235
|
+
)
|
|
236
|
+
except Exception as e:
|
|
237
|
+
logger.error(f"Failed to generate defaults config for {tool_name}: {e}")
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _write_defaults_config(
|
|
242
|
+
defaults: dict[str, Any],
|
|
243
|
+
tool_name: str,
|
|
244
|
+
config_format: str,
|
|
245
|
+
) -> Path:
|
|
246
|
+
"""Write defaults configuration to a temporary file.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
defaults: Default configuration dictionary.
|
|
250
|
+
tool_name: Name of the tool.
|
|
251
|
+
config_format: Output format (json, yaml).
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Path: Path to temporary config file.
|
|
255
|
+
|
|
256
|
+
Raises:
|
|
257
|
+
ImportError: If PyYAML is not installed and YAML format is requested.
|
|
258
|
+
"""
|
|
259
|
+
suffix_map = {"json": ".json", "yaml": ".yaml"}
|
|
260
|
+
suffix = suffix_map.get(config_format, ".json")
|
|
261
|
+
|
|
262
|
+
temp_fd, temp_path_str = tempfile.mkstemp(
|
|
263
|
+
prefix=f"lintro-{tool_name}-defaults-",
|
|
264
|
+
suffix=suffix,
|
|
265
|
+
)
|
|
266
|
+
os.close(temp_fd)
|
|
267
|
+
temp_path = Path(temp_path_str)
|
|
268
|
+
_temp_files.append(temp_path)
|
|
269
|
+
|
|
270
|
+
if config_format == "yaml":
|
|
271
|
+
if yaml is None:
|
|
272
|
+
raise ImportError("PyYAML required for YAML output")
|
|
273
|
+
content = yaml.dump(defaults, default_flow_style=False)
|
|
274
|
+
else:
|
|
275
|
+
content = json.dumps(defaults, indent=2)
|
|
276
|
+
|
|
277
|
+
temp_path.write_text(content, encoding="utf-8")
|
|
278
|
+
logger.debug(f"Generated defaults config for {tool_name}: {temp_path}")
|
|
279
|
+
|
|
280
|
+
return temp_path
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def get_defaults_injection_args(
|
|
284
|
+
tool_name: str,
|
|
285
|
+
config_path: Path | None,
|
|
286
|
+
) -> list[str]:
|
|
287
|
+
"""Get CLI arguments to inject defaults config file into a tool.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
tool_name: Name of the tool.
|
|
291
|
+
config_path: Path to defaults config file (or None).
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
list[str]: CLI arguments to pass to the tool.
|
|
295
|
+
"""
|
|
296
|
+
if config_path is None:
|
|
297
|
+
return []
|
|
298
|
+
|
|
299
|
+
tool_lower = tool_name.lower()
|
|
300
|
+
config_str = str(config_path)
|
|
301
|
+
|
|
302
|
+
# Tool-specific config flags
|
|
303
|
+
config_flags: dict[str, list[str]] = {
|
|
304
|
+
"prettier": ["--config", config_str],
|
|
305
|
+
"yamllint": ["-c", config_str],
|
|
306
|
+
"markdownlint": ["--config", config_str],
|
|
307
|
+
"hadolint": ["--config", config_str],
|
|
308
|
+
"bandit": ["-c", config_str],
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return config_flags.get(tool_lower, [])
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def cleanup_temp_config(config_path: Path) -> None:
|
|
315
|
+
"""Explicitly clean up a temporary config file.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
config_path: Path to temporary config file.
|
|
319
|
+
"""
|
|
320
|
+
try:
|
|
321
|
+
if config_path in _temp_files:
|
|
322
|
+
_temp_files.remove(config_path)
|
|
323
|
+
if config_path.exists():
|
|
324
|
+
config_path.unlink()
|
|
325
|
+
logger.debug(f"Cleaned up temp config: {config_path}")
|
|
326
|
+
except Exception as e:
|
|
327
|
+
logger.debug(f"Failed to clean up {config_path}: {e}")
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# =============================================================================
|
|
331
|
+
# DEPRECATED: Legacy functions for backward compatibility
|
|
332
|
+
# These will be removed in a future version.
|
|
333
|
+
# =============================================================================
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def generate_tool_config(
|
|
337
|
+
tool_name: str,
|
|
338
|
+
lintro_config: LintroConfig,
|
|
339
|
+
) -> Path | None:
|
|
340
|
+
"""Generate a temporary configuration file for a tool.
|
|
341
|
+
|
|
342
|
+
DEPRECATED: This function is deprecated. Use get_enforce_cli_args() for
|
|
343
|
+
CLI flag injection and generate_defaults_config() for defaults.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
tool_name: Name of the tool.
|
|
347
|
+
lintro_config: Lintro configuration.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
Path | None: Path to generated config file, or None.
|
|
351
|
+
"""
|
|
352
|
+
logger.warning(
|
|
353
|
+
f"generate_tool_config() is deprecated for {tool_name}. "
|
|
354
|
+
"Use get_enforce_cli_args() instead.",
|
|
355
|
+
)
|
|
356
|
+
return generate_defaults_config(
|
|
357
|
+
tool_name=tool_name,
|
|
358
|
+
lintro_config=lintro_config,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def get_config_injection_args(
|
|
363
|
+
tool_name: str,
|
|
364
|
+
config_path: Path | None,
|
|
365
|
+
) -> list[str]:
|
|
366
|
+
"""Get CLI arguments to inject config file into a tool.
|
|
367
|
+
|
|
368
|
+
DEPRECATED: Use get_defaults_injection_args() instead.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
tool_name: Name of the tool.
|
|
372
|
+
config_path: Path to config file (or None).
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
list[str]: CLI arguments to pass to the tool.
|
|
376
|
+
"""
|
|
377
|
+
logger.warning(
|
|
378
|
+
f"get_config_injection_args() is deprecated for {tool_name}. "
|
|
379
|
+
"Use get_defaults_injection_args() instead.",
|
|
380
|
+
)
|
|
381
|
+
return get_defaults_injection_args(
|
|
382
|
+
tool_name=tool_name,
|
|
383
|
+
config_path=config_path,
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def get_no_auto_config_args(tool_name: str) -> list[str]:
|
|
388
|
+
"""Get CLI arguments to disable auto-config discovery.
|
|
389
|
+
|
|
390
|
+
DEPRECATED: No longer needed with the tiered model.
|
|
391
|
+
Tools use their native configs by default.
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
tool_name: Name of the tool.
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
list[str]: Empty list (no longer used).
|
|
398
|
+
"""
|
|
399
|
+
logger.warning(
|
|
400
|
+
f"get_no_auto_config_args() is deprecated for {tool_name}. "
|
|
401
|
+
"No longer needed with the tiered config model.",
|
|
402
|
+
)
|
|
403
|
+
return []
|
lintro/enums/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Enumeration types used throughout the Lintro codebase."""
|
|
@@ -6,6 +6,8 @@ from enum import StrEnum, auto
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class DarglintStrictness(StrEnum):
|
|
9
|
+
"""Strictness levels recognized by Darglint checks."""
|
|
10
|
+
|
|
9
11
|
SHORT = auto()
|
|
10
12
|
LONG = auto()
|
|
11
13
|
FULL = auto()
|
|
@@ -14,6 +16,14 @@ class DarglintStrictness(StrEnum):
|
|
|
14
16
|
def normalize_darglint_strictness(
|
|
15
17
|
value: str | DarglintStrictness,
|
|
16
18
|
) -> DarglintStrictness:
|
|
19
|
+
"""Normalize a strictness value, defaulting to FULL on error.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
value: String or enum member representing strictness.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
DarglintStrictness: Normalized strictness enum value.
|
|
26
|
+
"""
|
|
17
27
|
if isinstance(value, DarglintStrictness):
|
|
18
28
|
return value
|
|
19
29
|
try:
|
lintro/enums/hadolint_enums.py
CHANGED
|
@@ -6,6 +6,8 @@ from enum import StrEnum, auto
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class HadolintFormat(StrEnum):
|
|
9
|
+
"""Supported output formats for Hadolint."""
|
|
10
|
+
|
|
9
11
|
TTY = auto()
|
|
10
12
|
JSON = auto()
|
|
11
13
|
CHECKSTYLE = auto()
|
|
@@ -18,6 +20,8 @@ class HadolintFormat(StrEnum):
|
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class HadolintFailureThreshold(StrEnum):
|
|
23
|
+
"""Hadolint failure thresholds used to gate exit status."""
|
|
24
|
+
|
|
21
25
|
ERROR = auto()
|
|
22
26
|
WARNING = auto()
|
|
23
27
|
INFO = auto()
|
|
@@ -27,6 +31,15 @@ class HadolintFailureThreshold(StrEnum):
|
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
def normalize_hadolint_format(value: str | HadolintFormat) -> HadolintFormat:
|
|
34
|
+
"""Normalize user input to a HadolintFormat.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
value: Existing enum member or string name of the format.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
HadolintFormat: Canonical enum value, defaulting to ``TTY`` when
|
|
41
|
+
parsing fails.
|
|
42
|
+
"""
|
|
30
43
|
if isinstance(value, HadolintFormat):
|
|
31
44
|
return value
|
|
32
45
|
try:
|
|
@@ -38,6 +51,15 @@ def normalize_hadolint_format(value: str | HadolintFormat) -> HadolintFormat:
|
|
|
38
51
|
def normalize_hadolint_threshold(
|
|
39
52
|
value: str | HadolintFailureThreshold,
|
|
40
53
|
) -> HadolintFailureThreshold:
|
|
54
|
+
"""Normalize user input to a HadolintFailureThreshold.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
value: Existing enum member or string name of the threshold.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
HadolintFailureThreshold: Canonical enum value, defaulting to ``INFO``
|
|
61
|
+
when parsing fails.
|
|
62
|
+
"""
|
|
41
63
|
if isinstance(value, HadolintFailureThreshold):
|
|
42
64
|
return value
|
|
43
65
|
try:
|
lintro/enums/tool_name.py
CHANGED
lintro/enums/tool_type.py
CHANGED
|
@@ -17,6 +17,7 @@ class ToolType(Flag):
|
|
|
17
17
|
DOCUMENTATION = Tool that checks documentation
|
|
18
18
|
SECURITY = Tool that checks for security issues
|
|
19
19
|
INFRASTRUCTURE = Tool that checks infrastructure code
|
|
20
|
+
TEST_RUNNER = Tool that runs tests
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
23
|
LINTER = auto()
|
|
@@ -25,3 +26,4 @@ class ToolType(Flag):
|
|
|
25
26
|
DOCUMENTATION = auto()
|
|
26
27
|
SECURITY = auto()
|
|
27
28
|
INFRASTRUCTURE = auto()
|
|
29
|
+
TEST_RUNNER = auto()
|
lintro/enums/yamllint_format.py
CHANGED
|
@@ -6,6 +6,8 @@ from enum import StrEnum, auto
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class YamllintFormat(StrEnum):
|
|
9
|
+
"""Output styles supported by Yamllint's CLI."""
|
|
10
|
+
|
|
9
11
|
PARSABLE = auto()
|
|
10
12
|
STANDARD = auto()
|
|
11
13
|
COLORED = auto()
|
|
@@ -14,6 +16,15 @@ class YamllintFormat(StrEnum):
|
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
def normalize_yamllint_format(value: str | YamllintFormat) -> YamllintFormat:
|
|
19
|
+
"""Normalize a value to a YamllintFormat enum member.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
value: Existing enum member or string name of the format.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
YamllintFormat: Canonical enum value, defaulting to ``PARSABLE`` when
|
|
26
|
+
parsing fails.
|
|
27
|
+
"""
|
|
17
28
|
if isinstance(value, YamllintFormat):
|
|
18
29
|
return value
|
|
19
30
|
try:
|
lintro/exceptions/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Project-specific exception classes and error helpers."""
|
lintro/formatters/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Formatters for converting tool outputs into human-friendly tables."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core formatting abstractions for tool-agnostic table rendering."""
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
"""Output style abstraction for rendering tabular data.
|
|
2
|
+
|
|
3
|
+
Defines a minimal interface consumed by format-specific implementations.
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
from abc import ABC, abstractmethod
|
|
2
7
|
from typing import Any
|
|
3
8
|
|
|
4
9
|
|
|
5
10
|
class OutputStyle(ABC):
|
|
11
|
+
"""Abstract base class for output style renderers.
|
|
12
|
+
|
|
13
|
+
Implementations convert tabular data into a concrete textual
|
|
14
|
+
representation (e.g., grid, markdown, plain).
|
|
15
|
+
"""
|
|
16
|
+
|
|
6
17
|
@abstractmethod
|
|
7
18
|
def format(
|
|
8
19
|
self,
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
"""Interfaces for describing table columns and rows for tool issues."""
|
|
2
|
+
|
|
1
3
|
from abc import ABC, abstractmethod
|
|
2
4
|
from typing import Any
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
class TableDescriptor(ABC):
|
|
8
|
+
"""Describe how to extract tabular data for a tool's issues.
|
|
9
|
+
|
|
10
|
+
Concrete implementations define column ordering and how to map issue
|
|
11
|
+
objects into a list of column values.
|
|
12
|
+
"""
|
|
13
|
+
|
|
6
14
|
@abstractmethod
|
|
7
15
|
def get_columns(self) -> list[str]:
|
|
8
16
|
"""Return the list of column names in order."""
|
lintro/formatters/styles/csv.py
CHANGED
lintro/formatters/styles/grid.py
CHANGED
lintro/formatters/styles/html.py
CHANGED
lintro/formatters/styles/json.py
CHANGED
|
@@ -12,10 +12,18 @@ from lintro.formatters.tools.darglint_formatter import (
|
|
|
12
12
|
DarglintTableDescriptor,
|
|
13
13
|
format_darglint_issues,
|
|
14
14
|
)
|
|
15
|
+
from lintro.formatters.tools.eslint_formatter import (
|
|
16
|
+
EslintTableDescriptor,
|
|
17
|
+
format_eslint_issues,
|
|
18
|
+
)
|
|
15
19
|
from lintro.formatters.tools.hadolint_formatter import (
|
|
16
20
|
HadolintTableDescriptor,
|
|
17
21
|
format_hadolint_issues,
|
|
18
22
|
)
|
|
23
|
+
from lintro.formatters.tools.markdownlint_formatter import (
|
|
24
|
+
MarkdownlintTableDescriptor,
|
|
25
|
+
format_markdownlint_issues,
|
|
26
|
+
)
|
|
19
27
|
from lintro.formatters.tools.prettier_formatter import (
|
|
20
28
|
PrettierTableDescriptor,
|
|
21
29
|
format_prettier_issues,
|
|
@@ -36,8 +44,12 @@ __all__ = [
|
|
|
36
44
|
"format_bandit_issues",
|
|
37
45
|
"DarglintTableDescriptor",
|
|
38
46
|
"format_darglint_issues",
|
|
47
|
+
"EslintTableDescriptor",
|
|
48
|
+
"format_eslint_issues",
|
|
39
49
|
"HadolintTableDescriptor",
|
|
40
50
|
"format_hadolint_issues",
|
|
51
|
+
"MarkdownlintTableDescriptor",
|
|
52
|
+
"format_markdownlint_issues",
|
|
41
53
|
"PrettierTableDescriptor",
|
|
42
54
|
"format_prettier_issues",
|
|
43
55
|
"RuffTableDescriptor",
|