thailint 0.7.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 (41) hide show
  1. src/cli.py +233 -1
  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 +45 -12
  6. src/linters/dry/block_filter.py +15 -8
  7. src/linters/dry/block_grouper.py +4 -0
  8. src/linters/dry/cache.py +3 -2
  9. src/linters/dry/cache_query.py +4 -0
  10. src/linters/dry/duplicate_storage.py +5 -4
  11. src/linters/dry/token_hasher.py +5 -1
  12. src/linters/dry/violation_builder.py +4 -0
  13. src/linters/dry/violation_filter.py +4 -0
  14. src/linters/dry/violation_generator.py +1 -1
  15. src/linters/file_header/bash_parser.py +4 -0
  16. src/linters/file_placement/directory_matcher.py +4 -0
  17. src/linters/file_placement/pattern_matcher.py +4 -0
  18. src/linters/file_placement/pattern_validator.py +4 -0
  19. src/linters/magic_numbers/context_analyzer.py +4 -0
  20. src/linters/magic_numbers/typescript_analyzer.py +4 -0
  21. src/linters/method_property/__init__.py +49 -0
  22. src/linters/method_property/config.py +135 -0
  23. src/linters/method_property/linter.py +419 -0
  24. src/linters/method_property/python_analyzer.py +472 -0
  25. src/linters/method_property/violation_builder.py +116 -0
  26. src/linters/nesting/python_analyzer.py +4 -0
  27. src/linters/nesting/typescript_function_extractor.py +4 -0
  28. src/linters/print_statements/typescript_analyzer.py +4 -0
  29. src/linters/srp/class_analyzer.py +4 -0
  30. src/linters/srp/python_analyzer.py +55 -20
  31. src/linters/srp/typescript_metrics_calculator.py +83 -47
  32. src/linters/srp/violation_builder.py +4 -0
  33. src/linters/stateless_class/__init__.py +25 -0
  34. src/linters/stateless_class/config.py +58 -0
  35. src/linters/stateless_class/linter.py +355 -0
  36. src/linters/stateless_class/python_analyzer.py +299 -0
  37. {thailint-0.7.0.dist-info → thailint-0.9.0.dist-info}/METADATA +119 -3
  38. {thailint-0.7.0.dist-info → thailint-0.9.0.dist-info}/RECORD +41 -32
  39. {thailint-0.7.0.dist-info → thailint-0.9.0.dist-info}/WHEEL +0 -0
  40. {thailint-0.7.0.dist-info → thailint-0.9.0.dist-info}/entry_points.txt +0 -0
  41. {thailint-0.7.0.dist-info → thailint-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thailint
3
- Version: 0.7.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
7
7
  Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
8
8
  Author: Steve Jackson
9
9
  Requires-Python: >=3.11,<4.0
10
- Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Environment :: Console
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: MIT 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-571%2F571%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)
@@ -98,6 +98,18 @@ thailint complements your existing linting stack by catching the patterns AI too
98
98
  - Configurable thresholds (lines, tokens, occurrences)
99
99
  - Language-specific detection (Python, TypeScript, JavaScript)
100
100
  - False positive filtering (keyword args, imports)
101
+ - **Method Property Linting** - Detect methods that should be @property decorators
102
+ - Python AST-based detection
103
+ - get_* prefix detection (Java-style getters)
104
+ - Simple computed value detection
105
+ - Action verb exclusion (to_*, finalize, serialize)
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
101
113
  - **Pluggable Architecture** - Easy to extend with custom linters
102
114
  - **Multi-Language Support** - Python, TypeScript, JavaScript, and more
103
115
  - **Flexible Configuration** - YAML/JSON configs with pattern matching
@@ -1011,6 +1023,108 @@ Overview: Created 2024-01-15. # thailint: ignore[file-header]
1011
1023
 
1012
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.
1013
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
+
1014
1128
  ## Pre-commit Hooks
1015
1129
 
1016
1130
  Automate code quality checks before every commit and push with pre-commit hooks.
