thailint 0.3.0__tar.gz → 0.3.1__tar.gz
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.
- {thailint-0.3.0 → thailint-0.3.1}/PKG-INFO +1 -1
- {thailint-0.3.0 → thailint-0.3.1}/pyproject.toml +2 -1
- {thailint-0.3.0 → thailint-0.3.1}/src/cli.py +101 -0
- {thailint-0.3.0 → thailint-0.3.1}/CHANGELOG.md +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/LICENSE +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/README.md +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/analyzers/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/analyzers/typescript_base.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/api.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/config.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/base.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/cli_utils.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/config_parser.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/linter_utils.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/registry.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/rule_discovery.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/types.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/core/violation_builder.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/ignore.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/loader.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/base_token_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/block_filter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/block_grouper.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/cache.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/cache_query.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/config.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/config_loader.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/deduplicator.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/duplicate_storage.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/file_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/inline_ignore.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/linter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/python_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/storage_initializer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/token_hasher.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/typescript_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_builder.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_filter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_generator.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/config_loader.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/directory_matcher.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/linter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/path_resolver.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/pattern_matcher.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/pattern_validator.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/rule_checker.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/violation_factory.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/config.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/context_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/linter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/python_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/typescript_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/violation_builder.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/config.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/linter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/python_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/typescript_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/typescript_function_extractor.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/violation_builder.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/class_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/config.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/heuristics.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/linter.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/metrics_evaluator.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/python_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/typescript_analyzer.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/typescript_metrics_calculator.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/violation_builder.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/core.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/language_detector.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/utils/__init__.py +0 -0
- {thailint-0.3.0 → thailint-0.3.1}/src/utils/project_root.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: thailint
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
|
|
@@ -17,7 +17,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
17
17
|
|
|
18
18
|
[tool.poetry]
|
|
19
19
|
name = "thailint"
|
|
20
|
-
version = "0.3.
|
|
20
|
+
version = "0.3.1"
|
|
21
21
|
description = "The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages"
|
|
22
22
|
authors = ["Steve Jackson"]
|
|
23
23
|
license = "MIT"
|
|
@@ -101,6 +101,7 @@ xenon = "^0.9.3"
|
|
|
101
101
|
safety = "^3.2.11"
|
|
102
102
|
pip-audit = "^2.8.0"
|
|
103
103
|
loguru = "^0.7.3"
|
|
104
|
+
pytest-xdist = "^3.8.0"
|
|
104
105
|
|
|
105
106
|
[tool.poetry.scripts]
|
|
106
107
|
thailint = "src.cli:cli"
|
|
@@ -1077,5 +1077,106 @@ def _run_dry_lint(orchestrator, path_objs, recursive):
|
|
|
1077
1077
|
return dry_violations
|
|
1078
1078
|
|
|
1079
1079
|
|
|
1080
|
+
def _setup_magic_numbers_orchestrator(
|
|
1081
|
+
path_objs: list[Path], config_file: str | None, verbose: bool
|
|
1082
|
+
):
|
|
1083
|
+
"""Set up orchestrator for magic-numbers command."""
|
|
1084
|
+
first_path = path_objs[0] if path_objs else Path.cwd()
|
|
1085
|
+
project_root = first_path if first_path.is_dir() else first_path.parent
|
|
1086
|
+
|
|
1087
|
+
from src.orchestrator.core import Orchestrator
|
|
1088
|
+
|
|
1089
|
+
orchestrator = Orchestrator(project_root=project_root)
|
|
1090
|
+
|
|
1091
|
+
if config_file:
|
|
1092
|
+
_load_config_file(orchestrator, config_file, verbose)
|
|
1093
|
+
|
|
1094
|
+
return orchestrator
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
def _run_magic_numbers_lint(orchestrator, path_objs: list[Path], recursive: bool):
|
|
1098
|
+
"""Execute magic-numbers lint on files or directories."""
|
|
1099
|
+
all_violations = _execute_linting_on_paths(orchestrator, path_objs, recursive)
|
|
1100
|
+
return [v for v in all_violations if "magic-number" in v.rule_id]
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@cli.command("magic-numbers")
|
|
1104
|
+
@click.argument("paths", nargs=-1, type=click.Path())
|
|
1105
|
+
@click.option("--config", "-c", "config_file", type=click.Path(), help="Path to config file")
|
|
1106
|
+
@format_option
|
|
1107
|
+
@click.option("--recursive/--no-recursive", default=True, help="Scan directories recursively")
|
|
1108
|
+
@click.pass_context
|
|
1109
|
+
def magic_numbers( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
1110
|
+
ctx,
|
|
1111
|
+
paths: tuple[str, ...],
|
|
1112
|
+
config_file: str | None,
|
|
1113
|
+
format: str,
|
|
1114
|
+
recursive: bool,
|
|
1115
|
+
):
|
|
1116
|
+
"""Check for magic numbers in code.
|
|
1117
|
+
|
|
1118
|
+
Detects unnamed numeric literals in Python and TypeScript/JavaScript code
|
|
1119
|
+
that should be extracted as named constants for better readability.
|
|
1120
|
+
|
|
1121
|
+
PATHS: Files or directories to lint (defaults to current directory if none provided)
|
|
1122
|
+
|
|
1123
|
+
Examples:
|
|
1124
|
+
|
|
1125
|
+
\b
|
|
1126
|
+
# Check current directory (all files recursively)
|
|
1127
|
+
thai-lint magic-numbers
|
|
1128
|
+
|
|
1129
|
+
\b
|
|
1130
|
+
# Check specific directory
|
|
1131
|
+
thai-lint magic-numbers src/
|
|
1132
|
+
|
|
1133
|
+
\b
|
|
1134
|
+
# Check single file
|
|
1135
|
+
thai-lint magic-numbers src/app.py
|
|
1136
|
+
|
|
1137
|
+
\b
|
|
1138
|
+
# Check multiple files
|
|
1139
|
+
thai-lint magic-numbers src/app.py src/utils.py tests/test_app.py
|
|
1140
|
+
|
|
1141
|
+
\b
|
|
1142
|
+
# Check mix of files and directories
|
|
1143
|
+
thai-lint magic-numbers src/app.py tests/
|
|
1144
|
+
|
|
1145
|
+
\b
|
|
1146
|
+
# Get JSON output
|
|
1147
|
+
thai-lint magic-numbers --format json .
|
|
1148
|
+
|
|
1149
|
+
\b
|
|
1150
|
+
# Use custom config file
|
|
1151
|
+
thai-lint magic-numbers --config .thailint.yaml src/
|
|
1152
|
+
"""
|
|
1153
|
+
verbose = ctx.obj.get("verbose", False)
|
|
1154
|
+
|
|
1155
|
+
if not paths:
|
|
1156
|
+
paths = (".",)
|
|
1157
|
+
|
|
1158
|
+
path_objs = [Path(p) for p in paths]
|
|
1159
|
+
|
|
1160
|
+
try:
|
|
1161
|
+
_execute_magic_numbers_lint(path_objs, config_file, format, recursive, verbose)
|
|
1162
|
+
except Exception as e:
|
|
1163
|
+
_handle_linting_error(e, verbose)
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
def _execute_magic_numbers_lint( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
1167
|
+
path_objs, config_file, format, recursive, verbose
|
|
1168
|
+
):
|
|
1169
|
+
"""Execute magic-numbers lint."""
|
|
1170
|
+
_validate_paths_exist(path_objs)
|
|
1171
|
+
orchestrator = _setup_magic_numbers_orchestrator(path_objs, config_file, verbose)
|
|
1172
|
+
magic_numbers_violations = _run_magic_numbers_lint(orchestrator, path_objs, recursive)
|
|
1173
|
+
|
|
1174
|
+
if verbose:
|
|
1175
|
+
logger.info(f"Found {len(magic_numbers_violations)} magic number violation(s)")
|
|
1176
|
+
|
|
1177
|
+
format_violations(magic_numbers_violations, format)
|
|
1178
|
+
sys.exit(1 if magic_numbers_violations else 0)
|
|
1179
|
+
|
|
1180
|
+
|
|
1080
1181
|
if __name__ == "__main__":
|
|
1081
1182
|
cli()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|