thailint 0.4.0__tar.gz → 0.4.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.4.0 → thailint-0.4.1}/PKG-INFO +15 -2
- {thailint-0.4.0 → thailint-0.4.1}/README.md +14 -1
- {thailint-0.4.0 → thailint-0.4.1}/pyproject.toml +1 -1
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/config.py +6 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/linter.py +49 -0
- {thailint-0.4.0 → thailint-0.4.1}/CHANGELOG.md +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/LICENSE +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/analyzers/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/analyzers/typescript_base.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/api.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/cli.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/config.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/base.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/cli_utils.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/config_parser.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/linter_utils.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/registry.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/rule_discovery.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/types.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/core/violation_builder.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linter_config/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linter_config/ignore.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linter_config/loader.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/base_token_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/block_filter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/block_grouper.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/cache.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/cache_query.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/config.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/config_loader.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/deduplicator.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/duplicate_storage.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/file_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/inline_ignore.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/linter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/python_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/storage_initializer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/token_hasher.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/typescript_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/violation_builder.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/violation_filter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/dry/violation_generator.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/config_loader.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/directory_matcher.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/linter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/path_resolver.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/pattern_matcher.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/pattern_validator.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/rule_checker.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/file_placement/violation_factory.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/context_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/python_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/typescript_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/magic_numbers/violation_builder.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/config.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/linter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/python_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/typescript_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/typescript_function_extractor.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/nesting/violation_builder.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/class_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/config.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/heuristics.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/linter.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/metrics_evaluator.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/python_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/typescript_analyzer.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/typescript_metrics_calculator.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/linters/srp/violation_builder.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/orchestrator/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/orchestrator/core.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/orchestrator/language_detector.py +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/templates/thailint_config_template.yaml +0 -0
- {thailint-0.4.0 → thailint-0.4.1}/src/utils/__init__.py +0 -0
- {thailint-0.4.0 → thailint-0.4.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.4.
|
|
3
|
+
Version: 0.4.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
|
|
@@ -35,11 +35,20 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
|
|
36
36
|
[](https://opensource.org/licenses/MIT)
|
|
37
37
|
[](https://www.python.org/downloads/)
|
|
38
|
-
[](tests/)
|
|
39
39
|
[](htmlcov/)
|
|
40
40
|
|
|
41
41
|
The AI Linter - Enterprise-ready linting and governance for AI-generated code across multiple languages.
|
|
42
42
|
|
|
43
|
+
## Documentation
|
|
44
|
+
|
|
45
|
+
**New to thailint?** Start here:
|
|
46
|
+
- **[Quick Start Guide](docs/quick-start.md)** - Get running in 5 minutes
|
|
47
|
+
- **[Configuration Reference](docs/configuration.md)** - Complete config options for all linters
|
|
48
|
+
- **[Troubleshooting Guide](docs/troubleshooting.md)** - Common issues and solutions
|
|
49
|
+
|
|
50
|
+
**Full Documentation:** Browse the **[docs/](docs/)** folder for comprehensive guides covering installation, all linters, configuration patterns, and integration examples.
|
|
51
|
+
|
|
43
52
|
## Overview
|
|
44
53
|
|
|
45
54
|
thailint is a modern, enterprise-ready multi-language linter designed specifically for AI-generated code. It focuses on common mistakes and anti-patterns that AI coding assistants frequently introduce—issues that existing linters don't catch or don't handle consistently across languages.
|
|
@@ -55,6 +64,8 @@ We're not trying to replace the wonderful existing linters like Pylint, ESLint,
|
|
|
55
64
|
|
|
56
65
|
thailint complements your existing linting stack by catching the patterns AI tools repeatedly miss.
|
|
57
66
|
|
|
67
|
+
**Complete documentation available in the [docs/](docs/) folder** covering installation, configuration, all linters, and troubleshooting.
|
|
68
|
+
|
|
58
69
|
## Features
|
|
59
70
|
|
|
60
71
|
### Core Capabilities
|
|
@@ -151,6 +162,8 @@ thailint dry --config .thailint.yaml src/
|
|
|
151
162
|
thailint dry --format json src/
|
|
152
163
|
```
|
|
153
164
|
|
|
165
|
+
**New to thailint?** See the **[Quick Start Guide](docs/quick-start.md)** for a complete walkthrough including config generation, understanding output, and next steps.
|
|
166
|
+
|
|
154
167
|
### Library Mode
|
|
155
168
|
|
|
156
169
|
```python
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
5
|
-
[](tests/)
|
|
6
6
|
[](htmlcov/)
|
|
7
7
|
|
|
8
8
|
The AI Linter - Enterprise-ready linting and governance for AI-generated code across multiple languages.
|
|
9
9
|
|
|
10
|
+
## Documentation
|
|
11
|
+
|
|
12
|
+
**New to thailint?** Start here:
|
|
13
|
+
- **[Quick Start Guide](docs/quick-start.md)** - Get running in 5 minutes
|
|
14
|
+
- **[Configuration Reference](docs/configuration.md)** - Complete config options for all linters
|
|
15
|
+
- **[Troubleshooting Guide](docs/troubleshooting.md)** - Common issues and solutions
|
|
16
|
+
|
|
17
|
+
**Full Documentation:** Browse the **[docs/](docs/)** folder for comprehensive guides covering installation, all linters, configuration patterns, and integration examples.
|
|
18
|
+
|
|
10
19
|
## Overview
|
|
11
20
|
|
|
12
21
|
thailint is a modern, enterprise-ready multi-language linter designed specifically for AI-generated code. It focuses on common mistakes and anti-patterns that AI coding assistants frequently introduce—issues that existing linters don't catch or don't handle consistently across languages.
|
|
@@ -22,6 +31,8 @@ We're not trying to replace the wonderful existing linters like Pylint, ESLint,
|
|
|
22
31
|
|
|
23
32
|
thailint complements your existing linting stack by catching the patterns AI tools repeatedly miss.
|
|
24
33
|
|
|
34
|
+
**Complete documentation available in the [docs/](docs/) folder** covering installation, configuration, all linters, and troubleshooting.
|
|
35
|
+
|
|
25
36
|
## Features
|
|
26
37
|
|
|
27
38
|
### Core Capabilities
|
|
@@ -118,6 +129,8 @@ thailint dry --config .thailint.yaml src/
|
|
|
118
129
|
thailint dry --format json src/
|
|
119
130
|
```
|
|
120
131
|
|
|
132
|
+
**New to thailint?** See the **[Quick Start Guide](docs/quick-start.md)** for a complete walkthrough including config generation, understanding output, and next steps.
|
|
133
|
+
|
|
121
134
|
### Library Mode
|
|
122
135
|
|
|
123
136
|
```python
|
|
@@ -17,7 +17,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
17
17
|
|
|
18
18
|
[tool.poetry]
|
|
19
19
|
name = "thailint"
|
|
20
|
-
version = "0.4.
|
|
20
|
+
version = "0.4.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"
|
|
@@ -33,6 +33,7 @@ class MagicNumberConfig:
|
|
|
33
33
|
default_factory=lambda: {-1, 0, 1, 2, 3, 4, 5, 10, 100, 1000}
|
|
34
34
|
)
|
|
35
35
|
max_small_integer: int = 10
|
|
36
|
+
ignore: list[str] = field(default_factory=list)
|
|
36
37
|
|
|
37
38
|
def __post_init__(self) -> None:
|
|
38
39
|
"""Validate configuration values."""
|
|
@@ -69,8 +70,13 @@ class MagicNumberConfig:
|
|
|
69
70
|
)
|
|
70
71
|
max_small_integer = config.get("max_small_integer", 10)
|
|
71
72
|
|
|
73
|
+
ignore_patterns = config.get("ignore", [])
|
|
74
|
+
if not isinstance(ignore_patterns, list):
|
|
75
|
+
ignore_patterns = []
|
|
76
|
+
|
|
72
77
|
return cls(
|
|
73
78
|
enabled=config.get("enabled", True),
|
|
74
79
|
allowed_numbers=allowed_numbers,
|
|
75
80
|
max_small_integer=max_small_integer,
|
|
81
|
+
ignore=ignore_patterns,
|
|
76
82
|
)
|
|
@@ -24,6 +24,7 @@ Implementation: Composition pattern with helper classes, AST-based analysis with
|
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
import ast
|
|
27
|
+
from pathlib import Path
|
|
27
28
|
|
|
28
29
|
from src.core.base import BaseLintContext, MultiLanguageLintRule
|
|
29
30
|
from src.core.linter_utils import load_linter_config
|
|
@@ -98,6 +99,48 @@ class MagicNumberRule(MultiLanguageLintRule): # thailint: ignore[srp]
|
|
|
98
99
|
return None
|
|
99
100
|
return load_linter_config(context, "magic_numbers", MagicNumberConfig)
|
|
100
101
|
|
|
102
|
+
def _is_file_ignored(self, context: BaseLintContext, config: MagicNumberConfig) -> bool:
|
|
103
|
+
"""Check if file matches ignore patterns.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
context: Lint context
|
|
107
|
+
config: Magic numbers configuration
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
True if file should be ignored
|
|
111
|
+
"""
|
|
112
|
+
if not config.ignore:
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
if not context.file_path:
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
file_path = Path(context.file_path)
|
|
119
|
+
for pattern in config.ignore:
|
|
120
|
+
if self._matches_pattern(file_path, pattern):
|
|
121
|
+
return True
|
|
122
|
+
return False
|
|
123
|
+
|
|
124
|
+
def _matches_pattern(self, file_path: Path, pattern: str) -> bool:
|
|
125
|
+
"""Check if file path matches a glob pattern.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
file_path: Path to check
|
|
129
|
+
pattern: Glob pattern (e.g., "test/**", "**/test_*.py", "specific/file.py")
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
True if path matches pattern
|
|
133
|
+
"""
|
|
134
|
+
# Try glob pattern matching first (handles **, *, etc.)
|
|
135
|
+
if file_path.match(pattern):
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
# Also check if pattern is a substring (for partial path matching)
|
|
139
|
+
if pattern in str(file_path):
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
return False
|
|
143
|
+
|
|
101
144
|
def _check_python(self, context: BaseLintContext, config: MagicNumberConfig) -> list[Violation]:
|
|
102
145
|
"""Check Python code for magic number violations.
|
|
103
146
|
|
|
@@ -108,6 +151,9 @@ class MagicNumberRule(MultiLanguageLintRule): # thailint: ignore[srp]
|
|
|
108
151
|
Returns:
|
|
109
152
|
List of violations found in Python code
|
|
110
153
|
"""
|
|
154
|
+
if self._is_file_ignored(context, config):
|
|
155
|
+
return []
|
|
156
|
+
|
|
111
157
|
tree = self._parse_python_code(context.file_content)
|
|
112
158
|
if tree is None:
|
|
113
159
|
return []
|
|
@@ -267,6 +313,9 @@ class MagicNumberRule(MultiLanguageLintRule): # thailint: ignore[srp]
|
|
|
267
313
|
Returns:
|
|
268
314
|
List of violations found in TypeScript/JavaScript code
|
|
269
315
|
"""
|
|
316
|
+
if self._is_file_ignored(context, config):
|
|
317
|
+
return []
|
|
318
|
+
|
|
270
319
|
analyzer = TypeScriptMagicNumberAnalyzer()
|
|
271
320
|
root_node = analyzer.parse_typescript(context.file_content or "")
|
|
272
321
|
if root_node is None:
|
|
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
|