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.
- {thailint-0.1.3 → thailint-0.14.0}/CHANGELOG.md +223 -2
- thailint-0.14.0/PKG-INFO +185 -0
- thailint-0.14.0/README.md +149 -0
- {thailint-0.1.3 → thailint-0.14.0}/pyproject.toml +16 -5
- {thailint-0.1.3 → thailint-0.14.0}/src/__init__.py +8 -2
- thailint-0.14.0/src/analyzers/__init__.py +24 -0
- thailint-0.14.0/src/analyzers/ast_utils.py +54 -0
- thailint-0.14.0/src/analyzers/typescript_base.py +152 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/api.py +1 -1
- thailint-0.14.0/src/cli/__init__.py +30 -0
- thailint-0.14.0/src/cli/__main__.py +22 -0
- thailint-0.14.0/src/cli/config.py +478 -0
- thailint-0.14.0/src/cli/config_merge.py +241 -0
- thailint-0.14.0/src/cli/linters/__init__.py +67 -0
- thailint-0.14.0/src/cli/linters/code_patterns.py +222 -0
- thailint-0.14.0/src/cli/linters/code_smells.py +333 -0
- thailint-0.14.0/src/cli/linters/documentation.py +81 -0
- thailint-0.14.0/src/cli/linters/performance.py +274 -0
- thailint-0.14.0/src/cli/linters/shared.py +315 -0
- thailint-0.14.0/src/cli/linters/structure.py +318 -0
- thailint-0.14.0/src/cli/linters/structure_quality.py +323 -0
- thailint-0.14.0/src/cli/main.py +120 -0
- thailint-0.14.0/src/cli/utils.py +395 -0
- thailint-0.14.0/src/cli_main.py +37 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/config.py +16 -37
- thailint-0.14.0/src/core/base.py +224 -0
- thailint-0.14.0/src/core/cli_utils.py +223 -0
- thailint-0.14.0/src/core/config_parser.py +129 -0
- thailint-0.14.0/src/core/constants.py +54 -0
- thailint-0.14.0/src/core/linter_utils.py +257 -0
- thailint-0.14.0/src/core/registry.py +95 -0
- thailint-0.14.0/src/core/rule_discovery.py +195 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/core/types.py +13 -0
- thailint-0.14.0/src/core/violation_builder.py +185 -0
- thailint-0.14.0/src/core/violation_utils.py +69 -0
- thailint-0.14.0/src/formatters/__init__.py +22 -0
- thailint-0.14.0/src/formatters/sarif.py +202 -0
- thailint-0.14.0/src/linter_config/directive_markers.py +109 -0
- thailint-0.14.0/src/linter_config/ignore.py +333 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linter_config/loader.py +47 -24
- thailint-0.14.0/src/linter_config/pattern_utils.py +65 -0
- thailint-0.14.0/src/linter_config/rule_matcher.py +89 -0
- thailint-0.14.0/src/linters/collection_pipeline/__init__.py +90 -0
- thailint-0.14.0/src/linters/collection_pipeline/any_all_analyzer.py +281 -0
- thailint-0.14.0/src/linters/collection_pipeline/ast_utils.py +40 -0
- thailint-0.14.0/src/linters/collection_pipeline/config.py +75 -0
- thailint-0.14.0/src/linters/collection_pipeline/continue_analyzer.py +94 -0
- thailint-0.14.0/src/linters/collection_pipeline/detector.py +360 -0
- thailint-0.14.0/src/linters/collection_pipeline/filter_map_analyzer.py +402 -0
- thailint-0.14.0/src/linters/collection_pipeline/linter.py +420 -0
- thailint-0.14.0/src/linters/collection_pipeline/suggestion_builder.py +130 -0
- thailint-0.14.0/src/linters/dry/__init__.py +23 -0
- thailint-0.14.0/src/linters/dry/base_token_analyzer.py +83 -0
- thailint-0.14.0/src/linters/dry/block_filter.py +365 -0
- thailint-0.14.0/src/linters/dry/block_grouper.py +63 -0
- thailint-0.14.0/src/linters/dry/cache.py +266 -0
- thailint-0.14.0/src/linters/dry/cache_query.py +65 -0
- thailint-0.14.0/src/linters/dry/config.py +177 -0
- thailint-0.14.0/src/linters/dry/config_loader.py +44 -0
- thailint-0.14.0/src/linters/dry/constant.py +92 -0
- thailint-0.14.0/src/linters/dry/constant_matcher.py +223 -0
- thailint-0.14.0/src/linters/dry/constant_violation_builder.py +98 -0
- thailint-0.14.0/src/linters/dry/deduplicator.py +120 -0
- thailint-0.14.0/src/linters/dry/duplicate_storage.py +64 -0
- thailint-0.14.0/src/linters/dry/file_analyzer.py +92 -0
- thailint-0.14.0/src/linters/dry/inline_ignore.py +131 -0
- thailint-0.14.0/src/linters/dry/linter.py +227 -0
- thailint-0.14.0/src/linters/dry/python_analyzer.py +289 -0
- thailint-0.14.0/src/linters/dry/python_constant_extractor.py +100 -0
- thailint-0.14.0/src/linters/dry/single_statement_detector.py +417 -0
- thailint-0.14.0/src/linters/dry/storage_initializer.py +42 -0
- thailint-0.14.0/src/linters/dry/token_hasher.py +173 -0
- thailint-0.14.0/src/linters/dry/typescript_analyzer.py +278 -0
- thailint-0.14.0/src/linters/dry/typescript_constant_extractor.py +138 -0
- thailint-0.14.0/src/linters/dry/typescript_statement_detector.py +255 -0
- thailint-0.14.0/src/linters/dry/typescript_value_extractor.py +69 -0
- thailint-0.14.0/src/linters/dry/violation_builder.py +78 -0
- thailint-0.14.0/src/linters/dry/violation_filter.py +95 -0
- thailint-0.14.0/src/linters/dry/violation_generator.py +171 -0
- thailint-0.14.0/src/linters/file_header/__init__.py +24 -0
- thailint-0.14.0/src/linters/file_header/atemporal_detector.py +105 -0
- thailint-0.14.0/src/linters/file_header/base_parser.py +93 -0
- thailint-0.14.0/src/linters/file_header/bash_parser.py +66 -0
- thailint-0.14.0/src/linters/file_header/config.py +140 -0
- thailint-0.14.0/src/linters/file_header/css_parser.py +70 -0
- thailint-0.14.0/src/linters/file_header/field_validator.py +72 -0
- thailint-0.14.0/src/linters/file_header/linter.py +308 -0
- thailint-0.14.0/src/linters/file_header/markdown_parser.py +130 -0
- thailint-0.14.0/src/linters/file_header/python_parser.py +42 -0
- thailint-0.14.0/src/linters/file_header/typescript_parser.py +73 -0
- thailint-0.14.0/src/linters/file_header/violation_builder.py +79 -0
- thailint-0.14.0/src/linters/file_placement/config_loader.py +88 -0
- thailint-0.14.0/src/linters/file_placement/directory_matcher.py +84 -0
- thailint-0.14.0/src/linters/file_placement/linter.py +444 -0
- thailint-0.14.0/src/linters/file_placement/path_resolver.py +61 -0
- thailint-0.14.0/src/linters/file_placement/pattern_matcher.py +90 -0
- thailint-0.14.0/src/linters/file_placement/pattern_validator.py +124 -0
- thailint-0.14.0/src/linters/file_placement/rule_checker.py +229 -0
- thailint-0.14.0/src/linters/file_placement/violation_factory.py +177 -0
- thailint-0.14.0/src/linters/lazy_ignores/__init__.py +43 -0
- thailint-0.14.0/src/linters/lazy_ignores/config.py +66 -0
- thailint-0.14.0/src/linters/lazy_ignores/directive_utils.py +121 -0
- thailint-0.14.0/src/linters/lazy_ignores/header_parser.py +177 -0
- thailint-0.14.0/src/linters/lazy_ignores/linter.py +158 -0
- thailint-0.14.0/src/linters/lazy_ignores/matcher.py +135 -0
- thailint-0.14.0/src/linters/lazy_ignores/python_analyzer.py +205 -0
- thailint-0.14.0/src/linters/lazy_ignores/rule_id_utils.py +180 -0
- thailint-0.14.0/src/linters/lazy_ignores/skip_detector.py +298 -0
- thailint-0.14.0/src/linters/lazy_ignores/types.py +69 -0
- thailint-0.14.0/src/linters/lazy_ignores/typescript_analyzer.py +146 -0
- thailint-0.14.0/src/linters/lazy_ignores/violation_builder.py +131 -0
- thailint-0.14.0/src/linters/lbyl/__init__.py +29 -0
- thailint-0.14.0/src/linters/lbyl/config.py +63 -0
- thailint-0.14.0/src/linters/lbyl/pattern_detectors/__init__.py +25 -0
- thailint-0.14.0/src/linters/lbyl/pattern_detectors/base.py +46 -0
- thailint-0.14.0/src/linters/magic_numbers/__init__.py +48 -0
- thailint-0.14.0/src/linters/magic_numbers/config.py +82 -0
- thailint-0.14.0/src/linters/magic_numbers/context_analyzer.py +249 -0
- thailint-0.14.0/src/linters/magic_numbers/linter.py +462 -0
- thailint-0.14.0/src/linters/magic_numbers/python_analyzer.py +64 -0
- thailint-0.14.0/src/linters/magic_numbers/typescript_analyzer.py +215 -0
- thailint-0.14.0/src/linters/magic_numbers/typescript_ignore_checker.py +81 -0
- thailint-0.14.0/src/linters/magic_numbers/violation_builder.py +98 -0
- thailint-0.14.0/src/linters/method_property/__init__.py +49 -0
- thailint-0.14.0/src/linters/method_property/config.py +138 -0
- thailint-0.14.0/src/linters/method_property/linter.py +414 -0
- thailint-0.14.0/src/linters/method_property/python_analyzer.py +473 -0
- thailint-0.14.0/src/linters/method_property/violation_builder.py +119 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/__init__.py +6 -2
- {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/config.py +17 -4
- thailint-0.14.0/src/linters/nesting/linter.py +178 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linters/nesting/python_analyzer.py +4 -0
- thailint-0.14.0/src/linters/nesting/typescript_analyzer.py +111 -0
- thailint-0.14.0/src/linters/nesting/typescript_function_extractor.py +130 -0
- thailint-0.14.0/src/linters/nesting/violation_builder.py +140 -0
- thailint-0.14.0/src/linters/performance/__init__.py +91 -0
- thailint-0.14.0/src/linters/performance/config.py +43 -0
- thailint-0.14.0/src/linters/performance/constants.py +49 -0
- thailint-0.14.0/src/linters/performance/linter.py +149 -0
- thailint-0.14.0/src/linters/performance/python_analyzer.py +365 -0
- thailint-0.14.0/src/linters/performance/regex_analyzer.py +312 -0
- thailint-0.14.0/src/linters/performance/regex_linter.py +139 -0
- thailint-0.14.0/src/linters/performance/typescript_analyzer.py +236 -0
- thailint-0.14.0/src/linters/performance/violation_builder.py +160 -0
- thailint-0.14.0/src/linters/print_statements/__init__.py +53 -0
- thailint-0.14.0/src/linters/print_statements/config.py +78 -0
- thailint-0.14.0/src/linters/print_statements/linter.py +413 -0
- thailint-0.14.0/src/linters/print_statements/python_analyzer.py +153 -0
- thailint-0.14.0/src/linters/print_statements/typescript_analyzer.py +125 -0
- thailint-0.14.0/src/linters/print_statements/violation_builder.py +96 -0
- thailint-0.14.0/src/linters/srp/__init__.py +99 -0
- thailint-0.14.0/src/linters/srp/class_analyzer.py +117 -0
- thailint-0.14.0/src/linters/srp/config.py +82 -0
- thailint-0.14.0/src/linters/srp/heuristics.py +90 -0
- thailint-0.14.0/src/linters/srp/linter.py +233 -0
- thailint-0.14.0/src/linters/srp/metrics_evaluator.py +47 -0
- thailint-0.14.0/src/linters/srp/python_analyzer.py +107 -0
- thailint-0.14.0/src/linters/srp/typescript_analyzer.py +75 -0
- thailint-0.14.0/src/linters/srp/typescript_metrics_calculator.py +126 -0
- thailint-0.14.0/src/linters/srp/violation_builder.py +117 -0
- thailint-0.14.0/src/linters/stateless_class/__init__.py +25 -0
- thailint-0.14.0/src/linters/stateless_class/config.py +58 -0
- thailint-0.14.0/src/linters/stateless_class/linter.py +349 -0
- thailint-0.14.0/src/linters/stateless_class/python_analyzer.py +290 -0
- thailint-0.14.0/src/linters/stringly_typed/__init__.py +36 -0
- thailint-0.14.0/src/linters/stringly_typed/config.py +189 -0
- thailint-0.14.0/src/linters/stringly_typed/context_filter.py +451 -0
- thailint-0.14.0/src/linters/stringly_typed/function_call_violation_builder.py +135 -0
- thailint-0.14.0/src/linters/stringly_typed/ignore_checker.py +102 -0
- thailint-0.14.0/src/linters/stringly_typed/ignore_utils.py +51 -0
- thailint-0.14.0/src/linters/stringly_typed/linter.py +376 -0
- thailint-0.14.0/src/linters/stringly_typed/python/__init__.py +33 -0
- thailint-0.14.0/src/linters/stringly_typed/python/analyzer.py +348 -0
- thailint-0.14.0/src/linters/stringly_typed/python/call_tracker.py +175 -0
- thailint-0.14.0/src/linters/stringly_typed/python/comparison_tracker.py +257 -0
- thailint-0.14.0/src/linters/stringly_typed/python/condition_extractor.py +134 -0
- thailint-0.14.0/src/linters/stringly_typed/python/conditional_detector.py +179 -0
- thailint-0.14.0/src/linters/stringly_typed/python/constants.py +21 -0
- thailint-0.14.0/src/linters/stringly_typed/python/match_analyzer.py +94 -0
- thailint-0.14.0/src/linters/stringly_typed/python/validation_detector.py +189 -0
- thailint-0.14.0/src/linters/stringly_typed/python/variable_extractor.py +96 -0
- thailint-0.14.0/src/linters/stringly_typed/storage.py +630 -0
- thailint-0.14.0/src/linters/stringly_typed/storage_initializer.py +45 -0
- thailint-0.14.0/src/linters/stringly_typed/typescript/__init__.py +28 -0
- thailint-0.14.0/src/linters/stringly_typed/typescript/analyzer.py +157 -0
- thailint-0.14.0/src/linters/stringly_typed/typescript/call_tracker.py +335 -0
- thailint-0.14.0/src/linters/stringly_typed/typescript/comparison_tracker.py +378 -0
- thailint-0.14.0/src/linters/stringly_typed/violation_generator.py +405 -0
- thailint-0.14.0/src/orchestrator/core.py +471 -0
- thailint-0.14.0/src/templates/thailint_config_template.yaml +354 -0
- thailint-0.14.0/src/utils/__init__.py +4 -0
- thailint-0.14.0/src/utils/project_root.py +206 -0
- thailint-0.1.3/PKG-INFO +0 -629
- thailint-0.1.3/README.md +0 -596
- thailint-0.1.3/src/.ai/layout.yaml +0 -48
- thailint-0.1.3/src/cli.py +0 -698
- thailint-0.1.3/src/core/base.py +0 -122
- thailint-0.1.3/src/core/registry.py +0 -170
- thailint-0.1.3/src/linter_config/ignore.py +0 -403
- thailint-0.1.3/src/linters/file_placement/linter.py +0 -621
- thailint-0.1.3/src/linters/nesting/linter.py +0 -257
- thailint-0.1.3/src/linters/nesting/typescript_analyzer.py +0 -180
- thailint-0.1.3/src/orchestrator/core.py +0 -188
- {thailint-0.1.3 → thailint-0.14.0}/LICENSE +0 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/core/__init__.py +0 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linter_config/__init__.py +0 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linters/__init__.py +0 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/linters/file_placement/__init__.py +0 -0
- {thailint-0.1.3 → thailint-0.14.0}/src/orchestrator/__init__.py +0 -0
- {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 `
|
|
147
|
-
- Integrated nesting checks into `
|
|
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
|
thailint-0.14.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
[](https://www.python.org/downloads/)
|
|
40
|
+
[](https://pypi.org/project/thai-lint/)
|
|
41
|
+
[](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
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://pypi.org/project/thai-lint/)
|
|
6
|
+
[](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.
|
|
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://
|
|
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 ::
|
|
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.
|
|
105
|
-
thai-lint = "src.
|
|
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
|