thailint 0.3.0__py3-none-any.whl → 0.3.2__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.
src/cli.py CHANGED
@@ -1077,5 +1077,106 @@ def _run_dry_lint(orchestrator, path_objs, recursive):
1077
1077
  return dry_violations
1078
1078
 
1079
1079
 
1080
+ def _setup_magic_numbers_orchestrator(
1081
+ path_objs: list[Path], config_file: str | None, verbose: bool
1082
+ ):
1083
+ """Set up orchestrator for magic-numbers command."""
1084
+ first_path = path_objs[0] if path_objs else Path.cwd()
1085
+ project_root = first_path if first_path.is_dir() else first_path.parent
1086
+
1087
+ from src.orchestrator.core import Orchestrator
1088
+
1089
+ orchestrator = Orchestrator(project_root=project_root)
1090
+
1091
+ if config_file:
1092
+ _load_config_file(orchestrator, config_file, verbose)
1093
+
1094
+ return orchestrator
1095
+
1096
+
1097
+ def _run_magic_numbers_lint(orchestrator, path_objs: list[Path], recursive: bool):
1098
+ """Execute magic-numbers lint on files or directories."""
1099
+ all_violations = _execute_linting_on_paths(orchestrator, path_objs, recursive)
1100
+ return [v for v in all_violations if "magic-number" in v.rule_id]
1101
+
1102
+
1103
+ @cli.command("magic-numbers")
1104
+ @click.argument("paths", nargs=-1, type=click.Path())
1105
+ @click.option("--config", "-c", "config_file", type=click.Path(), help="Path to config file")
1106
+ @format_option
1107
+ @click.option("--recursive/--no-recursive", default=True, help="Scan directories recursively")
1108
+ @click.pass_context
1109
+ def magic_numbers( # pylint: disable=too-many-arguments,too-many-positional-arguments
1110
+ ctx,
1111
+ paths: tuple[str, ...],
1112
+ config_file: str | None,
1113
+ format: str,
1114
+ recursive: bool,
1115
+ ):
1116
+ """Check for magic numbers in code.
1117
+
1118
+ Detects unnamed numeric literals in Python and TypeScript/JavaScript code
1119
+ that should be extracted as named constants for better readability.
1120
+
1121
+ PATHS: Files or directories to lint (defaults to current directory if none provided)
1122
+
1123
+ Examples:
1124
+
1125
+ \b
1126
+ # Check current directory (all files recursively)
1127
+ thai-lint magic-numbers
1128
+
1129
+ \b
1130
+ # Check specific directory
1131
+ thai-lint magic-numbers src/
1132
+
1133
+ \b
1134
+ # Check single file
1135
+ thai-lint magic-numbers src/app.py
1136
+
1137
+ \b
1138
+ # Check multiple files
1139
+ thai-lint magic-numbers src/app.py src/utils.py tests/test_app.py
1140
+
1141
+ \b
1142
+ # Check mix of files and directories
1143
+ thai-lint magic-numbers src/app.py tests/
1144
+
1145
+ \b
1146
+ # Get JSON output
1147
+ thai-lint magic-numbers --format json .
1148
+
1149
+ \b
1150
+ # Use custom config file
1151
+ thai-lint magic-numbers --config .thailint.yaml src/
1152
+ """
1153
+ verbose = ctx.obj.get("verbose", False)
1154
+
1155
+ if not paths:
1156
+ paths = (".",)
1157
+
1158
+ path_objs = [Path(p) for p in paths]
1159
+
1160
+ try:
1161
+ _execute_magic_numbers_lint(path_objs, config_file, format, recursive, verbose)
1162
+ except Exception as e:
1163
+ _handle_linting_error(e, verbose)
1164
+
1165
+
1166
+ def _execute_magic_numbers_lint( # pylint: disable=too-many-arguments,too-many-positional-arguments
1167
+ path_objs, config_file, format, recursive, verbose
1168
+ ):
1169
+ """Execute magic-numbers lint."""
1170
+ _validate_paths_exist(path_objs)
1171
+ orchestrator = _setup_magic_numbers_orchestrator(path_objs, config_file, verbose)
1172
+ magic_numbers_violations = _run_magic_numbers_lint(orchestrator, path_objs, recursive)
1173
+
1174
+ if verbose:
1175
+ logger.info(f"Found {len(magic_numbers_violations)} magic number violation(s)")
1176
+
1177
+ format_violations(magic_numbers_violations, format)
1178
+ sys.exit(1 if magic_numbers_violations else 0)
1179
+
1180
+
1080
1181
  if __name__ == "__main__":