@@ -1300,6 +1414,8 @@ docker run --rm -v /path/to/workspace:/workspace \
1300
1414
  - **[Nesting Depth Linter](https://thai-lint.readthedocs.io/en/latest/nesting-linter/)** - Nesting depth analysis guide
1301
1415
  - **[SRP Linter](https://thai-lint.readthedocs.io/en/latest/srp-linter/)** - Single Responsibility Principle guide
1302
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
1303
1419
  - **[Pre-commit Hooks](https://thai-lint.readthedocs.io/en/latest/pre-commit-hooks/)** - Automated quality checks
1304
1420
  - **[SARIF Output Guide](docs/sarif-output.md)** - SARIF format for GitHub Code Scanning and CI/CD
1305
1421
  - **[Publishing Guide](https://thai-lint.readthedocs.io/en/latest/releasing/)** - Release and publishing workflow
@@ -2,47 +2,47 @@ 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=H8DAOCRIu4pK2fbTqryJ0arwKmJ9w3kkeRdtC-FVdAY,55579
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=HB09W-uVsEcgCbvUwUHS5Jm2n0bqBXA3744vMc4GAqk,2542
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=FN1QDXQu6HYhdHo6fkzUDUrMX4TqaLV_myBOQRsmPfk,8242
25
- src/linters/dry/block_grouper.py,sha256=gBvSPgy8jumChZ53px3P7hDCJfi5PDrKhwxLTgNy7ig,1810
26
- src/linters/dry/cache.py,sha256=QbFajUNb3v2LVuYbTJXY9ExXjjIsd73DQ5Y1hB-SH1s,5879
27
- src/linters/dry/cache_query.py,sha256=NTBh4ISy76LJb9tJ6G94fE0R2OiE0eQ-zVvB08WG2bA,1802
24
+ src/linters/dry/block_filter.py,sha256=9hTPWbtO432qMPdgwHz4ZB-sFyV0kFI6hewBOW1mrB4,8382
25
+ src/linters/dry/block_grouper.py,sha256=NP66BlofaY7HVXcWwmK5lyiNXbaTlU1V3IbcZubIq_I,1937
26
+ src/linters/dry/cache.py,sha256=dedkGU5SolTjmTTsmj-dwPEnxyhWZ2aBiHGkQy1JwXo,5881
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
31
- src/linters/dry/duplicate_storage.py,sha256=3OxE2mtoWGAsNNrB8J2c-4JirLUoqZ9ptydO5beM-mg,1971
31
+ src/linters/dry/duplicate_storage.py,sha256=9pIALnwAuz5BJUYNXrPbObbP932CE9x0vgUkICryT_s,1970
32
32
  src/linters/dry/file_analyzer.py,sha256=ufSQ85ddsGTqGnBHZNTdV_5DGfTpUmJOB58sIdJNV0I,2928
33
33
  src/linters/dry/inline_ignore.py,sha256=ASfA-fp_1aPpkakN2e0T6qdTh8S7Jqj89ovxXJLmFlc,4439
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
41
- src/linters/dry/violation_generator.py,sha256=cc6aKvTxtHSZm0F7Y-gL1bmD3JUphRmAvcbqk9aUzGg,6128
39
+ src/linters/dry/violation_builder.py,sha256=WkCibSNytoqMHGC-3GrVff4PD7-SOnVzzZgkMeqmzco,2952
40
+ src/linters/dry/violation_filter.py,sha256=RJVZZ3RWqJhIdkRQ8YcXXG9XGhiQmaiZ4_IzHWpbCG8,3265
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,51 +53,60 @@ 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
+ src/linters/method_property/__init__.py,sha256=t0C6zD5WLm-McgmvVajQJg4HQfOi7_4YzNLhKNA484w,1415
71
+ src/linters/method_property/config.py,sha256=lcKfeCIeWBcD91j0AchccWhGvc68epiQeKbgL6DCEA8,5359
72
+ src/linters/method_property/linter.py,sha256=zdXUqx76A8J7Ryvg333jrAUDFWx4I4n3dzayAcN2k8w,12721
73
+ src/linters/method_property/python_analyzer.py,sha256=QQTpKrdCJzFqu7gdQfAqno9_wbzHlOQYQdCzMPriRM0,15244
74
+ src/linters/method_property/violation_builder.py,sha256=GKZC8TS9vZq_lKK5ffOVUHUlMpZN3_-Mv3inRE-v2pE,4141
70
75
  src/linters/nesting/__init__.py,sha256=tszmyCEQMpEwB5H84WcAUfRYDQl7jpsn04es5DtAHsM,3200
71
76
  src/linters/nesting/config.py,sha256=PfPA2wJn3i6HHXeM0qu6Qx-v1KJdRwlRkFOdpf7NhS8,2405
72
77
  src/linters/nesting/linter.py,sha256=-klbXIbg145beICop81CNQ5J1OInQaeycDT8u3Ff2Ww,6236
73
- src/linters/nesting/python_analyzer.py,sha256=DF2lVnxYstakOpP_Zizox583Ypkb4eUpgQYEpu6x8gk,3078
78
+ src/linters/nesting/python_analyzer.py,sha256=__fs_NE9xA4NM1MDOHBGdrI0zICkTcgbVZtfT03cxF0,3230
74
79
  src/linters/nesting/typescript_analyzer.py,sha256=wO6p6QNnyW1uaieTCZjaqR56C68AjifAv23tYaSuR2c,3860
75
- src/linters/nesting/typescript_function_extractor.py,sha256=dDB1otJnFMCo-Pj4mTr4gekKe7V4ArOAtX6gV0dBDc4,4494
80
+ src/linters/nesting/typescript_function_extractor.py,sha256=5CRyP04jWP5b6NkkOGoScee6sJFZ1V-mkA0hxLkTUt8,4710
76
81
  src/linters/nesting/violation_builder.py,sha256=sMHS45F2lrA1WYrG3Uug8HfeRPljnXcyJPHSe2F76Bs,4828
77
82
  src/linters/print_statements/__init__.py,sha256=yhvdTFSqBB4UDreeadTHKFzhayxeT6JkF3yxUHMgn1g,1893
78
83
  src/linters/print_statements/config.py,sha256=rth3XmzqZGzXkRXDIVZswdtNOXIe1vIRaF46tVLKnyQ,3041
79
84
  src/linters/print_statements/linter.py,sha256=J23gtU6FQ2uH2Sj38PPRiV4k2HU0uto2Bqf2D28pKrI,14630
80
85
  src/linters/print_statements/python_analyzer.py,sha256=SyCkh8HkYAfcSM7LCwDE1ahhxwPgrlnSVLs1iRemyaw,5461
81
- src/linters/print_statements/typescript_analyzer.py,sha256=v2R6ZG80eTQq92oE3Y3E4ZwUfBmXwB9G5QKftqbRbD8,5155
86
+ src/linters/print_statements/typescript_analyzer.py,sha256=4nCC2nNoQF8xtTou2XDA6jlWEuzNRsxdro50ZoVZZzE,5377
82
87
  src/linters/print_statements/violation_builder.py,sha256=Vs5m3AnWjrQqQHf6JJDaPP5B1V3YNl5pepG_oiTJnx4,3333
83
88
  src/linters/srp/__init__.py,sha256=GbhaSB2_AYY-mWgG_ThbyAcDXoVZuB5eLzguoShf38w,3367
84
- src/linters/srp/class_analyzer.py,sha256=wuwviwhN1F_VVPaQ3pZvffmY3e9ToxPNJhv6BjhsgZc,3761
89
+ src/linters/srp/class_analyzer.py,sha256=vSBKLDBc734Iy-p9Ux7ygnNYaUtkT3ivUUJS54tyKs0,3912
85
90
  src/linters/srp/config.py,sha256=hTxrM21HIOmg0sM6eJ_h3hRnuxqRZEgs13Ie97-PDr4,3397
86
91
  src/linters/srp/heuristics.py,sha256=Fwrro3I0qOV4o0epM0ZkqgQUU9bK1b2igxoxWjReljU,3185
87
92
  src/linters/srp/linter.py,sha256=aXeMKmMf5PC5P2E-mstys2xndkrvpZF6tAq9xRdzOYo,7624
88
93
  src/linters/srp/metrics_evaluator.py,sha256=Prk_dPacas_dX7spAzV0g734srmzT5u0t5d4mTG9g2o,1606
89
- src/linters/srp/python_analyzer.py,sha256=hA1gtiLJISier6B3rHJX5EkimQc8FJapy-XNtR7xaBQ,2621
94
+ src/linters/srp/python_analyzer.py,sha256=PH27l38BFPNmj22Z10QDBioLDCZ4xpJFzBfTh_4XMZ4,3585
90
95
  src/linters/srp/typescript_analyzer.py,sha256=Wi0P_G1v5AnZYtMN3sNm1iHva84-8Kep2LZ5RmAS4c4,2885
91
- src/linters/srp/typescript_metrics_calculator.py,sha256=2VLRux_tf1Cw645wwTuol3Z5A6-mkl4cgyW34myy00Q,2728
92
- 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
93
102
  src/orchestrator/__init__.py,sha256=XXLDJq2oaB-TpP2Y97GRnde9EkITGuFCmuLrDfxI9nY,245
94
103
  src/orchestrator/core.py,sha256=z0YcwsK18uhlztIPi54ux3mOm8fHMREYJoudsJPhC0Q,8857
95
104
  src/orchestrator/language_detector.py,sha256=rHyVMApit80NTTNyDH1ObD1usKD8LjGmH3DwqNAWYGc,2736
96
105
  src/templates/thailint_config_template.yaml,sha256=vxyhRRi25_xOnHDRx0jzz69dgPqKU2IU5-YFGUoX5lM,4953
97
106
  src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
98
107
  src/utils/project_root.py,sha256=b3YTEGTa9RPcOeHn1IByMMWyRiUabfVlpnlektL0A0o,6156
99
- thailint-0.7.0.dist-info/METADATA,sha256=DiyHLUK6NNz3o2MtQsJPJX-3PWdUX0vyMt2SsSI3ot0,41840
100
- thailint-0.7.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
101
- thailint-0.7.0.dist-info/entry_points.txt,sha256=l7DQJgU18sVLDpSaXOXY3lLhnQHQIRrSJZTQjG1cEAk,62
102
- thailint-0.7.0.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
103
- thailint-0.7.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,,