thailint 0.14.0__py3-none-any.whl → 0.15.1__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/analyzers/rust_base.py +155 -0
- src/analyzers/rust_context.py +141 -0
- src/cli/config.py +6 -4
- src/cli/linters/code_patterns.py +64 -16
- src/cli/linters/code_smells.py +23 -14
- src/cli/linters/documentation.py +5 -3
- src/cli/linters/performance.py +23 -10
- src/cli/linters/shared.py +22 -6
- src/cli/linters/structure.py +13 -4
- src/cli/linters/structure_quality.py +9 -4
- src/cli/utils.py +4 -4
- src/config.py +34 -21
- src/core/python_lint_rule.py +101 -0
- src/linter_config/ignore.py +2 -1
- src/linters/cqs/__init__.py +54 -0
- src/linters/cqs/config.py +55 -0
- src/linters/cqs/function_analyzer.py +201 -0
- src/linters/cqs/input_detector.py +139 -0
- src/linters/cqs/linter.py +159 -0
- src/linters/cqs/output_detector.py +84 -0
- src/linters/cqs/python_analyzer.py +54 -0
- src/linters/cqs/types.py +82 -0
- src/linters/cqs/typescript_cqs_analyzer.py +61 -0
- src/linters/cqs/typescript_function_analyzer.py +192 -0
- src/linters/cqs/typescript_input_detector.py +203 -0
- src/linters/cqs/typescript_output_detector.py +117 -0
- src/linters/cqs/violation_builder.py +94 -0
- src/linters/dry/typescript_value_extractor.py +2 -1
- src/linters/file_header/linter.py +2 -1
- src/linters/file_placement/linter.py +6 -6
- src/linters/file_placement/pattern_validator.py +6 -5
- src/linters/file_placement/rule_checker.py +10 -5
- src/linters/lazy_ignores/config.py +5 -3
- src/linters/lazy_ignores/python_analyzer.py +5 -1
- src/linters/lazy_ignores/types.py +2 -1
- src/linters/lbyl/__init__.py +3 -1
- src/linters/lbyl/linter.py +67 -0
- src/linters/lbyl/pattern_detectors/__init__.py +30 -2
- src/linters/lbyl/pattern_detectors/base.py +24 -7
- src/linters/lbyl/pattern_detectors/dict_key_detector.py +107 -0
- src/linters/lbyl/pattern_detectors/division_check_detector.py +232 -0
- src/linters/lbyl/pattern_detectors/file_exists_detector.py +220 -0
- src/linters/lbyl/pattern_detectors/hasattr_detector.py +119 -0
- src/linters/lbyl/pattern_detectors/isinstance_detector.py +119 -0
- src/linters/lbyl/pattern_detectors/len_check_detector.py +173 -0
- src/linters/lbyl/pattern_detectors/none_check_detector.py +146 -0
- src/linters/lbyl/pattern_detectors/string_validator_detector.py +145 -0
- src/linters/lbyl/python_analyzer.py +215 -0
- src/linters/lbyl/violation_builder.py +354 -0
- src/linters/stringly_typed/ignore_checker.py +4 -6
- src/orchestrator/language_detector.py +5 -3
- {thailint-0.14.0.dist-info → thailint-0.15.1.dist-info}/METADATA +4 -2
- {thailint-0.14.0.dist-info → thailint-0.15.1.dist-info}/RECORD +56 -29
- {thailint-0.14.0.dist-info → thailint-0.15.1.dist-info}/WHEEL +0 -0
- {thailint-0.14.0.dist-info → thailint-0.15.1.dist-info}/entry_points.txt +0 -0
- {thailint-0.14.0.dist-info → thailint-0.15.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Build Violation objects with EAFP suggestions for LBYL patterns
|
|
3
|
+
|
|
4
|
+
Scope: Creates violations for detected LBYL anti-patterns with fix suggestions
|
|
5
|
+
|
|
6
|
+
Overview: Provides module-level functions that create Violation objects for LBYL
|
|
7
|
+
anti-patterns detected in Python code. Each violation includes the rule ID, location,
|
|
8
|
+
descriptive message, and an EAFP suggestion showing how to refactor the code using
|
|
9
|
+
try/except. Supports dict key check, hasattr, isinstance, file exists, len check,
|
|
10
|
+
None check, string validator, and division zero-check patterns.
|
|
11
|
+
|
|
12
|
+
Dependencies: src.core.types for Violation, src.core.base for BaseLintContext
|
|
13
|
+
|
|
14
|
+
Exports: build_dict_key_violation, build_hasattr_violation, build_isinstance_violation,
|
|
15
|
+
build_file_exists_violation, build_len_check_violation, create_syntax_error_violation,
|
|
16
|
+
build_none_check_violation, build_string_validator_violation, build_division_check_violation
|
|
17
|
+
|
|
18
|
+
Interfaces: Module functions for building LBYL violations
|
|
19
|
+
|
|
20
|
+
Implementation: Factory functions for each violation type with descriptive suggestions
|
|
21
|
+
|
|
22
|
+
Suppressions:
|
|
23
|
+
too-many-arguments, too-many-positional-arguments: build_string_validator_violation
|
|
24
|
+
requires 6 parameters (file_path, line, column, string_name, validator_method,
|
|
25
|
+
conversion_func) to create accurate violation messages and suggestions
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from src.core.base import BaseLintContext
|
|
29
|
+
from src.core.types import Violation
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_dict_key_violation(
|
|
33
|
+
file_path: str,
|
|
34
|
+
line: int,
|
|
35
|
+
column: int,
|
|
36
|
+
dict_name: str,
|
|
37
|
+
key_expression: str,
|
|
38
|
+
) -> Violation:
|
|
39
|
+
"""Build a violation for dict key LBYL pattern.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
file_path: Path to the file containing the violation
|
|
43
|
+
line: Line number (1-indexed)
|
|
44
|
+
column: Column number (0-indexed)
|
|
45
|
+
dict_name: Name of the dict being checked
|
|
46
|
+
key_expression: Expression used as key
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Violation object with EAFP suggestion
|
|
50
|
+
"""
|
|
51
|
+
message = (
|
|
52
|
+
f"LBYL pattern: 'if {key_expression} in {dict_name}' followed by "
|
|
53
|
+
f"'{dict_name}[{key_expression}]'"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
suggestion = (
|
|
57
|
+
f"Use EAFP: 'with suppress(KeyError): value = {dict_name}[{key_expression}]' "
|
|
58
|
+
f"or 'try: ... except KeyError: ...'"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return Violation(
|
|
62
|
+
rule_id="lbyl.dict-key-check",
|
|
63
|
+
file_path=file_path,
|
|
64
|
+
line=line,
|
|
65
|
+
column=column,
|
|
66
|
+
message=message,
|
|
67
|
+
suggestion=suggestion,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def build_hasattr_violation(
|
|
72
|
+
file_path: str,
|
|
73
|
+
line: int,
|
|
74
|
+
column: int,
|
|
75
|
+
object_name: str,
|
|
76
|
+
attribute_name: str,
|
|
77
|
+
) -> Violation:
|
|
78
|
+
"""Build a violation for hasattr LBYL pattern.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
file_path: Path to the file containing the violation
|
|
82
|
+
line: Line number (1-indexed)
|
|
83
|
+
column: Column number (0-indexed)
|
|
84
|
+
object_name: Name of the object being checked
|
|
85
|
+
attribute_name: Name of the attribute being checked
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Violation object with EAFP suggestion
|
|
89
|
+
"""
|
|
90
|
+
message = (
|
|
91
|
+
f"LBYL pattern: 'if hasattr({object_name}, '{attribute_name}')' followed by "
|
|
92
|
+
f"'{object_name}.{attribute_name}'"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
suggestion = f"Use EAFP: 'try: {object_name}.{attribute_name} except AttributeError: ...'"
|
|
96
|
+
|
|
97
|
+
return Violation(
|
|
98
|
+
rule_id="lbyl.hasattr-check",
|
|
99
|
+
file_path=file_path,
|
|
100
|
+
line=line,
|
|
101
|
+
column=column,
|
|
102
|
+
message=message,
|
|
103
|
+
suggestion=suggestion,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def build_isinstance_violation(
|
|
108
|
+
file_path: str,
|
|
109
|
+
line: int,
|
|
110
|
+
column: int,
|
|
111
|
+
object_name: str,
|
|
112
|
+
type_name: str,
|
|
113
|
+
) -> Violation:
|
|
114
|
+
"""Build a violation for isinstance LBYL pattern.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
file_path: Path to the file containing the violation
|
|
118
|
+
line: Line number (1-indexed)
|
|
119
|
+
column: Column number (0-indexed)
|
|
120
|
+
object_name: Name of the object being checked
|
|
121
|
+
type_name: Name of the type being checked against
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Violation object with EAFP suggestion
|
|
125
|
+
"""
|
|
126
|
+
message = (
|
|
127
|
+
f"LBYL pattern: 'if isinstance({object_name}, {type_name})' before type-specific operation"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
suggestion = (
|
|
131
|
+
"Consider EAFP: 'try: ... except (TypeError, AttributeError): ...' "
|
|
132
|
+
"instead of isinstance check"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return Violation(
|
|
136
|
+
rule_id="lbyl.isinstance-check",
|
|
137
|
+
file_path=file_path,
|
|
138
|
+
line=line,
|
|
139
|
+
column=column,
|
|
140
|
+
message=message,
|
|
141
|
+
suggestion=suggestion,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def create_syntax_error_violation(error: SyntaxError, context: BaseLintContext) -> Violation:
|
|
146
|
+
"""Create a violation for a syntax error.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
error: The SyntaxError from parsing
|
|
150
|
+
context: Lint context with file information
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Violation indicating syntax error
|
|
154
|
+
"""
|
|
155
|
+
file_path = str(context.file_path) if context.file_path else "unknown"
|
|
156
|
+
line = error.lineno or 1
|
|
157
|
+
column = error.offset or 0
|
|
158
|
+
|
|
159
|
+
return Violation(
|
|
160
|
+
rule_id="lbyl.syntax-error",
|
|
161
|
+
file_path=file_path,
|
|
162
|
+
line=line,
|
|
163
|
+
column=column,
|
|
164
|
+
message=f"Syntax error: {error.msg}",
|
|
165
|
+
suggestion="Fix the syntax error before running LBYL analysis",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def build_file_exists_violation(
|
|
170
|
+
file_path: str,
|
|
171
|
+
line: int,
|
|
172
|
+
column: int,
|
|
173
|
+
path_expression: str,
|
|
174
|
+
check_type: str,
|
|
175
|
+
) -> Violation:
|
|
176
|
+
"""Build a violation for file exists LBYL pattern.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
file_path: Path to the file containing the violation
|
|
180
|
+
line: Line number (1-indexed)
|
|
181
|
+
column: Column number (0-indexed)
|
|
182
|
+
path_expression: Expression representing the file path being checked
|
|
183
|
+
check_type: Type of check ("os.path.exists", "Path.exists", "exists")
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Violation object with EAFP suggestion
|
|
187
|
+
"""
|
|
188
|
+
message = (
|
|
189
|
+
f"LBYL pattern: 'if {check_type}({path_expression})' followed by "
|
|
190
|
+
f"file operation on '{path_expression}'"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
suggestion = (
|
|
194
|
+
f"Use EAFP: 'try: with open({path_expression}) as f: ... except FileNotFoundError: ...'"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return Violation(
|
|
198
|
+
rule_id="lbyl.file-exists-check",
|
|
199
|
+
file_path=file_path,
|
|
200
|
+
line=line,
|
|
201
|
+
column=column,
|
|
202
|
+
message=message,
|
|
203
|
+
suggestion=suggestion,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def build_len_check_violation(
|
|
208
|
+
file_path: str,
|
|
209
|
+
line: int,
|
|
210
|
+
column: int,
|
|
211
|
+
collection_name: str,
|
|
212
|
+
index_expression: str,
|
|
213
|
+
) -> Violation:
|
|
214
|
+
"""Build a violation for len check LBYL pattern.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
file_path: Path to the file containing the violation
|
|
218
|
+
line: Line number (1-indexed)
|
|
219
|
+
column: Column number (0-indexed)
|
|
220
|
+
collection_name: Name of the collection being checked
|
|
221
|
+
index_expression: Expression used as index
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Violation object with EAFP suggestion
|
|
225
|
+
"""
|
|
226
|
+
message = (
|
|
227
|
+
f"LBYL pattern: 'if len({collection_name}) > {index_expression}' followed by "
|
|
228
|
+
f"'{collection_name}[...]'"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
suggestion = (
|
|
232
|
+
f"Use EAFP: 'try: value = {collection_name}[{index_expression}] except IndexError: ...'"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return Violation(
|
|
236
|
+
rule_id="lbyl.len-check",
|
|
237
|
+
file_path=file_path,
|
|
238
|
+
line=line,
|
|
239
|
+
column=column,
|
|
240
|
+
message=message,
|
|
241
|
+
suggestion=suggestion,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def build_none_check_violation(
|
|
246
|
+
file_path: str,
|
|
247
|
+
line: int,
|
|
248
|
+
column: int,
|
|
249
|
+
variable_name: str,
|
|
250
|
+
) -> Violation:
|
|
251
|
+
"""Build a violation for None check LBYL pattern.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
file_path: Path to the file containing the violation
|
|
255
|
+
line: Line number (1-indexed)
|
|
256
|
+
column: Column number (0-indexed)
|
|
257
|
+
variable_name: Name of the variable being checked for None
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
Violation object with EAFP suggestion
|
|
261
|
+
"""
|
|
262
|
+
message = (
|
|
263
|
+
f"LBYL pattern: 'if {variable_name} is not None' followed by '{variable_name}.<method>()'"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
suggestion = (
|
|
267
|
+
f"Use EAFP: 'try: {variable_name}.<method>() except AttributeError: ...' "
|
|
268
|
+
f"or check if None is a valid state to handle differently"
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
return Violation(
|
|
272
|
+
rule_id="lbyl.none-check",
|
|
273
|
+
file_path=file_path,
|
|
274
|
+
line=line,
|
|
275
|
+
column=column,
|
|
276
|
+
message=message,
|
|
277
|
+
suggestion=suggestion,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def build_string_validator_violation( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
282
|
+
file_path: str,
|
|
283
|
+
line: int,
|
|
284
|
+
column: int,
|
|
285
|
+
string_name: str,
|
|
286
|
+
validator_method: str,
|
|
287
|
+
conversion_func: str,
|
|
288
|
+
) -> Violation:
|
|
289
|
+
"""Build a violation for string validator LBYL pattern.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
file_path: Path to the file containing the violation
|
|
293
|
+
line: Line number (1-indexed)
|
|
294
|
+
column: Column number (0-indexed)
|
|
295
|
+
string_name: Name of the string being validated
|
|
296
|
+
validator_method: Validation method used (isnumeric, isdigit, etc.)
|
|
297
|
+
conversion_func: Conversion function used (int, float)
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Violation object with EAFP suggestion
|
|
301
|
+
"""
|
|
302
|
+
message = (
|
|
303
|
+
f"LBYL pattern: 'if {string_name}.{validator_method}()' followed by "
|
|
304
|
+
f"'{conversion_func}({string_name})'"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
suggestion = f"Use EAFP: 'try: value = {conversion_func}({string_name}) except ValueError: ...'"
|
|
308
|
+
|
|
309
|
+
return Violation(
|
|
310
|
+
rule_id="lbyl.string-validator",
|
|
311
|
+
file_path=file_path,
|
|
312
|
+
line=line,
|
|
313
|
+
column=column,
|
|
314
|
+
message=message,
|
|
315
|
+
suggestion=suggestion,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def build_division_check_violation(
|
|
320
|
+
file_path: str,
|
|
321
|
+
line: int,
|
|
322
|
+
column: int,
|
|
323
|
+
divisor_name: str,
|
|
324
|
+
operation: str,
|
|
325
|
+
) -> Violation:
|
|
326
|
+
"""Build a violation for division zero-check LBYL pattern.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
file_path: Path to the file containing the violation
|
|
330
|
+
line: Line number (1-indexed)
|
|
331
|
+
column: Column number (0-indexed)
|
|
332
|
+
divisor_name: Name of the divisor being checked for zero
|
|
333
|
+
operation: Division operation used (/, //, %, /=, //=, %=)
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
Violation object with EAFP suggestion
|
|
337
|
+
"""
|
|
338
|
+
message = (
|
|
339
|
+
f"LBYL pattern: 'if {divisor_name} != 0' followed by "
|
|
340
|
+
f"'{operation}' operation with '{divisor_name}'"
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
suggestion = (
|
|
344
|
+
f"Use EAFP: 'try: result = ... {operation} {divisor_name} except ZeroDivisionError: ...'"
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
return Violation(
|
|
348
|
+
rule_id="lbyl.division-check",
|
|
349
|
+
file_path=file_path,
|
|
350
|
+
line=line,
|
|
351
|
+
column=column,
|
|
352
|
+
message=message,
|
|
353
|
+
suggestion=suggestion,
|
|
354
|
+
)
|
|
@@ -19,6 +19,7 @@ Implementation: Uses cached IgnoreDirectiveParser singleton, reads file content
|
|
|
19
19
|
supports both stringly-typed.* and stringly-typed specific rule matching
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
from contextlib import suppress
|
|
22
23
|
from pathlib import Path
|
|
23
24
|
|
|
24
25
|
from src.core.types import Violation
|
|
@@ -73,7 +74,7 @@ class IgnoreChecker:
|
|
|
73
74
|
Returns:
|
|
74
75
|
File content or empty string if unreadable
|
|
75
76
|
"""
|
|
76
|
-
|
|
77
|
+
with suppress(KeyError):
|
|
77
78
|
return self._file_content_cache[file_path]
|
|
78
79
|
|
|
79
80
|
content = self._read_file_content(file_path)
|
|
@@ -90,12 +91,9 @@ class IgnoreChecker:
|
|
|
90
91
|
File content or empty string if unreadable
|
|
91
92
|
"""
|
|
92
93
|
try:
|
|
93
|
-
|
|
94
|
-
if path.exists():
|
|
95
|
-
return path.read_text(encoding="utf-8")
|
|
94
|
+
return Path(file_path).read_text(encoding="utf-8")
|
|
96
95
|
except (OSError, UnicodeDecodeError):
|
|
97
|
-
|
|
98
|
-
return ""
|
|
96
|
+
return ""
|
|
99
97
|
|
|
100
98
|
def clear_cache(self) -> None:
|
|
101
99
|
"""Clear file content cache."""
|
|
@@ -17,12 +17,13 @@ Dependencies: pathlib for file path handling and content reading
|
|
|
17
17
|
Exports: detect_language(file_path: Path) -> str function, EXTENSION_MAP constant
|
|
18
18
|
|
|
19
19
|
Interfaces: detect_language(file_path: Path) -> str returns language identifier string
|
|
20
|
-
(python, javascript, typescript, java, go, unknown)
|
|
20
|
+
(python, javascript, typescript, java, go, rust, unknown)
|
|
21
21
|
|
|
22
22
|
Implementation: Dictionary-based extension lookup for O(1) detection, first-line shebang
|
|
23
23
|
parsing with substring matching, lazy file reading only when extension unknown
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
+
from contextlib import suppress
|
|
26
27
|
from pathlib import Path
|
|
27
28
|
|
|
28
29
|
# Extension to language mapping
|
|
@@ -34,6 +35,7 @@ EXTENSION_MAP = {
|
|
|
34
35
|
".jsx": "javascript",
|
|
35
36
|
".java": "java",
|
|
36
37
|
".go": "go",
|
|
38
|
+
".rs": "rust",
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
|
|
@@ -67,10 +69,10 @@ def detect_language(file_path: Path) -> str:
|
|
|
67
69
|
file_path: Path to file to analyze.
|
|
68
70
|
|
|
69
71
|
Returns:
|
|
70
|
-
Language identifier (python, javascript, typescript, java, go, unknown).
|
|
72
|
+
Language identifier (python, javascript, typescript, java, go, rust, unknown).
|
|
71
73
|
"""
|
|
72
74
|
ext = file_path.suffix.lower()
|
|
73
|
-
|
|
75
|
+
with suppress(KeyError):
|
|
74
76
|
return EXTENSION_MAP[ext]
|
|
75
77
|
|
|
76
78
|
if file_path.exists() and file_path.stat().st_size > 0:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thailint
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.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
|
License-File: LICENSE
|
|
7
|
-
Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python,performance,typescript
|
|
7
|
+
Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python,performance,typescript,rust
|
|
8
8
|
Author: Steve Jackson
|
|
9
9
|
Requires-Python: >=3.11,<4.0
|
|
10
10
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -27,6 +27,7 @@ Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
|
27
27
|
Requires-Dist: pyprojroot (>=0.3.0,<0.4.0)
|
|
28
28
|
Requires-Dist: pyyaml (>=6.0,<7.0)
|
|
29
29
|
Requires-Dist: tree-sitter (>=0.25.2,<0.26.0)
|
|
30
|
+
Requires-Dist: tree-sitter-rust (>=0.23.2,<0.24.0)
|
|
30
31
|
Requires-Dist: tree-sitter-typescript (>=0.23.2,<0.24.0)
|
|
31
32
|
Project-URL: Documentation, https://thai-lint.readthedocs.io/
|
|
32
33
|
Project-URL: Homepage, https://github.com/be-wise-be-kind/thai-lint
|
|
@@ -84,6 +85,7 @@ That's it. See violations, fix them, ship better code.
|
|
|
84
85
|
| **Lazy Ignores** | Unjustified linting suppressions | `thailint lazy-ignores src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lazy-ignores-linter/) |
|
|
85
86
|
| **Print Statements** | Debug prints left in code | `thailint print-statements src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/print-statements-linter/) |
|
|
86
87
|
| **Stringly Typed** | Strings that should be enums | `thailint stringly-typed src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stringly-typed-linter/) |
|
|
88
|
+
| **LBYL** | Look Before You Leap anti-patterns | `thailint lbyl src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lbyl-linter/) |
|
|
87
89
|
|
|
88
90
|
## Configuration
|
|
89
91
|
|
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
src/__init__.py,sha256=0IT3HnAnSBEfos4G_27cflJiaoWWfeSEfHxsUr53OsM,2192
|
|
2
2
|
src/analyzers/__init__.py,sha256=hCN7ugG_Xs2N_WfWO7ZId-Cv4kvN1AxhIYTA4SD2fJ4,1062
|
|
3
3
|
src/analyzers/ast_utils.py,sha256=iWCRzlTw2QF5wWzQx1OmKshx7TU3pHxC8_omv9XUInw,1630
|
|
4
|
+
src/analyzers/rust_base.py,sha256=_sqmXhH4vylXbQEPp-gHnUYmf6F_2c5YXZgXBqk2Kcg,5185
|
|
5
|
+
src/analyzers/rust_context.py,sha256=8dV-LRst6CUPc2Z9iBXt70GtRTKo62PF3_uFBtFAKuw,4046
|
|
4
6
|
src/analyzers/typescript_base.py,sha256=Dtc_2jLSNoadh53MyeW2syrJMBIMVPvotcM8SeDEXH8,5244
|
|
5
7
|
src/api.py,sha256=pJ5l3qxccKBEY-BkANwzTgLAl1ZFq7OP6hx6LSxbhDw,4664
|
|
6
8
|
src/cli/__init__.py,sha256=nMxKv4D0t09LwUm4Z5w-b7vIuyn24SFzv78BKzE3AOQ,1272
|
|
7
9
|
src/cli/__main__.py,sha256=xIKI57yqB1NOw9eXnGXfU8rC2UwcAJYjDxlZbt9eP0w,671
|
|
8
|
-
src/cli/config.py,sha256=
|
|
10
|
+
src/cli/config.py,sha256=wh9lp0Z2FUEKbYawB65Y9vrlu1Yiqe8-CD_vnRDqwEg,14467
|
|
9
11
|
src/cli/config_merge.py,sha256=A1eCthiLwjj0SEhOcxa6t2hYwWMapGJpL9sCmYvUFw4,8464
|
|
10
12
|
src/cli/linters/__init__.py,sha256=Dlx2CRHT5_QeIeCJ0horPXci9zRP_KzSz_-mg0VMbOw,2343
|
|
11
|
-
src/cli/linters/code_patterns.py,sha256=
|
|
12
|
-
src/cli/linters/code_smells.py,sha256=
|
|
13
|
-
src/cli/linters/documentation.py,sha256=
|
|
14
|
-
src/cli/linters/performance.py,sha256=
|
|
15
|
-
src/cli/linters/shared.py,sha256=
|
|
16
|
-
src/cli/linters/structure.py,sha256=
|
|
17
|
-
src/cli/linters/structure_quality.py,sha256=
|
|
13
|
+
src/cli/linters/code_patterns.py,sha256=2AcFdLPPdkJ8U883ozXE_0eLWRdiL_xfzXm4kmRn-Ro,11072
|
|
14
|
+
src/cli/linters/code_smells.py,sha256=yrKqRD3JTVVqyPL8rwK9VPbHgccXoj2IfaLK3lBF4Jc,11782
|
|
15
|
+
src/cli/linters/documentation.py,sha256=AhkyXfH2FbcxXT3BV6GIKkGbWCjyrz8qcKhz3sx7Yww,3289
|
|
16
|
+
src/cli/linters/performance.py,sha256=qvCW6T84zNZi1TyuxHtsEksgCtMA5TUgt_UdSq0vqHo,9878
|
|
17
|
+
src/cli/linters/shared.py,sha256=eVXhBDr69fRGAP4lApTR_M0gDfLeWlDAqx6VCEAWXsU,10117
|
|
18
|
+
src/cli/linters/structure.py,sha256=EGjw0zMLdGi4lTwM1zd_FzxQ7A-AG3fNPcKcF5uGFSo,10748
|
|
19
|
+
src/cli/linters/structure_quality.py,sha256=0npTcI6OUMVmvd-Ha6NjDZb2Dn1EhpfTLXmMRB69qaI,10739
|
|
18
20
|
src/cli/main.py,sha256=mRyRN_IQI2WyqDCxI8vuzdhbkCkVrK6INfJPjU8ayIU,3844
|
|
19
|
-
src/cli/utils.py,sha256=
|
|
21
|
+
src/cli/utils.py,sha256=wFMvW7ScseHxKgvAmuQCWWHBGbtBzu8oPwATsCyNsfU,12610
|
|
20
22
|
src/cli_main.py,sha256=C0Ey7YNlG3ipqb3KsJZ8rL8PJ4ueVp_45IUirGidvHI,1618
|
|
21
|
-
src/config.py,sha256=
|
|
23
|
+
src/config.py,sha256=O3ixzsYekGjlggmIsawCU1bctOa0MyG2IczHpg3mGyw,12753
|
|
22
24
|
src/core/__init__.py,sha256=5FtsDvhMt4SNRx3pbcGURrxn135XRbeRrjSUxiXwkNc,381
|
|
23
25
|
src/core/base.py,sha256=u5A8geprlKnsJk4ShiLHTKXRekZUB4I6rPQWxgiFeto,8019
|
|
24
26
|
src/core/cli_utils.py,sha256=ZdFSPrZ4WfpTMh-mc_Z3u5OYidE1YyPRKflMynPosa8,6552
|
|
25
27
|
src/core/config_parser.py,sha256=CRHV2-csxag6yQzx_4IYYz57QSUYjPkeSb0XvOyshRI,4272
|
|
26
28
|
src/core/constants.py,sha256=PKtPDqk6k9VuOSgjq1FAdi2CTvlnhdXvLj91dNaMDTA,1584
|
|
27
29
|
src/core/linter_utils.py,sha256=StnKFzJgSvLyao1S0LpTKhsXo8nOwpdKpxo7mXl5PIg,8594
|
|
30
|
+
src/core/python_lint_rule.py,sha256=OpdIDLPV1MDtmjy6GPrrOA3_rRV2_x14keHAQQtI_pc,3516
|
|
28
31
|
src/core/registry.py,sha256=yRA8mQLiZwjmgxl1wSTgdj1cuo_QXuRdrXt3NpCBUgE,3285
|
|
29
32
|
src/core/rule_discovery.py,sha256=tgRH-BJGKsQTxfa249yrY7UJuonRjobMCENqmhcbAeY,5496
|
|
30
33
|
src/core/types.py,sha256=SElFzf_VSrAMsoiE0aU8ZYXuvKqdfwfM5umUHx4eT8w,3342
|
|
@@ -34,7 +37,7 @@ src/formatters/__init__.py,sha256=yE1yIL8lplTMEjsmQm7F-kOMaYq7OjmbFuiwwK0D-gM,81
|
|
|
34
37
|
src/formatters/sarif.py,sha256=gGOwb_v7j4mx4bpvV1NNDd-JyHH8i8XX89iQ6uRSvG4,7050
|
|
35
38
|
src/linter_config/__init__.py,sha256=_I2VVlZlfKyT-tKukuUA5-aVcHLOe3m6C2cev43AiEc,298
|
|
36
39
|
src/linter_config/directive_markers.py,sha256=nRc2Mp3B1mn6tu1XH88ugMxWffk1k8OUNohepaRQ0S0,3245
|
|
37
|
-
src/linter_config/ignore.py,sha256=
|
|
40
|
+
src/linter_config/ignore.py,sha256=40afiMsu1zC29RiwGX8hUPUqM056H_wcOgZZUNOwIes,13111
|
|
38
41
|
src/linter_config/loader.py,sha256=K6mKRkP2jgwar-pwBoJGWgwynLVjqdez-l3Nd6bUCMk,3363
|
|
39
42
|
src/linter_config/pattern_utils.py,sha256=BjV95SySST3HqZBwF1Og8yoHqFxuqQ16VPCacE21ks0,2056
|
|
40
43
|
src/linter_config/rule_matcher.py,sha256=EWqSv4UY90fWps3AzDCSF7PZCbYyFTEBZT2h_txcRms,2779
|
|
@@ -48,6 +51,19 @@ src/linters/collection_pipeline/detector.py,sha256=7_keKR5lGo5rvOVCAvV_6-bG29I_S
|
|
|
48
51
|
src/linters/collection_pipeline/filter_map_analyzer.py,sha256=QbTjObryaLVB71MD4b4SyoOMEO_EgMNedNZLVm05QCQ,11829
|
|
49
52
|
src/linters/collection_pipeline/linter.py,sha256=53pkC1a6mvNTzjK_LDV_JmMysbZBLUsM_NjavvAZZBQ,13552
|
|
50
53
|
src/linters/collection_pipeline/suggestion_builder.py,sha256=4-RHBw95u7gPKpoN1xZlpSOkqzXY7_TRrB_otUXsdDE,4357
|
|
54
|
+
src/linters/cqs/__init__.py,sha256=d78ktPDBk_D9BStrNA99lYFHmuIVWke9wbVHiX_h81g,2120
|
|
55
|
+
src/linters/cqs/config.py,sha256=09U8rGSC8B4QS6ivrCKFPTXzLsU6oTSAjgIkwUrmQlc,2148
|
|
56
|
+
src/linters/cqs/function_analyzer.py,sha256=lPAmqLM2slEN0YkVEUy8xrq3pT7dQahy6sQUY6KvgfA,7756
|
|
57
|
+
src/linters/cqs/input_detector.py,sha256=GdCqXvVIGXOjKdCy5rQsX-IP88-taPcU3TLCumjMIqc,5004
|
|
58
|
+
src/linters/cqs/linter.py,sha256=QWgKuIzE678nUy60dY5BMh1NllLblSh9sbfIxmRlq-o,5666
|
|
59
|
+
src/linters/cqs/output_detector.py,sha256=uLddl9skCTICYXHSvIDYsKLbmKb3wXpZVkXjASVf-fk,3077
|
|
60
|
+
src/linters/cqs/python_analyzer.py,sha256=84x8-vUPRK0GkAgPKB-UzGmRX5Sb84Vq-fi_tpTQAGE,1879
|
|
61
|
+
src/linters/cqs/types.py,sha256=QL_kt1ywYB8KC2QRO-vMMygqHPVMoNS9FAU19zQmRs0,2816
|
|
62
|
+
src/linters/cqs/typescript_cqs_analyzer.py,sha256=kd1_b6dsKDWifxD436zss32eoiX5opURsqm6G8no7YQ,2318
|
|
63
|
+
src/linters/cqs/typescript_function_analyzer.py,sha256=f3TVZXpaDYRUc8xEw3TRBc4Xbg41qmAbACRnjHkTdcQ,7790
|
|
64
|
+
src/linters/cqs/typescript_input_detector.py,sha256=0PazhU69Utc_TGJTehYtSFLn0nhDfELWiX5YcvLWyWk,7979
|
|
65
|
+
src/linters/cqs/typescript_output_detector.py,sha256=b3JlDabgvRElsAkkopIVJfGq6BV0y_wcsNvWzPGO9F4,4122
|
|
66
|
+
src/linters/cqs/violation_builder.py,sha256=6bRWs9b9bqiSYaxi87gxWieKMTZaPCwHMMpplVpKZMo,2868
|
|
51
67
|
src/linters/dry/__init__.py,sha256=p58tN3z_VbulfTkRm1kLZJ43Bemt66T2sro1teirUY8,826
|
|
52
68
|
src/linters/dry/base_token_analyzer.py,sha256=hkR3MI6UYwQ7PNJiyGiIPiX7uMrDRHr0mzI-aG8wVCM,3199
|
|
53
69
|
src/linters/dry/block_filter.py,sha256=3RgmRSqYFk2eqATLOWN3hET09JuaPEFux3ResA0ltqo,11432
|
|
@@ -72,7 +88,7 @@ src/linters/dry/token_hasher.py,sha256=RoUXByVHwf9TZjRqXB3aI1htNZS0pX41oOsUxvlsF
|
|
|
72
88
|
src/linters/dry/typescript_analyzer.py,sha256=xGUcQO8MvJnAVgn5GZRwQAc5xZsD0T-qOQlFuJcvfZM,10777
|
|
73
89
|
src/linters/dry/typescript_constant_extractor.py,sha256=ri5NivpcxLAxwdMJvbeTF4Vu0WS_Fgf7FydQGoVNgm0,5130
|
|
74
90
|
src/linters/dry/typescript_statement_detector.py,sha256=8WiwcjLs8j8_wp0UTsoXN0vVr1mNa562O1CB-FtaQR4,8848
|
|
75
|
-
src/linters/dry/typescript_value_extractor.py,sha256=
|
|
91
|
+
src/linters/dry/typescript_value_extractor.py,sha256=TbHIvcEnmjSV1WNnkRbXeUi_JA9-rGX0_BrD4bczO9Y,2519
|
|
76
92
|
src/linters/dry/violation_builder.py,sha256=WkCibSNytoqMHGC-3GrVff4PD7-SOnVzzZgkMeqmzco,2952
|
|
77
93
|
src/linters/dry/violation_filter.py,sha256=2e6NHN7GYadt27Pz5kiXhttKPJu1loiXhOi0G3J3Epk,3211
|
|
78
94
|
src/linters/dry/violation_generator.py,sha256=7jkRfauwAEdipFuDhoy82eIeXS1ECN4W_3jspMlnFaU,6068
|
|
@@ -83,7 +99,7 @@ src/linters/file_header/bash_parser.py,sha256=aRlIbR6x8IeYAj8w6a3eQzdZZivHB0oPg8
|
|
|
83
99
|
src/linters/file_header/config.py,sha256=gdnZoJ-lEq8DACr6C2UKLorHiFCNdQspP_88FQBtoyc,4755
|
|
84
100
|
src/linters/file_header/css_parser.py,sha256=ijpGMixg2ZqNWWdiZjSNtMXCOhm6XDfSY7OU68B9fS8,2332
|
|
85
101
|
src/linters/file_header/field_validator.py,sha256=owA-ahjx0cUWBIqCxT0dMyGTABQA0b8HbdWbZPQk7pw,2769
|
|
86
|
-
src/linters/file_header/linter.py,sha256=
|
|
102
|
+
src/linters/file_header/linter.py,sha256=t51VJzKnRo8s_RM0iZLSQBmmLT4mmM8UDpaRekNurwE,12564
|
|
87
103
|
src/linters/file_header/markdown_parser.py,sha256=4rNYrxuZbJz4LoSmv0U741Cv7wP9jftTl0Ty7mBDHRI,5323
|
|
88
104
|
src/linters/file_header/python_parser.py,sha256=RTOeEt1b3tCvFWbZIt89awQA37CUOSBIGagEYnayn-M,1432
|
|
89
105
|
src/linters/file_header/typescript_parser.py,sha256=R11Vkr6dUVaU8t90m8rrkMzODtBYk7u-TYFsMDRwzX8,2532
|
|
@@ -91,28 +107,39 @@ src/linters/file_header/violation_builder.py,sha256=HPYTmrcCmcO6Dx5dhmj85zZgEBM5
|
|
|
91
107
|
src/linters/file_placement/__init__.py,sha256=vJ43GZujcbAk-K3DwfsQZ0J3yP_5G35CKssatLyntXk,862
|
|
92
108
|
src/linters/file_placement/config_loader.py,sha256=tLBeP9njYmtD0FNQsKkywMQJWrZaDBl7z_5sqVLzndc,2690
|
|
93
109
|
src/linters/file_placement/directory_matcher.py,sha256=1rxJtCEzqDYDQnscVX6pzk7gxCMD11pVIGaWcli-tHY,2742
|
|
94
|
-
src/linters/file_placement/linter.py,sha256=
|
|
110
|
+
src/linters/file_placement/linter.py,sha256=tjmoTYadTrXpyGXGiUNYwo8g5P2eGZ82LArgp9S8ztk,15283
|
|
95
111
|
src/linters/file_placement/path_resolver.py,sha256=S6g7xOYsoSc0O_RDJh8j4Z2klcwzp16rSUfEAErGOTI,1972
|
|
96
112
|
src/linters/file_placement/pattern_matcher.py,sha256=56PCVL_4ajpTCnebHNUZKMJyAWeUOUHkeEwd4o3ofXQ,3183
|
|
97
|
-
src/linters/file_placement/pattern_validator.py,sha256=
|
|
98
|
-
src/linters/file_placement/rule_checker.py,sha256=
|
|
113
|
+
src/linters/file_placement/pattern_validator.py,sha256=P6qbgnVxxFlBrsPzxjXjVlVPpr4ppeuJMhhnCScE6fA,4266
|
|
114
|
+
src/linters/file_placement/rule_checker.py,sha256=HInWmyxxZfqmrBH-5RealvYIV5ChzGd4EwxB6RNZE9w,7930
|
|
99
115
|
src/linters/file_placement/violation_factory.py,sha256=NkQmBcgpa3g3W2ZdFZNQ5djLVP4x9OKs65d7F1rCKvM,6040
|
|
100
116
|
src/linters/lazy_ignores/__init__.py,sha256=qPwCC1Y-TPn6tNLTO4X6QsACaAiPMBpsIKlKh_dSz5k,1656
|
|
101
|
-
src/linters/lazy_ignores/config.py,sha256=
|
|
117
|
+
src/linters/lazy_ignores/config.py,sha256=IBW9hO5QgVyIhuSJw6KrupCjbVilDiNUUHL-TcQMOXU,2591
|
|
102
118
|
src/linters/lazy_ignores/directive_utils.py,sha256=6Mc56hrcFe21LG7PMmIVEPDGKUF6F9dffhHkwixj1R8,3432
|
|
103
119
|
src/linters/lazy_ignores/header_parser.py,sha256=ADtVJUoJfoVx_zehoPpo6YLws0N-7c2PLK1PhNqn5Uk,6030
|
|
104
120
|
src/linters/lazy_ignores/linter.py,sha256=1bl3b2NliVurlb9bUcZUzd8sBZG6KJhRODD-Mb46HnE,6052
|
|
105
121
|
src/linters/lazy_ignores/matcher.py,sha256=jLE12aPPEz6tBejFrmXGXdCb7kzeFh8IYH5b_UjHqpQ,5201
|
|
106
|
-
src/linters/lazy_ignores/python_analyzer.py,sha256=
|
|
122
|
+
src/linters/lazy_ignores/python_analyzer.py,sha256=ia60Y0mw0FxngXWw55JqZggWL8HJD6M3mN93PoqyOGA,7367
|
|
107
123
|
src/linters/lazy_ignores/rule_id_utils.py,sha256=sE7kAQFO6zGAR5JQN2OLLVjAdiVNPZONTb0sY01ri9w,5809
|
|
108
124
|
src/linters/lazy_ignores/skip_detector.py,sha256=9RK5uD4b2pAfdJsK1dHRTAWG4kKfAf1yfjc1OBsI14M,10461
|
|
109
|
-
src/linters/lazy_ignores/types.py,sha256=
|
|
125
|
+
src/linters/lazy_ignores/types.py,sha256=ygcRYjiuCAx4qDZoBG6xSWNbd1Fh7_FPwoyH8PvLFvc,2251
|
|
110
126
|
src/linters/lazy_ignores/typescript_analyzer.py,sha256=k8R60Mcw9OxvHFFUPhUErrb-tbek7Q7PXXZDq_H0ioM,5322
|
|
111
127
|
src/linters/lazy_ignores/violation_builder.py,sha256=Z5RlCRJKkTfetkRVqsu1rfJRgBeiE9RTEu1djr-nmto,4203
|
|
112
|
-
src/linters/lbyl/__init__.py,sha256=
|
|
128
|
+
src/linters/lbyl/__init__.py,sha256=5_an3Zy9iQvbajvuQT_DTMtlIMfOWxwewZGFe-cSDg8,1124
|
|
113
129
|
src/linters/lbyl/config.py,sha256=kWCjBRs1HEVf9oK4dHKHfjQX8KU-o5i-Jc_94ULDD4Y,2434
|
|
114
|
-
src/linters/lbyl/
|
|
115
|
-
src/linters/lbyl/pattern_detectors/
|
|
130
|
+
src/linters/lbyl/linter.py,sha256=sp6PETOKuk13wzfWYPYmWVqcdCwcFRr6CGvFmNPunaU,2288
|
|
131
|
+
src/linters/lbyl/pattern_detectors/__init__.py,sha256=23wnoXvQs9IFpk1RqjQhqpdtUhEE-MjiIlKrrhrtfxs,2064
|
|
132
|
+
src/linters/lbyl/pattern_detectors/base.py,sha256=O1R2k9ZLECLou7IN-FsNHC530CFxqQ6knhxhhQwpp6w,1881
|
|
133
|
+
src/linters/lbyl/pattern_detectors/dict_key_detector.py,sha256=xUPlHP1ZP8eQhUG8SUd5_Ke_J-h-XuB8_0ZPe9XGhH4,3982
|
|
134
|
+
src/linters/lbyl/pattern_detectors/division_check_detector.py,sha256=FG8PTtF0Ukg6cf7AGhqsSzuyDw90y7R2F63w0BAwwbA,7936
|
|
135
|
+
src/linters/lbyl/pattern_detectors/file_exists_detector.py,sha256=ZXK0rr60QgUNXm96mZmIuoMzHzpZ1USGiR4E_snoWUs,8410
|
|
136
|
+
src/linters/lbyl/pattern_detectors/hasattr_detector.py,sha256=mE0-mgMxArQ2RdQsI8u2dlRUm912k-pufd-6cAEbdfo,4376
|
|
137
|
+
src/linters/lbyl/pattern_detectors/isinstance_detector.py,sha256=3Zv_jPqB29vlrnthAOyEd6fN3f2P-cYtASLHt0PIKp4,4600
|
|
138
|
+
src/linters/lbyl/pattern_detectors/len_check_detector.py,sha256=A2Hlz7tAPmrcccJlXHEVKnEUGwSt9poBwcksRljQshM,6407
|
|
139
|
+
src/linters/lbyl/pattern_detectors/none_check_detector.py,sha256=mrLIK6sZ1QwM734qr5MtsyU-yaXr8zBNOjasXQ5PsEs,5428
|
|
140
|
+
src/linters/lbyl/pattern_detectors/string_validator_detector.py,sha256=GXXcsCfmp0yU7cgmg2LpYl8JRXpeRjZhYdq5A-lTPZY,5068
|
|
141
|
+
src/linters/lbyl/python_analyzer.py,sha256=auPrWFUEmFxtv1GB3exJzz7uX71gXqEUCHKO64UDR8w,8041
|
|
142
|
+
src/linters/lbyl/violation_builder.py,sha256=6wVX9U7Jq1ONWcGuasvIwJE9mXHcT778p0OcPC0Wx7w,10296
|
|
116
143
|
src/linters/magic_numbers/__init__.py,sha256=17dkCUf0uiYLvpOZF01VDojj92NzxXZMtRhrSBUzsdc,1689
|
|
117
144
|
src/linters/magic_numbers/config.py,sha256=3zV6ZNezouBWUYy4kMw5PUlPNvIWXVwOxTz1moZfRoI,3270
|
|
118
145
|
src/linters/magic_numbers/context_analyzer.py,sha256=EgDyxxjvEqyD3FX0Fnxj5RcOPyvyVs_rYFxj2HOxYdg,7309
|
|
@@ -166,7 +193,7 @@ src/linters/stringly_typed/__init__.py,sha256=6r4IIykZ6mm551KQpRTSDp418EFqJQbuzj
|
|
|
166
193
|
src/linters/stringly_typed/config.py,sha256=-M7fwwr9axQsQcGtowVINC9Bh1cS1b2-KPxFb2GtL3M,7500
|
|
167
194
|
src/linters/stringly_typed/context_filter.py,sha256=JohTFvXiHKfVzUowRbsDrY37QngJDmhFfoxyoTzKriY,11422
|
|
168
195
|
src/linters/stringly_typed/function_call_violation_builder.py,sha256=RiuzeKmUzb6Fzdc4j8lXl4V-jf-0xae-5t7YcIaKTMY,4234
|
|
169
|
-
src/linters/stringly_typed/ignore_checker.py,sha256=
|
|
196
|
+
src/linters/stringly_typed/ignore_checker.py,sha256=QU1x3S6RVujmnIWMTKWD4bwSfrmPLLRBp36T2KD_o1g,3382
|
|
170
197
|
src/linters/stringly_typed/ignore_utils.py,sha256=hw0wfnGFJQkysr1qi_vmykZPr02SNBElwVHFu55tB6M,1531
|
|
171
198
|
src/linters/stringly_typed/linter.py,sha256=mKokag3XCQl4QuhT25sekuiX2bMERDUdq9SNxqBpNCw,13440
|
|
172
199
|
src/linters/stringly_typed/python/__init__.py,sha256=y1ELj3We0_VeA0ygXd1DxudSWrZE5OhLGtZNkKwuomA,1359
|
|
@@ -188,12 +215,12 @@ src/linters/stringly_typed/typescript/comparison_tracker.py,sha256=TiEldIqppu6i2
|
|
|
188
215
|
src/linters/stringly_typed/violation_generator.py,sha256=aye60bShNnt8f6BPQwduTOLX97jAuy7Z7DLq9wzrFB4,14769
|
|
189
216
|
src/orchestrator/__init__.py,sha256=XXLDJq2oaB-TpP2Y97GRnde9EkITGuFCmuLrDfxI9nY,245
|
|
190
217
|
src/orchestrator/core.py,sha256=rt3h-YFgF1aAFeKvTa0PP7k_8zfwpeGIqrIxKuyckxY,17683
|
|
191
|
-
src/orchestrator/language_detector.py,sha256=
|
|
218
|
+
src/orchestrator/language_detector.py,sha256=ALt2BEZKXQM2dWr1ChF9lZVj83YF4Bl9xwrB9ezfmMc,2799
|
|
192
219
|
src/templates/thailint_config_template.yaml,sha256=57ZtLxnIoOHtR5Ejq3clb4nhY9J4n6h36XFb79ZZPlc,12020
|
|
193
220
|
src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
|
|
194
221
|
src/utils/project_root.py,sha256=aaxUM-LQ1okrPClmZWPFd_D09W3V1ArgJiidEEp_eU8,6262
|
|
195
|
-
thailint-0.
|
|
196
|
-
thailint-0.
|
|
197
|
-
thailint-0.
|
|
198
|
-
thailint-0.
|
|
199
|
-
thailint-0.
|
|
222
|
+
thailint-0.15.1.dist-info/METADATA,sha256=w_Yxiwk8_exglxZu_OPpJd50uNkq8AbXo8ntyTy9ql0,7205
|
|
223
|
+
thailint-0.15.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
224
|
+
thailint-0.15.1.dist-info/entry_points.txt,sha256=DNoGUlxpaMFqxQDgHp1yeGqohOjdFR-kH19uHYi3OUY,72
|
|
225
|
+
thailint-0.15.1.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
|
|
226
|
+
thailint-0.15.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|