1081
1182
  cli()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: thailint
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
5
5
  License: MIT
6
6
  Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
@@ -35,14 +35,25 @@ Description-Content-Type: text/markdown
35
35
 
36
36
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
37
37
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
38
- [![Tests](https://img.shields.io/badge/tests-317%2F317%20passing-brightgreen.svg)](tests/)
39
- [![Coverage](https://img.shields.io/badge/coverage-90%25-brightgreen.svg)](htmlcov/)
38
+ [![Tests](https://img.shields.io/badge/tests-253%2F253%20passing-brightgreen.svg)](tests/)
39
+ [![Coverage](https://img.shields.io/badge/coverage-88%25-brightgreen.svg)](htmlcov/)
40
40
 
41
41
  The AI Linter - Enterprise-ready linting and governance for AI-generated code across multiple languages.
42
42
 
43
43
  ## Overview
44
44
 
45
- thailint is a modern, enterprise-ready multi-language linter designed specifically for AI-generated code. It enforces project structure, file placement rules, and coding standards across Python, TypeScript, and other languages.
45
+ thailint is a modern, enterprise-ready multi-language linter designed specifically for AI-generated code. It focuses on common mistakes and anti-patterns that AI coding assistants frequently introduce—issues that existing linters don't catch or don't handle consistently across languages.
46
+
47
+ **Why thailint?**
48
+
49
+ We're not trying to replace the wonderful existing linters like Pylint, ESLint, or Ruff. Instead, thailint fills critical gaps:
50
+
51
+ - **AI-Specific Patterns**: AI assistants have predictable blind spots (excessive nesting, magic numbers, SRP violations) that traditional linters miss
52
+ - **Cross-Language Consistency**: Detects the same anti-patterns across Python, TypeScript, and JavaScript with unified rules
53
+ - **No Existing Solutions**: Issues like excessive nesting depth, file placement violations, and cross-project code duplication lack comprehensive multi-language detection
54
+ - **Governance Layer**: Enforces project-wide structure and organization patterns that AI can't infer from local context
55
+
56
+ thailint complements your existing linting stack by catching the patterns AI tools repeatedly miss.
46
57
 
47
58
  ## Features
48
59
 
@@ -917,49 +928,96 @@ def test_no_violations():
917
928
  ### Setup Development Environment
918
929
 
919
930
  ```bash
920
- # Install development dependencies
921
- pip install -e ".[dev]"
931
+ # Install dependencies and activate virtualenv
932
+ just init
922
933
 
923
- # Install pre-commit hooks (if using)
924
- pre-commit install
934
+ # Or manually:
935
+ poetry install
936
+ source $(poetry env info --path)/bin/activate
925
937
  ```
926
938
 
927
939
  ### Running Tests
928
940
 
929
941
  ```bash
930
- # Run all tests
931
- pytest
942
+ # Run all tests (parallel mode - fast)
943
+ just test
932
944
 
933
- # Run with coverage
934
- pytest --cov=src --cov-report=html
945
+ # Run with coverage (serial mode)
946
+ just test-coverage
935
947
 
936
948
  # Run specific test
937
- pytest tests/test_cli.py::test_hello_command
949
+ poetry run pytest tests/test_cli.py::test_hello_command -v
938
950
  ```
939
951
 
940
952
  ### Code Quality
941
953
 
942
954
  ```bash
943
- # Lint code
944
- ruff check src tests
955
+ # Fast linting (Ruff only - use during development)
956
+ just lint
957
+
958
+ # Comprehensive linting (Ruff + Pylint + Flake8 + MyPy)
959
+ just lint-all
960
+
961
+ # Security scanning
962
+ just lint-security
963
+
964
+ # Complexity analysis (Radon + Xenon + Nesting)
965
+ just lint-complexity
966
+
967
+ # SOLID principles (SRP)
968
+ just lint-solid
969
+
970
+ # DRY principles (duplicate code detection)
971
+ just lint-dry
972
+
973
+ # ALL quality checks (runs everything)
974
+ just lint-full
975
+
976
+ # Auto-fix formatting issues
977
+ just format
978
+ ```
979
+
980
+ ### Dogfooding (Lint Our Own Code)
981
+
982
+ ```bash
983
+ # Lint file placement
984
+ just lint-placement
945
985
 
946
- # Format code
947
- ruff format src tests
986
+ # Check nesting depth
987
+ just lint-nesting
948
988
 
949
- # Type checking
950
- mypy src/
989
+ # Check for magic numbers
990
+ poetry run thai-lint magic-numbers src/
951
991
  ```
952
992
 
953
- ### Building
993
+ ### Building and Publishing
954
994
 
955
995
  ```bash
956
996
  # Build Python package
957
997
  poetry build
958
998
 
959
- # Build Docker image locally (optional)
999
+ # Build Docker image locally
960
1000
  docker build -t washad/thailint:latest .
1001
+
1002
+ # Publish to PyPI and Docker Hub (runs tests + linting + version bump)
1003
+ just publish
961
1004
  ```
962
1005
 
1006
+ ### Quick Development Workflows
1007
+
1008
+ ```bash
1009
+ # Make changes, then run quality checks
1010
+ just lint-full
1011
+
1012
+ # Share changes for collaboration (skips hooks)
1013
+ just share "WIP: feature description"
1014
+
1015
+ # Clean up cache and artifacts
1016
+ just clean
1017
+ ```
1018
+
1019
+ See `just --list` or `just help` for all available commands.
1020
+
963
1021
  ## Docker Usage
964
1022
 
965
1023
  ```bash
@@ -2,7 +2,7 @@ src/__init__.py,sha256=f601zncODr2twrUHqTLS5wyOdZqZi9tMjAe2INhRKqU,2175
2
2
  src/analyzers/__init__.py,sha256=fFloZtjkBGwYbAhKTxS3Qy3yDr2_3i3WSfKTw1mAioo,972
3
3
  src/analyzers/typescript_base.py,sha256=4I7fAcMOAY9vY1AXh52QpohgFmguBECwOkvBRP4zCS4,5054
4
4
  src/api.py,sha256=pJ5l3qxccKBEY-BkANwzTgLAl1ZFq7OP6hx6LSxbhDw,4664
5
- src/cli.py,sha256=TTg7nrMF3tEfcj_rbotfvosTjuIWaQqpBjxxj9Tlipw,32421
5
+ src/cli.py,sha256=1qhjXAy7JDdav90xQ5pOeH1_f1A9qYJLIwxTQzq3oiU,35657
6
6
  src/config.py,sha256=2ebAjIpAhw4bHbOxViEA5nCjfBlDEIrMR59DBrzcYzM,12460
7
7
  src/core/__init__.py,sha256=5FtsDvhMt4SNRx3pbcGURrxn135XRbeRrjSUxiXwkNc,381
8
8
  src/core/base.py,sha256=Eklcagi2ktfY4Kytl_ObXov2U49N9OGDpw4cu4PUzGY,7824
@@ -75,8 +75,8 @@ src/orchestrator/core.py,sha256=zb4H4HtDNLmnsRCUXI3oNtfM3T-nTPW9Q2pAbI61VEs,8374
75
75
  src/orchestrator/language_detector.py,sha256=rHyVMApit80NTTNyDH1ObD1usKD8LjGmH3DwqNAWYGc,2736
76
76
  src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
77
77
  src/utils/project_root.py,sha256=ldv2-XeMT0IElpSgrHdTaP2CUfwmdZix8vQ2qXO1O5s,2735
78
- thailint-0.3.0.dist-info/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
79
- thailint-0.3.0.dist-info/METADATA,sha256=3Xe02fShk9DLYJUZ5dS4vugRqyQcGLhUrSJYE9qSCQM,31385
80
- thailint-0.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
81
- thailint-0.3.0.dist-info/entry_points.txt,sha256=l7DQJgU18sVLDpSaXOXY3lLhnQHQIRrSJZTQjG1cEAk,62
82
- thailint-0.3.0.dist-info/RECORD,,
78
+ thailint-0.3.2.dist-info/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
79
+ thailint-0.3.2.dist-info/METADATA,sha256=P46brGR5esX9nGSoCtedmac_zupk8pAN4iHS2dJhM_g,33249
80
+ thailint-0.3.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
81
+ thailint-0.3.2.dist-info/entry_points.txt,sha256=l7DQJgU18sVLDpSaXOXY3lLhnQHQIRrSJZTQjG1cEAk,62
82
+ thailint-0.3.2.dist-info/RECORD,,