thailint 0.8.0__py3-none-any.whl → 0.9.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.
Files changed (33) hide show
  1. src/cli.py +115 -0
  2. src/core/base.py +4 -0
  3. src/core/rule_discovery.py +110 -84
  4. src/core/violation_builder.py +75 -15
  5. src/linter_config/loader.py +43 -11
  6. src/linters/dry/block_filter.py +4 -0
  7. src/linters/dry/block_grouper.py +4 -0
  8. src/linters/dry/cache_query.py +4 -0
  9. src/linters/dry/token_hasher.py +5 -1
  10. src/linters/dry/violation_builder.py +4 -0
  11. src/linters/dry/violation_filter.py +4 -0
  12. src/linters/file_header/bash_parser.py +4 -0
  13. src/linters/file_placement/directory_matcher.py +4 -0
  14. src/linters/file_placement/pattern_matcher.py +4 -0
  15. src/linters/file_placement/pattern_validator.py +4 -0
  16. src/linters/magic_numbers/context_analyzer.py +4 -0
  17. src/linters/magic_numbers/typescript_analyzer.py +4 -0
  18. src/linters/nesting/python_analyzer.py +4 -0
  19. src/linters/nesting/typescript_function_extractor.py +4 -0
  20. src/linters/print_statements/typescript_analyzer.py +4 -0
  21. src/linters/srp/class_analyzer.py +4 -0
  22. src/linters/srp/python_analyzer.py +55 -20
  23. src/linters/srp/typescript_metrics_calculator.py +83 -47
  24. src/linters/srp/violation_builder.py +4 -0
  25. src/linters/stateless_class/__init__.py +25 -0
  26. src/linters/stateless_class/config.py +58 -0
  27. src/linters/stateless_class/linter.py +355 -0
  28. src/linters/stateless_class/python_analyzer.py +299 -0
  29. {thailint-0.8.0.dist-info → thailint-0.9.0.dist-info}/METADATA +112 -2
  30. {thailint-0.8.0.dist-info → thailint-0.9.0.dist-info}/RECORD +33 -29
  31. {thailint-0.8.0.dist-info → thailint-0.9.0.dist-info}/WHEEL +0 -0
  32. {thailint-0.8.0.dist-info → thailint-0.9.0.dist-info}/entry_points.txt +0 -0
  33. {thailint-0.8.0.dist-info → thailint-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thailint
3
- Version: 0.8.0
3
+ Version: 0.9.0
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
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
39
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
40
- [![Tests](https://img.shields.io/badge/tests-682%2F682%20passing-brightgreen.svg)](tests/)
40
+ [![Tests](https://img.shields.io/badge/tests-728%2F728%20passing-brightgreen.svg)](tests/)
41
41
  [![Coverage](https://img.shields.io/badge/coverage-87%25-brightgreen.svg)](htmlcov/)
42
42
  [![Documentation Status](https://readthedocs.org/projects/thai-lint/badge/?version=latest)](https://thai-lint.readthedocs.io/en/latest/?badge=latest)
43
43
  [![SARIF 2.1.0](https://img.shields.io/badge/SARIF-2.1.0-orange.svg)](docs/sarif-output.md)
@@ -104,6 +104,12 @@ thailint complements your existing linting stack by catching the patterns AI too
104
104
  - Simple computed value detection
105
105
  - Action verb exclusion (to_*, finalize, serialize)
106
106
  - Test file detection
107
+ - **Stateless Class Linting** - Detect classes that should be module-level functions
108
+ - Python AST-based detection
109
+ - No constructor (__init__ or __new__) detection
110
+ - No instance state (self.attr) detection
111
+ - Excludes ABC, Protocol, and decorated classes
112
+ - Helpful refactoring suggestions
107
113
  - **Pluggable Architecture** - Easy to extend with custom linters
108
114
  - **Multi-Language Support** - Python, TypeScript, JavaScript, and more
109
115
  - **Flexible Configuration** - YAML/JSON configs with pattern matching
@@ -1017,6 +1023,108 @@ Overview: Created 2024-01-15. # thailint: ignore[file-header]
1017
1023
 
1018
1024
  See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[File Header Linter Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/)** for complete documentation.
1019
1025
 
1026
+ ## Stateless Class Linter
1027
+
1028
+ ### Overview
1029
+
1030
+ The stateless class linter detects Python classes that have no state (no constructor, no instance attributes) and should be refactored to module-level functions. This is a common anti-pattern in AI-generated code.
1031
+
1032
+ ### What Are Stateless Classes?
1033
+
1034
+ Stateless classes are classes that:
1035
+ - Have no `__init__` or `__new__` method
1036
+ - Have no instance attributes (`self.attr` assignments)
1037
+ - Have 2+ methods (grouped functionality without state)
1038
+
1039
+ ```python
1040
+ # Bad - Stateless class (no state, just grouped functions)
1041
+ class TokenHasher:
1042
+ def hash_token(self, token: str) -> str:
1043
+ return hashlib.sha256(token.encode()).hexdigest()
1044
+
1045
+ def verify_token(self, token: str, hash_value: str) -> bool:
1046
+ return self.hash_token(token) == hash_value
1047
+
1048
+ # Good - Module-level functions
1049
+ def hash_token(token: str) -> str:
1050
+ return hashlib.sha256(token.encode()).hexdigest()
1051
+
1052
+ def verify_token(token: str, hash_value: str) -> bool:
1053
+ return hash_token(token) == hash_value
1054
+ ```
1055
+
1056
+ ### Quick Start
1057
+
1058
+ ```bash
1059
+ # Check stateless classes in current directory
1060
+ thailint stateless-class .
1061
+
1062
+ # Check specific directory
1063
+ thailint stateless-class src/
1064
+
1065
+ # Get JSON output
1066
+ thailint stateless-class --format json src/
1067
+ ```
1068
+
1069
+ ### Configuration
1070
+
1071
+ Add to `.thailint.yaml`:
1072
+
1073
+ ```yaml
1074
+ stateless-class:
1075
+ enabled: true
1076
+ min_methods: 2 # Minimum methods to flag
1077
+ ```
1078
+
1079
+ ### Example Violation
1080
+
1081
+ **Code with stateless class:**
1082
+ ```python
1083
+ class StringUtils:
1084
+ def capitalize_words(self, text: str) -> str:
1085
+ return ' '.join(w.capitalize() for w in text.split())
1086
+
1087
+ def reverse_words(self, text: str) -> str:
1088
+ return ' '.join(reversed(text.split()))
1089
+ ```
1090
+
1091
+ **Violation message:**
1092
+ ```
1093
+ src/utils.py:1 - Class 'StringUtils' has no state and should be refactored to module-level functions
1094
+ ```
1095
+
1096
+ **Refactored code:**
1097
+ ```python
1098
+ def capitalize_words(text: str) -> str:
1099
+ return ' '.join(w.capitalize() for w in text.split())
1100
+
1101
+ def reverse_words(text: str) -> str:
1102
+ return ' '.join(reversed(text.split()))
1103
+ ```
1104
+
1105
+ ### Exclusion Rules
1106
+
1107
+ The linter does NOT flag classes that:
1108
+ - Have `__init__` or `__new__` constructors
1109
+ - Have instance attributes (`self.attr = value`)
1110
+ - Have class-level attributes
1111
+ - Inherit from ABC or Protocol
1112
+ - Have any decorator (`@dataclass`, `@register`, etc.)
1113
+ - Have 0-1 methods
1114
+
1115
+ ### Ignoring Violations
1116
+
1117
+ ```python
1118
+ # Line-level ignore
1119
+ class TokenHasher: # thailint: ignore[stateless-class] - Legacy API
1120
+ def hash(self, token): ...
1121
+
1122
+ # File-level ignore
1123
+ # thailint: ignore-file[stateless-class]
1124
+ ```
1125
+
1126
+ See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[Stateless Class Linter Guide](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/)** for complete documentation.
1127
+
1020
1128
  ## Pre-commit Hooks
1021
1129
 
1022
1130
  Automate code quality checks before every commit and push with pre-commit hooks.
@@ -1306,6 +1414,8 @@ docker run --rm -v /path/to/workspace:/workspace \
1306
1414
  - **[Nesting Depth Linter](https://thai-lint.readthedocs.io/en/latest/nesting-linter/)** - Nesting depth analysis guide
1307
1415
  - **[SRP Linter](https://thai-lint.readthedocs.io/en/latest/srp-linter/)** - Single Responsibility Principle guide
1308
1416
  - **[DRY Linter](https://thai-lint.readthedocs.io/en/latest/dry-linter/)** - Duplicate code detection guide
1417
+ - **[Method Property Linter](https://thai-lint.readthedocs.io/en/latest/method-property-linter/)** - Method-to-property conversion guide
1418
+ - **[Stateless Class Linter](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/)** - Stateless class detection guide
1309
1419
  - **[Pre-commit Hooks](https://thai-lint.readthedocs.io/en/latest/pre-commit-hooks/)** - Automated quality checks
1310
1420
  - **[SARIF Output Guide](docs/sarif-output.md)** - SARIF format for GitHub Code Scanning and CI/CD
1311
1421
  - **[Publishing Guide](https://thai-lint.readthedocs.io/en/latest/releasing/)** - Release and publishing workflow
@@ -2,29 +2,29 @@ src/__init__.py,sha256=f601zncODr2twrUHqTLS5wyOdZqZi9tMjAe2INhRKqU,2175
2
2
  src/analyzers/__init__.py,sha256=fFloZtjkBGwYbAhKTxS3Qy3yDr2_3i3WSfKTw1mAioo,972
3
3
  src/analyzers/typescript_base.py,sha256=4I7fAcMOAY9vY1AXh52QpohgFmguBECwOkvBRP4zCS4,5054
4
4
  src/api.py,sha256=pJ5l3qxccKBEY-BkANwzTgLAl1ZFq7OP6hx6LSxbhDw,4664
5
- src/cli.py,sha256=E0PEazl-fuuNu8psnUBAQ53PihtLwgKyAOL3v193Z-o,59424
5
+ src/cli.py,sha256=ABjxAdnQeyFb9a-d1B0yIidewCxVpCY7n9fYEmgsSUM,63240
6
6
  src/config.py,sha256=2ebAjIpAhw4bHbOxViEA5nCjfBlDEIrMR59DBrzcYzM,12460
7
7
  src/core/__init__.py,sha256=5FtsDvhMt4SNRx3pbcGURrxn135XRbeRrjSUxiXwkNc,381
8
- src/core/base.py,sha256=Eklcagi2ktfY4Kytl_ObXov2U49N9OGDpw4cu4PUzGY,7824
8
+ src/core/base.py,sha256=7bb_CAEohgEFXDgIK6Qc_zt6Cz4U9K6uhLhunbMX8f0,7966
9
9
  src/core/cli_utils.py,sha256=vKw0jF1rZv_N7gbzvV5TeO9rV5VPfd89fneKrglQ2Hs,6502
10
10
  src/core/config_parser.py,sha256=zAY4bDptNlVID0a4JDXN0YlUKXLM92cFqTAwhp_8uGc,4183
11
11
  src/core/linter_utils.py,sha256=4jmC2YfpPvGhS_XHlHXa5SBIJh9CQlNj5zuW_GpdPKc,5273
12
12
  src/core/registry.py,sha256=yRA8mQLiZwjmgxl1wSTgdj1cuo_QXuRdrXt3NpCBUgE,3285
13
- src/core/rule_discovery.py,sha256=smxJ9PEyMqEAIicsWaHOaSHD1PHUAOeFZT_a3DNRwgE,4163
13
+ src/core/rule_discovery.py,sha256=MWsyylfQqUBIayyQfd1Vu5RhQzGQ6IqxjYn7KsagCdk,4439
14
14
  src/core/types.py,sha256=dIYLaCDNtCAzVaplx5S5yxywkLIuX0BN9No_l2zCfV0,2887
15
- src/core/violation_builder.py,sha256=7AQODqxwc3qp_4m1MPzknkeNGlht1LsDjPsTPpWAGJY,4678
15
+ src/core/violation_builder.py,sha256=le9YCMcJt0hFji41-cCplpowys-jT44kGe-59_Du1ZM,6592
16
16
  src/formatters/__init__.py,sha256=yE1yIL8lplTMEjsmQm7F-kOMaYq7OjmbFuiwwK0D-gM,815
17
17
  src/formatters/sarif.py,sha256=gGOwb_v7j4mx4bpvV1NNDd-JyHH8i8XX89iQ6uRSvG4,7050
18
18
  src/linter_config/__init__.py,sha256=_I2VVlZlfKyT-tKukuUA5-aVcHLOe3m6C2cev43AiEc,298
19
19
  src/linter_config/ignore.py,sha256=S2Ub0CCOOC-wpU5Y_EodMprciw18fgWcnp4z_h1MYNk,19638
20
- src/linter_config/loader.py,sha256=BM4GJZqkEJSKxR3jIMgz0WqB_uWxXNiHsKWtwUA43AE,2545
20
+ src/linter_config/loader.py,sha256=K6mKRkP2jgwar-pwBoJGWgwynLVjqdez-l3Nd6bUCMk,3363
21
21
  src/linters/__init__.py,sha256=-nnNsL8E5-2p9qlLKp_TaShHAjPH-NacOEU1sXmAR9k,77
22
22
  src/linters/dry/__init__.py,sha256=p58tN3z_VbulfTkRm1kLZJ43Bemt66T2sro1teirUY8,826
23
23
  src/linters/dry/base_token_analyzer.py,sha256=SgnsX4a4kUzOsA9hTkLkg4yB8I77ewAyiUp6cAybUrg,2684
24
- src/linters/dry/block_filter.py,sha256=8Sc4tZqHj5GpVxJTQRMCtbMLt6zscuylF2fccEwPo2w,8248
25
- src/linters/dry/block_grouper.py,sha256=gBvSPgy8jumChZ53px3P7hDCJfi5PDrKhwxLTgNy7ig,1810
24
+ src/linters/dry/block_filter.py,sha256=9hTPWbtO432qMPdgwHz4ZB-sFyV0kFI6hewBOW1mrB4,8382
25
+ src/linters/dry/block_grouper.py,sha256=NP66BlofaY7HVXcWwmK5lyiNXbaTlU1V3IbcZubIq_I,1937
26
26
  src/linters/dry/cache.py,sha256=dedkGU5SolTjmTTsmj-dwPEnxyhWZ2aBiHGkQy1JwXo,5881
27
- src/linters/dry/cache_query.py,sha256=NTBh4ISy76LJb9tJ6G94fE0R2OiE0eQ-zVvB08WG2bA,1802
27
+ src/linters/dry/cache_query.py,sha256=qu_uHe360ZvKmFTBvfREjjPMGbJgLQsFTKPVIA2jQJ0,1949
28
28
  src/linters/dry/config.py,sha256=XaHX5SnbH8cEBHiNKMSuYQJwCbKL-Q9XgZVRcc9UBgQ,5439
29
29
  src/linters/dry/config_loader.py,sha256=wikqnigOp6p1h9jaAATV_3bDXSiaIUFaf9xg1jQMDpo,1313
30
30
  src/linters/dry/deduplicator.py,sha256=a1TRvldxCszf5QByo1ihXF3W98dpGuyaRT74jPfQftM,3988
@@ -34,15 +34,15 @@ src/linters/dry/inline_ignore.py,sha256=ASfA-fp_1aPpkakN2e0T6qdTh8S7Jqj89ovxXJLm
34
34
  src/linters/dry/linter.py,sha256=XMLwCgGrFX0l0dVUJs1jpsXOfgxeKKDbxOtN5h5Emhk,5835
35
35
  src/linters/dry/python_analyzer.py,sha256=jmMUw2YhwkRrAJJDHaHKffGUjCiz5OzWwv_ZJrzNXqw,27367
36
36
  src/linters/dry/storage_initializer.py,sha256=ykMALFs4uMUrN0_skEwySDl_t5Dm_LGHllF0OxDhiUI,1366
37
- src/linters/dry/token_hasher.py,sha256=71njBzUsWvQjIWo38AKeRHQsG8K4jrjLTKuih-i6Gis,5372
37
+ src/linters/dry/token_hasher.py,sha256=VT7BkzYMIWadvGrnL8bFlH3lzRfgdZSj5lDU364tRNA,5589
38
38
  src/linters/dry/typescript_analyzer.py,sha256=ShNoB2KfPe010wKEZoFxn-ZKh0MnRUwgADDQKQtfedI,21627
39
- src/linters/dry/violation_builder.py,sha256=EUiEQIOZjzAoHEqZiIR8WZP8m4dgqJjcveR5mdMyClI,2803
40
- src/linters/dry/violation_filter.py,sha256=aTOMz8kXG2sZlSVcf3cAxgxHs7f2kBXInfr1V_04fUQ,3125
39
+ src/linters/dry/violation_builder.py,sha256=WkCibSNytoqMHGC-3GrVff4PD7-SOnVzzZgkMeqmzco,2952
40
+ src/linters/dry/violation_filter.py,sha256=RJVZZ3RWqJhIdkRQ8YcXXG9XGhiQmaiZ4_IzHWpbCG8,3265
41
41
  src/linters/dry/violation_generator.py,sha256=hbMs8Fo2hS8JCXicZcZni6NEkv4fJRsyrsjzrqN6qVw,6122
42
42
  src/linters/file_header/__init__.py,sha256=S3a2xrOlxnNWD02To5K2ZwILsNEvSj1IvUAH8RjgOV4,791
43
43
  src/linters/file_header/atemporal_detector.py,sha256=bgQJPDuJj1J5gHKIIOz1TYbBwu8GHrcMafWFVqZ_zZE,3192
44
44
  src/linters/file_header/base_parser.py,sha256=HbuJpXQ4V3zTDTP_D0iFqoT7kab6gk8A1lZdlqCb6tc,3202
45
- src/linters/file_header/bash_parser.py,sha256=ZnPleRD4c16ibYMBc682N9W-Qgtz9lKtLSqSmbo7oqg,2147
45
+ src/linters/file_header/bash_parser.py,sha256=y74YLSQ6FKXnkl9RCu31N3llDxeAH9wRgmSjjFKrr8A,2316
46
46
  src/linters/file_header/config.py,sha256=Ewrln4W4QDnInTgWr8WgSlQEjAuDyMbUuh9GHAa9a4c,4030
47
47
  src/linters/file_header/css_parser.py,sha256=ijpGMixg2ZqNWWdiZjSNtMXCOhm6XDfSY7OU68B9fS8,2332
48
48
  src/linters/file_header/field_validator.py,sha256=uASqHj7ID4JJZzgc6X3SmRRLWV35NnX2iZElCt3HW1o,2830
@@ -53,19 +53,19 @@ src/linters/file_header/typescript_parser.py,sha256=R11Vkr6dUVaU8t90m8rrkMzODtBY
53
53
  src/linters/file_header/violation_builder.py,sha256=HPYTmrcCmcO6Dx5dhmj85zZgEBM5EZqTgql-0CA0A0k,2745
54
54
  src/linters/file_placement/__init__.py,sha256=vJ43GZujcbAk-K3DwfsQZ0J3yP_5G35CKssatLyntXk,862
55
55
  src/linters/file_placement/config_loader.py,sha256=Of5sTG2S-04efn3KOlXrSxpMcC1ipBpSvCjtJOMmWno,2640
56
- src/linters/file_placement/directory_matcher.py,sha256=YaBeLGiT4bgqN_v4FmEmSASOBxkMC1lyEYpL17wLIDY,2607
56
+ src/linters/file_placement/directory_matcher.py,sha256=1rxJtCEzqDYDQnscVX6pzk7gxCMD11pVIGaWcli-tHY,2742
57
57
  src/linters/file_placement/linter.py,sha256=A4mndpyIyxEzq64rLw2ILNA7APx_QmwzUfnhB0PyuCs,14190
58
58
  src/linters/file_placement/path_resolver.py,sha256=S6g7xOYsoSc0O_RDJh8j4Z2klcwzp16rSUfEAErGOTI,1972
59
- src/linters/file_placement/pattern_matcher.py,sha256=3HZWYgQKXz_y13z3lO1YHn51khCaiGOrneGxKXGWGw0,1898
60
- src/linters/file_placement/pattern_validator.py,sha256=eMt5GB5lgJMhhQACOlfDXQFfSfNrOY-wJN1JanGka6Q,3717
59
+ src/linters/file_placement/pattern_matcher.py,sha256=0TWozhKGqQk66oJpP66ewlmOI3bI8GpDf37PyImZcUA,2030
60
+ src/linters/file_placement/pattern_validator.py,sha256=KW2Wv4owIGiLxxC3hhyVsKkIuzC95pGv3wQD3m4_eYo,3853
61
61
  src/linters/file_placement/rule_checker.py,sha256=JONXcaYxZ8CM_7Zg6Th01p5cve1rJ8YkReAUJ44nfUg,7795
62
62
  src/linters/file_placement/violation_factory.py,sha256=NkQmBcgpa3g3W2ZdFZNQ5djLVP4x9OKs65d7F1rCKvM,6040
63
63
  src/linters/magic_numbers/__init__.py,sha256=17dkCUf0uiYLvpOZF01VDojj92NzxXZMtRhrSBUzsdc,1689
64
64
  src/linters/magic_numbers/config.py,sha256=3zV6ZNezouBWUYy4kMw5PUlPNvIWXVwOxTz1moZfRoI,3270
65
- src/linters/magic_numbers/context_analyzer.py,sha256=cGXozlKll10Zao56c2E8ThIyH2mSQaPaUau_g7ngRLw,8446
65
+ src/linters/magic_numbers/context_analyzer.py,sha256=bWv5EK3CDO0_iSd-SvDgOJeX4PGKSxG6F_cLjZnt9S8,8582
66
66
  src/linters/magic_numbers/linter.py,sha256=maj4NgrDapv0RurKvaVgOI1BUujixZv4E7UeYy4eGT4,18394
67
67
  src/linters/magic_numbers/python_analyzer.py,sha256=0u1cFaaFCqOW5yeW-YbmPoZuVIeN_KtmkFyyxup6aR0,2803
68
- src/linters/magic_numbers/typescript_analyzer.py,sha256=NTU1XY-Hudse5oxOtEiG6nA0Rs5Icn9HXELnyPj8OZU,7554
68
+ src/linters/magic_numbers/typescript_analyzer.py,sha256=2Ra9SsXTLkZP5t-s-38ErIk4kY6EqzPfLz0I61EyIGg,7773
69
69
  src/linters/magic_numbers/violation_builder.py,sha256=SqIQv3N9lpP2GRC1TC5InrvaEdrAq24V7Ec2Xj5olb0,3308
70
70
  src/linters/method_property/__init__.py,sha256=t0C6zD5WLm-McgmvVajQJg4HQfOi7_4YzNLhKNA484w,1415
71
71
  src/linters/method_property/config.py,sha256=lcKfeCIeWBcD91j0AchccWhGvc68epiQeKbgL6DCEA8,5359
@@ -75,34 +75,38 @@ src/linters/method_property/violation_builder.py,sha256=GKZC8TS9vZq_lKK5ffOVUHUl
75
75
  src/linters/nesting/__init__.py,sha256=tszmyCEQMpEwB5H84WcAUfRYDQl7jpsn04es5DtAHsM,3200
76
76
  src/linters/nesting/config.py,sha256=PfPA2wJn3i6HHXeM0qu6Qx-v1KJdRwlRkFOdpf7NhS8,2405
77
77
  src/linters/nesting/linter.py,sha256=-klbXIbg145beICop81CNQ5J1OInQaeycDT8u3Ff2Ww,6236
78
- src/linters/nesting/python_analyzer.py,sha256=DF2lVnxYstakOpP_Zizox583Ypkb4eUpgQYEpu6x8gk,3078
78
+ src/linters/nesting/python_analyzer.py,sha256=__fs_NE9xA4NM1MDOHBGdrI0zICkTcgbVZtfT03cxF0,3230
79
79
  src/linters/nesting/typescript_analyzer.py,sha256=wO6p6QNnyW1uaieTCZjaqR56C68AjifAv23tYaSuR2c,3860
80
- src/linters/nesting/typescript_function_extractor.py,sha256=dDB1otJnFMCo-Pj4mTr4gekKe7V4ArOAtX6gV0dBDc4,4494
80
+ src/linters/nesting/typescript_function_extractor.py,sha256=5CRyP04jWP5b6NkkOGoScee6sJFZ1V-mkA0hxLkTUt8,4710
81
81
  src/linters/nesting/violation_builder.py,sha256=sMHS45F2lrA1WYrG3Uug8HfeRPljnXcyJPHSe2F76Bs,4828
82
82
  src/linters/print_statements/__init__.py,sha256=yhvdTFSqBB4UDreeadTHKFzhayxeT6JkF3yxUHMgn1g,1893
83
83
  src/linters/print_statements/config.py,sha256=rth3XmzqZGzXkRXDIVZswdtNOXIe1vIRaF46tVLKnyQ,3041
84
84
  src/linters/print_statements/linter.py,sha256=J23gtU6FQ2uH2Sj38PPRiV4k2HU0uto2Bqf2D28pKrI,14630
85
85
  src/linters/print_statements/python_analyzer.py,sha256=SyCkh8HkYAfcSM7LCwDE1ahhxwPgrlnSVLs1iRemyaw,5461
86
- src/linters/print_statements/typescript_analyzer.py,sha256=v2R6ZG80eTQq92oE3Y3E4ZwUfBmXwB9G5QKftqbRbD8,5155
86
+ src/linters/print_statements/typescript_analyzer.py,sha256=4nCC2nNoQF8xtTou2XDA6jlWEuzNRsxdro50ZoVZZzE,5377
87
87
  src/linters/print_statements/violation_builder.py,sha256=Vs5m3AnWjrQqQHf6JJDaPP5B1V3YNl5pepG_oiTJnx4,3333
88
88
  src/linters/srp/__init__.py,sha256=GbhaSB2_AYY-mWgG_ThbyAcDXoVZuB5eLzguoShf38w,3367
89
- src/linters/srp/class_analyzer.py,sha256=wuwviwhN1F_VVPaQ3pZvffmY3e9ToxPNJhv6BjhsgZc,3761
89
+ src/linters/srp/class_analyzer.py,sha256=vSBKLDBc734Iy-p9Ux7ygnNYaUtkT3ivUUJS54tyKs0,3912
90
90
  src/linters/srp/config.py,sha256=hTxrM21HIOmg0sM6eJ_h3hRnuxqRZEgs13Ie97-PDr4,3397
91
91
  src/linters/srp/heuristics.py,sha256=Fwrro3I0qOV4o0epM0ZkqgQUU9bK1b2igxoxWjReljU,3185
92
92
  src/linters/srp/linter.py,sha256=aXeMKmMf5PC5P2E-mstys2xndkrvpZF6tAq9xRdzOYo,7624
93
93
  src/linters/srp/metrics_evaluator.py,sha256=Prk_dPacas_dX7spAzV0g734srmzT5u0t5d4mTG9g2o,1606
94
- src/linters/srp/python_analyzer.py,sha256=hA1gtiLJISier6B3rHJX5EkimQc8FJapy-XNtR7xaBQ,2621
94
+ src/linters/srp/python_analyzer.py,sha256=PH27l38BFPNmj22Z10QDBioLDCZ4xpJFzBfTh_4XMZ4,3585
95
95
  src/linters/srp/typescript_analyzer.py,sha256=Wi0P_G1v5AnZYtMN3sNm1iHva84-8Kep2LZ5RmAS4c4,2885
96
- src/linters/srp/typescript_metrics_calculator.py,sha256=2VLRux_tf1Cw645wwTuol3Z5A6-mkl4cgyW34myy00Q,2728
97
- src/linters/srp/violation_builder.py,sha256=jaIjVtRYWUTs1SVJVwd0FxCojo0DxhPzfhyfMKmAroM,3881
96
+ src/linters/srp/typescript_metrics_calculator.py,sha256=0RyHTWzBJbLUT3BqFuNc1wJVoS5nNI1Ph-tF_cp4EEI,3499
97
+ src/linters/srp/violation_builder.py,sha256=AMZIFNEAt-7sYVtV7x4VIuvTilxFMnU_IOH1j4wZZ_c,4072
98
+ src/linters/stateless_class/__init__.py,sha256=8ePpinmCD27PCz7ukwUWcNwo-ZgyvhOquns-U51MyiQ,1063
99
+ src/linters/stateless_class/config.py,sha256=u8Jt_xygIkuxZx2o0Uw_XFatOh11QhC9aN8lB_vfnLk,1993
100
+ src/linters/stateless_class/linter.py,sha256=ECMDxL0ZIZDKFJ2APnpy6yzNs-gkklpmBdaSBEZQfHE,11129
101
+ src/linters/stateless_class/python_analyzer.py,sha256=Nv8mTM7HKjqDA8Kyu-bw3GOo9eq9XA4zD3GYsjQmV9E,7789
98
102
  src/orchestrator/__init__.py,sha256=XXLDJq2oaB-TpP2Y97GRnde9EkITGuFCmuLrDfxI9nY,245
99
103
  src/orchestrator/core.py,sha256=z0YcwsK18uhlztIPi54ux3mOm8fHMREYJoudsJPhC0Q,8857
100
104
  src/orchestrator/language_detector.py,sha256=rHyVMApit80NTTNyDH1ObD1usKD8LjGmH3DwqNAWYGc,2736
101
105
  src/templates/thailint_config_template.yaml,sha256=vxyhRRi25_xOnHDRx0jzz69dgPqKU2IU5-YFGUoX5lM,4953
102
106
  src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
103
107
  src/utils/project_root.py,sha256=b3YTEGTa9RPcOeHn1IByMMWyRiUabfVlpnlektL0A0o,6156
104
- thailint-0.8.0.dist-info/METADATA,sha256=JLoEBO87HaZBzNk9wlkn1MeCO_S2wG5dKnL6itrbDe0,42115
105
- thailint-0.8.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
106
- thailint-0.8.0.dist-info/entry_points.txt,sha256=l7DQJgU18sVLDpSaXOXY3lLhnQHQIRrSJZTQjG1cEAk,62
107
- thailint-0.8.0.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
108
- thailint-0.8.0.dist-info/RECORD,,
108
+ thailint-0.9.0.dist-info/METADATA,sha256=zcAW2ZVfxz5MPGZlcs3EasPdflQZrdhb3Ev7R5xZkXU,45453
109
+ thailint-0.9.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
110
+ thailint-0.9.0.dist-info/entry_points.txt,sha256=l7DQJgU18sVLDpSaXOXY3lLhnQHQIRrSJZTQjG1cEAk,62
111
+ thailint-0.9.0.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
112
+ thailint-0.9.0.dist-info/RECORD,,