thailint 0.3.0__tar.gz → 0.3.1__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 (82) hide show
  1. {thailint-0.3.0 → thailint-0.3.1}/PKG-INFO +1 -1
  2. {thailint-0.3.0 → thailint-0.3.1}/pyproject.toml +2 -1
  3. {thailint-0.3.0 → thailint-0.3.1}/src/cli.py +101 -0
  4. {thailint-0.3.0 → thailint-0.3.1}/CHANGELOG.md +0 -0
  5. {thailint-0.3.0 → thailint-0.3.1}/LICENSE +0 -0
  6. {thailint-0.3.0 → thailint-0.3.1}/README.md +0 -0
  7. {thailint-0.3.0 → thailint-0.3.1}/src/__init__.py +0 -0
  8. {thailint-0.3.0 → thailint-0.3.1}/src/analyzers/__init__.py +0 -0
  9. {thailint-0.3.0 → thailint-0.3.1}/src/analyzers/typescript_base.py +0 -0
  10. {thailint-0.3.0 → thailint-0.3.1}/src/api.py +0 -0
  11. {thailint-0.3.0 → thailint-0.3.1}/src/config.py +0 -0
  12. {thailint-0.3.0 → thailint-0.3.1}/src/core/__init__.py +0 -0
  13. {thailint-0.3.0 → thailint-0.3.1}/src/core/base.py +0 -0
  14. {thailint-0.3.0 → thailint-0.3.1}/src/core/cli_utils.py +0 -0
  15. {thailint-0.3.0 → thailint-0.3.1}/src/core/config_parser.py +0 -0
  16. {thailint-0.3.0 → thailint-0.3.1}/src/core/linter_utils.py +0 -0
  17. {thailint-0.3.0 → thailint-0.3.1}/src/core/registry.py +0 -0
  18. {thailint-0.3.0 → thailint-0.3.1}/src/core/rule_discovery.py +0 -0
  19. {thailint-0.3.0 → thailint-0.3.1}/src/core/types.py +0 -0
  20. {thailint-0.3.0 → thailint-0.3.1}/src/core/violation_builder.py +0 -0
  21. {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/__init__.py +0 -0
  22. {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/ignore.py +0 -0
  23. {thailint-0.3.0 → thailint-0.3.1}/src/linter_config/loader.py +0 -0
  24. {thailint-0.3.0 → thailint-0.3.1}/src/linters/__init__.py +0 -0
  25. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/__init__.py +0 -0
  26. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/base_token_analyzer.py +0 -0
  27. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/block_filter.py +0 -0
  28. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/block_grouper.py +0 -0
  29. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/cache.py +0 -0
  30. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/cache_query.py +0 -0
  31. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/config.py +0 -0
  32. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/config_loader.py +0 -0
  33. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/deduplicator.py +0 -0
  34. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/duplicate_storage.py +0 -0
  35. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/file_analyzer.py +0 -0
  36. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/inline_ignore.py +0 -0
  37. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/linter.py +0 -0
  38. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/python_analyzer.py +0 -0
  39. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/storage_initializer.py +0 -0
  40. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/token_hasher.py +0 -0
  41. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/typescript_analyzer.py +0 -0
  42. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_builder.py +0 -0
  43. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_filter.py +0 -0
  44. {thailint-0.3.0 → thailint-0.3.1}/src/linters/dry/violation_generator.py +0 -0
  45. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/__init__.py +0 -0
  46. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/config_loader.py +0 -0
  47. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/directory_matcher.py +0 -0
  48. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/linter.py +0 -0
  49. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/path_resolver.py +0 -0
  50. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/pattern_matcher.py +0 -0
  51. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/pattern_validator.py +0 -0
  52. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/rule_checker.py +0 -0
  53. {thailint-0.3.0 → thailint-0.3.1}/src/linters/file_placement/violation_factory.py +0 -0
  54. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/__init__.py +0 -0
  55. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/config.py +0 -0
  56. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/context_analyzer.py +0 -0
  57. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/linter.py +0 -0
  58. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/python_analyzer.py +0 -0
  59. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/typescript_analyzer.py +0 -0
  60. {thailint-0.3.0 → thailint-0.3.1}/src/linters/magic_numbers/violation_builder.py +0 -0
  61. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/__init__.py +0 -0
  62. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/config.py +0 -0
  63. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/linter.py +0 -0
  64. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/python_analyzer.py +0 -0
  65. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/typescript_analyzer.py +0 -0
  66. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/typescript_function_extractor.py +0 -0
  67. {thailint-0.3.0 → thailint-0.3.1}/src/linters/nesting/violation_builder.py +0 -0
  68. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/__init__.py +0 -0
  69. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/class_analyzer.py +0 -0
  70. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/config.py +0 -0
  71. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/heuristics.py +0 -0
  72. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/linter.py +0 -0
  73. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/metrics_evaluator.py +0 -0
  74. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/python_analyzer.py +0 -0
  75. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/typescript_analyzer.py +0 -0
  76. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/typescript_metrics_calculator.py +0 -0
  77. {thailint-0.3.0 → thailint-0.3.1}/src/linters/srp/violation_builder.py +0 -0
  78. {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/__init__.py +0 -0
  79. {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/core.py +0 -0
  80. {thailint-0.3.0 → thailint-0.3.1}/src/orchestrator/language_detector.py +0 -0
  81. {thailint-0.3.0 → thailint-0.3.1}/src/utils/__init__.py +0 -0
  82. {thailint-0.3.0 → thailint-0.3.1}/src/utils/project_root.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: thailint
3
- Version: 0.3.0
3
+ Version: 0.3.1
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
@@ -17,7 +17,7 @@ build-backend = "poetry.core.masonry.api"
17
17
 
18
18
  [tool.poetry]
19
19
  name = "thailint"
20
- version = "0.3.0"
20
+ version = "0.3.1"
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"
@@ -101,6 +101,7 @@ xenon = "^0.9.3"
101
101
  safety = "^3.2.11"
102
102
  pip-audit = "^2.8.0"
103
103
  loguru = "^0.7.3"
104
+ pytest-xdist = "^3.8.0"
104
105
 
105
106
  [tool.poetry.scripts]
106
107
  thailint = "src.cli:cli"
@@ -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()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes