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.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +96 -2
- crackerjack/__main__.py +637 -138
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +39 -0
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/lsp/_base.py +194 -0
- crackerjack/adapters/lsp/_client.py +358 -0
- crackerjack/adapters/lsp/_manager.py +193 -0
- crackerjack/adapters/lsp/skylos.py +283 -0
- crackerjack/adapters/lsp/zuban.py +557 -0
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +66 -0
- crackerjack/agents/architect_agent.py +238 -0
- crackerjack/agents/base.py +167 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +600 -0
- crackerjack/agents/documentation_agent.py +520 -0
- crackerjack/agents/dry_agent.py +585 -0
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +230 -0
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/import_optimization_agent.py +1181 -0
- crackerjack/agents/performance_agent.py +325 -0
- crackerjack/agents/performance_helpers.py +205 -0
- crackerjack/agents/proactive_agent.py +55 -0
- crackerjack/agents/refactoring_agent.py +511 -0
- crackerjack/agents/refactoring_helpers.py +247 -0
- crackerjack/agents/security_agent.py +793 -0
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +570 -0
- crackerjack/agents/test_specialist_agent.py +526 -0
- crackerjack/agents/tracker.py +110 -0
- crackerjack/api.py +647 -0
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/cache_handlers.py +209 -0
- crackerjack/cli/cache_handlers_enhanced.py +680 -0
- crackerjack/cli/facade.py +162 -0
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +700 -0
- crackerjack/cli/interactive.py +488 -0
- crackerjack/cli/options.py +1216 -0
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/utils.py +19 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +1307 -0
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +275 -0
- crackerjack/config/global_lock_config.py +207 -0
- crackerjack/config/hooks.py +390 -0
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +738 -0
- crackerjack/core/autofix_coordinator.py +282 -0
- crackerjack/core/container.py +105 -0
- crackerjack/core/enhanced_container.py +583 -0
- crackerjack/core/file_lifecycle.py +472 -0
- crackerjack/core/performance.py +244 -0
- crackerjack/core/performance_monitor.py +357 -0
- crackerjack/core/phase_coordinator.py +1227 -0
- crackerjack/core/proactive_workflow.py +267 -0
- crackerjack/core/resource_manager.py +425 -0
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +601 -0
- crackerjack/core/session_coordinator.py +239 -0
- crackerjack/core/timeout_manager.py +563 -0
- crackerjack/core/websocket_lifecycle.py +410 -0
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +2243 -0
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/INDEX.md +11 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +767 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +1065 -0
- crackerjack/dynamic_config.py +678 -0
- crackerjack/errors.py +378 -0
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +13 -0
- crackerjack/executors/async_hook_executor.py +938 -0
- crackerjack/executors/cached_hook_executor.py +316 -0
- crackerjack/executors/hook_executor.py +1295 -0
- crackerjack/executors/hook_lock_manager.py +708 -0
- crackerjack/executors/individual_hook_executor.py +739 -0
- crackerjack/executors/lsp_aware_hook_executor.py +349 -0
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +433 -0
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +93 -0
- crackerjack/intelligence/README.md +557 -0
- crackerjack/intelligence/__init__.py +37 -0
- crackerjack/intelligence/adaptive_learning.py +693 -0
- crackerjack/intelligence/agent_orchestrator.py +485 -0
- crackerjack/intelligence/agent_registry.py +377 -0
- crackerjack/intelligence/agent_selector.py +439 -0
- crackerjack/intelligence/integration.py +250 -0
- crackerjack/interactive.py +719 -0
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +585 -0
- crackerjack/managers/publish_manager.py +631 -0
- crackerjack/managers/test_command_builder.py +391 -0
- crackerjack/managers/test_executor.py +474 -0
- crackerjack/managers/test_manager.py +1357 -0
- crackerjack/managers/test_progress.py +187 -0
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +352 -0
- crackerjack/mcp/client_runner.py +121 -0
- crackerjack/mcp/context.py +802 -0
- crackerjack/mcp/dashboard.py +657 -0
- crackerjack/mcp/enhanced_progress_monitor.py +493 -0
- crackerjack/mcp/file_monitor.py +394 -0
- crackerjack/mcp/progress_components.py +607 -0
- crackerjack/mcp/progress_monitor.py +1016 -0
- crackerjack/mcp/rate_limiter.py +336 -0
- crackerjack/mcp/server.py +24 -0
- crackerjack/mcp/server_core.py +526 -0
- crackerjack/mcp/service_watchdog.py +505 -0
- crackerjack/mcp/state.py +407 -0
- crackerjack/mcp/task_manager.py +259 -0
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +19 -0
- crackerjack/mcp/tools/core_tools.py +469 -0
- crackerjack/mcp/tools/error_analyzer.py +283 -0
- crackerjack/mcp/tools/execution_tools.py +384 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
- crackerjack/mcp/tools/intelligence_tools.py +264 -0
- crackerjack/mcp/tools/monitoring_tools.py +628 -0
- crackerjack/mcp/tools/proactive_tools.py +367 -0
- crackerjack/mcp/tools/progress_tools.py +222 -0
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +358 -0
- crackerjack/mcp/tools/workflow_executor.py +699 -0
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +54 -0
- crackerjack/mcp/websocket/endpoints.py +492 -0
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +406 -0
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
- crackerjack/mcp/websocket/server.py +174 -0
- crackerjack/mcp/websocket/websocket_handler.py +276 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +40 -0
- crackerjack/models/config.py +730 -0
- crackerjack/models/config_adapter.py +265 -0
- crackerjack/models/protocols.py +1535 -0
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/resource_protocols.py +299 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +173 -0
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +405 -0
- crackerjack/monitoring/metrics_collector.py +427 -0
- crackerjack/monitoring/regression_prevention.py +580 -0
- crackerjack/monitoring/websocket_server.py +406 -0
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +894 -0
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +180 -0
- crackerjack/orchestration/execution_strategies.py +361 -0
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +647 -0
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +254 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +264 -0
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/security/__init__.py +0 -0
- crackerjack/security/audit.py +197 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +9 -0
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/ai/contextual_ai_assistant.py +542 -0
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +617 -0
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +530 -0
- crackerjack/services/cache.py +369 -0
- crackerjack/services/changelog_automation.py +399 -0
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +132 -0
- crackerjack/services/config_merge.py +546 -0
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +493 -0
- crackerjack/services/coverage_badge_service.py +173 -0
- crackerjack/services/coverage_ratchet.py +381 -0
- crackerjack/services/debug.py +733 -0
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +622 -0
- crackerjack/services/documentation_generator.py +493 -0
- crackerjack/services/documentation_service.py +704 -0
- crackerjack/services/enhanced_filesystem.py +497 -0
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +149 -0
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +381 -0
- crackerjack/services/git.py +422 -0
- crackerjack/services/health_metrics.py +615 -0
- crackerjack/services/heatmap_generator.py +744 -0
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +823 -0
- crackerjack/services/input_validator.py +668 -0
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +289 -0
- crackerjack/services/logging.py +228 -0
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +414 -0
- crackerjack/services/metrics.py +587 -0
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/monitoring/performance_benchmarks.py +410 -0
- crackerjack/services/monitoring/performance_cache.py +388 -0
- crackerjack/services/monitoring/performance_monitor.py +569 -0
- crackerjack/services/parallel_executor.py +527 -0
- crackerjack/services/pattern_cache.py +333 -0
- crackerjack/services/pattern_detector.py +478 -0
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +523 -0
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/quality/quality_baseline.py +395 -0
- crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
- crackerjack/services/quality/quality_intelligence.py +949 -0
- crackerjack/services/regex_patterns.py +58 -0
- crackerjack/services/regex_utils.py +483 -0
- crackerjack/services/secure_path_utils.py +524 -0
- crackerjack/services/secure_status_formatter.py +450 -0
- crackerjack/services/secure_subprocess.py +635 -0
- crackerjack/services/security.py +239 -0
- crackerjack/services/security_logger.py +495 -0
- crackerjack/services/server_manager.py +411 -0
- crackerjack/services/smart_scheduling.py +167 -0
- crackerjack/services/status_authentication.py +460 -0
- crackerjack/services/status_security_manager.py +315 -0
- crackerjack/services/terminal_utils.py +0 -0
- crackerjack/services/thread_safe_status_collector.py +441 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +43 -0
- crackerjack/services/unified_config.py +115 -0
- crackerjack/services/validation_rate_limiter.py +220 -0
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +461 -0
- crackerjack/services/version_checker.py +223 -0
- crackerjack/services/websocket_resource_limiter.py +438 -0
- crackerjack/services/zuban_lsp_service.py +391 -0
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/__init__.py +59 -0
- crackerjack/slash_commands/init.md +112 -0
- crackerjack/slash_commands/run.md +197 -0
- crackerjack/slash_commands/status.md +127 -0
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_input_validator_patterns.py +236 -0
- crackerjack/tools/validate_regex_patterns.py +188 -0
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/__init__.py +1 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- crackerjack-0.45.2.dist-info/METADATA +1678 -0
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -14
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config.yaml +0 -91
- crackerjack/.pytest_cache/.gitignore +0 -2
- crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
- crackerjack/.pytest_cache/README.md +0 -8
- crackerjack/.pytest_cache/v/cache/nodeids +0 -1
- crackerjack/.pytest_cache/v/cache/stepwise +0 -1
- crackerjack/.ruff_cache/.gitignore +0 -1
- crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
- crackerjack/crackerjack.py +0 -855
- crackerjack/pyproject.toml +0 -214
- crackerjack-0.18.2.dist-info/METADATA +0 -420
- crackerjack-0.18.2.dist-info/RECORD +0 -59
- crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
> Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Data](<./README.md>)
|
|
2
|
+
|
|
3
|
+
# Data
|
|
4
|
+
|
|
5
|
+
Static data and assets used by the package (keep small; large assets belong elsewhere).
|
|
6
|
+
|
|
7
|
+
## Related
|
|
8
|
+
|
|
9
|
+
- [Crackerjack Package](<../README.md>) - Parent package
|
|
10
|
+
- [Documentation](<../documentation/README.md>) - Documentation helpers
|
|
11
|
+
- [UI Templates](<../ui/templates/README.md>) - UI template files
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Data access layer utilities backed by ACB infrastructure."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from crackerjack.data.models import QualityBaselineRecord
|
|
6
|
+
from crackerjack.data.repository import QualityBaselineRepository
|
|
7
|
+
|
|
8
|
+
__all__ = ["QualityBaselineRecord", "QualityBaselineRepository"]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""SQLModel data models for the Crackerjack data layer."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import JSON, Column, DateTime, String
|
|
9
|
+
from sqlmodel import Field, SQLModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QualityBaselineRecord(SQLModel, table=True):
|
|
13
|
+
"""Persistent representation of quality metrics for a git revision."""
|
|
14
|
+
|
|
15
|
+
__tablename__ = "quality_baselines"
|
|
16
|
+
|
|
17
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
18
|
+
git_hash: str = Field(sa_column=Column(String(64), unique=True, index=True))
|
|
19
|
+
recorded_at: datetime = Field(
|
|
20
|
+
default_factory=datetime.utcnow,
|
|
21
|
+
sa_column=Column(DateTime(timezone=True), index=True),
|
|
22
|
+
)
|
|
23
|
+
coverage_percent: float = Field(default=0.0)
|
|
24
|
+
test_count: int = Field(default=0)
|
|
25
|
+
test_pass_rate: float = Field(default=0.0)
|
|
26
|
+
hook_failures: int = Field(default=0)
|
|
27
|
+
complexity_violations: int = Field(default=0)
|
|
28
|
+
security_issues: int = Field(default=0)
|
|
29
|
+
type_errors: int = Field(default=0)
|
|
30
|
+
linting_issues: int = Field(default=0)
|
|
31
|
+
quality_score: int = Field(default=0)
|
|
32
|
+
extra_metadata: dict[str, Any] | None = Field(
|
|
33
|
+
default=None,
|
|
34
|
+
sa_column=Column(JSON, nullable=True),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def update_from_dict(self, data: dict[str, Any]) -> None:
|
|
38
|
+
"""Update this record in-place from a dictionary of values."""
|
|
39
|
+
for key, value in data.items():
|
|
40
|
+
if not hasattr(self, key):
|
|
41
|
+
continue
|
|
42
|
+
setattr(self, key, value)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ProjectHealthRecord(SQLModel, table=True):
|
|
46
|
+
"""Persistent representation of project health metrics."""
|
|
47
|
+
|
|
48
|
+
__tablename__ = "project_health"
|
|
49
|
+
|
|
50
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
51
|
+
project_root: str = Field(sa_column=Column(String(255), unique=True, index=True))
|
|
52
|
+
lint_error_trend: list[int] = Field(default_factory=list, sa_column=Column(JSON))
|
|
53
|
+
test_coverage_trend: list[float] = Field(
|
|
54
|
+
default_factory=list,
|
|
55
|
+
sa_column=Column(JSON),
|
|
56
|
+
)
|
|
57
|
+
dependency_age: dict[str, int] = Field(
|
|
58
|
+
default_factory=dict,
|
|
59
|
+
sa_column=Column(JSON),
|
|
60
|
+
)
|
|
61
|
+
config_completeness: float = Field(default=0.0)
|
|
62
|
+
last_updated: datetime = Field(
|
|
63
|
+
default_factory=datetime.utcnow,
|
|
64
|
+
sa_column=Column(DateTime(timezone=True)),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class DependencyMonitorCacheRecord(SQLModel, table=True):
|
|
69
|
+
"""Cache entry for dependency monitor state."""
|
|
70
|
+
|
|
71
|
+
__tablename__ = "dependency_monitor_cache"
|
|
72
|
+
|
|
73
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
74
|
+
project_root: str = Field(sa_column=Column(String(255), unique=True, index=True))
|
|
75
|
+
cache_data: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON))
|
|
76
|
+
updated_at: datetime = Field(
|
|
77
|
+
default_factory=datetime.utcnow,
|
|
78
|
+
sa_column=Column(DateTime(timezone=True)),
|
|
79
|
+
)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""Data repositories backed by ACB SQL adapter."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import typing as t
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from crackerjack.data.models import (
|
|
10
|
+
DependencyMonitorCacheRecord,
|
|
11
|
+
ProjectHealthRecord,
|
|
12
|
+
QualityBaselineRecord,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
LOGGER = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from acb.depends import depends
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from acb.adapters.models._hybrid import ACBQuery # type: ignore[attr-defined]
|
|
22
|
+
from acb.adapters.models._memory import (
|
|
23
|
+
MemoryDatabaseAdapter, # type: ignore[attr-defined]
|
|
24
|
+
)
|
|
25
|
+
from acb.adapters.models._pydantic import (
|
|
26
|
+
PydanticModelAdapter, # type: ignore[attr-defined]
|
|
27
|
+
)
|
|
28
|
+
from acb.adapters.models._query import registry # type: ignore[attr-defined]
|
|
29
|
+
|
|
30
|
+
# Register in-memory adapters for default usage
|
|
31
|
+
registry.register_database_adapter("memory", MemoryDatabaseAdapter())
|
|
32
|
+
registry.register_model_adapter("pydantic", PydanticModelAdapter())
|
|
33
|
+
|
|
34
|
+
# ACB hybrid query is available - use in-memory adapter as default
|
|
35
|
+
# (SQL/NoSQL adapters can be configured when those databases are set up)
|
|
36
|
+
_query_instance = ACBQuery(
|
|
37
|
+
database_adapter_name="memory",
|
|
38
|
+
model_adapter_name="pydantic",
|
|
39
|
+
)
|
|
40
|
+
depends.set(ACBQuery, _query_instance)
|
|
41
|
+
|
|
42
|
+
except ImportError: # pragma: no cover - fallback when hybrid query missing
|
|
43
|
+
LOGGER.warning(
|
|
44
|
+
"ACB hybrid query adapter not available; using in-memory query fallback.",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
class _InMemorySimpleOps:
|
|
48
|
+
def __init__(self, model: type[Any], store: list[Any]) -> None:
|
|
49
|
+
self._model = model
|
|
50
|
+
self._store = store
|
|
51
|
+
|
|
52
|
+
async def create_or_update(
|
|
53
|
+
self,
|
|
54
|
+
data: dict[str, Any],
|
|
55
|
+
key_field: str,
|
|
56
|
+
) -> Any:
|
|
57
|
+
key_value = data.get(key_field)
|
|
58
|
+
for existing in self._store:
|
|
59
|
+
if getattr(existing, key_field, None) == key_value:
|
|
60
|
+
if hasattr(existing, "update_from_dict"):
|
|
61
|
+
existing.update_from_dict(data)
|
|
62
|
+
else:
|
|
63
|
+
for key, value in data.items():
|
|
64
|
+
if hasattr(existing, key):
|
|
65
|
+
setattr(existing, key, value)
|
|
66
|
+
return existing
|
|
67
|
+
instance = self._model(**data)
|
|
68
|
+
self._store.append(instance)
|
|
69
|
+
return instance
|
|
70
|
+
|
|
71
|
+
async def find(self, **filters: Any) -> Any | None:
|
|
72
|
+
for existing in self._store:
|
|
73
|
+
if all(
|
|
74
|
+
getattr(existing, key, None) == value
|
|
75
|
+
for key, value in filters.items()
|
|
76
|
+
):
|
|
77
|
+
return existing
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
async def delete(self, **filters: Any) -> bool:
|
|
81
|
+
to_remove = [
|
|
82
|
+
existing
|
|
83
|
+
for existing in self._store
|
|
84
|
+
if all(
|
|
85
|
+
getattr(existing, key, None) == value
|
|
86
|
+
for key, value in filters.items()
|
|
87
|
+
)
|
|
88
|
+
]
|
|
89
|
+
for item in to_remove:
|
|
90
|
+
self._store.remove(item)
|
|
91
|
+
return bool(to_remove)
|
|
92
|
+
|
|
93
|
+
async def all(self) -> list[Any]:
|
|
94
|
+
return self._store.copy()
|
|
95
|
+
|
|
96
|
+
class _InMemoryAdvancedOps:
|
|
97
|
+
def __init__(self, simple_ops: _InMemorySimpleOps) -> None:
|
|
98
|
+
self._simple = simple_ops
|
|
99
|
+
self._order_field: str | None = None
|
|
100
|
+
self._limit: int | None = None
|
|
101
|
+
|
|
102
|
+
def order_by_desc(self, field: str) -> _InMemoryAdvancedOps:
|
|
103
|
+
self._order_field = field
|
|
104
|
+
return self
|
|
105
|
+
|
|
106
|
+
def limit(self, limit: int) -> _InMemoryAdvancedOps:
|
|
107
|
+
self._limit = limit
|
|
108
|
+
return self
|
|
109
|
+
|
|
110
|
+
async def all(self) -> list[Any]:
|
|
111
|
+
records = await self._simple.all()
|
|
112
|
+
if self._order_field:
|
|
113
|
+
|
|
114
|
+
def key_fn(item: Any) -> Any:
|
|
115
|
+
return getattr(item, self._order_field or "", None)
|
|
116
|
+
|
|
117
|
+
records.sort(key=key_fn, reverse=True)
|
|
118
|
+
if self._limit is not None:
|
|
119
|
+
records = records[: self._limit]
|
|
120
|
+
return records
|
|
121
|
+
|
|
122
|
+
class _InMemoryModelInterface:
|
|
123
|
+
def __init__(self, model: type[Any], store: list[Any]) -> None:
|
|
124
|
+
self.simple = _InMemorySimpleOps(model, store)
|
|
125
|
+
self.advanced = _InMemoryAdvancedOps(self.simple)
|
|
126
|
+
|
|
127
|
+
class ACBQuery: # type: ignore[no-redef]
|
|
128
|
+
def __init__(self) -> None:
|
|
129
|
+
self._stores: dict[type[Any], list[Any]] = {}
|
|
130
|
+
|
|
131
|
+
def for_model(self, model: type[Any]) -> _InMemoryModelInterface:
|
|
132
|
+
if model not in self._stores:
|
|
133
|
+
self._stores[model] = []
|
|
134
|
+
return _InMemoryModelInterface(model, self._stores[model])
|
|
135
|
+
|
|
136
|
+
depends.set(ACBQuery, ACBQuery())
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class QualityBaselineRepository:
|
|
140
|
+
def __init__(self) -> None:
|
|
141
|
+
self.query = depends.get_sync(ACBQuery)
|
|
142
|
+
|
|
143
|
+
async def upsert(self, data: dict[str, Any]) -> QualityBaselineRecord:
|
|
144
|
+
result = await self.query.for_model(
|
|
145
|
+
QualityBaselineRecord
|
|
146
|
+
).simple.create_or_update(data, "git_hash")
|
|
147
|
+
return t.cast(QualityBaselineRecord, result)
|
|
148
|
+
|
|
149
|
+
async def get_by_git_hash(self, git_hash: str) -> QualityBaselineRecord | None:
|
|
150
|
+
result = await self.query.for_model(QualityBaselineRecord).simple.find(
|
|
151
|
+
git_hash=git_hash
|
|
152
|
+
)
|
|
153
|
+
return t.cast(QualityBaselineRecord | None, result)
|
|
154
|
+
|
|
155
|
+
async def list_recent(self, limit: int = 10) -> list[QualityBaselineRecord]:
|
|
156
|
+
result = (
|
|
157
|
+
await self.query.for_model(QualityBaselineRecord)
|
|
158
|
+
.advanced.order_by_desc("recorded_at")
|
|
159
|
+
.limit(limit)
|
|
160
|
+
.all()
|
|
161
|
+
)
|
|
162
|
+
return t.cast(list[QualityBaselineRecord], result)
|
|
163
|
+
|
|
164
|
+
async def delete_for_git_hash(self, git_hash: str) -> bool:
|
|
165
|
+
result = await self.query.for_model(QualityBaselineRecord).simple.delete(
|
|
166
|
+
git_hash=git_hash
|
|
167
|
+
)
|
|
168
|
+
return t.cast(bool, result)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class HealthMetricsRepository:
|
|
172
|
+
def __init__(self) -> None:
|
|
173
|
+
self.query = depends.get_sync(ACBQuery)
|
|
174
|
+
|
|
175
|
+
async def upsert(
|
|
176
|
+
self,
|
|
177
|
+
project_root: str,
|
|
178
|
+
data: dict[str, Any],
|
|
179
|
+
) -> ProjectHealthRecord:
|
|
180
|
+
result = await self.query.for_model(
|
|
181
|
+
ProjectHealthRecord
|
|
182
|
+
).simple.create_or_update(data, "project_root")
|
|
183
|
+
return t.cast(ProjectHealthRecord, result)
|
|
184
|
+
|
|
185
|
+
async def get(self, project_root: str) -> ProjectHealthRecord | None:
|
|
186
|
+
result = await self.query.for_model(ProjectHealthRecord).simple.find(
|
|
187
|
+
project_root=project_root
|
|
188
|
+
)
|
|
189
|
+
return t.cast(ProjectHealthRecord | None, result)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class DependencyMonitorRepository:
|
|
193
|
+
def __init__(self) -> None:
|
|
194
|
+
self.query = depends.get_sync(ACBQuery)
|
|
195
|
+
|
|
196
|
+
async def upsert(
|
|
197
|
+
self,
|
|
198
|
+
project_root: str,
|
|
199
|
+
cache_data: dict[str, Any],
|
|
200
|
+
) -> DependencyMonitorCacheRecord:
|
|
201
|
+
result = await self.query.for_model(
|
|
202
|
+
DependencyMonitorCacheRecord
|
|
203
|
+
).simple.create_or_update(cache_data, "project_root")
|
|
204
|
+
return t.cast(DependencyMonitorCacheRecord, result)
|
|
205
|
+
|
|
206
|
+
async def get(self, project_root: str) -> DependencyMonitorCacheRecord | None:
|
|
207
|
+
result = await self.query.for_model(DependencyMonitorCacheRecord).simple.find(
|
|
208
|
+
project_root=project_root
|
|
209
|
+
)
|
|
210
|
+
return t.cast(DependencyMonitorCacheRecord | None, result)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
> Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Decorators](<./README.md>)
|
|
2
|
+
|
|
3
|
+
# Decorators
|
|
4
|
+
|
|
5
|
+
Cross-cutting decorators and helper wrappers for error handling, retry logic, validation, and performance optimization. All decorators support both sync and async functions automatically.
|
|
6
|
+
|
|
7
|
+
## Available Decorators
|
|
8
|
+
|
|
9
|
+
### Error Handling
|
|
10
|
+
|
|
11
|
+
**`handle_errors`** - Centralized error handling with transformation and fallback support
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from crackerjack.decorators import handle_errors
|
|
15
|
+
from crackerjack.errors import FileError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@handle_errors(
|
|
19
|
+
error_types=[FileNotFoundError, PermissionError],
|
|
20
|
+
transform_to=FileError,
|
|
21
|
+
fallback={},
|
|
22
|
+
)
|
|
23
|
+
def load_config(path: str) -> dict:
|
|
24
|
+
with open(path) as f:
|
|
25
|
+
return json.load(f)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**`log_errors`** - Log errors with context before re-raising
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import logging
|
|
32
|
+
from crackerjack.decorators import log_errors
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@log_errors(logger=logger, level="error", include_traceback=True)
|
|
38
|
+
async def critical_operation() -> bool:
|
|
39
|
+
return await perform_operation()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**`graceful_degradation`** - Gracefully degrade on errors with optional warnings
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from crackerjack.decorators import graceful_degradation
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@graceful_degradation(fallback_value=[], warn=True)
|
|
49
|
+
def get_optional_features() -> list[str]:
|
|
50
|
+
# Returns [] on error with warning
|
|
51
|
+
return fetch_features()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Retry and Timeout
|
|
55
|
+
|
|
56
|
+
**`retry`** - Retry decorator with exponential backoff
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from crackerjack.decorators import retry
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@retry(max_attempts=3, exceptions=[ConnectionError], backoff=0.5)
|
|
63
|
+
async def fetch_data() -> dict:
|
|
64
|
+
return await api_client.get()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**`with_timeout`** - Timeout enforcement for long-running operations
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from crackerjack.decorators import with_timeout
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@with_timeout(seconds=30, error_message="Operation timed out")
|
|
74
|
+
def heavy_computation() -> int:
|
|
75
|
+
return compute_result()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Validation
|
|
79
|
+
|
|
80
|
+
**`validate_args`** - Validate function arguments using callables and type checks
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from crackerjack.decorators import validate_args
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@validate_args(
|
|
87
|
+
validators={"path": lambda p: Path(p).exists(), "count": lambda n: n > 0},
|
|
88
|
+
type_check=True,
|
|
89
|
+
)
|
|
90
|
+
def process_files(path: str, count: int) -> bool:
|
|
91
|
+
return True
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Pattern Detection
|
|
95
|
+
|
|
96
|
+
**`cache_errors`** - Detect and cache error patterns for AI-powered analysis
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from crackerjack.decorators import cache_errors
|
|
100
|
+
from pathlib import Path
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@cache_errors(error_type="lint", auto_analyze=True)
|
|
104
|
+
async def run_linter(files: list[Path]) -> bool:
|
|
105
|
+
# Errors automatically cached and analyzed
|
|
106
|
+
return await linter.run(files)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Best Practices
|
|
110
|
+
|
|
111
|
+
### Complexity Guidelines
|
|
112
|
+
|
|
113
|
+
Keep decorator implementation complexity ≤15 per function using helper methods:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
def _create_async_wrapper(func, config):
|
|
117
|
+
"""Helper to create async wrapper - reduces complexity."""
|
|
118
|
+
|
|
119
|
+
@wraps(func)
|
|
120
|
+
async def wrapper(*args, **kwargs):
|
|
121
|
+
return await func(*args, **kwargs)
|
|
122
|
+
|
|
123
|
+
return wrapper
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Sync and Async Support
|
|
127
|
+
|
|
128
|
+
All decorators automatically detect function type using `is_async_function`:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from crackerjack.decorators.helpers import is_async_function
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def decorator(func):
|
|
135
|
+
if is_async_function(func):
|
|
136
|
+
return _create_async_wrapper(func)
|
|
137
|
+
return _create_sync_wrapper(func)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Error Context
|
|
141
|
+
|
|
142
|
+
Use `get_function_context` for rich error reporting:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from crackerjack.decorators.helpers import get_function_context
|
|
146
|
+
|
|
147
|
+
context = get_function_context(func)
|
|
148
|
+
# Returns: {
|
|
149
|
+
# "function_name": "my_function",
|
|
150
|
+
# "module": "mymodule",
|
|
151
|
+
# "qualname": "MyClass.my_function",
|
|
152
|
+
# "is_async": True
|
|
153
|
+
# }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Combining Decorators
|
|
157
|
+
|
|
158
|
+
Stack decorators from innermost to outermost:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
@log_errors()
|
|
162
|
+
@retry(max_attempts=3)
|
|
163
|
+
@with_timeout(seconds=30)
|
|
164
|
+
@handle_errors(fallback={})
|
|
165
|
+
async def fetch_and_process() -> dict:
|
|
166
|
+
return await process()
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Implementation Modules
|
|
170
|
+
|
|
171
|
+
- **`error_handling.py`** - Core error decorators (retry, handle_errors, timeout, etc.)
|
|
172
|
+
- **`patterns.py`** - Pattern detection decorators (cache_errors)
|
|
173
|
+
- **`utils.py`** - Shared utilities for decorator implementation
|
|
174
|
+
|
|
175
|
+
## Related
|
|
176
|
+
|
|
177
|
+
- [Exceptions](<../exceptions/README.md>) - Custom exception types
|
|
178
|
+
- [Errors](../errors/README.md) - Error handling and error types
|
|
179
|
+
- [MCP Cache](<../mcp/README.md>) - Error pattern caching for AI analysis
|
|
180
|
+
- [Architecture: ACB Patterns](../../docs/guides/CLAUDE.md#critical-architectural-pattern-protocol-based-di) - Dependency injection patterns
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .error_handling import (
|
|
2
|
+
graceful_degradation,
|
|
3
|
+
handle_errors,
|
|
4
|
+
log_errors,
|
|
5
|
+
retry,
|
|
6
|
+
validate_args,
|
|
7
|
+
with_timeout,
|
|
8
|
+
)
|
|
9
|
+
from .error_handling_decorators import (
|
|
10
|
+
handle_all_errors,
|
|
11
|
+
handle_file_errors,
|
|
12
|
+
handle_json_errors,
|
|
13
|
+
handle_network_errors,
|
|
14
|
+
handle_subprocess_errors,
|
|
15
|
+
handle_validation_errors,
|
|
16
|
+
retry_on_error,
|
|
17
|
+
)
|
|
18
|
+
from .patterns import cache_errors
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"retry",
|
|
22
|
+
"handle_errors",
|
|
23
|
+
"with_timeout",
|
|
24
|
+
"log_errors",
|
|
25
|
+
"graceful_degradation",
|
|
26
|
+
"validate_args",
|
|
27
|
+
"handle_file_errors",
|
|
28
|
+
"handle_json_errors",
|
|
29
|
+
"handle_subprocess_errors",
|
|
30
|
+
"handle_validation_errors",
|
|
31
|
+
"handle_network_errors",
|
|
32
|
+
"handle_all_errors",
|
|
33
|
+
"retry_on_error",
|
|
34
|
+
"cache_errors",
|
|
35
|
+
]
|