thailint 0.1.3__tar.gz → 0.14.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. {thailint-0.1.3 → thailint-0.14.0}/CHANGELOG.md +223 -2
  2. thailint-0.14.0/PKG-INFO +185 -0
  3. thailint-0.14.0/README.md +149 -0
  4. {thailint-0.1.3 → thailint-0.14.0}/pyproject.toml +16 -5
  5. {thailint-0.1.3 → thailint-0.14.0}/src/__init__.py +8 -2
  6. thailint-0.14.0/src/analyzers/__init__.py +24 -0
  7. thailint-0.14.0/src/analyzers/ast_utils.py +54 -0
  8. thailint-0.14.0/src/analyzers/typescript_base.py +152 -0
  9. {thailint-0.1.3 → thailint-0.14.0}/src/api.py +1 -1
  10. thailint-0.14.0/src/cli/__init__.py +30 -0
  11. thailint-0.14.0/src/cli/__main__.py +22 -0
  12. thailint-0.14.0/src/cli/config.py +478 -0
  13. thailint-0.14.0/src/cli/config_merge.py +241 -0
  14. thailint-0.14.0/src/cli/linters/__init__.py +67 -0
  15. thailint-0.14.0/src/cli/linters/code_patterns.py +222 -0
  16. thailint-0.14.0/src/cli/linters/code_smells.py +333 -0
  17. thailint-0.14.0/src/cli/linters/documentation.py +81 -0
  18. thailint-0.14.0/src/cli/linters/performance.py +274 -0
  19. thailint-0.14.0/src/cli/linters/shared.py +315 -0
  20. thailint-0.14.0/src/cli/linters/structure.py +318 -0
  21. thailint-0.14.0/src/cli/linters/structure_quality.py +323 -0
  22. thailint-0.14.0/src/cli/main.py +120 -0
  23. thailint-0.14.0/src/cli/utils.py +395 -0
  24. thailint-0.14.0/src/cli_main.py +37 -0
  25. {thailint-0.1.3 → thailint-0.14.0}/src/config.py +16 -37
  26. thailint-0.14.0/src/core/base.py +224 -0
  27. thailint-0.14.0/src/core/cli_utils.py +223 -0
  28. thailint-0.14.0/src/core/config_parser.py +129 -0
  29. thailint-0.14.0/src/core/constants.py +54 -0
  30. thailint-0.14.0/src/core/linter_utils.py +257 -0
  31. thailint-0.14.0/src/core/registry.py +95 -0
  32. thailint-0.14.0/src/core/rule_discovery.py +195 -0
  33. {thailint-0.1.3 → thailint-0.14.0}/src/core/types.py +13 -0
  34. thailint-0.14.0/src/core/violation_builder.py +185 -0
  35. thailint-0.14.0/src/core/violation_utils.py +69 -0
  36. thailint-0.14.0/src/formatters/__init__.py +22 -0
  37. thailint-0.14.0/src/formatters/sarif.py +202 -0
  38. thailint-0.14.0/src/linter_config/directive_markers.py +109 -0
  39. thailint-0.14.0/src/linter_config/ignore.py +333 -0
  40. {thailint-0.1.3 → thailint-0.14.0}/src/linter_config/loader.py +47 -24
  41. thailint-0.14.0/src/linter_config/pattern_utils.py +65 -0
  42. thailint-0.14.0/src/linter_config/rule_matcher.py +89 -0
  43. thailint-0.14.0/src/linters/collection_pipeline/__init__.py +90 -0
  44. thailint-0.14.0/src/linters/collection_pipeline/any_all_analyzer.py +281 -0
  45. thailint-0.14.0/src/linters/collection_pipeline/ast_utils.py +40 -0
  46. thailint-0.14.0/src/linters/collection_pipeline/config.py +75 -0
  47. thailint-0.14.0/src/linters/collection_pipeline/continue_analyzer.py +94 -0
  48. thailint-0.14.0/src/linters/collection_pipeline/detector.py +360 -0
  49. thailint-0.14.0/src/linters/collection_pipeline/filter_map_analyzer.py +402 -0
  50. thailint-0.14.0/src/linters/collection_pipeline/linter.py +420 -0
  51. thailint-0.14.0/src/linters/collection_pipeline/suggestion_builder.py +130 -0
  52. thailint-0.14.0/src/linters/dry/__init__.py +23 -0
  53. thailint-0.14.0/src/linters/dry/base_token_analyzer.py +83 -0
  54. thailint-0.14.0/src/linters/dry/block_filter.py +365 -0
  55. thailint-0.14.0/src/linters/dry/block_grouper.py +63 -0
  56. thailint-0.14.0/src/linters/dry/cache.py +266 -0
  57. thailint-0.14.0/src/linters/dry/cache_query.py +65 -0
  58. thailint-0.14.0/src/linters/dry/config.py +177 -0
  59. thailint-0.14.0/src/linters/dry/config_loader.py +44 -0
  60. thailint-0.14.0/src/linters/dry/constant.py +92 -0
  61. thailint-0.14.0/src/linters/dry/constant_matcher.py +223 -0
  62. thailint-0.14.0/src/linters/dry/constant_violation_builder.py +98 -0
  63. thailint-0.14.0/src/linters/dry/deduplicator.py +120 -0
  64. thailint-0.14.0/src/linters/dry/duplicate_storage.py +64 -0
  65. thailint-0.14.0/src/linters/dry/file_analyzer.py +92 -0
  66. thailint-0.14.0/src/linters/dry/inline_ignore.py +131 -0
  67. thailint-0.14.0/src/linters/dry/linter.py +227 -0
  68. thailint-0.14.0/src/linters/dry/python_analyzer.py +289 -0
  69. thailint-0.14.0/src/linters/dry/python_constant_extractor.py +100 -0
  70. thailint-0.14.0/src/linters/dry/single_statement_detector.py +417 -0
  71. thailint-0.14.0/src/linters/dry/storage_initializer.py +42 -0
  72. thailint-0.14.0/src/linters/dry/token_hasher.py +173 -0
  73. thailint-0.14.0/src/linters/dry/typescript_analyzer.py +278 -0
  74. thailint-0.14.0/src/linters/dry/typescript_constant_extractor.py +138 -0
  75. thailint-0.14.0/src/linters/dry/typescript_statement_detector.py +255 -0
  76. thailint-0.14.0/src/linters/dry/typescript_value_extractor.py +69 -0
  77. thailint-0.14.0/src/linters/dry/violation_builder.py +78 -0
  78. thailint-0.14.0/src/linters/dry/violation_filter.py +95 -0
  79. thailint-0.14.0/src/linters/dry/violation_generator.py +171 -0
  80. thailint-0.14.0/src/linters/file_header/__init__.py +24 -0
  81. thailint-0.14.0/src/linters/file_header/atemporal_detector.py +105 -0
  82. thailint-0.14.0/src/linters/file_header/base_parser.py +93 -0
  83. thailint-0.14.0/src/linters/file_header/bash_parser.py +66 -0
  84. thailint-0.14.0/src/linters/file_header/config.py +140 -0
  85. thailint-0.14.0/src/linters/file_header/css_parser.py +70 -0
  86. thailint-0.14.0/src/linters/file_header/field_validator.py +72 -0
  87. thailint-0.14.0/src/linters/file_header/linter.py +308 -0
  88. thailint-0.14.0/src/linters/file_header/markdown_parser.py +130 -0
  89. thailint-0.14.0/src/linters/file_header/python_parser.py +42 -0
  90. thailint-0.14.0/src/linters/file_header/typescript_parser.py +73 -0
  91. thailint-0.14.0/src/linters/file_header/violation_builder.py +79 -0
  92. thailint-0.14.0/src/linters/file_placement/config_loader.py +88 -0
  93. thailint-0.14.0/src/linters/file_placement/directory_matcher.py +84 -0
  94. thailint-0.14.0/src/linters/file_placement/linter.py +444 -0
  95. thailint-0.14.0/src/linters/file_placement/path_resolver.py +61 -0
  96. thailint-0.14.0/src/linters/file_placement/pattern_matcher.py +90 -0
  97. thailint-0.14.0/src/linters/file_placement/pattern_validator.py +124 -0
  98. thailint-0.14.0/src/linters/file_placement/rule_checker.py +229 -0
  99. thailint-0.14.0/src/linters/file_placement/violation_factory.py +177 -0
  100. thailint-0.14.0/src/linters/lazy_ignores/__init__.py +43 -0
  101. thailint-0.14.0/src/linters/lazy_ignores/config.py +66 -0
  102. thailint-0.14.0/src/linters/lazy_ignores/directive_utils.py +121 -0
  103. thailint-0.14.0/src/linters/lazy_ignores/header_parser.py +177 -0
  104. thailint-0.14.0/src/linters/lazy_ignores/linter.py +158 -0
  105. thailint-0.14.0/src/linters/lazy_ignores/matcher.py +135 -0
  106. thailint-0.14.0/src/linters/lazy_ignores/python_analyzer.py +205 -0
  107. thailint-0.14.0/src/linters/lazy_ignores/rule_id_utils.py +180 -0
  108. thailint-0.14.0/src/linters/lazy_ignores/skip_detector.py +298 -0
  109. thailint-0.14.0/src/linters/lazy_ignores/types.py +69 -0
  110. thailint-0.14.0/src/linters/lazy_ignores/typescript_analyzer.py +146 -0
  111. thailint-0.14.0/src/linters/lazy_ignores/violation_builder.py +131 -0
  112. thailint-0.14.0/src/linters/lbyl/__init__.py +29 -0
  113. thailint-0.14.0/src/linters/lbyl/config.py +63 -0
  114. thailint-0.14.0/src/linters/lbyl/pattern_detectors/__init__.py +25 -0
  115. thailint-0.14.0/src/linters/lbyl/pattern_detectors/base.py +46 -0
  116. thailint-0.14.0/src/linters/magic_numbers/__init__.py +48 -0
  117. thailint-0.14.0/src/linters/magic_numbers/config.py +82 -0
  118. thailint-0.14.0/src/linters/magic_numbers/context_analyzer.py +249 -0
  119. thailint-0.14.0/src/linters/magic_numbers/linter.py +462 -0
  120. thailint-0.14.0/src/linters/magic_numbers/python_analyzer.py +64 -0
  121. thailint-0.14.0/src/linters/magic_numbers/typescript_analyzer.py +215 -0
  122. thailint-0.14.0/src/linters/magic_numbers/typescript_ignore_checker.py +81 -0
  123. thailint-0.14.0/src/linters/magic_numbers/violation_builder.py +98 -0
  124. thailint-0.14.0/src/linters/method_property/__init__.py +49 -0
  125. thailint-0.14.0/src/linters/method_property/config.py +138 -0
  126. thailint-0.14.0/src/linters/method_property/linter.py +414 -0
  127. thailint-0.14.0/src/linters/method_property/python_analyzer.py +473 -0
  128. thailint-0.14.0/src/linters/method_property/violation_builder.py +119 -0
  129. {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/__init__.py +6 -2
  130. {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/config.py +17 -4
  131. thailint-0.14.0/src/linters/nesting/linter.py +178 -0
  132. {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/python_analyzer.py +4 -0
  133. thailint-0.14.0/src/linters/nesting/typescript_analyzer.py +111 -0
  134. thailint-0.14.0/src/linters/nesting/typescript_function_extractor.py +130 -0
  135. thailint-0.14.0/src/linters/nesting/violation_builder.py +140 -0
  136. thailint-0.14.0/src/linters/performance/__init__.py +91 -0
  137. thailint-0.14.0/src/linters/performance/config.py +43 -0
  138. thailint-0.14.0/src/linters/performance/constants.py +49 -0
  139. thailint-0.14.0/src/linters/performance/linter.py +149 -0
  140. thailint-0.14.0/src/linters/performance/python_analyzer.py +365 -0
  141. thailint-0.14.0/src/linters/performance/regex_analyzer.py +312 -0
  142. thailint-0.14.0/src/linters/performance/regex_linter.py +139 -0
  143. thailint-0.14.0/src/linters/performance/typescript_analyzer.py +236 -0
  144. thailint-0.14.0/src/linters/performance/violation_builder.py +160 -0
  145. thailint-0.14.0/src/linters/print_statements/__init__.py +53 -0
  146. thailint-0.14.0/src/linters/print_statements/config.py +78 -0
  147. thailint-0.14.0/src/linters/print_statements/linter.py +413 -0
  148. thailint-0.14.0/src/linters/print_statements/python_analyzer.py +153 -0
  149. thailint-0.14.0/src/linters/print_statements/typescript_analyzer.py +125 -0
  150. thailint-0.14.0/src/linters/print_statements/violation_builder.py +96 -0
  151. thailint-0.14.0/src/linters/srp/__init__.py +99 -0
  152. thailint-0.14.0/src/linters/srp/class_analyzer.py +117 -0
  153. thailint-0.14.0/src/linters/srp/config.py +82 -0
  154. thailint-0.14.0/src/linters/srp/heuristics.py +90 -0
  155. thailint-0.14.0/src/linters/srp/linter.py +233 -0
  156. thailint-0.14.0/src/linters/srp/metrics_evaluator.py +47 -0
  157. thailint-0.14.0/src/linters/srp/python_analyzer.py +107 -0
  158. thailint-0.14.0/src/linters/srp/typescript_analyzer.py +75 -0
  159. thailint-0.14.0/src/linters/srp/typescript_metrics_calculator.py +126 -0
  160. thailint-0.14.0/src/linters/srp/violation_builder.py +117 -0
  161. thailint-0.14.0/src/linters/stateless_class/__init__.py +25 -0
  162. thailint-0.14.0/src/linters/stateless_class/config.py +58 -0
  163. thailint-0.14.0/src/linters/stateless_class/linter.py +349 -0
  164. thailint-0.14.0/src/linters/stateless_class/python_analyzer.py +290 -0
  165. thailint-0.14.0/src/linters/stringly_typed/__init__.py +36 -0
  166. thailint-0.14.0/src/linters/stringly_typed/config.py +189 -0
  167. thailint-0.14.0/src/linters/stringly_typed/context_filter.py +451 -0
  168. thailint-0.14.0/src/linters/stringly_typed/function_call_violation_builder.py +135 -0
  169. thailint-0.14.0/src/linters/stringly_typed/ignore_checker.py +102 -0
  170. thailint-0.14.0/src/linters/stringly_typed/ignore_utils.py +51 -0
  171. thailint-0.14.0/src/linters/stringly_typed/linter.py +376 -0
  172. thailint-0.14.0/src/linters/stringly_typed/python/__init__.py +33 -0
  173. thailint-0.14.0/src/linters/stringly_typed/python/analyzer.py +348 -0
  174. thailint-0.14.0/src/linters/stringly_typed/python/call_tracker.py +175 -0
  175. thailint-0.14.0/src/linters/stringly_typed/python/comparison_tracker.py +257 -0
  176. thailint-0.14.0/src/linters/stringly_typed/python/condition_extractor.py +134 -0
  177. thailint-0.14.0/src/linters/stringly_typed/python/conditional_detector.py +179 -0
  178. thailint-0.14.0/src/linters/stringly_typed/python/constants.py +21 -0
  179. thailint-0.14.0/src/linters/stringly_typed/python/match_analyzer.py +94 -0
  180. thailint-0.14.0/src/linters/stringly_typed/python/validation_detector.py +189 -0
  181. thailint-0.14.0/src/linters/stringly_typed/python/variable_extractor.py +96 -0
  182. thailint-0.14.0/src/linters/stringly_typed/storage.py +630 -0
  183. thailint-0.14.0/src/linters/stringly_typed/storage_initializer.py +45 -0
  184. thailint-0.14.0/src/linters/stringly_typed/typescript/__init__.py +28 -0
  185. thailint-0.14.0/src/linters/stringly_typed/typescript/analyzer.py +157 -0
  186. thailint-0.14.0/src/linters/stringly_typed/typescript/call_tracker.py +335 -0
  187. thailint-0.14.0/src/linters/stringly_typed/typescript/comparison_tracker.py +378 -0
  188. thailint-0.14.0/src/linters/stringly_typed/violation_generator.py +405 -0
  189. thailint-0.14.0/src/orchestrator/core.py +471 -0
  190. thailint-0.14.0/src/templates/thailint_config_template.yaml +354 -0
  191. thailint-0.14.0/src/utils/__init__.py +4 -0
  192. thailint-0.14.0/src/utils/project_root.py +206 -0
  193. thailint-0.1.3/PKG-INFO +0 -629
  194. thailint-0.1.3/README.md +0 -596
  195. thailint-0.1.3/src/.ai/layout.yaml +0 -48
  196. thailint-0.1.3/src/cli.py +0 -698
  197. thailint-0.1.3/src/core/base.py +0 -122
  198. thailint-0.1.3/src/core/registry.py +0 -170
  199. thailint-0.1.3/src/linter_config/ignore.py +0 -403
  200. thailint-0.1.3/src/linters/file_placement/linter.py +0 -621
  201. thailint-0.1.3/src/linters/nesting/linter.py +0 -257
  202. thailint-0.1.3/src/linters/nesting/typescript_analyzer.py +0 -180
  203. thailint-0.1.3/src/orchestrator/core.py +0 -188
  204. {thailint-0.1.3 → thailint-0.14.0}/LICENSE +0 -0
  205. {thailint-0.1.3 → thailint-0.14.0}/src/core/__init__.py +0 -0
  206. {thailint-0.1.3 → thailint-0.14.0}/src/linter_config/__init__.py +0 -0
  207. {thailint-0.1.3 → thailint-0.14.0}/src/linters/__init__.py +0 -0
  208. {thailint-0.1.3 → thailint-0.14.0}/src/linters/file_placement/__init__.py +0 -0
  209. {thailint-0.1.3 → thailint-0.14.0}/src/orchestrator/__init__.py +0 -0
  210. {thailint-0.1.3 → thailint-0.14.0}/src/orchestrator/language_detector.py +0 -0
@@ -24,6 +24,227 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
24
 
25
25
  ## [Unreleased]
26
26
 
27
+ ### Added
28
+
29
+ - **Stateless Class Linter** - Detect Python classes without state that should be module-level functions
30
+ - AST-based detection of classes without `__init__`/`__new__` constructors
31
+ - Detects classes without instance state (`self.attr` assignments)
32
+ - Excludes ABC, Protocol, and decorated classes (legitimate patterns)
33
+ - Excludes classes with class-level attributes
34
+ - Minimum 2 methods required to flag (avoids false positives on simple wrappers)
35
+ - CLI command: `thailint stateless-class src/`
36
+ - JSON and SARIF output formats
37
+ - Configuration via `.thailint.yaml` with `min_methods` and `ignore` options
38
+ - Self-dogfooded: 23 violations in thai-lint codebase were fixed
39
+ - 28 tests (15 detector + 13 CLI) with 100% pass rate
40
+ - Documentation: `docs/stateless-class-linter.md`
41
+
42
+ - **Project Root Detection System** - Three-level precedence system for accurate configuration and ignore pattern resolution
43
+ - `--project-root` CLI option for explicit project root specification (highest priority)
44
+ - Automatic project root inference from `--config` path (config's parent directory becomes project root)
45
+ - Auto-detection fallback that walks up from file location to find markers (`.git`, `.thailint.yaml`, `pyproject.toml`)
46
+ - Priority order: `--project-root` > config inference > auto-detection
47
+ - Click path validation (exists, is directory) with helpful error messages
48
+ - All paths resolved to absolute paths immediately for consistency
49
+
50
+ - **Docker Sibling Directory Support** - Solves critical Docker use case where config and code are in separate directories
51
+ - Explicit project root specification: `docker run -v $(pwd):/workspace thailint --project-root /workspace/root magic-numbers /workspace/backend/`
52
+ - Automatic config path inference: `docker run -v $(pwd):/workspace thailint --config /workspace/root/.thailint.yaml magic-numbers /workspace/backend/`
53
+ - Monorepo support with shared configuration across multiple projects
54
+ - CI/CD-friendly with explicit paths preventing auto-detection issues
55
+
56
+ - **Enhanced Configuration System**
57
+ - Config loading now respects project root context
58
+ - Ignore patterns resolve relative to project root (not file location)
59
+ - Config search paths: explicit `--config` > project-root/.thailint.yaml > auto-detected locations
60
+ - Pyprojroot fallback for test environment compatibility
61
+
62
+ - **Test Suite**
63
+ - 42 tests for project root detection (29 new + 13 updated, 100% passing)
64
+ - `tests/unit/test_cli_project_root.py` - Explicit `--project-root` tests (15 tests)
65
+ - `tests/unit/test_cli_config_inference.py` - Config path inference tests (14 tests)
66
+ - Priority order tests verifying explicit > inferred > auto-detection
67
+ - Error handling tests for invalid paths (doesn't exist, is file not directory)
68
+ - Integration tests with real directory structures
69
+
70
+ ### Changed
71
+
72
+ - **CLI Commands** - All linter commands now accept `--project-root` option
73
+ - `thailint magic-numbers --project-root PATH [TARGET]`
74
+ - `thailint nesting --project-root PATH [TARGET]`
75
+ - `thailint srp --project-root PATH [TARGET]`
76
+ - `thailint file-placement --project-root PATH [TARGET]`
77
+ - All commands support combined usage: `--project-root` with `--config`
78
+
79
+ - **Orchestrator Initialization** - Now accepts explicit project root parameter
80
+ - `Orchestrator(project_root=Path, config_path=Path)` signature
81
+ - Project root passed from CLI to orchestrator for all linting operations
82
+ - Config loading uses project root context for path resolution
83
+
84
+ - **Path Resolution** - All ignore patterns resolve relative to project root
85
+ - Previous behavior: patterns resolved relative to file being linted
86
+ - New behavior: patterns resolved relative to project root directory
87
+ - More predictable and consistent ignore pattern matching
88
+ - Better Docker compatibility with volume mounts
89
+
90
+ ### Documentation
91
+
92
+ - **README.md** - Added comprehensive Docker sibling directory examples
93
+ - "Docker with Sibling Directories" section (lines 171-207)
94
+ - "Docker with Sibling Directories (Advanced)" section (lines 1071-1107)
95
+ - Directory structure examples and use cases
96
+ - Priority order explanation with multiple solution approaches
97
+
98
+ - **CLI Reference** (docs/cli-reference.md)
99
+ - Complete `--project-root` option documentation (lines 120-170)
100
+ - Enhanced `--config` section explaining automatic project root inference (lines 92-118)
101
+ - Use case examples: Docker, monorepos, CI/CD, ignore patterns
102
+ - Error handling examples and exit codes
103
+ - Priority order documentation
104
+
105
+ - **Troubleshooting Guide** (docs/troubleshooting.md)
106
+ - New "Docker sibling directory structure not working" section (lines 754-856)
107
+ - Problem symptoms and root cause explanation
108
+ - Three solution approaches ranked by recommendation
109
+ - Debugging steps with test commands
110
+ - Cross-references to related documentation
111
+
112
+ - **Technical Architecture** (.ai/docs/python-cli-architecture.md)
113
+ - New "Project Root Detection" component documentation (section 2)
114
+ - Architecture diagram updated with project root detection layer
115
+ - Design decisions and implementation patterns
116
+ - Testing strategy and related components
117
+ - Docker use case examples and configuration integration
118
+
119
+ ### Fixed
120
+
121
+ - **Docker Sibling Directory Issue** - Config and code can now be in separate, non-nested directories
122
+ - Previous: Only worked when code was nested under config directory
123
+ - Fixed: Works with any directory structure using `--project-root` or config inference
124
+ - Ignore patterns now resolve correctly in Docker volume mount scenarios
125
+
126
+ - **Ignore Pattern Resolution** - Patterns now resolve consistently relative to project root
127
+ - Previous: Resolved relative to file being linted (inconsistent behavior)
128
+ - Fixed: Resolved relative to project root (predictable, consistent)
129
+ - Especially important for Docker and monorepo scenarios
130
+
131
+ - **Test Environment Compatibility** - Added pyprojroot fallback for pytest environments
132
+ - Tests can run in isolated temporary directories
133
+ - Auto-detection gracefully handles test scenarios without project markers
134
+ - No impact on production code behavior
135
+
136
+ ### Infrastructure
137
+
138
+ - Test suite execution time: All tests pass in <120ms (optimized for fast feedback)
139
+ - TDD approach: RED tests → GREEN implementation → Documentation
140
+ - Pre-commit hooks validated for all changes
141
+ - Zero regressions in existing functionality (13 existing tests updated, all passing)
142
+
143
+ ## [0.2.1] - 2025-10-09
144
+
145
+ **Docker Path Validation Fix** - Fixes critical Docker image bug where file-specific linting failed due to premature path validation.
146
+
147
+ ### Fixed
148
+
149
+ - **Docker Path Validation** - Removed Click's `exists=True` parameter that validated paths before Docker volumes were mounted
150
+ - All linter commands now work with file paths in Docker: `docker run -v $(pwd):/data thailint nesting /data/file.py`
151
+ - Better error messages when paths don't exist, with Docker usage hints
152
+ - Manual path validation happens after argument parsing, compatible with both CLI and Docker contexts
153
+
154
+ ### Changed
155
+
156
+ - Path validation moved from Click argument parsing to execution functions
157
+ - Added `_validate_paths_exist()` helper function with user-friendly error messages
158
+
159
+ ## [0.3.0] - TBD
160
+
161
+ **Single Responsibility Principle (SRP) Linter Release** - Adds comprehensive SRP violation detection for Python and TypeScript code. Uses heuristic-based analysis with configurable thresholds for method count, lines of code, and responsibility keywords. Includes language-specific configurations and extensive refactoring pattern documentation.
162
+
163
+ ### Added
164
+
165
+ - **SRP Linter** - Complete Single Responsibility Principle violation detection
166
+ - Heuristic-based analysis using method count, LOC, and keyword detection
167
+ - Configurable thresholds: `max_methods` (default: 7), `max_loc` (default: 200)
168
+ - Language-specific thresholds for Python, TypeScript, and JavaScript
169
+ - Responsibility keyword detection (Manager, Handler, Processor, Utility, Helper)
170
+ - AST-based analysis using Python `ast` module and `tree-sitter-typescript`
171
+ - Helpful violation messages with refactoring suggestions
172
+
173
+ - **CLI Command: `thailint srp`**
174
+ - `thailint srp [PATH]` - Check files for SRP violations
175
+ - `--max-methods N` - Override method count threshold
176
+ - `--max-loc N` - Override lines of code threshold
177
+ - `--config PATH` - Use specific config file
178
+ - `--format json/text` - Output format selection
179
+ - `--help` - Comprehensive command documentation
180
+
181
+ - **Library API**
182
+ - `srp_lint(path, config)` - Convenience function
183
+ - `SRPRule` - Direct rule class for advanced usage
184
+ - `from src import srp_lint, SRPRule` - Exported in package
185
+
186
+ - **Comprehensive Documentation**
187
+ - `docs/srp-linter.md` - Complete SRP linter guide
188
+ - Configuration examples and best practices
189
+ - 4 refactoring patterns with before/after code examples
190
+ - CI/CD integration examples (GitHub Actions, pre-commit hooks)
191
+ - Troubleshooting guide and common issues
192
+ - Real-world refactoring examples
193
+
194
+ - **Language-Specific Configuration**
195
+ - Python: More strict thresholds (8 methods, 200 LOC)
196
+ - TypeScript: More lenient thresholds (10 methods, 250 LOC) for type verbosity
197
+ - JavaScript: Balanced thresholds (10 methods, 225 LOC)
198
+ - Configurable keyword list for responsibility detection
199
+
200
+ - **Test Suite**
201
+ - 91 tests for SRP linter (100% passing)
202
+ - Python SRP tests (20 tests)
203
+ - TypeScript SRP tests (20 tests)
204
+ - Configuration tests (10 tests)
205
+ - Integration tests (13 tests)
206
+ - Edge case tests (10 tests)
207
+ - Violation message tests (8 tests)
208
+ - Ignore directive tests (10 tests)
209
+
210
+ - **Refactoring Patterns Documentation**
211
+ - Extract Class pattern (split god classes into focused classes)
212
+ - Split Configuration/Logic pattern (separate concerns)
213
+ - Extract Language-Specific Logic pattern (per-language analyzers)
214
+ - Utility Module pattern (group related helpers)
215
+
216
+ ### Changed
217
+
218
+ - **Code Quality Improvements**
219
+ - Refactored 6 classes with SRP violations
220
+ - Applied Extract Class pattern to large classes
221
+ - Improved modularity and maintainability
222
+ - Zero SRP violations in codebase
223
+
224
+ - **README Updates**
225
+ - Added comprehensive SRP linter section with examples
226
+ - Updated feature list with SRP capabilities
227
+ - Added refactoring patterns and examples
228
+
229
+ ### Fixed
230
+
231
+ - Language-specific configuration loading for SRP thresholds
232
+ - Config priority: language-specific → top-level → built-in defaults
233
+
234
+ ### Documentation
235
+
236
+ - Complete SRP linter guide (`docs/srp-linter.md`)
237
+ - Updated CLI reference with SRP command
238
+ - Configuration examples for SRP rules
239
+ - 4 refactoring patterns with code examples
240
+ - Real-world refactoring case studies
241
+
242
+ ### Infrastructure
243
+
244
+ - Updated Makefile with `just lint-solid` target
245
+ - Integrated SRP checks into quality gates
246
+ - CI/CD ready (proper exit codes and JSON output)
247
+
27
248
  ## [0.2.0] - 2025-10-07
28
249
 
29
250
  **Nesting Depth Linter Release** - Adds comprehensive nesting depth analysis for Python and TypeScript code. Includes AST-based analysis with tree-sitter, configurable depth limits, and extensive refactoring patterns. Validated on the thai-lint codebase (zero violations after refactoring 23 functions).
@@ -143,8 +364,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
143
364
 
144
365
  ### Infrastructure
145
366
 
146
- - Updated Makefile with `make lint-nesting` target
147
- - Integrated nesting checks into `make lint-full`
367
+ - Updated Makefile with `just lint-nesting` target
368
+ - Integrated nesting checks into `just lint-full`
148
369
  - CI/CD ready (proper exit codes and JSON output)
149
370
 
150
371
  ## [0.1.0] - 2025-10-06
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.4
2
+ Name: thailint
3
+ Version: 0.14.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,performance,typescript
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
+ | **Performance** | O(n²) patterns: string += in loops, regex in loops | `thailint perf src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/performance-linter/) |
78
+ | **SRP** | Classes doing too much | `thailint srp src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/srp-linter/) |
79
+ | **File Header** | Missing documentation headers | `thailint file-header src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/) |
80
+ | **Stateless Class** | Classes that should be functions | `thailint stateless-class src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/) |
81
+ | **Collection Pipeline** | Loops with embedded filtering | `thailint pipeline src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/collection-pipeline-linter/) |
82
+ | **Method Property** | Methods that should be @property | `thailint method-property src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/method-property-linter/) |
83
+ | **File Placement** | Files in wrong directories | `thailint file-placement src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/) |
84
+ | **Lazy Ignores** | Unjustified linting suppressions | `thailint lazy-ignores src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lazy-ignores-linter/) |
85
+ | **Print Statements** | Debug prints left in code | `thailint print-statements src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/print-statements-linter/) |
86
+ | **Stringly Typed** | Strings that should be enums | `thailint stringly-typed src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stringly-typed-linter/) |
87
+
88
+ ## Configuration
89
+
90
+ Create `.thailint.yaml` in your project root:
91
+
92
+ ```yaml
93
+ dry:
94
+ enabled: true
95
+ min_duplicate_lines: 4
96
+
97
+ nesting:
98
+ enabled: true
99
+ max_nesting_depth: 3
100
+
101
+ magic-numbers:
102
+ enabled: true
103
+ allowed_numbers: [-1, 0, 1, 2, 10, 100]
104
+ ```
105
+
106
+ Or generate one automatically:
107
+ ```bash
108
+ thailint init-config --preset lenient # or: strict, standard
109
+ ```
110
+
111
+ See [Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/) for all options.
112
+
113
+ ## Output Formats
114
+
115
+ ```bash
116
+ # Human-readable (default)
117
+ thailint dry src/
118
+
119
+ # JSON for CI/CD
120
+ thailint dry --format json src/
121
+
122
+ # SARIF for GitHub Code Scanning
123
+ thailint dry --format sarif src/ > results.sarif
124
+ ```
125
+
126
+ ## Ignoring Violations
127
+
128
+ ```python
129
+ # Line-level
130
+ timeout = 3600 # thailint: ignore[magic-numbers]
131
+
132
+ # File-level
133
+ # thailint: ignore-file[dry]
134
+ ```
135
+
136
+ Or in config:
137
+ ```yaml
138
+ dry:
139
+ ignore:
140
+ - "tests/"
141
+ - "**/generated/**"
142
+ ```
143
+
144
+ See [How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/) for all 5 ignore levels.
145
+
146
+ ## CI/CD Integration
147
+
148
+ ```yaml
149
+ # GitHub Actions
150
+ - name: Run thailint
151
+ run: |
152
+ pip install thai-lint
153
+ thailint dry src/
154
+ thailint nesting src/
155
+ ```
156
+
157
+ Exit codes: `0` = success, `1` = violations found, `2` = error.
158
+
159
+ ## Documentation
160
+
161
+ - **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** - Get running in 5 minutes
162
+ - **[Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/)** - All config options
163
+ - **[Troubleshooting](https://thai-lint.readthedocs.io/en/latest/troubleshooting/)** - Common issues
164
+ - **[Full Documentation](https://thai-lint.readthedocs.io/)** - Everything else
165
+
166
+ ## Contributing
167
+
168
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
169
+
170
+ ```bash
171
+ git clone https://github.com/be-wise-be-kind/thai-lint.git
172
+ cd thai-lint
173
+ poetry install
174
+ just test
175
+ ```
176
+
177
+ ## License
178
+
179
+ MIT License - see [LICENSE](LICENSE) for details.
180
+
181
+ ## Support
182
+
183
+ - **Issues**: [github.com/be-wise-be-kind/thai-lint/issues](https://github.com/be-wise-be-kind/thai-lint/issues)
184
+ - **Docs**: [thai-lint.readthedocs.io](https://thai-lint.readthedocs.io/)
185
+
@@ -0,0 +1,149 @@
1
+ # thai-lint
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
5
+ [![PyPI](https://img.shields.io/pypi/v/thai-lint)](https://pypi.org/project/thai-lint/)
6
+ [![Documentation](https://readthedocs.org/projects/thai-lint/badge/?version=latest)](https://thai-lint.readthedocs.io/)
7
+
8
+ **The AI Linter** - Catch the mistakes AI coding assistants keep making.
9
+
10
+ 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.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install thai-lint
16
+ ```
17
+
18
+ Or with Docker:
19
+ ```bash
20
+ docker run --rm -v $(pwd):/data washad/thailint:latest --help
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ # Generate a config file (optional)
27
+ thailint init-config
28
+
29
+ # Run any linter
30
+ thailint dry src/
31
+ ```
32
+
33
+ That's it. See violations, fix them, ship better code.
34
+
35
+ ## Available Linters
36
+
37
+ | Linter | What It Catches | Command | Docs |
38
+ |--------|-----------------|---------|------|
39
+ | **DRY** | Duplicate code across files | `thailint dry src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/dry-linter/) |
40
+ | **Nesting** | Deeply nested if/for/while blocks | `thailint nesting src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/nesting-linter/) |
41
+ | **Magic Numbers** | Unnamed numeric literals | `thailint magic-numbers src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/) |
42
+ | **Performance** | O(n²) patterns: string += in loops, regex in loops | `thailint perf src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/performance-linter/) |
43
+ | **SRP** | Classes doing too much | `thailint srp src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/srp-linter/) |
44
+ | **File Header** | Missing documentation headers | `thailint file-header src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/) |
45
+ | **Stateless Class** | Classes that should be functions | `thailint stateless-class src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/) |
46
+ | **Collection Pipeline** | Loops with embedded filtering | `thailint pipeline src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/collection-pipeline-linter/) |
47
+ | **Method Property** | Methods that should be @property | `thailint method-property src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/method-property-linter/) |
48
+ | **File Placement** | Files in wrong directories | `thailint file-placement src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/) |
49
+ | **Lazy Ignores** | Unjustified linting suppressions | `thailint lazy-ignores src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lazy-ignores-linter/) |
50
+ | **Print Statements** | Debug prints left in code | `thailint print-statements src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/print-statements-linter/) |
51
+ | **Stringly Typed** | Strings that should be enums | `thailint stringly-typed src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stringly-typed-linter/) |
52
+
53
+ ## Configuration
54
+
55
+ Create `.thailint.yaml` in your project root:
56
+
57
+ ```yaml
58
+ dry:
59
+ enabled: true
60
+ min_duplicate_lines: 4
61
+
62
+ nesting:
63
+ enabled: true
64
+ max_nesting_depth: 3
65
+
66
+ magic-numbers:
67
+ enabled: true
68
+ allowed_numbers: [-1, 0, 1, 2, 10, 100]
69
+ ```
70
+
71
+ Or generate one automatically:
72
+ ```bash
73
+ thailint init-config --preset lenient # or: strict, standard
74
+ ```
75
+
76
+ See [Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/) for all options.
77
+
78
+ ## Output Formats
79
+
80
+ ```bash
81
+ # Human-readable (default)
82
+ thailint dry src/
83
+
84
+ # JSON for CI/CD
85
+ thailint dry --format json src/
86
+
87
+ # SARIF for GitHub Code Scanning
88
+ thailint dry --format sarif src/ > results.sarif
89
+ ```
90
+
91
+ ## Ignoring Violations
92
+
93
+ ```python
94
+ # Line-level
95
+ timeout = 3600 # thailint: ignore[magic-numbers]
96
+
97
+ # File-level
98
+ # thailint: ignore-file[dry]
99
+ ```
100
+
101
+ Or in config:
102
+ ```yaml
103
+ dry:
104
+ ignore:
105
+ - "tests/"
106
+ - "**/generated/**"
107
+ ```
108
+
109
+ See [How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/) for all 5 ignore levels.
110
+
111
+ ## CI/CD Integration
112
+
113
+ ```yaml
114
+ # GitHub Actions
115
+ - name: Run thailint
116
+ run: |
117
+ pip install thai-lint
118
+ thailint dry src/
119
+ thailint nesting src/
120
+ ```
121
+
122
+ Exit codes: `0` = success, `1` = violations found, `2` = error.
123
+
124
+ ## Documentation
125
+
126
+ - **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** - Get running in 5 minutes
127
+ - **[Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/)** - All config options
128
+ - **[Troubleshooting](https://thai-lint.readthedocs.io/en/latest/troubleshooting/)** - Common issues
129
+ - **[Full Documentation](https://thai-lint.readthedocs.io/)** - Everything else
130
+
131
+ ## Contributing
132
+
133
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
134
+
135
+ ```bash
136
+ git clone https://github.com/be-wise-be-kind/thai-lint.git
137
+ cd thai-lint
138
+ poetry install
139
+ just test
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT License - see [LICENSE](LICENSE) for details.
145
+
146
+ ## Support
147
+
148
+ - **Issues**: [github.com/be-wise-be-kind/thai-lint/issues](https://github.com/be-wise-be-kind/thai-lint/issues)
149
+ - **Docs**: [thai-lint.readthedocs.io](https://thai-lint.readthedocs.io/)
@@ -17,14 +17,14 @@ build-backend = "poetry.core.masonry.api"
17
17
 
18
18
  [tool.poetry]
19
19
  name = "thailint"
20
- version = "0.1.3"
20
+ version = "0.14.0"
21
21
  description = "The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages"
22
22
  authors = ["Steve Jackson"]
23
23
  license = "MIT"
24
24
  readme = "README.md"
25
25
  homepage = "https://github.com/be-wise-be-kind/thai-lint"
26
26
  repository = "https://github.com/be-wise-be-kind/thai-lint"
27
- documentation = "https://github.com/be-wise-be-kind/thai-lint#readme"
27
+ documentation = "https://thai-lint.readthedocs.io/"
28
28
  keywords = [
29
29
  "linter",
30
30
  "ai",
@@ -36,9 +36,11 @@ keywords = [
36
36
  "cli",
37
37
  "docker",
38
38
  "python",
39
+ "performance",
40
+ "typescript",
39
41
  ]
40
42
  classifiers = [
41
- "Development Status :: 3 - Alpha",
43
+ "Development Status :: 4 - Beta",
42
44
  "Intended Audience :: Developers",
43
45
  "License :: OSI Approved :: MIT License",
44
46
  "Programming Language :: Python :: 3",
@@ -73,6 +75,7 @@ click = "^8.1.0"
73
75
  pyyaml = "^6.0"
74
76
  tree-sitter = "^0.25.2"
75
77
  tree-sitter-typescript = "^0.23.2"
78
+ pyprojroot = "^0.3.0"
76
79
 
77
80
  [tool.poetry.group.dev.dependencies]
78
81
  # Core testing and linting
@@ -99,10 +102,12 @@ xenon = "^0.9.3"
99
102
  # Comprehensive security
100
103
  safety = "^3.2.11"
101
104
  pip-audit = "^2.8.0"
105
+ loguru = "^0.7.3"
106
+ pytest-xdist = "^3.8.0"
102
107
 
103
108
  [tool.poetry.scripts]
104
- thailint = "src.cli:cli"
105
- thai-lint = "src.cli:cli"
109
+ thailint = "src.cli_main:cli"
110
+ thai-lint = "src.cli_main:cli"
106
111
 
107
112
  # Ruff configuration
108
113
  [tool.ruff]
@@ -151,6 +156,7 @@ omit = [
151
156
  "tests/*",
152
157
  "*/__init__.py",
153
158
  ]
159
+ dynamic_context = "test_function"
154
160
 
155
161
  [tool.coverage.report]
156
162
  exclude_lines = [
@@ -162,6 +168,9 @@ exclude_lines = [
162
168
  "if TYPE_CHECKING:",
163
169
  ]
164
170
 
171
+ [tool.coverage.html]
172
+ show_contexts = true
173
+
165
174
  # mypy configuration
166
175
  [tool.mypy]
167
176
  python_version = "3.11"
@@ -203,6 +212,7 @@ disallow_incomplete_defs = false
203
212
  # Pylint configuration
204
213
  [tool.pylint.messages_control]
205
214
  disable = [
215
+ "duplicate-code",
206
216
  "C0111", # missing-docstring (handled by flake8-docstrings)
207
217
  "R0903", # too-few-public-methods (often fine for CLIs)
208
218
  "R0912", # too-many-branches (validation methods intentionally have many branches)
@@ -220,6 +230,7 @@ disable = [
220
230
 
221
231
  [tool.pylint.format]
222
232
  max-line-length = 120
233
+ max-module-lines = 500
223
234
 
224
235
  # Flake8 configuration (in .flake8 file, not pyproject.toml)
225
236
  # Note: Flake8 doesn't support pyproject.toml natively