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,391 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import psutil
|
|
5
|
+
from acb.console import Console
|
|
6
|
+
from acb.depends import Inject, depends
|
|
7
|
+
|
|
8
|
+
from crackerjack.config.settings import CrackerjackSettings
|
|
9
|
+
from crackerjack.models.protocols import OptionsProtocol
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestCommandBuilder:
|
|
13
|
+
@depends.inject
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
pkg_path: Inject[Path],
|
|
17
|
+
console: Inject[Console],
|
|
18
|
+
settings: Inject[CrackerjackSettings],
|
|
19
|
+
) -> None:
|
|
20
|
+
# Normalize to pathlib.Path to avoid async path methods
|
|
21
|
+
try:
|
|
22
|
+
self.pkg_path = Path(str(pkg_path))
|
|
23
|
+
except Exception:
|
|
24
|
+
self.pkg_path = Path(pkg_path)
|
|
25
|
+
|
|
26
|
+
self.console = console
|
|
27
|
+
self.settings = settings
|
|
28
|
+
|
|
29
|
+
def build_command(self, options: OptionsProtocol) -> list[str]:
|
|
30
|
+
cmd = ["uv", "run", "python", "-m", "pytest"]
|
|
31
|
+
|
|
32
|
+
self._add_coverage_options(cmd, options)
|
|
33
|
+
self._add_worker_options(cmd, options)
|
|
34
|
+
self._add_benchmark_options(cmd, options)
|
|
35
|
+
self._add_timeout_options(cmd, options)
|
|
36
|
+
self._add_verbosity_options(cmd, options)
|
|
37
|
+
self._add_test_path(cmd)
|
|
38
|
+
|
|
39
|
+
return cmd
|
|
40
|
+
|
|
41
|
+
def _handle_not_implemented_error(self, print_info: bool) -> int:
|
|
42
|
+
"""Handle NotImplementedError specifically."""
|
|
43
|
+
if print_info and self.console:
|
|
44
|
+
self.console.print(
|
|
45
|
+
"[yellow]⚠️ CPU detection unavailable, using 2 workers[/yellow]"
|
|
46
|
+
)
|
|
47
|
+
return 2
|
|
48
|
+
|
|
49
|
+
def _handle_general_error(self, print_info: bool, e: Exception) -> int:
|
|
50
|
+
"""Handle general exceptions gracefully."""
|
|
51
|
+
if print_info and self.console:
|
|
52
|
+
self.console.print(
|
|
53
|
+
f"[yellow]⚠️ Worker detection failed: {e}. Using 2 workers.[/yellow]"
|
|
54
|
+
)
|
|
55
|
+
return 2
|
|
56
|
+
|
|
57
|
+
def get_optimal_workers(
|
|
58
|
+
self, options: OptionsProtocol, print_info: bool = True
|
|
59
|
+
) -> int | str:
|
|
60
|
+
"""Calculate optimal worker count using pytest-xdist.
|
|
61
|
+
|
|
62
|
+
This method leverages pytest-xdist's built-in '-n auto' for CPU detection
|
|
63
|
+
while adding memory safety checks and support for custom worker configurations.
|
|
64
|
+
|
|
65
|
+
Worker Selection Logic:
|
|
66
|
+
----------------------
|
|
67
|
+
1. Emergency rollback: CRACKERJACK_DISABLE_AUTO_WORKERS=1 → 1 worker
|
|
68
|
+
2. Explicit value (test_workers > 0): Use as-is
|
|
69
|
+
3. Auto-detect (test_workers = 0 AND auto_detect_workers=True): Return "auto"
|
|
70
|
+
4. Legacy mode (test_workers = 0 AND auto_detect_workers=False): 1 worker
|
|
71
|
+
5. Fractional (test_workers < 0): Divide CPU count by abs(value)
|
|
72
|
+
|
|
73
|
+
Safety Bounds:
|
|
74
|
+
-------------
|
|
75
|
+
- Minimum: 1 worker (sequential execution)
|
|
76
|
+
- Maximum: 8 workers (configurable via settings.testing.max_workers)
|
|
77
|
+
- Memory: 2GB per worker minimum (configurable)
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
--------
|
|
81
|
+
>>> options = Options(test_workers=4)
|
|
82
|
+
>>> builder.get_optimal_workers(options)
|
|
83
|
+
4 # Explicit value
|
|
84
|
+
|
|
85
|
+
>>> options = Options(test_workers=0) # auto_detect_workers=True
|
|
86
|
+
>>> builder.get_optimal_workers(options)
|
|
87
|
+
"auto" # Delegates to pytest-xdist
|
|
88
|
+
|
|
89
|
+
>>> options = Options(test_workers=-2) # 8-core machine
|
|
90
|
+
>>> builder.get_optimal_workers(options)
|
|
91
|
+
4 # 8 // 2 = 4 (with memory safety check)
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
int | str: Number of workers (1-8) or "auto" for pytest-xdist detection
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
Never raises - returns safe default (2) on any error
|
|
98
|
+
"""
|
|
99
|
+
try:
|
|
100
|
+
# Check for emergency rollback
|
|
101
|
+
if self._check_emergency_rollback(print_info):
|
|
102
|
+
return 1
|
|
103
|
+
|
|
104
|
+
# Check explicit worker count
|
|
105
|
+
explicit_result = self._check_explicit_workers(options, print_info)
|
|
106
|
+
if explicit_result is not None:
|
|
107
|
+
return explicit_result
|
|
108
|
+
|
|
109
|
+
# Check auto-detection
|
|
110
|
+
auto_result = self._check_auto_detection(options, print_info)
|
|
111
|
+
if auto_result is not None:
|
|
112
|
+
return auto_result
|
|
113
|
+
|
|
114
|
+
# Check fractional workers
|
|
115
|
+
fractional_result = self._check_fractional_workers(options, print_info)
|
|
116
|
+
if fractional_result is not None:
|
|
117
|
+
return fractional_result
|
|
118
|
+
|
|
119
|
+
# Safe default if no conditions match
|
|
120
|
+
return 2
|
|
121
|
+
|
|
122
|
+
except NotImplementedError:
|
|
123
|
+
return self._handle_not_implemented_error(print_info)
|
|
124
|
+
except Exception as e:
|
|
125
|
+
return self._handle_general_error(print_info, e)
|
|
126
|
+
|
|
127
|
+
def _check_emergency_rollback(self, print_info: bool) -> bool:
|
|
128
|
+
"""Check for emergency rollback via environment variable."""
|
|
129
|
+
if os.getenv("CRACKERJACK_DISABLE_AUTO_WORKERS") == "1":
|
|
130
|
+
if print_info and self.console:
|
|
131
|
+
self.console.print(
|
|
132
|
+
"[yellow]⚠️ Auto-detection disabled via environment variable[/yellow]"
|
|
133
|
+
)
|
|
134
|
+
return True
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
def _check_explicit_workers(
|
|
138
|
+
self, options: OptionsProtocol, print_info: bool
|
|
139
|
+
) -> int | None:
|
|
140
|
+
"""Check for explicit worker count."""
|
|
141
|
+
if hasattr(options, "test_workers") and options.test_workers > 0:
|
|
142
|
+
return options.test_workers
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
def _check_auto_detection(
|
|
146
|
+
self, options: OptionsProtocol, print_info: bool
|
|
147
|
+
) -> str | int | None:
|
|
148
|
+
"""Check for auto-detection setting."""
|
|
149
|
+
if hasattr(options, "test_workers") and options.test_workers == 0:
|
|
150
|
+
# Check if auto-detection is enabled in settings
|
|
151
|
+
if self.settings and self.settings.testing.auto_detect_workers:
|
|
152
|
+
# Show message only when getting optimal workers with print_info=True
|
|
153
|
+
if print_info and self.console:
|
|
154
|
+
self.console.print(
|
|
155
|
+
"[cyan]🔧 Using pytest-xdist auto-detection for workers[/cyan]"
|
|
156
|
+
)
|
|
157
|
+
return "auto" # pytest-xdist will handle CPU detection
|
|
158
|
+
|
|
159
|
+
# Legacy behavior: auto_detect_workers=False
|
|
160
|
+
return 1
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
def _check_fractional_workers(
|
|
164
|
+
self, options: OptionsProtocol, print_info: bool
|
|
165
|
+
) -> int | None:
|
|
166
|
+
"""Check for fractional worker setting."""
|
|
167
|
+
if hasattr(options, "test_workers") and options.test_workers < 0:
|
|
168
|
+
import multiprocessing
|
|
169
|
+
|
|
170
|
+
cpu_count = multiprocessing.cpu_count()
|
|
171
|
+
divisor = abs(options.test_workers)
|
|
172
|
+
workers = max(1, cpu_count // divisor)
|
|
173
|
+
|
|
174
|
+
# Apply memory safety check
|
|
175
|
+
workers = self._apply_memory_limit(workers)
|
|
176
|
+
|
|
177
|
+
if print_info and self.console:
|
|
178
|
+
self.console.print(
|
|
179
|
+
f"[cyan]🔧 Fractional workers: {cpu_count} cores ÷ {divisor} = {workers} workers[/cyan]"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return workers
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
def _apply_memory_limit(self, workers: int) -> int:
|
|
186
|
+
"""Limit workers based on available memory to prevent OOM.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
workers: Desired number of workers
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
int: Worker count limited by available memory
|
|
193
|
+
"""
|
|
194
|
+
try:
|
|
195
|
+
# Get memory threshold from settings (default 2GB per worker)
|
|
196
|
+
memory_per_worker = (
|
|
197
|
+
self.settings.testing.memory_per_worker_gb if self.settings else 2.0
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Calculate available memory in GB
|
|
201
|
+
available_gb = psutil.virtual_memory().available / (1024**3)
|
|
202
|
+
|
|
203
|
+
# Calculate max workers based on memory
|
|
204
|
+
max_by_memory = max(1, int(available_gb / memory_per_worker))
|
|
205
|
+
|
|
206
|
+
# Return the minimum of desired workers and memory-limited workers
|
|
207
|
+
limited_workers = min(workers, max_by_memory)
|
|
208
|
+
|
|
209
|
+
# Log if we're limiting due to memory
|
|
210
|
+
if limited_workers < workers and self.console:
|
|
211
|
+
self.console.print(
|
|
212
|
+
f"[yellow]⚠️ Limited to {limited_workers} workers (available memory: {available_gb:.1f}GB)[/yellow]"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
return limited_workers
|
|
216
|
+
|
|
217
|
+
except Exception:
|
|
218
|
+
# Conservative fallback if psutil fails
|
|
219
|
+
return min(workers, 4)
|
|
220
|
+
|
|
221
|
+
def get_test_timeout(self, options: OptionsProtocol) -> int:
|
|
222
|
+
if hasattr(options, "test_timeout") and options.test_timeout:
|
|
223
|
+
return options.test_timeout
|
|
224
|
+
|
|
225
|
+
if hasattr(options, "benchmark") and options.benchmark:
|
|
226
|
+
return 900
|
|
227
|
+
return 300
|
|
228
|
+
|
|
229
|
+
def _detect_package_name(self) -> str:
|
|
230
|
+
"""Detect the main package name for coverage reporting."""
|
|
231
|
+
# Method 1: Try to read from pyproject.toml
|
|
232
|
+
pyproject_path = self.pkg_path / "pyproject.toml"
|
|
233
|
+
if pyproject_path.exists():
|
|
234
|
+
from contextlib import suppress
|
|
235
|
+
|
|
236
|
+
with suppress(Exception):
|
|
237
|
+
import tomllib
|
|
238
|
+
|
|
239
|
+
with pyproject_path.open("rb") as f:
|
|
240
|
+
data = tomllib.load(f)
|
|
241
|
+
project_name = data.get("project", {}).get("name")
|
|
242
|
+
if project_name:
|
|
243
|
+
# Convert project name to package name (hyphens to underscores)
|
|
244
|
+
return project_name.replace("-", "_")
|
|
245
|
+
# Fall back to directory detection
|
|
246
|
+
|
|
247
|
+
# Method 2: Look for Python packages in the project root
|
|
248
|
+
for item in self.pkg_path.iterdir():
|
|
249
|
+
if (
|
|
250
|
+
item.is_dir()
|
|
251
|
+
and not item.name.startswith(".")
|
|
252
|
+
and item.name not in ("tests", "docs", "build", "dist", "__pycache__")
|
|
253
|
+
and (item / "__init__.py").exists()
|
|
254
|
+
):
|
|
255
|
+
return item.name
|
|
256
|
+
|
|
257
|
+
# Method 3: Fallback to crackerjack if nothing found (for crackerjack itself)
|
|
258
|
+
return "crackerjack"
|
|
259
|
+
|
|
260
|
+
def _add_coverage_options(self, cmd: list[str], options: OptionsProtocol) -> None:
|
|
261
|
+
# Determine package name from project structure
|
|
262
|
+
package_name = self._detect_package_name()
|
|
263
|
+
|
|
264
|
+
cmd.extend(
|
|
265
|
+
[
|
|
266
|
+
f"--cov={package_name}",
|
|
267
|
+
"--cov-report=term-missing",
|
|
268
|
+
"--cov-report=html",
|
|
269
|
+
"--cov-report=json", # Required for badge updates
|
|
270
|
+
"--cov-fail-under=0",
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def _add_worker_options(self, cmd: list[str], options: OptionsProtocol) -> None:
|
|
275
|
+
"""Add pytest-xdist worker options with proper distribution strategy.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
cmd: Command list to append worker options to
|
|
279
|
+
options: Test options containing worker configuration
|
|
280
|
+
"""
|
|
281
|
+
workers = self.get_optimal_workers(options)
|
|
282
|
+
|
|
283
|
+
# Skip benchmarks for parallelization (results get skewed)
|
|
284
|
+
if hasattr(options, "benchmark") and options.benchmark:
|
|
285
|
+
if self.console:
|
|
286
|
+
self.console.print(
|
|
287
|
+
"[yellow]⚠️ Benchmarks running sequentially (parallel execution skews results)[/yellow]"
|
|
288
|
+
)
|
|
289
|
+
return
|
|
290
|
+
|
|
291
|
+
if workers == "auto":
|
|
292
|
+
# Use pytest-xdist's native auto-detection
|
|
293
|
+
cmd.extend(["-n", "auto", "--dist=loadfile"])
|
|
294
|
+
if self.console:
|
|
295
|
+
self.console.print(
|
|
296
|
+
"[cyan]🚀 Tests running with auto-detected workers (--dist=loadfile)[/cyan]"
|
|
297
|
+
)
|
|
298
|
+
elif isinstance(workers, int) and workers > 1:
|
|
299
|
+
# Explicit worker count
|
|
300
|
+
cmd.extend(["-n", str(workers), "--dist=loadfile"])
|
|
301
|
+
if self.console:
|
|
302
|
+
self.console.print(
|
|
303
|
+
f"[cyan]🚀 Tests running with {workers} workers (--dist=loadfile)[/cyan]"
|
|
304
|
+
)
|
|
305
|
+
else:
|
|
306
|
+
# Sequential execution (workers == 1)
|
|
307
|
+
if self.console:
|
|
308
|
+
self.console.print("[cyan]🧪 Tests running sequentially[/cyan]")
|
|
309
|
+
|
|
310
|
+
def _add_benchmark_options(self, cmd: list[str], options: OptionsProtocol) -> None:
|
|
311
|
+
if hasattr(options, "benchmark") and options.benchmark:
|
|
312
|
+
cmd.extend(
|
|
313
|
+
[
|
|
314
|
+
"--benchmark-only",
|
|
315
|
+
"--benchmark-sort=mean",
|
|
316
|
+
"--benchmark-columns=min, max, mean, stddev",
|
|
317
|
+
]
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
def _add_timeout_options(self, cmd: list[str], options: OptionsProtocol) -> None:
|
|
321
|
+
timeout = self.get_test_timeout(options)
|
|
322
|
+
cmd.extend(["--timeout", str(timeout)])
|
|
323
|
+
|
|
324
|
+
def _add_verbosity_options(self, cmd: list[str], options: OptionsProtocol) -> None:
|
|
325
|
+
"""Add verbosity options with enhanced detail levels.
|
|
326
|
+
|
|
327
|
+
Verbosity Levels:
|
|
328
|
+
- Standard (-v): Basic test names
|
|
329
|
+
- Verbose (-vv): Assertions, captured output, test details
|
|
330
|
+
- Extra verbose (-vvv): Full locals, all test internals (ai_debug mode)
|
|
331
|
+
"""
|
|
332
|
+
# Determine verbosity level
|
|
333
|
+
if options.verbose:
|
|
334
|
+
if getattr(options, "ai_debug", False):
|
|
335
|
+
cmd.append("-vvv") # Extra verbose for AI debugging
|
|
336
|
+
self.console.print("[cyan]🔍 Using extra verbose mode (-vvv)[/cyan]")
|
|
337
|
+
else:
|
|
338
|
+
cmd.append("-vv") # Double verbose shows more context
|
|
339
|
+
self.console.print("[cyan]🔍 Using verbose mode (-vv)[/cyan]")
|
|
340
|
+
else:
|
|
341
|
+
cmd.append("-v") # Standard verbose
|
|
342
|
+
|
|
343
|
+
cmd.extend(
|
|
344
|
+
[
|
|
345
|
+
# Longer tracebacks in verbose mode
|
|
346
|
+
"--tb=long" if options.verbose else "--tb=short",
|
|
347
|
+
# Show all test outcomes summary (not just failures)
|
|
348
|
+
"-ra",
|
|
349
|
+
"--strict-markers",
|
|
350
|
+
"--strict-config",
|
|
351
|
+
]
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
def _add_test_path(self, cmd: list[str]) -> None:
|
|
355
|
+
test_paths = ["tests", "test"]
|
|
356
|
+
|
|
357
|
+
for test_path in test_paths:
|
|
358
|
+
full_path = self.pkg_path / test_path
|
|
359
|
+
if full_path.exists() and full_path.is_dir():
|
|
360
|
+
cmd.append(str(full_path))
|
|
361
|
+
return
|
|
362
|
+
|
|
363
|
+
cmd.append(str(self.pkg_path))
|
|
364
|
+
|
|
365
|
+
def build_specific_test_command(self, test_pattern: str) -> list[str]:
|
|
366
|
+
cmd = ["uv", "run", "python", "-m", "pytest", "-v"] # Always use verbose mode
|
|
367
|
+
|
|
368
|
+
cmd.extend(
|
|
369
|
+
[
|
|
370
|
+
"--cov=crackerjack",
|
|
371
|
+
"--cov-report=term-missing",
|
|
372
|
+
]
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
cmd.extend(["-k", test_pattern])
|
|
376
|
+
|
|
377
|
+
self._add_test_path(cmd)
|
|
378
|
+
|
|
379
|
+
return cmd
|
|
380
|
+
|
|
381
|
+
def build_validation_command(self) -> list[str]:
|
|
382
|
+
return [
|
|
383
|
+
"uv",
|
|
384
|
+
"run",
|
|
385
|
+
"python",
|
|
386
|
+
"-m",
|
|
387
|
+
"pytest",
|
|
388
|
+
"--collect-only",
|
|
389
|
+
# Removed --quiet to ensure collection headers are visible
|
|
390
|
+
"tests" if (self.pkg_path / "tests").exists() else ".",
|
|
391
|
+
]
|