Coverage for lintro / utils / config_validation.py: 88%
43 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Configuration validation functions for Lintro.
3This module provides functions for validating configuration consistency
4across tools and checking tool injectability.
5"""
7from __future__ import annotations
9from lintro.enums.tool_name import ToolName
10from lintro.utils.config import load_lintro_tool_config
11from lintro.utils.config_constants import GLOBAL_SETTINGS, ToolConfigInfo
12from lintro.utils.config_priority import _get_nested_value, get_effective_line_length
13from lintro.utils.native_parsers import _load_native_tool_config
16def is_tool_injectable(tool_name: str | ToolName) -> bool:
17 """Check if Lintro can inject config to a tool.
19 Args:
20 tool_name: Name of the tool (string or ToolName enum).
22 Returns:
23 True if Lintro can inject config via CLI or generated config file.
24 """
25 injectable_set: set[ToolName] = GLOBAL_SETTINGS["line_length"]["injectable"]
26 # ToolName is a StrEnum, so string comparison works
27 tool_name_lower = tool_name.lower() if isinstance(tool_name, str) else tool_name
28 return tool_name_lower in injectable_set
31def validate_config_consistency() -> list[str]:
32 """Check for inconsistencies in line length settings across tools.
34 Returns:
35 List of warning messages about inconsistent configurations.
36 """
37 warnings: list[str] = []
38 effective_line_length = get_effective_line_length(ToolName.RUFF)
40 if effective_line_length is None:
41 return warnings
43 # Check each tool's native config for mismatches
44 tools_config: dict[ToolName, str] = GLOBAL_SETTINGS["line_length"]["tools"]
45 for tool_name, setting_key in tools_config.items():
46 if tool_name == ToolName.RUFF:
47 continue # Skip Ruff (it's the source of truth)
49 native = _load_native_tool_config(tool_name)
50 native_value = _get_nested_value(native, setting_key)
52 if native_value is not None and native_value != effective_line_length:
53 injectable = is_tool_injectable(tool_name)
54 if injectable:
55 warnings.append(
56 f"{tool_name}: Native config has {setting_key}={native_value}, "
57 f"but Lintro will override with {effective_line_length}",
58 )
59 else:
60 warnings.append(
61 f"Warning: {tool_name}: Native config has "
62 f"{setting_key}={native_value}, "
63 f"differs from central line_length={effective_line_length}. "
64 f"Lintro cannot override this tool's native config - "
65 f"update manually for consistency.",
66 )
68 return warnings
71def get_tool_config_summary() -> dict[str, ToolConfigInfo]:
72 """Get a summary of configuration for all tools.
74 Returns:
75 Dictionary mapping tool names to their config info.
76 """
77 tools = [
78 ToolName.RUFF,
79 ToolName.BLACK,
80 ToolName.YAMLLINT,
81 ToolName.MARKDOWNLINT,
82 ToolName.BANDIT,
83 ToolName.HADOLINT,
84 ToolName.ACTIONLINT,
85 ]
86 summary: dict[str, ToolConfigInfo] = {}
88 for tool_name in tools:
89 info = ToolConfigInfo(
90 tool_name=tool_name,
91 native_config=_load_native_tool_config(tool_name),
92 lintro_tool_config=load_lintro_tool_config(tool_name),
93 is_injectable=is_tool_injectable(tool_name),
94 )
96 # Compute effective line_length
97 effective_ll = get_effective_line_length(tool_name)
98 if effective_ll is not None:
99 info.effective_config["line_length"] = effective_ll
101 summary[tool_name] = info
103 # Add warnings
104 warnings = validate_config_consistency()
105 for warning in warnings:
106 for tool_name in tools:
107 if tool_name in warning.lower():
108 summary[tool_name].warnings.append(warning)
109 break
111 return summary