thailint 0.11.0__py3-none-any.whl → 0.13.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 (129) hide show
  1. src/analyzers/__init__.py +4 -3
  2. src/analyzers/ast_utils.py +54 -0
  3. src/analyzers/typescript_base.py +4 -0
  4. src/cli/__init__.py +3 -0
  5. src/cli/config.py +12 -12
  6. src/cli/config_merge.py +241 -0
  7. src/cli/linters/__init__.py +3 -0
  8. src/cli/linters/code_patterns.py +113 -5
  9. src/cli/linters/code_smells.py +118 -7
  10. src/cli/linters/documentation.py +3 -0
  11. src/cli/linters/structure.py +3 -0
  12. src/cli/linters/structure_quality.py +3 -0
  13. src/cli/utils.py +29 -9
  14. src/cli_main.py +3 -0
  15. src/config.py +2 -1
  16. src/core/base.py +3 -2
  17. src/core/cli_utils.py +3 -1
  18. src/core/config_parser.py +5 -2
  19. src/core/constants.py +54 -0
  20. src/core/linter_utils.py +4 -0
  21. src/core/rule_discovery.py +5 -1
  22. src/core/violation_builder.py +3 -0
  23. src/linter_config/directive_markers.py +109 -0
  24. src/linter_config/ignore.py +225 -383
  25. src/linter_config/pattern_utils.py +65 -0
  26. src/linter_config/rule_matcher.py +89 -0
  27. src/linters/collection_pipeline/any_all_analyzer.py +281 -0
  28. src/linters/collection_pipeline/ast_utils.py +40 -0
  29. src/linters/collection_pipeline/config.py +12 -0
  30. src/linters/collection_pipeline/continue_analyzer.py +2 -8
  31. src/linters/collection_pipeline/detector.py +262 -32
  32. src/linters/collection_pipeline/filter_map_analyzer.py +402 -0
  33. src/linters/collection_pipeline/linter.py +18 -35
  34. src/linters/collection_pipeline/suggestion_builder.py +68 -1
  35. src/linters/dry/base_token_analyzer.py +16 -9
  36. src/linters/dry/block_filter.py +7 -4
  37. src/linters/dry/cache.py +7 -2
  38. src/linters/dry/config.py +7 -1
  39. src/linters/dry/constant_matcher.py +34 -25
  40. src/linters/dry/file_analyzer.py +4 -2
  41. src/linters/dry/inline_ignore.py +7 -16
  42. src/linters/dry/linter.py +48 -25
  43. src/linters/dry/python_analyzer.py +18 -10
  44. src/linters/dry/python_constant_extractor.py +51 -52
  45. src/linters/dry/single_statement_detector.py +14 -12
  46. src/linters/dry/token_hasher.py +115 -115
  47. src/linters/dry/typescript_analyzer.py +11 -6
  48. src/linters/dry/typescript_constant_extractor.py +4 -0
  49. src/linters/dry/typescript_statement_detector.py +208 -208
  50. src/linters/dry/typescript_value_extractor.py +3 -0
  51. src/linters/dry/violation_filter.py +1 -4
  52. src/linters/dry/violation_generator.py +1 -4
  53. src/linters/file_header/atemporal_detector.py +4 -0
  54. src/linters/file_header/base_parser.py +4 -0
  55. src/linters/file_header/bash_parser.py +4 -0
  56. src/linters/file_header/field_validator.py +5 -8
  57. src/linters/file_header/linter.py +19 -12
  58. src/linters/file_header/markdown_parser.py +6 -0
  59. src/linters/file_placement/config_loader.py +3 -1
  60. src/linters/file_placement/linter.py +22 -8
  61. src/linters/file_placement/pattern_matcher.py +21 -4
  62. src/linters/file_placement/pattern_validator.py +21 -7
  63. src/linters/file_placement/rule_checker.py +2 -2
  64. src/linters/lazy_ignores/__init__.py +43 -0
  65. src/linters/lazy_ignores/config.py +66 -0
  66. src/linters/lazy_ignores/directive_utils.py +121 -0
  67. src/linters/lazy_ignores/header_parser.py +177 -0
  68. src/linters/lazy_ignores/linter.py +158 -0
  69. src/linters/lazy_ignores/matcher.py +135 -0
  70. src/linters/lazy_ignores/python_analyzer.py +201 -0
  71. src/linters/lazy_ignores/rule_id_utils.py +180 -0
  72. src/linters/lazy_ignores/skip_detector.py +298 -0
  73. src/linters/lazy_ignores/types.py +67 -0
  74. src/linters/lazy_ignores/typescript_analyzer.py +146 -0
  75. src/linters/lazy_ignores/violation_builder.py +131 -0
  76. src/linters/lbyl/__init__.py +29 -0
  77. src/linters/lbyl/config.py +63 -0
  78. src/linters/lbyl/pattern_detectors/__init__.py +25 -0
  79. src/linters/lbyl/pattern_detectors/base.py +46 -0
  80. src/linters/magic_numbers/context_analyzer.py +227 -229
  81. src/linters/magic_numbers/linter.py +20 -15
  82. src/linters/magic_numbers/python_analyzer.py +4 -16
  83. src/linters/magic_numbers/typescript_analyzer.py +9 -16
  84. src/linters/method_property/config.py +4 -0
  85. src/linters/method_property/linter.py +5 -4
  86. src/linters/method_property/python_analyzer.py +5 -4
  87. src/linters/method_property/violation_builder.py +3 -0
  88. src/linters/nesting/typescript_analyzer.py +6 -12
  89. src/linters/nesting/typescript_function_extractor.py +0 -4
  90. src/linters/print_statements/linter.py +6 -4
  91. src/linters/print_statements/python_analyzer.py +85 -81
  92. src/linters/print_statements/typescript_analyzer.py +6 -15
  93. src/linters/srp/heuristics.py +4 -4
  94. src/linters/srp/linter.py +12 -12
  95. src/linters/srp/violation_builder.py +0 -4
  96. src/linters/stateless_class/linter.py +30 -36
  97. src/linters/stateless_class/python_analyzer.py +11 -20
  98. src/linters/stringly_typed/__init__.py +22 -9
  99. src/linters/stringly_typed/config.py +32 -8
  100. src/linters/stringly_typed/context_filter.py +451 -0
  101. src/linters/stringly_typed/function_call_violation_builder.py +135 -0
  102. src/linters/stringly_typed/ignore_checker.py +102 -0
  103. src/linters/stringly_typed/ignore_utils.py +51 -0
  104. src/linters/stringly_typed/linter.py +376 -0
  105. src/linters/stringly_typed/python/__init__.py +9 -5
  106. src/linters/stringly_typed/python/analyzer.py +159 -9
  107. src/linters/stringly_typed/python/call_tracker.py +175 -0
  108. src/linters/stringly_typed/python/comparison_tracker.py +257 -0
  109. src/linters/stringly_typed/python/condition_extractor.py +3 -0
  110. src/linters/stringly_typed/python/conditional_detector.py +4 -1
  111. src/linters/stringly_typed/python/match_analyzer.py +8 -2
  112. src/linters/stringly_typed/python/validation_detector.py +3 -0
  113. src/linters/stringly_typed/storage.py +630 -0
  114. src/linters/stringly_typed/storage_initializer.py +45 -0
  115. src/linters/stringly_typed/typescript/__init__.py +28 -0
  116. src/linters/stringly_typed/typescript/analyzer.py +157 -0
  117. src/linters/stringly_typed/typescript/call_tracker.py +335 -0
  118. src/linters/stringly_typed/typescript/comparison_tracker.py +378 -0
  119. src/linters/stringly_typed/violation_generator.py +405 -0
  120. src/orchestrator/core.py +13 -4
  121. src/templates/thailint_config_template.yaml +166 -0
  122. src/utils/project_root.py +3 -0
  123. thailint-0.13.0.dist-info/METADATA +184 -0
  124. thailint-0.13.0.dist-info/RECORD +189 -0
  125. thailint-0.11.0.dist-info/METADATA +0 -1661
  126. thailint-0.11.0.dist-info/RECORD +0 -150
  127. {thailint-0.11.0.dist-info → thailint-0.13.0.dist-info}/WHEEL +0 -0
  128. {thailint-0.11.0.dist-info → thailint-0.13.0.dist-info}/entry_points.txt +0 -0
  129. {thailint-0.11.0.dist-info → thailint-0.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: thailint
3
+ Version: 0.13.0
4
+ Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
8
+ Author: Steve Jackson
9
+ Requires-Python: >=3.11,<4.0
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Classifier: Topic :: Software Development :: Testing
24
+ Classifier: Topic :: Utilities
25
+ Classifier: Typing :: Typed
26
+ Requires-Dist: click (>=8.1.0,<9.0.0)
27
+ Requires-Dist: pyprojroot (>=0.3.0,<0.4.0)
28
+ Requires-Dist: pyyaml (>=6.0,<7.0)
29
+ Requires-Dist: tree-sitter (>=0.25.2,<0.26.0)
30
+ Requires-Dist: tree-sitter-typescript (>=0.23.2,<0.24.0)
31
+ Project-URL: Documentation, https://thai-lint.readthedocs.io/
32
+ Project-URL: Homepage, https://github.com/be-wise-be-kind/thai-lint
33
+ Project-URL: Repository, https://github.com/be-wise-be-kind/thai-lint
34
+ Description-Content-Type: text/markdown
35
+
36
+ # thai-lint
37
+
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
40
+ [![PyPI](https://img.shields.io/pypi/v/thai-lint)](https://pypi.org/project/thai-lint/)
41
+ [![Documentation](https://readthedocs.org/projects/thai-lint/badge/?version=latest)](https://thai-lint.readthedocs.io/)
42
+
43
+ **The AI Linter** - Catch the mistakes AI coding assistants keep making.
44
+
45
+ thailint detects anti-patterns that AI tools frequently introduce: duplicate code, excessive nesting, magic numbers, SRP violations, and more. It works across Python, TypeScript, and JavaScript with unified rules - filling gaps that existing linters miss.
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install thai-lint
51
+ ```
52
+
53
+ Or with Docker:
54
+ ```bash
55
+ docker run --rm -v $(pwd):/data washad/thailint:latest --help
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ```bash
61
+ # Generate a config file (optional)
62
+ thailint init-config
63
+
64
+ # Run any linter
65
+ thailint dry src/
66
+ ```
67
+
68
+ That's it. See violations, fix them, ship better code.
69
+
70
+ ## Available Linters
71
+
72
+ | Linter | What It Catches | Command | Docs |
73
+ |--------|-----------------|---------|------|
74
+ | **DRY** | Duplicate code across files | `thailint dry src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/dry-linter/) |
75
+ | **Nesting** | Deeply nested if/for/while blocks | `thailint nesting src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/nesting-linter/) |
76
+ | **Magic Numbers** | Unnamed numeric literals | `thailint magic-numbers src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/) |
77
+ | **SRP** | Classes doing too much | `thailint srp src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/srp-linter/) |
78
+ | **File Header** | Missing documentation headers | `thailint file-header src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/) |
79
+ | **Stateless Class** | Classes that should be functions | `thailint stateless-class src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/) |
80
+ | **Collection Pipeline** | Loops with embedded filtering | `thailint pipeline src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/collection-pipeline-linter/) |
81
+ | **Method Property** | Methods that should be @property | `thailint method-property src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/method-property-linter/) |
82
+ | **File Placement** | Files in wrong directories | `thailint file-placement src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/) |
83
+ | **Lazy Ignores** | Unjustified linting suppressions | `thailint lazy-ignores src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lazy-ignores-linter/) |
84
+ | **Print Statements** | Debug prints left in code | `thailint print-statements src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/print-statements-linter/) |
85
+ | **Stringly Typed** | Strings that should be enums | `thailint stringly-typed src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stringly-typed-linter/) |
86
+
87
+ ## Configuration
88
+
89
+ Create `.thailint.yaml` in your project root:
90
+
91
+ ```yaml
92
+ dry:
93
+ enabled: true
94
+ min_duplicate_lines: 4
95
+
96
+ nesting:
97
+ enabled: true
98
+ max_nesting_depth: 3
99
+
100
+ magic-numbers:
101
+ enabled: true
102
+ allowed_numbers: [-1, 0, 1, 2, 10, 100]
103
+ ```
104
+
105
+ Or generate one automatically:
106
+ ```bash
107
+ thailint init-config --preset lenient # or: strict, standard
108
+ ```
109
+
110
+ See [Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/) for all options.
111
+
112
+ ## Output Formats
113
+
114
+ ```bash
115
+ # Human-readable (default)
116
+ thailint dry src/
117
+
118
+ # JSON for CI/CD
119
+ thailint dry --format json src/
120
+
121
+ # SARIF for GitHub Code Scanning
122
+ thailint dry --format sarif src/ > results.sarif
123
+ ```
124
+
125
+ ## Ignoring Violations
126
+
127
+ ```python
128
+ # Line-level
129
+ timeout = 3600 # thailint: ignore[magic-numbers]
130
+
131
+ # File-level
132
+ # thailint: ignore-file[dry]
133
+ ```
134
+
135
+ Or in config:
136
+ ```yaml
137
+ dry:
138
+ ignore:
139
+ - "tests/"
140
+ - "**/generated/**"
141
+ ```
142
+
143
+ See [How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/) for all 5 ignore levels.
144
+
145
+ ## CI/CD Integration
146
+
147
+ ```yaml
148
+ # GitHub Actions
149
+ - name: Run thailint
150
+ run: |
151
+ pip install thai-lint
152
+ thailint dry src/
153
+ thailint nesting src/
154
+ ```
155
+
156
+ Exit codes: `0` = success, `1` = violations found, `2` = error.
157
+
158
+ ## Documentation
159
+
160
+ - **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** - Get running in 5 minutes
161
+ - **[Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/)** - All config options
162
+ - **[Troubleshooting](https://thai-lint.readthedocs.io/en/latest/troubleshooting/)** - Common issues
163
+ - **[Full Documentation](https://thai-lint.readthedocs.io/)** - Everything else
164
+
165
+ ## Contributing
166
+
167
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
168
+
169
+ ```bash
170
+ git clone https://github.com/be-wise-be-kind/thai-lint.git
171
+ cd thai-lint
172
+ poetry install
173
+ just test
174
+ ```
175
+
176
+ ## License
177
+
178
+ MIT License - see [LICENSE](LICENSE) for details.
179
+
180
+ ## Support
181
+
182
+ - **Issues**: [github.com/be-wise-be-kind/thai-lint/issues](https://github.com/be-wise-be-kind/thai-lint/issues)
183
+ - **Docs**: [thai-lint.readthedocs.io](https://thai-lint.readthedocs.io/)
184
+
@@ -0,0 +1,189 @@
1
+ src/__init__.py,sha256=0IT3HnAnSBEfos4G_27cflJiaoWWfeSEfHxsUr53OsM,2192
2
+ src/analyzers/__init__.py,sha256=hCN7ugG_Xs2N_WfWO7ZId-Cv4kvN1AxhIYTA4SD2fJ4,1062
3
+ src/analyzers/ast_utils.py,sha256=iWCRzlTw2QF5wWzQx1OmKshx7TU3pHxC8_omv9XUInw,1630
4
+ src/analyzers/typescript_base.py,sha256=Dtc_2jLSNoadh53MyeW2syrJMBIMVPvotcM8SeDEXH8,5244
5
+ src/api.py,sha256=pJ5l3qxccKBEY-BkANwzTgLAl1ZFq7OP6hx6LSxbhDw,4664
6
+ src/cli/__init__.py,sha256=nMxKv4D0t09LwUm4Z5w-b7vIuyn24SFzv78BKzE3AOQ,1272
7
+ src/cli/__main__.py,sha256=xIKI57yqB1NOw9eXnGXfU8rC2UwcAJYjDxlZbt9eP0w,671
8
+ src/cli/config.py,sha256=qbBX8LQrlPcOrvPYcZw9Hobv9FqSI7T3xy2HUITRqAU,14426
9
+ src/cli/config_merge.py,sha256=A1eCthiLwjj0SEhOcxa6t2hYwWMapGJpL9sCmYvUFw4,8464
10
+ src/cli/linters/__init__.py,sha256=IsNYi7RmSQHN1L65rUuVZpfpRA3YT-M7eZAyBywpOss,2160
11
+ src/cli/linters/code_patterns.py,sha256=JiSQ9AloCZEryx67MARUn-XNvQxHyOfLiHZlGXHC5cs,16135
12
+ src/cli/linters/code_smells.py,sha256=hK7v-k9Fa-vCas702cICRV73xovfyhiITVy29MAErP8,15039
13
+ src/cli/linters/documentation.py,sha256=Ut_mUuHnxidUf9jX-Md-JoCgdqqGj6UzyDxrmusHfJQ,5300
14
+ src/cli/linters/shared.py,sha256=tHOsLF_L-xwf1KE4kVR7oES4IMOj-1ADWRnDhW36QzM,3010
15
+ src/cli/linters/structure.py,sha256=u29jiBxGsga-eqqe5vI-VwptF8eGzLMzOl476mIoDvU,10668
16
+ src/cli/linters/structure_quality.py,sha256=e0fpprTi13WaRVyqpJQYZD6fvslgfTVkIL9lwKOOzDk,10715
17
+ src/cli/main.py,sha256=mRyRN_IQI2WyqDCxI8vuzdhbkCkVrK6INfJPjU8ayIU,3844
18
+ src/cli/utils.py,sha256=L1q2i6NBkWoQZLYnkeNNdfzHYRhaUobbzqSr2w8JUFY,12595
19
+ src/cli_main.py,sha256=C0Ey7YNlG3ipqb3KsJZ8rL8PJ4ueVp_45IUirGidvHI,1618
20
+ src/config.py,sha256=6yQyfvYizffV6GQrnAlL30bKR4iKROPoxoe4al42Pqg,12531
21
+ src/core/__init__.py,sha256=5FtsDvhMt4SNRx3pbcGURrxn135XRbeRrjSUxiXwkNc,381
22
+ src/core/base.py,sha256=u5A8geprlKnsJk4ShiLHTKXRekZUB4I6rPQWxgiFeto,8019
23
+ src/core/cli_utils.py,sha256=ZdFSPrZ4WfpTMh-mc_Z3u5OYidE1YyPRKflMynPosa8,6552
24
+ src/core/config_parser.py,sha256=CRHV2-csxag6yQzx_4IYYz57QSUYjPkeSb0XvOyshRI,4272
25
+ src/core/constants.py,sha256=PKtPDqk6k9VuOSgjq1FAdi2CTvlnhdXvLj91dNaMDTA,1584
26
+ src/core/linter_utils.py,sha256=mMZHJFbLzZU8MDTWcfU0XVLF8vTrg6hO8WTKcjjpKqg,5448
27
+ src/core/registry.py,sha256=yRA8mQLiZwjmgxl1wSTgdj1cuo_QXuRdrXt3NpCBUgE,3285
28
+ src/core/rule_discovery.py,sha256=tgRH-BJGKsQTxfa249yrY7UJuonRjobMCENqmhcbAeY,5496
29
+ src/core/types.py,sha256=SElFzf_VSrAMsoiE0aU8ZYXuvKqdfwfM5umUHx4eT8w,3342
30
+ src/core/violation_builder.py,sha256=dOPFfZx6U5_TMgaTop-4SUV2jHOZjBo67uwgiS_s-uE,6694
31
+ src/core/violation_utils.py,sha256=hSTSfQaaB7038G2Au4vqBLYTnkoaSN3k70IxWacjbl8,1993
32
+ src/formatters/__init__.py,sha256=yE1yIL8lplTMEjsmQm7F-kOMaYq7OjmbFuiwwK0D-gM,815
33
+ src/formatters/sarif.py,sha256=gGOwb_v7j4mx4bpvV1NNDd-JyHH8i8XX89iQ6uRSvG4,7050
34
+ src/linter_config/__init__.py,sha256=_I2VVlZlfKyT-tKukuUA5-aVcHLOe3m6C2cev43AiEc,298
35
+ src/linter_config/directive_markers.py,sha256=nRc2Mp3B1mn6tu1XH88ugMxWffk1k8OUNohepaRQ0S0,3245
36
+ src/linter_config/ignore.py,sha256=lSt_2nGHiGe06Ha1pl2nZTbAVUjwhKtS2b3UHIZuA1I,13089
37
+ src/linter_config/loader.py,sha256=K6mKRkP2jgwar-pwBoJGWgwynLVjqdez-l3Nd6bUCMk,3363
38
+ src/linter_config/pattern_utils.py,sha256=BjV95SySST3HqZBwF1Og8yoHqFxuqQ16VPCacE21ks0,2056
39
+ src/linter_config/rule_matcher.py,sha256=EWqSv4UY90fWps3AzDCSF7PZCbYyFTEBZT2h_txcRms,2779
40
+ src/linters/__init__.py,sha256=-nnNsL8E5-2p9qlLKp_TaShHAjPH-NacOEU1sXmAR9k,77
41
+ src/linters/collection_pipeline/__init__.py,sha256=BcnbY3wgJB1XLfZ9J9qfUJQ1_yCo_THjGDTppxJEMZY,3231
42
+ src/linters/collection_pipeline/any_all_analyzer.py,sha256=u8NGIYrJTuP3U6je5rkeEUV2Bh1yePC12vl-czAU5GU,7554
43
+ src/linters/collection_pipeline/ast_utils.py,sha256=JZsJeel9BzVIOfnENgVcZR8wMNoQ-RJoxuBx-J7w9Uk,1227
44
+ src/linters/collection_pipeline/config.py,sha256=EDlPcYEsECfAhZu9h1z5MVszRdr9Okdp3Ea8bf8c2mI,2782
45
+ src/linters/collection_pipeline/continue_analyzer.py,sha256=Azn7-2MLpi0M68dXDLgXCbIBpCT1i3GSUGE13U2Tl4U,2728
46
+ src/linters/collection_pipeline/detector.py,sha256=7_keKR5lGo5rvOVCAvV_6-bG29I_SYAhkkxP6ES3wKg,11696
47
+ src/linters/collection_pipeline/filter_map_analyzer.py,sha256=QbTjObryaLVB71MD4b4SyoOMEO_EgMNedNZLVm05QCQ,11829
48
+ src/linters/collection_pipeline/linter.py,sha256=53pkC1a6mvNTzjK_LDV_JmMysbZBLUsM_NjavvAZZBQ,13552
49
+ src/linters/collection_pipeline/suggestion_builder.py,sha256=4-RHBw95u7gPKpoN1xZlpSOkqzXY7_TRrB_otUXsdDE,4357
50
+ src/linters/dry/__init__.py,sha256=p58tN3z_VbulfTkRm1kLZJ43Bemt66T2sro1teirUY8,826
51
+ src/linters/dry/base_token_analyzer.py,sha256=hkR3MI6UYwQ7PNJiyGiIPiX7uMrDRHr0mzI-aG8wVCM,3199
52
+ src/linters/dry/block_filter.py,sha256=3RgmRSqYFk2eqATLOWN3hET09JuaPEFux3ResA0ltqo,11432
53
+ src/linters/dry/block_grouper.py,sha256=NP66BlofaY7HVXcWwmK5lyiNXbaTlU1V3IbcZubIq_I,1937
54
+ src/linters/dry/cache.py,sha256=909Va6bsq_DREooZGE1VDisefN_QqfPTL1ZKPi7k7Bk,8911
55
+ src/linters/dry/cache_query.py,sha256=qu_uHe360ZvKmFTBvfREjjPMGbJgLQsFTKPVIA2jQJ0,1949
56
+ src/linters/dry/config.py,sha256=3l1Ly3JbeYLvBbpyBsti2hGAKvxDShZ6d4uc8FEMB0I,7283
57
+ src/linters/dry/config_loader.py,sha256=wikqnigOp6p1h9jaAATV_3bDXSiaIUFaf9xg1jQMDpo,1313
58
+ src/linters/dry/constant.py,sha256=n9cNwa-1GQPISGZ3dgGcpLv7tc-uy56ravHiFsIwoRk,3249
59
+ src/linters/dry/constant_matcher.py,sha256=GcfCRKNvUchandcqM8lz54BpEpSkdxr4K2Vb1aTAlcc,8074
60
+ src/linters/dry/constant_violation_builder.py,sha256=F88aLlgscWmyUeIr_EgF4CeheXEc6Iv2pBG2eKJTmts,4048
61
+ src/linters/dry/deduplicator.py,sha256=a1TRvldxCszf5QByo1ihXF3W98dpGuyaRT74jPfQftM,3988
62
+ src/linters/dry/duplicate_storage.py,sha256=9pIALnwAuz5BJUYNXrPbObbP932CE9x0vgUkICryT_s,1970
63
+ src/linters/dry/file_analyzer.py,sha256=3uO2fy8HvxFiRCtYaBs9LztkzvDynqmy7INYRaJjK-g,2990
64
+ src/linters/dry/inline_ignore.py,sha256=3fgPsn_kXeF7kVy_9FL8xYwSUA9cSmgUR3F0tOwzjuY,4275
65
+ src/linters/dry/linter.py,sha256=-8MiprIs2MsAj2fAmg-hCbasDVBkLLgMP9BR2_ZcDv0,9304
66
+ src/linters/dry/python_analyzer.py,sha256=b7n7u3NbOW3DFZHeC-bG3N_6VgW2NU2easG8pIHYaZc,10962
67
+ src/linters/dry/python_constant_extractor.py,sha256=v9-3NDCq9CKT6uvti_PRIC3DMEESHW2g3i2IfFy0hw8,3469
68
+ src/linters/dry/single_statement_detector.py,sha256=ZmMo_tsvVxugFmnNzWtGc-4e5sGOw18HHxHre3lRUUA,18220
69
+ src/linters/dry/storage_initializer.py,sha256=ykMALFs4uMUrN0_skEwySDl_t5Dm_LGHllF0OxDhiUI,1366
70
+ src/linters/dry/token_hasher.py,sha256=RoUXByVHwf9TZjRqXB3aI1htNZS0pX41oOsUxvlsF00,4951
71
+ src/linters/dry/typescript_analyzer.py,sha256=xGUcQO8MvJnAVgn5GZRwQAc5xZsD0T-qOQlFuJcvfZM,10777
72
+ src/linters/dry/typescript_constant_extractor.py,sha256=ri5NivpcxLAxwdMJvbeTF4Vu0WS_Fgf7FydQGoVNgm0,5130
73
+ src/linters/dry/typescript_statement_detector.py,sha256=8WiwcjLs8j8_wp0UTsoXN0vVr1mNa562O1CB-FtaQR4,8848
74
+ src/linters/dry/typescript_value_extractor.py,sha256=Wi6Yy0yklQSDpeA6FRCsquXILHD8RjRFKJI5Nsg3f70,2506
75
+ src/linters/dry/violation_builder.py,sha256=WkCibSNytoqMHGC-3GrVff4PD7-SOnVzzZgkMeqmzco,2952
76
+ src/linters/dry/violation_filter.py,sha256=2e6NHN7GYadt27Pz5kiXhttKPJu1loiXhOi0G3J3Epk,3211
77
+ src/linters/dry/violation_generator.py,sha256=7jkRfauwAEdipFuDhoy82eIeXS1ECN4W_3jspMlnFaU,6068
78
+ src/linters/file_header/__init__.py,sha256=S3a2xrOlxnNWD02To5K2ZwILsNEvSj1IvUAH8RjgOV4,791
79
+ src/linters/file_header/atemporal_detector.py,sha256=H6QJ5hCOtfCBEKPMGiPqhBdYR5Y9uWhoHMnhW3N9mKk,3353
80
+ src/linters/file_header/base_parser.py,sha256=k6ymg1ocuesA6PH7NMDQOy0LTgSglu0wXed68fPaHxM,3382
81
+ src/linters/file_header/bash_parser.py,sha256=aRlIbR6x8IeYAj8w6a3eQzdZZivHB0oPg843CTnQm-Y,2481
82
+ src/linters/file_header/config.py,sha256=Ewrln4W4QDnInTgWr8WgSlQEjAuDyMbUuh9GHAa9a4c,4030
83
+ src/linters/file_header/css_parser.py,sha256=ijpGMixg2ZqNWWdiZjSNtMXCOhm6XDfSY7OU68B9fS8,2332
84
+ src/linters/file_header/field_validator.py,sha256=owA-ahjx0cUWBIqCxT0dMyGTABQA0b8HbdWbZPQk7pw,2769
85
+ src/linters/file_header/linter.py,sha256=9XFk9H-0QtXvMBgHfVM5PcI1igDcE8ylLARr0547XZ4,12532
86
+ src/linters/file_header/markdown_parser.py,sha256=4rNYrxuZbJz4LoSmv0U741Cv7wP9jftTl0Ty7mBDHRI,5323
87
+ src/linters/file_header/python_parser.py,sha256=RTOeEt1b3tCvFWbZIt89awQA37CUOSBIGagEYnayn-M,1432
88
+ src/linters/file_header/typescript_parser.py,sha256=R11Vkr6dUVaU8t90m8rrkMzODtBYk7u-TYFsMDRwzX8,2532
89
+ src/linters/file_header/violation_builder.py,sha256=HPYTmrcCmcO6Dx5dhmj85zZgEBM5EZqTgql-0CA0A0k,2745
90
+ src/linters/file_placement/__init__.py,sha256=vJ43GZujcbAk-K3DwfsQZ0J3yP_5G35CKssatLyntXk,862
91
+ src/linters/file_placement/config_loader.py,sha256=tLBeP9njYmtD0FNQsKkywMQJWrZaDBl7z_5sqVLzndc,2690
92
+ src/linters/file_placement/directory_matcher.py,sha256=1rxJtCEzqDYDQnscVX6pzk7gxCMD11pVIGaWcli-tHY,2742
93
+ src/linters/file_placement/linter.py,sha256=8mKCs20iEyUs3GaguHSHvMYdXJhXkoPTOfACM3kAFLs,15310
94
+ src/linters/file_placement/path_resolver.py,sha256=S6g7xOYsoSc0O_RDJh8j4Z2klcwzp16rSUfEAErGOTI,1972
95
+ src/linters/file_placement/pattern_matcher.py,sha256=56PCVL_4ajpTCnebHNUZKMJyAWeUOUHkeEwd4o3ofXQ,3183
96
+ src/linters/file_placement/pattern_validator.py,sha256=kg96qbN62kL0cTMncIFsoofiEJl64jWW4-0eK9_mD98,4247
97
+ src/linters/file_placement/rule_checker.py,sha256=OIN8v6uwn6nFiKBKCs2IRgczNt8e5ZyxCvYgkH2KB9Q,7846
98
+ src/linters/file_placement/violation_factory.py,sha256=NkQmBcgpa3g3W2ZdFZNQ5djLVP4x9OKs65d7F1rCKvM,6040
99
+ src/linters/lazy_ignores/__init__.py,sha256=qPwCC1Y-TPn6tNLTO4X6QsACaAiPMBpsIKlKh_dSz5k,1656
100
+ src/linters/lazy_ignores/config.py,sha256=ZM1W9L_pJtirmafGuwiKJyD29dAQIoiNOEMMXnyMATA,2464
101
+ src/linters/lazy_ignores/directive_utils.py,sha256=6Mc56hrcFe21LG7PMmIVEPDGKUF6F9dffhHkwixj1R8,3432
102
+ src/linters/lazy_ignores/header_parser.py,sha256=ADtVJUoJfoVx_zehoPpo6YLws0N-7c2PLK1PhNqn5Uk,6030
103
+ src/linters/lazy_ignores/linter.py,sha256=1bl3b2NliVurlb9bUcZUzd8sBZG6KJhRODD-Mb46HnE,6052
104
+ src/linters/lazy_ignores/matcher.py,sha256=jLE12aPPEz6tBejFrmXGXdCb7kzeFh8IYH5b_UjHqpQ,5201
105
+ src/linters/lazy_ignores/python_analyzer.py,sha256=jccO9P539xRm4GB3-exge4oijkfvOLyXkWe8wSygciA,7064
106
+ src/linters/lazy_ignores/rule_id_utils.py,sha256=sE7kAQFO6zGAR5JQN2OLLVjAdiVNPZONTb0sY01ri9w,5809
107
+ src/linters/lazy_ignores/skip_detector.py,sha256=9RK5uD4b2pAfdJsK1dHRTAWG4kKfAf1yfjc1OBsI14M,10461
108
+ src/linters/lazy_ignores/types.py,sha256=1fsWUlNNutjfd0MzmAh7PsmkVDT4R9KPvlbHOL8QmeM,2136
109
+ src/linters/lazy_ignores/typescript_analyzer.py,sha256=k8R60Mcw9OxvHFFUPhUErrb-tbek7Q7PXXZDq_H0ioM,5322
110
+ src/linters/lazy_ignores/violation_builder.py,sha256=Z5RlCRJKkTfetkRVqsu1rfJRgBeiE9RTEu1djr-nmto,4203
111
+ src/linters/lbyl/__init__.py,sha256=rV7NcrP32ku1jp9kABWuvrstJNk4vfoH2IjWEwuwfos,1069
112
+ src/linters/lbyl/config.py,sha256=kWCjBRs1HEVf9oK4dHKHfjQX8KU-o5i-Jc_94ULDD4Y,2434
113
+ src/linters/lbyl/pattern_detectors/__init__.py,sha256=HXxpEmEiVD2K-IhDZ2qbR1mGfaxzOUj9Y3NFGSqcn_w,763
114
+ src/linters/lbyl/pattern_detectors/base.py,sha256=4LZYORaYFK0aj4xs4035hegj7cXJtaao0M95kM1QYTk,1272
115
+ src/linters/magic_numbers/__init__.py,sha256=17dkCUf0uiYLvpOZF01VDojj92NzxXZMtRhrSBUzsdc,1689
116
+ src/linters/magic_numbers/config.py,sha256=3zV6ZNezouBWUYy4kMw5PUlPNvIWXVwOxTz1moZfRoI,3270
117
+ src/linters/magic_numbers/context_analyzer.py,sha256=EgDyxxjvEqyD3FX0Fnxj5RcOPyvyVs_rYFxj2HOxYdg,7309
118
+ src/linters/magic_numbers/linter.py,sha256=CGo_35ujoCbNXbb0XI4KGCm5C9PCe_LzvXrgmvYN-I4,16736
119
+ src/linters/magic_numbers/python_analyzer.py,sha256=Ba-EODvAkUIOhqMFv86MxMlXqF20ngvgubiWN_U_IUk,2446
120
+ src/linters/magic_numbers/typescript_analyzer.py,sha256=-2YPmNWXHJN8R2siV3pJk_3Baj-A9nnvQRpU35YBKgs,7519
121
+ src/linters/magic_numbers/typescript_ignore_checker.py,sha256=9JWqtXd8KU_GCc_66KSZT2X7uQhNGpxE2ikOyjcLyao,2847
122
+ src/linters/magic_numbers/violation_builder.py,sha256=SqIQv3N9lpP2GRC1TC5InrvaEdrAq24V7Ec2Xj5olb0,3308
123
+ src/linters/method_property/__init__.py,sha256=t0C6zD5WLm-McgmvVajQJg4HQfOi7_4YzNLhKNA484w,1415
124
+ src/linters/method_property/config.py,sha256=6gTluzhwIT7eLhVRoPHihGlnLx_H7yY9SW5xpMU6o-w,5553
125
+ src/linters/method_property/linter.py,sha256=gnSmtobSwVxa1wd43az9qGIXpppG2_ENjmDgPZgI1Vg,12844
126
+ src/linters/method_property/python_analyzer.py,sha256=uyNUJHxACw01Z1Uz6lRUPe753MpzUOYuQ999rRt5ocE,15386
127
+ src/linters/method_property/violation_builder.py,sha256=A7SwZWlVG_7W5pJiHOvIroI2q4UuOQNryOYvmX3APLs,4251
128
+ src/linters/nesting/__init__.py,sha256=tszmyCEQMpEwB5H84WcAUfRYDQl7jpsn04es5DtAHsM,3200
129
+ src/linters/nesting/config.py,sha256=PfPA2wJn3i6HHXeM0qu6Qx-v1KJdRwlRkFOdpf7NhS8,2405
130
+ src/linters/nesting/linter.py,sha256=3uO9lbLQbTvjLaKRjYWi9GaNlmQmHcbwD3YmXH8DfXE,6431
131
+ src/linters/nesting/python_analyzer.py,sha256=__fs_NE9xA4NM1MDOHBGdrI0zICkTcgbVZtfT03cxF0,3230
132
+ src/linters/nesting/typescript_analyzer.py,sha256=70TsjP3EJWiHJ1ncMaveFE0e9_HdukWZr9LM0_MDXr8,3639
133
+ src/linters/nesting/typescript_function_extractor.py,sha256=dDB1otJnFMCo-Pj4mTr4gekKe7V4ArOAtX6gV0dBDc4,4494
134
+ src/linters/nesting/violation_builder.py,sha256=sMHS45F2lrA1WYrG3Uug8HfeRPljnXcyJPHSe2F76Bs,4828
135
+ src/linters/print_statements/__init__.py,sha256=yhvdTFSqBB4UDreeadTHKFzhayxeT6JkF3yxUHMgn1g,1893
136
+ src/linters/print_statements/config.py,sha256=rth3XmzqZGzXkRXDIVZswdtNOXIe1vIRaF46tVLKnyQ,3041
137
+ src/linters/print_statements/linter.py,sha256=CcKolaaHYJzhpxWXthYZ7xXhfTnxmyOIhuE40Ly3ofA,14351
138
+ src/linters/print_statements/python_analyzer.py,sha256=48IDRQEv861B90qCl5w8ASxcXR7juZ429YX2ST9n2ic,5028
139
+ src/linters/print_statements/typescript_analyzer.py,sha256=EFE3bjRENvCPEYmNNxZ4jiq1VCA-rEUAJ_VFWJApLqY,4935
140
+ src/linters/print_statements/violation_builder.py,sha256=Vs5m3AnWjrQqQHf6JJDaPP5B1V3YNl5pepG_oiTJnx4,3333
141
+ src/linters/srp/__init__.py,sha256=GbhaSB2_AYY-mWgG_ThbyAcDXoVZuB5eLzguoShf38w,3367
142
+ src/linters/srp/class_analyzer.py,sha256=tZ6xAT0Y7LkzeVlGHckQRhFdnssuetUYxTQdUHwBoCo,4045
143
+ src/linters/srp/config.py,sha256=hTxrM21HIOmg0sM6eJ_h3hRnuxqRZEgs13Ie97-PDr4,3397
144
+ src/linters/srp/heuristics.py,sha256=u2TTQS25hkVGcsFyJPFvmSqs-GpjL9ojsuVAUIgnSP0,3222
145
+ src/linters/srp/linter.py,sha256=ut6k8QDb4P2CXHl5Jnem0eFBN2lxcvsRyGnnQqMZL8w,7660
146
+ src/linters/srp/metrics_evaluator.py,sha256=Prk_dPacas_dX7spAzV0g734srmzT5u0t5d4mTG9g2o,1606
147
+ src/linters/srp/python_analyzer.py,sha256=PH27l38BFPNmj22Z10QDBioLDCZ4xpJFzBfTh_4XMZ4,3585
148
+ src/linters/srp/typescript_analyzer.py,sha256=Wi0P_G1v5AnZYtMN3sNm1iHva84-8Kep2LZ5RmAS4c4,2885
149
+ src/linters/srp/typescript_metrics_calculator.py,sha256=0RyHTWzBJbLUT3BqFuNc1wJVoS5nNI1Ph-tF_cp4EEI,3499
150
+ src/linters/srp/violation_builder.py,sha256=jaIjVtRYWUTs1SVJVwd0FxCojo0DxhPzfhyfMKmAroM,3881
151
+ src/linters/stateless_class/__init__.py,sha256=8ePpinmCD27PCz7ukwUWcNwo-ZgyvhOquns-U51MyiQ,1063
152
+ src/linters/stateless_class/config.py,sha256=u8Jt_xygIkuxZx2o0Uw_XFatOh11QhC9aN8lB_vfnLk,1993
153
+ src/linters/stateless_class/linter.py,sha256=Rm3fZfkyUOYeBodcLPUcMNKUHPuc5NgKOeDioGXyu_M,11338
154
+ src/linters/stateless_class/python_analyzer.py,sha256=psEx2pG-eZJfK9ViX4YaNCLFEXEqUoViA3rc32o_sVQ,7623
155
+ src/linters/stringly_typed/__init__.py,sha256=6r4IIykZ6mm551KQpRTSDp418EFqJQbuzjSfLHcwyBc,1511
156
+ src/linters/stringly_typed/config.py,sha256=-M7fwwr9axQsQcGtowVINC9Bh1cS1b2-KPxFb2GtL3M,7500
157
+ src/linters/stringly_typed/context_filter.py,sha256=JohTFvXiHKfVzUowRbsDrY37QngJDmhFfoxyoTzKriY,11422
158
+ src/linters/stringly_typed/function_call_violation_builder.py,sha256=RiuzeKmUzb6Fzdc4j8lXl4V-jf-0xae-5t7YcIaKTMY,4234
159
+ src/linters/stringly_typed/ignore_checker.py,sha256=sFV9NzsIhUWZe59h2X9JJv8yE3PWQLWAbhOG7Sl1Cs8,3438
160
+ src/linters/stringly_typed/ignore_utils.py,sha256=hw0wfnGFJQkysr1qi_vmykZPr02SNBElwVHFu55tB6M,1531
161
+ src/linters/stringly_typed/linter.py,sha256=mKokag3XCQl4QuhT25sekuiX2bMERDUdq9SNxqBpNCw,13440
162
+ src/linters/stringly_typed/python/__init__.py,sha256=y1ELj3We0_VeA0ygXd1DxudSWrZE5OhLGtZNkKwuomA,1359
163
+ src/linters/stringly_typed/python/analyzer.py,sha256=HAhSAMIXMr4FoSKE9ovrWuB0f3Zjp9Py3AoruArmaOU,12247
164
+ src/linters/stringly_typed/python/call_tracker.py,sha256=Re_BgUQQhWNTg9jM6XsyyqYxmeVhoqVJXPe2ITcNhhA,6046
165
+ src/linters/stringly_typed/python/comparison_tracker.py,sha256=MAYQF-IKYaJLV4DYwbAPz8E2fWFBoSMTxhCwnGFP5Jw,8384
166
+ src/linters/stringly_typed/python/condition_extractor.py,sha256=_Y-lSqmqfUYbJjmSjOcQDetCNwWvW6bAAdyHjRSVAek,4222
167
+ src/linters/stringly_typed/python/conditional_detector.py,sha256=js1wTcXwLOrHVAJY9dq0xqXVZVNXh5FSFQNvIZ4SUtg,6006
168
+ src/linters/stringly_typed/python/constants.py,sha256=IF3Y2W96hihHlr5HMenq5Q93uOo7KHzNazVVvhq3E58,671
169
+ src/linters/stringly_typed/python/match_analyzer.py,sha256=mgarAtnL79iOrK6xuiRE2Hw-9tR8ocrIRza6g0SorY8,2719
170
+ src/linters/stringly_typed/python/validation_detector.py,sha256=jzcowBcA7R_aKeXFf2sxI2yGGUoT1lGj1y7DTnmO88M,6288
171
+ src/linters/stringly_typed/python/variable_extractor.py,sha256=yYJQ5jTSMz94SD_0IMfCHMWcw1F57GmRuh9h51oiAEs,2769
172
+ src/linters/stringly_typed/storage.py,sha256=UoaY3Ejpb4k-7it15d_wzZFcEJNjWTClMJhkY6wkc9A,22021
173
+ src/linters/stringly_typed/storage_initializer.py,sha256=3-4St1ieN8325Xkb0HTS27dVyjjluM_X-bkwOfJW1JM,1548
174
+ src/linters/stringly_typed/typescript/__init__.py,sha256=lOgclS9wxLNyszfwVGbVxKfCkbTLX1pvskHzcADi5Xg,1121
175
+ src/linters/stringly_typed/typescript/analyzer.py,sha256=iNEk6wQJJfmJoRTXx29GEeqTpKzQ5TcNIimSuQPb6UU,6376
176
+ src/linters/stringly_typed/typescript/call_tracker.py,sha256=NPRpjqTe-Owi3_qJk_baojAazqaL6EsH4E2SIOsUAjU,11299
177
+ src/linters/stringly_typed/typescript/comparison_tracker.py,sha256=TiEldIqppu6i2XYd9a040HK0U4cy7IFf6Qjjlb93wAA,12573
178
+ src/linters/stringly_typed/violation_generator.py,sha256=aye60bShNnt8f6BPQwduTOLX97jAuy7Z7DLq9wzrFB4,14769
179
+ src/orchestrator/__init__.py,sha256=XXLDJq2oaB-TpP2Y97GRnde9EkITGuFCmuLrDfxI9nY,245
180
+ src/orchestrator/core.py,sha256=rt3h-YFgF1aAFeKvTa0PP7k_8zfwpeGIqrIxKuyckxY,17683
181
+ src/orchestrator/language_detector.py,sha256=rHyVMApit80NTTNyDH1ObD1usKD8LjGmH3DwqNAWYGc,2736
182
+ src/templates/thailint_config_template.yaml,sha256=ikW2cMaRiD-GLpsgaEKPUli3T8cuB5BPxjGcyan6eDo,11005
183
+ src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
184
+ src/utils/project_root.py,sha256=aaxUM-LQ1okrPClmZWPFd_D09W3V1ArgJiidEEp_eU8,6262
185
+ thailint-0.13.0.dist-info/METADATA,sha256=n8xyN_x-1fEfh6_AOCNvPUieDz_MWflnc01f__j7QTs,6815
186
+ thailint-0.13.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
187
+ thailint-0.13.0.dist-info/entry_points.txt,sha256=DNoGUlxpaMFqxQDgHp1yeGqohOjdFR-kH19uHYi3OUY,72
188
+ thailint-0.13.0.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
189
+ thailint-0.13.0.dist-info/RECORD,,