crackerjack 0.18.2__py3-none-any.whl → 0.45.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.
Files changed (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,105 @@
1
+ """Validate Python file AST syntax.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-ast hook. It scans Python files and validates their AST syntax.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_ast [files...]
8
+
9
+ Exit Codes:
10
+ 0: All Python files have valid ASTs
11
+ 1: One or more Python files have syntax errors (invalid ASTs)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import ast
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def validate_ast_file(file_path: Path) -> tuple[bool, str | None]:
25
+ """Validate a Python file's AST syntax.
26
+
27
+ Args:
28
+ file_path: Path to Python file to validate
29
+
30
+ Returns:
31
+ Tuple of (is_valid, error_message)
32
+ - is_valid: True if file has valid Python AST syntax
33
+ - error_message: Error description if is_valid is False, None otherwise
34
+ """
35
+ try:
36
+ with file_path.open(encoding="utf-8") as f:
37
+ content = f.read()
38
+
39
+ # Parse the content into an AST
40
+ ast.parse(content)
41
+ return True, None
42
+ except SyntaxError as e:
43
+ return False, f"Syntax error at line {e.lineno}: {e.msg}"
44
+ except Exception as e:
45
+ return False, f"Error reading file: {e}"
46
+
47
+
48
+ def main(argv: list[str] | None = None) -> int:
49
+ """Main entry point for check-ast tool.
50
+
51
+ Args:
52
+ argv: Command-line arguments (defaults to sys.argv[1:])
53
+
54
+ Returns:
55
+ Exit code: 0 if all Python files have valid ASTs, 1 if any errors found
56
+ """
57
+ parser = argparse.ArgumentParser(description="Validate Python file AST syntax")
58
+ parser.add_argument(
59
+ "files",
60
+ nargs="*",
61
+ type=Path,
62
+ help="Python files to check (default: all .py files)",
63
+ )
64
+
65
+ args = parser.parse_args(argv)
66
+
67
+ # Default to all git-tracked Python files if none specified
68
+ if not args.files:
69
+ # Get all tracked Python files (respects .gitignore via git ls-files)
70
+ files = get_files_by_extension([".py"])
71
+ if not files:
72
+ # Fallback to rglob if not in git repo
73
+ files = list(Path.cwd().rglob("*.py"))
74
+ else:
75
+ files = args.files
76
+
77
+ # Filter to existing files only
78
+ files = [f for f in files if f.is_file()]
79
+
80
+ if not files:
81
+ print("No Python files to check") # noqa: T201
82
+ return 0
83
+
84
+ # Process files
85
+ error_count = 0
86
+ for file_path in files:
87
+ is_valid, error_msg = validate_ast_file(file_path)
88
+
89
+ if not is_valid:
90
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
91
+ error_count += 1
92
+ else:
93
+ print(f"✓ {file_path}: Valid AST") # noqa: T201
94
+
95
+ # Return appropriate exit code
96
+ if error_count > 0:
97
+ print(f"\n{error_count} Python file(s) with AST errors", file=sys.stderr) # noqa: T201
98
+ return 1
99
+
100
+ print(f"\nAll {len(files)} Python file(s) have valid ASTs") # noqa: T201
101
+ return 0
102
+
103
+
104
+ if __name__ == "__main__":
105
+ sys.exit(main())
@@ -0,0 +1,103 @@
1
+ """Validate JSON file syntax.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-json hook. It scans JSON files and validates their syntax.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_json [files...]
8
+
9
+ Exit Codes:
10
+ 0: All JSON files are valid
11
+ 1: One or more JSON files have syntax errors
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def validate_json_file(file_path: Path) -> tuple[bool, str | None]:
25
+ """Validate a JSON file's syntax.
26
+
27
+ Args:
28
+ file_path: Path to JSON file to validate
29
+
30
+ Returns:
31
+ Tuple of (is_valid, error_message)
32
+ - is_valid: True if file has valid JSON syntax
33
+ - error_message: Error description if is_valid is False, None otherwise
34
+ """
35
+ try:
36
+ with file_path.open(encoding="utf-8") as f:
37
+ # Load JSON and validate structure
38
+ json.load(f)
39
+ return True, None
40
+ except json.JSONDecodeError as e:
41
+ return False, str(e)
42
+ except Exception as e:
43
+ return False, f"Error reading file: {e}"
44
+
45
+
46
+ def main(argv: list[str] | None = None) -> int:
47
+ """Main entry point for check-json tool.
48
+
49
+ Args:
50
+ argv: Command-line arguments (defaults to sys.argv[1:])
51
+
52
+ Returns:
53
+ Exit code: 0 if all JSON valid, 1 if any errors found
54
+ """
55
+ parser = argparse.ArgumentParser(description="Validate JSON file syntax")
56
+ parser.add_argument(
57
+ "files",
58
+ nargs="*",
59
+ type=Path,
60
+ help="JSON files to check (default: all .json files)",
61
+ )
62
+
63
+ args = parser.parse_args(argv)
64
+
65
+ # Default to all git-tracked JSON files if none specified
66
+ if not args.files:
67
+ # Get all tracked JSON files (respects .gitignore via git ls-files)
68
+ files = get_files_by_extension([".json"])
69
+ if not files:
70
+ # Fallback to rglob if not in git repo
71
+ files = list(Path.cwd().rglob("*.json"))
72
+ else:
73
+ files = args.files
74
+
75
+ # Filter to existing files only
76
+ files = [f for f in files if f.is_file()]
77
+
78
+ if not files:
79
+ print("No JSON files to check") # noqa: T201
80
+ return 0
81
+
82
+ # Process files
83
+ error_count = 0
84
+ for file_path in files:
85
+ is_valid, error_msg = validate_json_file(file_path)
86
+
87
+ if not is_valid:
88
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
89
+ error_count += 1
90
+ else:
91
+ print(f"✓ {file_path}: Valid JSON") # noqa: T201
92
+
93
+ # Return appropriate exit code
94
+ if error_count > 0:
95
+ print(f"\n{error_count} JSON file(s) with errors", file=sys.stderr) # noqa: T201
96
+ return 1
97
+
98
+ print(f"\nAll {len(files)} JSON file(s) are valid") # noqa: T201
99
+ return 0
100
+
101
+
102
+ if __name__ == "__main__":
103
+ sys.exit(main())
@@ -0,0 +1,297 @@
1
+ """Validate JSON files against JSON Schema definitions.
2
+
3
+ This tool is a native Python implementation for validating JSON files
4
+ against their corresponding JSON Schema definitions. It automatically
5
+ finds .json files and attempts to validate them against similarly named
6
+ .schema.json or .json files that follow the JSON Schema standard.
7
+
8
+ Usage:
9
+ python -m crackerjack.tools.check_jsonschema [files...]
10
+
11
+ Exit Codes:
12
+ 0: All JSON files are valid against their schemas
13
+ 1: One or more JSON files fail schema validation
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import json
20
+ import sys
21
+ import typing as t
22
+ from pathlib import Path
23
+
24
+ from ._git_utils import get_files_by_extension
25
+
26
+ if t.TYPE_CHECKING:
27
+ pass
28
+
29
+
30
+ def _check_filename_pattern_schema(json_file: Path) -> Path | None:
31
+ """Check for {name}.schema.json pattern."""
32
+ schema_path = json_file.with_name(f"{json_file.stem}.schema.json")
33
+ if schema_path.is_file():
34
+ return schema_path
35
+ return None
36
+
37
+
38
+ def _resolve_local_schema_path(json_file: Path, schema_ref: str) -> Path | None:
39
+ """Resolve a local schema file path.
40
+
41
+ Args:
42
+ json_file: The JSON file containing the schema reference
43
+ schema_ref: The schema reference string
44
+
45
+ Returns:
46
+ Path to schema file if found, None otherwise
47
+ """
48
+ if schema_ref.endswith((".json", ".schema.json")):
49
+ schema_path = json_file.parent / schema_ref
50
+ if schema_path.is_file():
51
+ return schema_path
52
+ return None
53
+
54
+
55
+ def _check_internal_schema_ref(json_file: Path) -> Path | None:
56
+ """Try to find a schema reference inside the JSON file."""
57
+ try:
58
+ with json_file.open(encoding="utf-8") as f:
59
+ data = json.load(f)
60
+
61
+ if isinstance(data, dict):
62
+ schema_ref = data.get("$schema")
63
+ if schema_ref and isinstance(schema_ref, str):
64
+ return _resolve_local_schema_path(json_file, schema_ref)
65
+ except (OSError, json.JSONDecodeError):
66
+ pass
67
+ return None
68
+
69
+
70
+ def _check_same_dir_schema(json_file: Path) -> Path | None:
71
+ """Try schema.json in the same directory."""
72
+ schema_path = json_file.with_name("schema.json")
73
+ if schema_path.is_file():
74
+ return schema_path
75
+ return None
76
+
77
+
78
+ def _check_parent_dir_schemas(json_file: Path) -> Path | None:
79
+ """Try finding schema.json in parent directories (up to 3 levels)."""
80
+ current_dir = json_file.parent
81
+ for _ in range(3):
82
+ schema_path = current_dir / "schema.json"
83
+ if schema_path.is_file():
84
+ return schema_path
85
+ if current_dir.parent == current_dir: # reached root
86
+ break
87
+ current_dir = current_dir.parent
88
+ return None
89
+
90
+
91
+ def find_schema_for_json(json_file: Path) -> Path | None:
92
+ """Find the corresponding schema file for a JSON file.
93
+
94
+ Looks for schema files in common patterns:
95
+ - {name}.schema.json
96
+ - {name}.json (if it contains $schema reference)
97
+ - schema.json in the same directory
98
+ - schema.json in parent directories
99
+
100
+ Args:
101
+ json_file: Path to the JSON file to validate
102
+
103
+ Returns:
104
+ Path to schema file, or None if not found
105
+ """
106
+ # Try {name}.schema.json pattern
107
+ result = _check_filename_pattern_schema(json_file)
108
+ if result:
109
+ return result
110
+
111
+ # Try to find a schema reference inside the JSON file
112
+ result = _check_internal_schema_ref(json_file)
113
+ if result:
114
+ return result
115
+
116
+ # Try schema.json in the same directory
117
+ result = _check_same_dir_schema(json_file)
118
+ if result:
119
+ return result
120
+
121
+ # Try finding schema.json in parent directories (up to 3 levels)
122
+ return _check_parent_dir_schemas(json_file)
123
+
124
+
125
+ def load_schema(schema_path: Path) -> dict[str, t.Any] | None:
126
+ """Load a JSON schema from file.
127
+
128
+ Args:
129
+ schema_path: Path to the schema file
130
+
131
+ Returns:
132
+ Schema as dictionary, or None if loading fails
133
+ """
134
+ try:
135
+ with schema_path.open(encoding="utf-8") as f:
136
+ schema = json.load(f)
137
+
138
+ # Basic validation that this looks like a schema
139
+ if not isinstance(schema, dict):
140
+ return None
141
+
142
+ return schema
143
+ except (OSError, json.JSONDecodeError) as e:
144
+ print(f"Could not load schema {schema_path}: {e}", file=sys.stderr) # noqa: T201
145
+ return None
146
+
147
+
148
+ def validate_json_against_schema(
149
+ json_file: Path, schema_path: Path
150
+ ) -> tuple[bool, str | None]:
151
+ """Validate a JSON file against a schema.
152
+
153
+ Args:
154
+ json_file: Path to the JSON file to validate
155
+ schema_path: Path to the schema file
156
+
157
+ Returns:
158
+ Tuple of (is_valid, error_message)
159
+ - is_valid: True if file validates against schema
160
+ - error_message: Error description if is_valid is False, None otherwise
161
+ """
162
+ try:
163
+ # Load schema
164
+ schema = load_schema(schema_path)
165
+ if not schema:
166
+ return False, f"Could not load schema: {schema_path}"
167
+
168
+ # Load JSON data
169
+ with json_file.open(encoding="utf-8") as f:
170
+ data = json.load(f)
171
+
172
+ # Import jsonschema only when needed to avoid dependency issues
173
+ import jsonschema
174
+
175
+ # Validate the data against the schema
176
+ validator_class = jsonschema.Draft7Validator
177
+ if hasattr(validator_class, "check_schema"):
178
+ # Validate the schema itself first
179
+ validator_class.check_schema(schema)
180
+
181
+ validator = validator_class(schema)
182
+ errors = list(validator.iter_errors(data))
183
+
184
+ if errors:
185
+ error_messages = [
186
+ f" {error.message}" for error in errors[:5]
187
+ ] # Limit to first 5 errors
188
+ if len(errors) > 5:
189
+ error_messages.append(f" ... and {len(errors) - 5} more errors")
190
+ return False, "Schema validation failed:\n" + "\n".join(error_messages)
191
+
192
+ return True, None
193
+
194
+ except ImportError:
195
+ return (
196
+ False,
197
+ "jsonschema library not available. Install with: pip install jsonschema",
198
+ )
199
+ except jsonschema.SchemaError as e:
200
+ return False, f"Invalid schema: {e}"
201
+ except json.JSONDecodeError as e:
202
+ return False, f"Invalid JSON in file: {e}"
203
+ except Exception as e:
204
+ return False, f"Validation error: {e}"
205
+
206
+
207
+ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
208
+ """Parse command-line arguments."""
209
+ parser = argparse.ArgumentParser(
210
+ description="Validate JSON files against JSON Schema definitions"
211
+ )
212
+ parser.add_argument(
213
+ "files",
214
+ nargs="*",
215
+ type=Path,
216
+ help="JSON files to validate against schemas (default: all .json files)",
217
+ )
218
+ parser.add_argument(
219
+ "--strict",
220
+ action="store_true",
221
+ help="Fail if no schema is found for a JSON file",
222
+ )
223
+
224
+ return parser.parse_args(argv)
225
+
226
+
227
+ def _get_json_files(args: argparse.Namespace) -> list[Path]:
228
+ """Get list of JSON files to validate."""
229
+ if not args.files:
230
+ # Get all tracked JSON files (respects .gitignore via git ls-files)
231
+ files = get_files_by_extension([".json"])
232
+ if not files:
233
+ # Fallback to rglob if not in git repo
234
+ files = list(Path.cwd().rglob("*.json"))
235
+ else:
236
+ files = args.files
237
+
238
+ # Filter to existing files only
239
+ return [f for f in files if f.is_file()]
240
+
241
+
242
+ def _process_file(file_path: Path, schema_path: Path | None, strict: bool) -> int:
243
+ """Process a single file and return error count increment."""
244
+ if not schema_path:
245
+ if strict:
246
+ print(f"✗ {file_path}: No schema found", file=sys.stderr) # noqa: T201
247
+ return 1
248
+ else:
249
+ print(f"→ {file_path}: No schema found, skipping validation") # noqa: T201
250
+ return 0
251
+
252
+ is_valid, error_msg = validate_json_against_schema(file_path, schema_path)
253
+
254
+ if not is_valid:
255
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
256
+ return 1
257
+ else:
258
+ print(f"✓ {file_path}: Valid against {schema_path.name}") # noqa: T201
259
+ return 0
260
+
261
+
262
+ def main(argv: list[str] | None = None) -> int:
263
+ """Main entry point for check-jsonschema tool.
264
+
265
+ Args:
266
+ argv: Command-line arguments (defaults to sys.argv[1:])
267
+
268
+ Returns:
269
+ Exit code: 0 if all JSON files validate against schemas, 1 if any errors found
270
+ """
271
+ args = _parse_args(argv)
272
+
273
+ files = _get_json_files(args)
274
+
275
+ if not files:
276
+ print("No JSON files to validate") # noqa: T201
277
+ return 0
278
+
279
+ # Process files
280
+ error_count = 0
281
+ for file_path in files:
282
+ schema_path = find_schema_for_json(file_path)
283
+ error_count += _process_file(file_path, schema_path, args.strict)
284
+
285
+ # Return appropriate exit code
286
+ if error_count > 0:
287
+ print(f"\n{error_count} JSON file(s) failed schema validation", file=sys.stderr) # noqa: T201
288
+ return 1
289
+
290
+ print(
291
+ f"\nAll {len([f for f in files if find_schema_for_json(f)])} JSON file(s) passed schema validation"
292
+ ) # noqa: T201
293
+ return 0
294
+
295
+
296
+ if __name__ == "__main__":
297
+ sys.exit(main())
@@ -0,0 +1,103 @@
1
+ """Validate TOML file syntax.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-toml hook. It scans TOML files and validates their syntax.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_toml [files...]
8
+
9
+ Exit Codes:
10
+ 0: All TOML files are valid
11
+ 1: One or more TOML files have syntax errors
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import sys
18
+ import tomllib
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def validate_toml_file(file_path: Path) -> tuple[bool, str | None]:
25
+ """Validate a TOML file's syntax.
26
+
27
+ Args:
28
+ file_path: Path to TOML file to validate
29
+
30
+ Returns:
31
+ Tuple of (is_valid, error_message)
32
+ - is_valid: True if file has valid TOML syntax
33
+ - error_message: Error description if is_valid is False, None otherwise
34
+ """
35
+ try:
36
+ with file_path.open("rb") as f:
37
+ # Load TOML and validate structure
38
+ tomllib.load(f)
39
+ return True, None
40
+ except tomllib.TOMLDecodeError as e:
41
+ return False, str(e)
42
+ except Exception as e:
43
+ return False, f"Error reading file: {e}"
44
+
45
+
46
+ def main(argv: list[str] | None = None) -> int:
47
+ """Main entry point for check-toml tool.
48
+
49
+ Args:
50
+ argv: Command-line arguments (defaults to sys.argv[1:])
51
+
52
+ Returns:
53
+ Exit code: 0 if all TOML valid, 1 if any errors found
54
+ """
55
+ parser = argparse.ArgumentParser(description="Validate TOML file syntax")
56
+ parser.add_argument(
57
+ "files",
58
+ nargs="*",
59
+ type=Path,
60
+ help="TOML files to check (default: all .toml files)",
61
+ )
62
+
63
+ args = parser.parse_args(argv)
64
+
65
+ # Default to all git-tracked TOML files if none specified
66
+ if not args.files:
67
+ # Get all tracked TOML files (respects .gitignore via git ls-files)
68
+ files = get_files_by_extension([".toml"])
69
+ if not files:
70
+ # Fallback to rglob if not in git repo
71
+ files = list(Path.cwd().rglob("*.toml"))
72
+ else:
73
+ files = args.files
74
+
75
+ # Filter to existing files only
76
+ files = [f for f in files if f.is_file()]
77
+
78
+ if not files:
79
+ print("No TOML files to check") # noqa: T201
80
+ return 0
81
+
82
+ # Process files
83
+ error_count = 0
84
+ for file_path in files:
85
+ is_valid, error_msg = validate_toml_file(file_path)
86
+
87
+ if not is_valid:
88
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
89
+ error_count += 1
90
+ else:
91
+ print(f"✓ {file_path}: Valid TOML") # noqa: T201
92
+
93
+ # Return appropriate exit code
94
+ if error_count > 0:
95
+ print(f"\n{error_count} TOML file(s) with errors", file=sys.stderr) # noqa: T201
96
+ return 1
97
+
98
+ print(f"\nAll {len(files)} TOML file(s) are valid") # noqa: T201
99
+ return 0
100
+
101
+
102
+ if __name__ == "__main__":
103
+ sys.exit(main())