thailint 0.15.8__py3-none-any.whl → 0.16.0__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.
- src/cli/config.py +4 -12
- src/cli/linters/__init__.py +5 -2
- src/cli/linters/code_patterns.py +42 -38
- src/cli/linters/code_smells.py +8 -17
- src/cli/linters/documentation.py +3 -6
- src/cli/linters/performance.py +4 -10
- src/cli/linters/shared.py +2 -7
- src/cli/linters/structure.py +4 -11
- src/cli/linters/structure_quality.py +4 -11
- src/cli/main.py +9 -12
- src/cli/utils.py +7 -16
- src/core/__init__.py +14 -0
- src/core/rule_aliases.py +84 -0
- src/linter_config/rule_matcher.py +53 -8
- src/linters/print_statements/__init__.py +23 -11
- src/linters/print_statements/conditional_verbose_analyzer.py +200 -0
- src/linters/print_statements/conditional_verbose_rule.py +254 -0
- src/linters/print_statements/linter.py +2 -2
- {thailint-0.15.8.dist-info → thailint-0.16.0.dist-info}/METADATA +3 -2
- {thailint-0.15.8.dist-info → thailint-0.16.0.dist-info}/RECORD +23 -20
- {thailint-0.15.8.dist-info → thailint-0.16.0.dist-info}/WHEEL +0 -0
- {thailint-0.15.8.dist-info → thailint-0.16.0.dist-info}/entry_points.txt +0 -0
- {thailint-0.15.8.dist-info → thailint-0.16.0.dist-info}/licenses/LICENSE +0 -0
src/cli/config.py
CHANGED
|
@@ -21,22 +21,18 @@ Implementation: Uses Click decorators for command definition, supports multiple
|
|
|
21
21
|
validates configuration changes before saving, uses template file for init-config generation
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
import logging
|
|
25
24
|
import sys
|
|
26
25
|
from pathlib import Path
|
|
27
26
|
|
|
28
27
|
import click
|
|
29
28
|
import yaml
|
|
29
|
+
from loguru import logger
|
|
30
30
|
|
|
31
31
|
from src.config import ConfigError, save_config, validate_config
|
|
32
32
|
|
|
33
33
|
from .config_merge import perform_merge
|
|
34
34
|
from .main import cli
|
|
35
35
|
|
|
36
|
-
# Configure module logger
|
|
37
|
-
logger = logging.getLogger(__name__)
|
|
38
|
-
|
|
39
|
-
|
|
40
36
|
# =============================================================================
|
|
41
37
|
# Config Command Group
|
|
42
38
|
# =============================================================================
|
|
@@ -177,8 +173,7 @@ def _save_and_report_success(
|
|
|
177
173
|
"""Save configuration and report success."""
|
|
178
174
|
save_config(cfg, config_path)
|
|
179
175
|
click.echo(f"Set {key} = {value}")
|
|
180
|
-
|
|
181
|
-
logger.info(f"Configuration updated: {key}={value}")
|
|
176
|
+
logger.debug(f"Configuration updated: {key}={value}")
|
|
182
177
|
|
|
183
178
|
|
|
184
179
|
@config.command("set")
|
|
@@ -256,8 +251,7 @@ def config_reset(ctx: click.Context, yes: bool) -> None:
|
|
|
256
251
|
save_config(DEFAULT_CONFIG.copy(), config_path)
|
|
257
252
|
click.echo("Configuration reset to defaults")
|
|
258
253
|
|
|
259
|
-
|
|
260
|
-
logger.info("Configuration reset to defaults")
|
|
254
|
+
logger.debug("Configuration reset to defaults")
|
|
261
255
|
except ConfigError as e:
|
|
262
256
|
click.echo(f"Error resetting configuration: {e}", err=True)
|
|
263
257
|
sys.exit(1)
|
|
@@ -462,7 +456,6 @@ def hello(ctx: click.Context, name: str, uppercase: bool) -> None:
|
|
|
462
456
|
thai-lint hello --name Bob --uppercase
|
|
463
457
|
"""
|
|
464
458
|
config = ctx.obj["config"]
|
|
465
|
-
verbose = ctx.obj.get("verbose", False)
|
|
466
459
|
|
|
467
460
|
# Get greeting from config or use default
|
|
468
461
|
greeting_template = config.get("greeting", "Hello")
|
|
@@ -476,5 +469,4 @@ def hello(ctx: click.Context, name: str, uppercase: bool) -> None:
|
|
|
476
469
|
# Output greeting
|
|
477
470
|
click.echo(message)
|
|
478
471
|
|
|
479
|
-
|
|
480
|
-
logger.info(f"Greeted {name} with template '{greeting_template}'")
|
|
472
|
+
logger.debug(f"Greeted {name} with template '{greeting_template}'")
|
src/cli/linters/__init__.py
CHANGED
|
@@ -6,8 +6,9 @@ Scope: Export and registration of all linter CLI commands (nesting, srp, dry, ma
|
|
|
6
6
|
Overview: Package initialization that imports all linter command modules to trigger their registration
|
|
7
7
|
with the main CLI group via Click decorators. Each submodule defines commands using @cli.command()
|
|
8
8
|
decorators that automatically register with the CLI when imported. Organized by logical grouping:
|
|
9
|
-
structure_quality (nesting, srp), code_smells (dry, magic-numbers), code_patterns (
|
|
9
|
+
structure_quality (nesting, srp), code_smells (dry, magic-numbers), code_patterns (improper-logging,
|
|
10
10
|
method-property, stateless-class), structure (file-placement, pipeline), documentation (file-header).
|
|
11
|
+
Note: print-statements is a deprecated alias for improper-logging.
|
|
11
12
|
|
|
12
13
|
Dependencies: Click for CLI framework, src.cli.main for CLI group, individual linter modules
|
|
13
14
|
|
|
@@ -34,6 +35,7 @@ from src.cli.linters import ( # noqa: F401
|
|
|
34
35
|
|
|
35
36
|
# Re-export command functions for testing and reference
|
|
36
37
|
from src.cli.linters.code_patterns import (
|
|
38
|
+
improper_logging,
|
|
37
39
|
method_property,
|
|
38
40
|
print_statements,
|
|
39
41
|
stateless_class,
|
|
@@ -52,7 +54,8 @@ __all__ = [
|
|
|
52
54
|
"dry",
|
|
53
55
|
"magic_numbers",
|
|
54
56
|
# Code pattern commands
|
|
55
|
-
"
|
|
57
|
+
"improper_logging",
|
|
58
|
+
"print_statements", # deprecated alias for improper_logging
|
|
56
59
|
"method_property",
|
|
57
60
|
"stateless_class",
|
|
58
61
|
# Structure commands
|
src/cli/linters/code_patterns.py
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Purpose: CLI commands for code pattern linters (
|
|
2
|
+
Purpose: CLI commands for code pattern linters (improper-logging, method-property, stateless-class, lazy-ignores, lbyl)
|
|
3
3
|
|
|
4
4
|
Scope: Commands that detect code patterns and anti-patterns in Python code
|
|
5
5
|
|
|
6
|
-
Overview: Provides CLI commands for code pattern linting:
|
|
7
|
-
console.log calls that should use proper logging
|
|
8
|
-
@property decorators, stateless-class detects
|
|
9
|
-
functions, lazy-ignores detects unjustified linting
|
|
10
|
-
You Leap anti-patterns. Each command supports
|
|
11
|
-
integrates with the orchestrator for execution.
|
|
6
|
+
Overview: Provides CLI commands for code pattern linting: improper-logging detects print() and
|
|
7
|
+
console.log calls that should use proper logging as well as conditional verbose patterns,
|
|
8
|
+
method-property finds methods that should be @property decorators, stateless-class detects
|
|
9
|
+
classes without state that should be module functions, lazy-ignores detects unjustified linting
|
|
10
|
+
suppressions, and lbyl detects Look Before You Leap anti-patterns. Each command supports
|
|
11
|
+
standard options (config, format, recursive) and integrates with the orchestrator for execution.
|
|
12
|
+
Note: print-statements is a deprecated alias for improper-logging.
|
|
12
13
|
|
|
13
14
|
Dependencies: click for CLI framework, src.cli.main for CLI group, src.cli.utils for shared utilities
|
|
14
15
|
|
|
15
|
-
Exports: print_statements, method_property, stateless_class, lazy_ignores, lbyl commands
|
|
16
|
+
Exports: improper_logging, print_statements (alias), method_property, stateless_class, lazy_ignores, lbyl commands
|
|
16
17
|
|
|
17
18
|
Interfaces: Click CLI commands registered to main CLI group
|
|
18
19
|
|
|
19
20
|
Implementation: Click decorators for command definition, orchestrator-based linting execution
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
|
-
import logging
|
|
23
23
|
import sys
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
from typing import TYPE_CHECKING, NoReturn
|
|
26
26
|
|
|
27
|
+
from loguru import logger
|
|
28
|
+
|
|
27
29
|
from src.cli.linters.shared import ExecuteParams, create_linter_command
|
|
28
30
|
from src.cli.utils import execute_linting_on_paths, setup_base_orchestrator, validate_paths_exist
|
|
29
31
|
from src.core.cli_utils import format_violations
|
|
@@ -32,53 +34,59 @@ from src.core.types import Violation
|
|
|
32
34
|
if TYPE_CHECKING:
|
|
33
35
|
from src.orchestrator.core import Orchestrator
|
|
34
36
|
|
|
35
|
-
# Configure module logger
|
|
36
|
-
logger = logging.getLogger(__name__)
|
|
37
|
-
|
|
38
37
|
|
|
39
38
|
# =============================================================================
|
|
40
|
-
#
|
|
39
|
+
# Improper Logging Command (formerly print-statements)
|
|
41
40
|
# =============================================================================
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
def
|
|
43
|
+
def _setup_improper_logging_orchestrator(
|
|
45
44
|
path_objs: list[Path], config_file: str | None, verbose: bool, project_root: Path | None = None
|
|
46
45
|
) -> "Orchestrator":
|
|
47
|
-
"""Set up orchestrator for
|
|
46
|
+
"""Set up orchestrator for improper-logging command."""
|
|
48
47
|
return setup_base_orchestrator(path_objs, config_file, verbose, project_root)
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
def
|
|
50
|
+
def _run_improper_logging_lint(
|
|
52
51
|
orchestrator: "Orchestrator", path_objs: list[Path], recursive: bool, parallel: bool = False
|
|
53
52
|
) -> list[Violation]:
|
|
54
|
-
"""Execute
|
|
53
|
+
"""Execute improper-logging lint on files or directories."""
|
|
55
54
|
all_violations = execute_linting_on_paths(orchestrator, path_objs, recursive, parallel)
|
|
56
|
-
return [v for v in all_violations if "
|
|
55
|
+
return [v for v in all_violations if v.rule_id.startswith("improper-logging.")]
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
def
|
|
60
|
-
"""Execute
|
|
58
|
+
def _execute_improper_logging_lint(params: ExecuteParams) -> NoReturn:
|
|
59
|
+
"""Execute improper-logging lint."""
|
|
61
60
|
validate_paths_exist(params.path_objs)
|
|
62
|
-
orchestrator =
|
|
61
|
+
orchestrator = _setup_improper_logging_orchestrator(
|
|
63
62
|
params.path_objs, params.config_file, params.verbose, params.project_root
|
|
64
63
|
)
|
|
65
|
-
|
|
64
|
+
improper_logging_violations = _run_improper_logging_lint(
|
|
66
65
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
67
66
|
)
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
logger.info(f"Found {len(print_statements_violations)} print statement violation(s)")
|
|
68
|
+
logger.debug(f"Found {len(improper_logging_violations)} improper logging violation(s)")
|
|
71
69
|
|
|
72
|
-
format_violations(
|
|
73
|
-
sys.exit(1 if
|
|
70
|
+
format_violations(improper_logging_violations, params.format)
|
|
71
|
+
sys.exit(1 if improper_logging_violations else 0)
|
|
74
72
|
|
|
75
73
|
|
|
74
|
+
# Primary command
|
|
75
|
+
improper_logging = create_linter_command(
|
|
76
|
+
"improper-logging",
|
|
77
|
+
_execute_improper_logging_lint,
|
|
78
|
+
"Check for improper logging patterns in code.",
|
|
79
|
+
"Detects print()/console statements and conditional verbose patterns that should\n"
|
|
80
|
+
" be replaced with proper logging configuration.",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Backward-compatible alias (deprecated)
|
|
76
84
|
print_statements = create_linter_command(
|
|
77
85
|
"print-statements",
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"Detects print() calls in Python and
|
|
81
|
-
" in TypeScript/JavaScript
|
|
86
|
+
_execute_improper_logging_lint, # Same executor as improper-logging
|
|
87
|
+
"Alias for improper-logging (deprecated).",
|
|
88
|
+
"DEPRECATED: Use 'improper-logging' instead. Detects print() calls in Python and\n"
|
|
89
|
+
" console.log/warn/error/debug/info calls in TypeScript/JavaScript.",
|
|
82
90
|
)
|
|
83
91
|
|
|
84
92
|
|
|
@@ -112,8 +120,7 @@ def _execute_method_property_lint(params: ExecuteParams) -> NoReturn:
|
|
|
112
120
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
113
121
|
)
|
|
114
122
|
|
|
115
|
-
|
|
116
|
-
logger.info(f"Found {len(method_property_violations)} method-property violation(s)")
|
|
123
|
+
logger.debug(f"Found {len(method_property_violations)} method-property violation(s)")
|
|
117
124
|
|
|
118
125
|
format_violations(method_property_violations, params.format)
|
|
119
126
|
sys.exit(1 if method_property_violations else 0)
|
|
@@ -159,8 +166,7 @@ def _execute_stateless_class_lint(params: ExecuteParams) -> NoReturn:
|
|
|
159
166
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
160
167
|
)
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
logger.info(f"Found {len(stateless_class_violations)} stateless-class violation(s)")
|
|
169
|
+
logger.debug(f"Found {len(stateless_class_violations)} stateless-class violation(s)")
|
|
164
170
|
|
|
165
171
|
format_violations(stateless_class_violations, params.format)
|
|
166
172
|
sys.exit(1 if stateless_class_violations else 0)
|
|
@@ -206,8 +212,7 @@ def _execute_lazy_ignores_lint(params: ExecuteParams) -> NoReturn:
|
|
|
206
212
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
207
213
|
)
|
|
208
214
|
|
|
209
|
-
|
|
210
|
-
logger.info(f"Found {len(lazy_ignores_violations)} lazy-ignores violation(s)")
|
|
215
|
+
logger.debug(f"Found {len(lazy_ignores_violations)} lazy-ignores violation(s)")
|
|
211
216
|
|
|
212
217
|
format_violations(lazy_ignores_violations, params.format)
|
|
213
218
|
sys.exit(1 if lazy_ignores_violations else 0)
|
|
@@ -253,8 +258,7 @@ def _execute_lbyl_lint(params: ExecuteParams) -> NoReturn:
|
|
|
253
258
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
254
259
|
)
|
|
255
260
|
|
|
256
|
-
|
|
257
|
-
logger.info(f"Found {len(lbyl_violations)} LBYL violation(s)")
|
|
261
|
+
logger.debug(f"Found {len(lbyl_violations)} LBYL violation(s)")
|
|
258
262
|
|
|
259
263
|
format_violations(lbyl_violations, params.format)
|
|
260
264
|
sys.exit(1 if lbyl_violations else 0)
|
src/cli/linters/code_smells.py
CHANGED
|
@@ -23,13 +23,13 @@ Suppressions:
|
|
|
23
23
|
many parameters by framework design (dry command has 8 params for extra options)
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
import logging
|
|
27
26
|
import sys
|
|
28
27
|
from pathlib import Path
|
|
29
28
|
from typing import TYPE_CHECKING, Any, NoReturn
|
|
30
29
|
|
|
31
30
|
import click
|
|
32
31
|
import yaml
|
|
32
|
+
from loguru import logger
|
|
33
33
|
|
|
34
34
|
from src.cli.linters.shared import (
|
|
35
35
|
ExecuteParams,
|
|
@@ -53,10 +53,6 @@ from src.core.types import Violation
|
|
|
53
53
|
if TYPE_CHECKING:
|
|
54
54
|
from src.orchestrator.core import Orchestrator
|
|
55
55
|
|
|
56
|
-
# Configure module logger
|
|
57
|
-
logger = logging.getLogger(__name__)
|
|
58
|
-
|
|
59
|
-
|
|
60
56
|
# =============================================================================
|
|
61
57
|
# DRY Command (custom options - cannot use create_linter_command)
|
|
62
58
|
# =============================================================================
|
|
@@ -87,8 +83,7 @@ def _load_dry_config_file(orchestrator: "Orchestrator", config_file: str, verbos
|
|
|
87
83
|
except KeyError:
|
|
88
84
|
return # No DRY config in file
|
|
89
85
|
orchestrator.config.update({"dry": dry_config})
|
|
90
|
-
|
|
91
|
-
logger.info(f"Loaded DRY config from {config_file}")
|
|
86
|
+
logger.debug(f"Loaded DRY config from {config_file}")
|
|
92
87
|
|
|
93
88
|
|
|
94
89
|
def _apply_dry_config_override(
|
|
@@ -108,10 +103,9 @@ def _clear_dry_cache(orchestrator: "Orchestrator", verbose: bool) -> None:
|
|
|
108
103
|
|
|
109
104
|
if cache_path.exists():
|
|
110
105
|
cache_path.unlink()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
logger.info("Cache file does not exist, nothing to clear")
|
|
106
|
+
logger.debug(f"Cleared cache: {cache_path}")
|
|
107
|
+
else:
|
|
108
|
+
logger.debug("Cache file does not exist, nothing to clear")
|
|
115
109
|
|
|
116
110
|
|
|
117
111
|
def _run_dry_lint(
|
|
@@ -242,8 +236,7 @@ def _execute_dry_lint( # pylint: disable=too-many-arguments,too-many-positional
|
|
|
242
236
|
|
|
243
237
|
dry_violations = _run_dry_lint(orchestrator, path_objs, recursive, parallel)
|
|
244
238
|
|
|
245
|
-
|
|
246
|
-
logger.info(f"Found {len(dry_violations)} DRY violation(s)")
|
|
239
|
+
logger.debug(f"Found {len(dry_violations)} DRY violation(s)")
|
|
247
240
|
|
|
248
241
|
format_violations(dry_violations, format)
|
|
249
242
|
sys.exit(1 if dry_violations else 0)
|
|
@@ -279,8 +272,7 @@ def _execute_magic_numbers_lint(params: ExecuteParams) -> NoReturn:
|
|
|
279
272
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
280
273
|
)
|
|
281
274
|
|
|
282
|
-
|
|
283
|
-
logger.info(f"Found {len(magic_numbers_violations)} magic number violation(s)")
|
|
275
|
+
logger.debug(f"Found {len(magic_numbers_violations)} magic number violation(s)")
|
|
284
276
|
|
|
285
277
|
format_violations(magic_numbers_violations, params.format)
|
|
286
278
|
sys.exit(1 if magic_numbers_violations else 0)
|
|
@@ -325,8 +317,7 @@ def _execute_stringly_typed_lint(params: ExecuteParams) -> NoReturn:
|
|
|
325
317
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
326
318
|
)
|
|
327
319
|
|
|
328
|
-
|
|
329
|
-
logger.info(f"Found {len(stringly_violations)} stringly-typed violation(s)")
|
|
320
|
+
logger.debug(f"Found {len(stringly_violations)} stringly-typed violation(s)")
|
|
330
321
|
|
|
331
322
|
format_violations(stringly_violations, params.format)
|
|
332
323
|
sys.exit(1 if stringly_violations else 0)
|
src/cli/linters/documentation.py
CHANGED
|
@@ -18,11 +18,12 @@ Interfaces: Click CLI commands registered to main CLI group
|
|
|
18
18
|
Implementation: Click decorators for command definition, orchestrator-based linting execution
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
import logging
|
|
22
21
|
import sys
|
|
23
22
|
from pathlib import Path
|
|
24
23
|
from typing import TYPE_CHECKING, NoReturn
|
|
25
24
|
|
|
25
|
+
from loguru import logger
|
|
26
|
+
|
|
26
27
|
from src.cli.linters.shared import ExecuteParams, create_linter_command
|
|
27
28
|
from src.cli.utils import execute_linting_on_paths, setup_base_orchestrator, validate_paths_exist
|
|
28
29
|
from src.core.cli_utils import format_violations
|
|
@@ -31,9 +32,6 @@ from src.core.types import Violation
|
|
|
31
32
|
if TYPE_CHECKING:
|
|
32
33
|
from src.orchestrator.core import Orchestrator
|
|
33
34
|
|
|
34
|
-
# Configure module logger
|
|
35
|
-
logger = logging.getLogger(__name__)
|
|
36
|
-
|
|
37
35
|
|
|
38
36
|
# =============================================================================
|
|
39
37
|
# File Header Command
|
|
@@ -65,8 +63,7 @@ def _execute_file_header_lint(params: ExecuteParams) -> NoReturn:
|
|
|
65
63
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
66
64
|
)
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
logger.info(f"Found {len(file_header_violations)} file header violation(s)")
|
|
66
|
+
logger.debug(f"Found {len(file_header_violations)} file header violation(s)")
|
|
70
67
|
|
|
71
68
|
format_violations(file_header_violations, params.format)
|
|
72
69
|
sys.exit(1 if file_header_violations else 0)
|
src/cli/linters/performance.py
CHANGED
|
@@ -24,12 +24,12 @@ Suppressions:
|
|
|
24
24
|
--rule option for 6 total parameters - framework design requirement for CLI extensibility.
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
-
import logging
|
|
28
27
|
import sys
|
|
29
28
|
from pathlib import Path
|
|
30
29
|
from typing import TYPE_CHECKING, NoReturn
|
|
31
30
|
|
|
32
31
|
import click
|
|
32
|
+
from loguru import logger
|
|
33
33
|
|
|
34
34
|
from src.cli.linters.shared import (
|
|
35
35
|
ExecuteParams,
|
|
@@ -46,9 +46,6 @@ from src.core.types import Violation
|
|
|
46
46
|
if TYPE_CHECKING:
|
|
47
47
|
from src.orchestrator.core import Orchestrator
|
|
48
48
|
|
|
49
|
-
# Configure module logger
|
|
50
|
-
logger = logging.getLogger(__name__)
|
|
51
|
-
|
|
52
49
|
|
|
53
50
|
# =============================================================================
|
|
54
51
|
# String Concat Loop Command
|
|
@@ -88,8 +85,7 @@ def _execute_string_concat_lint(params: ExecuteParams) -> NoReturn:
|
|
|
88
85
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
89
86
|
)
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
logger.info(f"Found {len(violations)} string-concat-loop violation(s)")
|
|
88
|
+
logger.debug(f"Found {len(violations)} string-concat-loop violation(s)")
|
|
93
89
|
|
|
94
90
|
format_violations(violations, params.format)
|
|
95
91
|
sys.exit(1 if violations else 0)
|
|
@@ -124,8 +120,7 @@ def _execute_regex_in_loop_lint(params: ExecuteParams) -> NoReturn:
|
|
|
124
120
|
orchestrator, params.path_objs, params.recursive, params.parallel
|
|
125
121
|
)
|
|
126
122
|
|
|
127
|
-
|
|
128
|
-
logger.info(f"Found {len(violations)} regex-in-loop violation(s)")
|
|
123
|
+
logger.debug(f"Found {len(violations)} regex-in-loop violation(s)")
|
|
129
124
|
|
|
130
125
|
format_violations(violations, params.format)
|
|
131
126
|
sys.exit(1 if violations else 0)
|
|
@@ -207,8 +202,7 @@ def _execute_perf_lint(params: ExecuteParams, rule: str | None) -> NoReturn:
|
|
|
207
202
|
orchestrator, params.path_objs, params.recursive, rule, params.parallel
|
|
208
203
|
)
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
logger.info(f"Found {len(violations)} performance violation(s)")
|
|
205
|
+
logger.debug(f"Found {len(violations)} performance violation(s)")
|
|
212
206
|
|
|
213
207
|
format_violations(violations, params.format)
|
|
214
208
|
sys.exit(1 if violations else 0)
|
src/cli/linters/shared.py
CHANGED
|
@@ -27,12 +27,12 @@ Suppressions:
|
|
|
27
27
|
by Click framework design (ctx, paths, config_file, format, recursive, parallel = 6 params)
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
-
import logging
|
|
31
30
|
from dataclasses import dataclass
|
|
32
31
|
from pathlib import Path
|
|
33
32
|
from typing import TYPE_CHECKING, Any
|
|
34
33
|
|
|
35
34
|
import click
|
|
35
|
+
from loguru import logger
|
|
36
36
|
|
|
37
37
|
from src.cli.utils import (
|
|
38
38
|
format_option,
|
|
@@ -185,10 +185,6 @@ def run_linter_command(
|
|
|
185
185
|
handle_linting_error(e, params.verbose)
|
|
186
186
|
|
|
187
187
|
|
|
188
|
-
# Configure module logger
|
|
189
|
-
logger = logging.getLogger(__name__)
|
|
190
|
-
|
|
191
|
-
|
|
192
188
|
def ensure_config_section(orchestrator: "Orchestrator", section: str) -> dict[str, Any]:
|
|
193
189
|
"""Ensure a config section exists and return it.
|
|
194
190
|
|
|
@@ -219,8 +215,7 @@ def set_config_value(config: dict[str, Any], key: str, value: Any, verbose: bool
|
|
|
219
215
|
if value is None:
|
|
220
216
|
return
|
|
221
217
|
config[key] = value
|
|
222
|
-
|
|
223
|
-
logger.debug(f"Overriding {key} to {value}")
|
|
218
|
+
logger.debug(f"Overriding {key} to {value}")
|
|
224
219
|
|
|
225
220
|
|
|
226
221
|
def filter_violations_by_prefix(violations: list[Violation], prefix: str) -> list[Violation]:
|
src/cli/linters/structure.py
CHANGED
|
@@ -25,12 +25,12 @@ Suppressions:
|
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
import json
|
|
28
|
-
import logging
|
|
29
28
|
import sys
|
|
30
29
|
from pathlib import Path
|
|
31
30
|
from typing import TYPE_CHECKING, Any, NoReturn
|
|
32
31
|
|
|
33
32
|
import click
|
|
33
|
+
from loguru import logger
|
|
34
34
|
|
|
35
35
|
from src.cli.linters.shared import (
|
|
36
36
|
ensure_config_section,
|
|
@@ -54,10 +54,6 @@ from src.core.types import Violation
|
|
|
54
54
|
if TYPE_CHECKING:
|
|
55
55
|
from src.orchestrator.core import Orchestrator
|
|
56
56
|
|
|
57
|
-
# Configure module logger
|
|
58
|
-
logger = logging.getLogger(__name__)
|
|
59
|
-
|
|
60
|
-
|
|
61
57
|
# =============================================================================
|
|
62
58
|
# File Placement Command
|
|
63
59
|
# =============================================================================
|
|
@@ -93,8 +89,7 @@ def _apply_inline_rules(orchestrator: "Orchestrator", rules: str, verbose: bool)
|
|
|
93
89
|
"""Parse and apply inline JSON rules."""
|
|
94
90
|
rules_config = _parse_json_rules(rules)
|
|
95
91
|
orchestrator.config.update(rules_config)
|
|
96
|
-
|
|
97
|
-
logger.debug(f"Applied inline rules: {rules_config}")
|
|
92
|
+
logger.debug(f"Applied inline rules: {rules_config}")
|
|
98
93
|
|
|
99
94
|
|
|
100
95
|
def _parse_json_rules(rules: str) -> dict[str, Any]:
|
|
@@ -195,8 +190,7 @@ def _execute_file_placement_lint( # pylint: disable=too-many-arguments,too-many
|
|
|
195
190
|
# Filter to only file-placement violations
|
|
196
191
|
violations = [v for v in all_violations if v.rule_id.startswith("file-placement")]
|
|
197
192
|
|
|
198
|
-
|
|
199
|
-
logger.info(f"Found {len(violations)} violation(s)")
|
|
193
|
+
logger.debug(f"Found {len(violations)} violation(s)")
|
|
200
194
|
|
|
201
195
|
format_violations(violations, format)
|
|
202
196
|
sys.exit(1 if violations else 0)
|
|
@@ -320,8 +314,7 @@ def _execute_pipeline_lint( # pylint: disable=too-many-arguments,too-many-posit
|
|
|
320
314
|
_apply_pipeline_config_override(orchestrator, min_continues, verbose)
|
|
321
315
|
pipeline_violations = _run_pipeline_lint(orchestrator, path_objs, recursive, parallel)
|
|
322
316
|
|
|
323
|
-
|
|
324
|
-
logger.info(f"Found {len(pipeline_violations)} collection-pipeline violation(s)")
|
|
317
|
+
logger.debug(f"Found {len(pipeline_violations)} collection-pipeline violation(s)")
|
|
325
318
|
|
|
326
319
|
format_violations(pipeline_violations, format)
|
|
327
320
|
sys.exit(1 if pipeline_violations else 0)
|
|
@@ -24,13 +24,13 @@ Suppressions:
|
|
|
24
24
|
- too-many-arguments,too-many-positional-arguments: Click commands require many parameters by framework design
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
-
import logging
|
|
28
27
|
import sys
|
|
29
28
|
from contextlib import suppress
|
|
30
29
|
from pathlib import Path
|
|
31
30
|
from typing import TYPE_CHECKING, NoReturn
|
|
32
31
|
|
|
33
32
|
import click
|
|
33
|
+
from loguru import logger
|
|
34
34
|
|
|
35
35
|
from src.cli.linters.shared import (
|
|
36
36
|
ensure_config_section,
|
|
@@ -52,10 +52,6 @@ from src.core.types import Violation
|
|
|
52
52
|
if TYPE_CHECKING:
|
|
53
53
|
from src.orchestrator.core import Orchestrator
|
|
54
54
|
|
|
55
|
-
# Configure module logger
|
|
56
|
-
logger = logging.getLogger(__name__)
|
|
57
|
-
|
|
58
|
-
|
|
59
55
|
# =============================================================================
|
|
60
56
|
# Nesting Command
|
|
61
57
|
# =============================================================================
|
|
@@ -79,8 +75,7 @@ def _apply_nesting_config_override(
|
|
|
79
75
|
nesting_config["max_nesting_depth"] = max_depth
|
|
80
76
|
_apply_nesting_to_languages(nesting_config, max_depth)
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
logger.debug(f"Overriding max_nesting_depth to {max_depth}")
|
|
78
|
+
logger.debug(f"Overriding max_nesting_depth to {max_depth}")
|
|
84
79
|
|
|
85
80
|
|
|
86
81
|
def _apply_nesting_to_languages(nesting_config: dict, max_depth: int) -> None:
|
|
@@ -189,8 +184,7 @@ def _execute_nesting_lint( # pylint: disable=too-many-arguments,too-many-positi
|
|
|
189
184
|
_apply_nesting_config_override(orchestrator, max_depth, verbose)
|
|
190
185
|
nesting_violations = _run_nesting_lint(orchestrator, path_objs, recursive, parallel)
|
|
191
186
|
|
|
192
|
-
|
|
193
|
-
logger.info(f"Found {len(nesting_violations)} nesting violation(s)")
|
|
187
|
+
logger.debug(f"Found {len(nesting_violations)} nesting violation(s)")
|
|
194
188
|
|
|
195
189
|
format_violations(nesting_violations, format)
|
|
196
190
|
sys.exit(1 if nesting_violations else 0)
|
|
@@ -321,8 +315,7 @@ def _execute_srp_lint( # pylint: disable=too-many-arguments,too-many-positional
|
|
|
321
315
|
_apply_srp_config_override(orchestrator, max_methods, max_loc, verbose)
|
|
322
316
|
srp_violations = _run_srp_lint(orchestrator, path_objs, recursive, parallel)
|
|
323
317
|
|
|
324
|
-
|
|
325
|
-
logger.info(f"Found {len(srp_violations)} SRP violation(s)")
|
|
318
|
+
logger.debug(f"Found {len(srp_violations)} SRP violation(s)")
|
|
326
319
|
|
|
327
320
|
format_violations(srp_violations, format)
|
|
328
321
|
sys.exit(1 if srp_violations else 0)
|
src/cli/main.py
CHANGED
|
@@ -21,32 +21,29 @@ Implementation: Uses Click decorators for group definition, stores parsed option
|
|
|
21
21
|
in test environments.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
import logging
|
|
25
24
|
import sys
|
|
26
25
|
from pathlib import Path
|
|
27
26
|
|
|
28
27
|
import click
|
|
28
|
+
from loguru import logger
|
|
29
29
|
|
|
30
30
|
from src import __version__
|
|
31
31
|
from src.config import ConfigError, load_config
|
|
32
32
|
|
|
33
|
-
# Configure module logger
|
|
34
|
-
logger = logging.getLogger(__name__)
|
|
35
|
-
|
|
36
33
|
|
|
37
34
|
def setup_logging(verbose: bool = False) -> None:
|
|
38
|
-
"""Configure
|
|
35
|
+
"""Configure loguru for the CLI application.
|
|
39
36
|
|
|
40
37
|
Args:
|
|
41
|
-
verbose: Enable DEBUG level logging if True,
|
|
38
|
+
verbose: Enable DEBUG level logging if True, WARNING otherwise.
|
|
42
39
|
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
logger.remove() # Remove default handler
|
|
41
|
+
level = "DEBUG" if verbose else "WARNING"
|
|
42
|
+
logger.add(
|
|
43
|
+
sys.stderr,
|
|
46
44
|
level=level,
|
|
47
|
-
format="
|
|
48
|
-
|
|
49
|
-
stream=sys.stdout,
|
|
45
|
+
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level:<8}</level> | <level>{message}</level>",
|
|
46
|
+
colorize=True,
|
|
50
47
|
)
|
|
51
48
|
|
|
52
49
|
|