crackerjack 0.37.9__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 +30 -1
- crackerjack/__main__.py +342 -1263
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +27 -5
- 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/{rust_tool_manager.py → lsp/_manager.py} +3 -3
- crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
- crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
- 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 +40 -12
- crackerjack/agents/base.py +1 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +49 -53
- crackerjack/agents/dry_agent.py +187 -3
- 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 +6 -8
- 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/performance_agent.py +121 -1152
- crackerjack/agents/refactoring_agent.py +156 -655
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +19 -1605
- crackerjack/api.py +5 -7
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +1 -1
- crackerjack/cli/cache_handlers.py +23 -18
- crackerjack/cli/cache_handlers_enhanced.py +1 -4
- crackerjack/cli/facade.py +70 -8
- 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 +249 -49
- crackerjack/cli/interactive.py +8 -5
- crackerjack/cli/options.py +203 -110
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +60 -24
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +256 -0
- crackerjack/config/global_lock_config.py +191 -54
- crackerjack/config/hooks.py +188 -16
- 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/async_workflow_orchestrator.py +79 -53
- crackerjack/core/autofix_coordinator.py +22 -9
- crackerjack/core/container.py +10 -9
- crackerjack/core/enhanced_container.py +9 -9
- crackerjack/core/performance.py +1 -1
- crackerjack/core/performance_monitor.py +5 -3
- crackerjack/core/phase_coordinator.py +1018 -634
- crackerjack/core/proactive_workflow.py +3 -3
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +167 -23
- crackerjack/core/session_coordinator.py +187 -382
- crackerjack/core/timeout_manager.py +161 -44
- 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 +1247 -953
- 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/README.md +11 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/ai_templates.py +1 -1
- crackerjack/documentation/dual_output_generator.py +11 -9
- crackerjack/documentation/reference_generator.py +104 -59
- crackerjack/dynamic_config.py +52 -61
- crackerjack/errors.py +1 -1
- 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 +2 -0
- crackerjack/executors/async_hook_executor.py +539 -77
- crackerjack/executors/cached_hook_executor.py +3 -3
- crackerjack/executors/hook_executor.py +967 -102
- crackerjack/executors/hook_lock_manager.py +31 -22
- crackerjack/executors/individual_hook_executor.py +66 -32
- crackerjack/executors/lsp_aware_hook_executor.py +136 -57
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +23 -7
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +8 -9
- crackerjack/intelligence/README.md +557 -0
- crackerjack/interactive.py +37 -10
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/async_hook_manager.py +41 -57
- crackerjack/managers/hook_manager.py +449 -79
- crackerjack/managers/publish_manager.py +81 -36
- crackerjack/managers/test_command_builder.py +290 -12
- crackerjack/managers/test_executor.py +93 -8
- crackerjack/managers/test_manager.py +1082 -75
- crackerjack/managers/test_progress.py +118 -26
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/cache.py +25 -2
- crackerjack/mcp/client_runner.py +35 -18
- crackerjack/mcp/context.py +9 -9
- crackerjack/mcp/dashboard.py +24 -8
- crackerjack/mcp/enhanced_progress_monitor.py +34 -23
- crackerjack/mcp/file_monitor.py +27 -6
- crackerjack/mcp/progress_components.py +45 -34
- crackerjack/mcp/progress_monitor.py +6 -9
- crackerjack/mcp/rate_limiter.py +11 -7
- crackerjack/mcp/server.py +2 -0
- crackerjack/mcp/server_core.py +187 -55
- crackerjack/mcp/service_watchdog.py +12 -9
- crackerjack/mcp/task_manager.py +2 -2
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +2 -0
- crackerjack/mcp/tools/core_tools.py +75 -52
- crackerjack/mcp/tools/execution_tools.py +87 -31
- crackerjack/mcp/tools/intelligence_tools.py +2 -2
- crackerjack/mcp/tools/proactive_tools.py +1 -1
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +180 -132
- crackerjack/mcp/tools/workflow_executor.py +87 -46
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/app.py +11 -1
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +27 -4
- 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 +16 -2930
- crackerjack/mcp/websocket/server.py +1 -3
- crackerjack/mcp/websocket/websocket_handler.py +107 -6
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +10 -1
- crackerjack/models/config.py +639 -22
- crackerjack/models/config_adapter.py +6 -6
- crackerjack/models/protocols.py +1167 -23
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +19 -3
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/ai_agent_watchdog.py +5 -4
- crackerjack/monitoring/metrics_collector.py +4 -3
- crackerjack/monitoring/regression_prevention.py +4 -3
- crackerjack/monitoring/websocket_server.py +4 -241
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +20 -67
- 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 +13 -6
- crackerjack/orchestration/execution_strategies.py +6 -6
- 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 +1 -1
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/hooks.py +3 -2
- crackerjack/plugins/loader.py +3 -3
- crackerjack/plugins/managers.py +1 -1
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +8 -21
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
- 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/api_extractor.py +5 -3
- crackerjack/services/bounded_status_operations.py +45 -5
- crackerjack/services/cache.py +249 -318
- crackerjack/services/changelog_automation.py +7 -3
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +83 -39
- crackerjack/services/config_merge.py +9 -6
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +13 -26
- crackerjack/services/coverage_badge_service.py +6 -4
- crackerjack/services/coverage_ratchet.py +53 -27
- crackerjack/services/debug.py +18 -7
- crackerjack/services/dependency_analyzer.py +4 -4
- crackerjack/services/dependency_monitor.py +13 -13
- crackerjack/services/documentation_generator.py +4 -2
- crackerjack/services/documentation_service.py +62 -33
- crackerjack/services/enhanced_filesystem.py +81 -27
- crackerjack/services/enterprise_optimizer.py +1 -1
- crackerjack/services/error_pattern_analyzer.py +10 -10
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +5 -7
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +80 -109
- crackerjack/services/git.py +99 -5
- crackerjack/services/health_metrics.py +4 -6
- crackerjack/services/heatmap_generator.py +12 -3
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +101 -49
- crackerjack/services/log_manager.py +2 -2
- crackerjack/services/logging.py +120 -68
- crackerjack/services/lsp_client.py +12 -12
- crackerjack/services/memory_optimizer.py +27 -22
- 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/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
- crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
- crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
- crackerjack/services/parallel_executor.py +166 -55
- 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 +21 -8
- 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_baseline.py → quality/quality_baseline.py} +163 -2
- crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
- crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
- crackerjack/services/regex_patterns.py +58 -2987
- crackerjack/services/regex_utils.py +55 -29
- crackerjack/services/secure_status_formatter.py +42 -15
- crackerjack/services/secure_subprocess.py +35 -2
- crackerjack/services/security.py +16 -8
- crackerjack/services/server_manager.py +40 -51
- crackerjack/services/smart_scheduling.py +46 -6
- crackerjack/services/status_authentication.py +3 -3
- crackerjack/services/thread_safe_status_collector.py +1 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +9 -5
- crackerjack/services/unified_config.py +43 -351
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +6 -4
- crackerjack/services/version_checker.py +14 -8
- crackerjack/services/zuban_lsp_service.py +5 -4
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/init.md +2 -12
- crackerjack/slash_commands/run.md +84 -50
- 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_regex_patterns.py +7 -3
- crackerjack/ui/README.md +11 -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.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack/managers/test_manager_backup.py +0 -1075
- crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
- crackerjack/mixins/__init__.py +0 -3
- crackerjack/mixins/error_handling.py +0 -145
- crackerjack/services/config.py +0 -358
- crackerjack/ui/server_panels.py +0 -125
- crackerjack-0.37.9.dist-info/RECORD +0 -231
- /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
- /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""Utility functions for regex pattern operations."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
# Import for type checking - circular import avoided
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from .core import MAX_ITERATIONS, CompiledPatternCache, ValidatedPattern
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
pass # SAFE_PATTERNS imported at runtime to avoid circular imports
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validate_all_patterns() -> dict[str, bool]:
|
|
15
|
+
"""Validate all patterns in the registry."""
|
|
16
|
+
from . import SAFE_PATTERNS
|
|
17
|
+
|
|
18
|
+
results: dict[str, bool] = {}
|
|
19
|
+
for name, pattern in SAFE_PATTERNS.items():
|
|
20
|
+
try:
|
|
21
|
+
pattern._validate()
|
|
22
|
+
results[name] = True
|
|
23
|
+
except ValueError as e:
|
|
24
|
+
results[name] = False
|
|
25
|
+
print(f"Pattern '{name}' failed validation: {e}")
|
|
26
|
+
return results
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find_pattern_for_text(text: str) -> list[str]:
|
|
30
|
+
"""Find all patterns that match the given text."""
|
|
31
|
+
from . import SAFE_PATTERNS
|
|
32
|
+
|
|
33
|
+
return [name for name, pattern in SAFE_PATTERNS.items() if pattern.test(text)]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def apply_safe_replacement(text: str, pattern_name: str) -> str:
|
|
37
|
+
"""Apply a named pattern to text."""
|
|
38
|
+
from . import SAFE_PATTERNS
|
|
39
|
+
|
|
40
|
+
if pattern_name not in SAFE_PATTERNS:
|
|
41
|
+
raise ValueError(f"Unknown pattern: {pattern_name}")
|
|
42
|
+
|
|
43
|
+
return SAFE_PATTERNS[pattern_name].apply(text)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_pattern_description(pattern_name: str) -> str:
|
|
47
|
+
"""Get description for a named pattern."""
|
|
48
|
+
from . import SAFE_PATTERNS
|
|
49
|
+
|
|
50
|
+
if pattern_name not in SAFE_PATTERNS:
|
|
51
|
+
return "Unknown pattern"
|
|
52
|
+
|
|
53
|
+
return SAFE_PATTERNS[pattern_name].description
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def fix_multi_word_hyphenation(text: str) -> str:
|
|
57
|
+
"""Fix multi-word hyphenation iteratively."""
|
|
58
|
+
from . import SAFE_PATTERNS
|
|
59
|
+
|
|
60
|
+
return SAFE_PATTERNS["fix_spaced_hyphens"].apply_iteratively(text)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def update_pyproject_version(content: str, new_version: str) -> str:
|
|
64
|
+
"""Update version in pyproject.toml content."""
|
|
65
|
+
from . import SAFE_PATTERNS
|
|
66
|
+
|
|
67
|
+
pattern_obj = SAFE_PATTERNS["update_pyproject_version"]
|
|
68
|
+
|
|
69
|
+
temp_pattern = ValidatedPattern(
|
|
70
|
+
name="temp_version_update",
|
|
71
|
+
pattern=pattern_obj.pattern,
|
|
72
|
+
replacement=f"\\g<1>{new_version}\\g<3>",
|
|
73
|
+
description=f"Update version to {new_version}",
|
|
74
|
+
test_cases=[
|
|
75
|
+
('version = "1.2.3"', f'version = "{new_version}"'),
|
|
76
|
+
],
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return re.compile(pattern_obj.pattern, re.MULTILINE).sub(
|
|
80
|
+
temp_pattern.replacement, content
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def apply_formatting_fixes(content: str) -> str:
|
|
85
|
+
"""Apply common formatting fixes to content."""
|
|
86
|
+
from . import SAFE_PATTERNS
|
|
87
|
+
|
|
88
|
+
pattern = SAFE_PATTERNS["remove_trailing_whitespace"]
|
|
89
|
+
content = re.compile(pattern.pattern, re.MULTILINE).sub(
|
|
90
|
+
pattern.replacement, content
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
content = SAFE_PATTERNS["normalize_multiple_newlines"].apply(content)
|
|
94
|
+
|
|
95
|
+
return content
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def apply_security_fixes(content: str) -> str:
|
|
99
|
+
"""Apply common security fixes to content."""
|
|
100
|
+
from . import SAFE_PATTERNS
|
|
101
|
+
|
|
102
|
+
content = SAFE_PATTERNS["fix_subprocess_run_shell"].apply(content)
|
|
103
|
+
content = SAFE_PATTERNS["fix_subprocess_call_shell"].apply(content)
|
|
104
|
+
content = SAFE_PATTERNS["fix_subprocess_popen_shell"].apply(content)
|
|
105
|
+
|
|
106
|
+
content = SAFE_PATTERNS["fix_unsafe_yaml_load"].apply(content)
|
|
107
|
+
content = SAFE_PATTERNS["fix_weak_md5_hash"].apply(content)
|
|
108
|
+
content = SAFE_PATTERNS["fix_weak_sha1_hash"].apply(content)
|
|
109
|
+
content = SAFE_PATTERNS["fix_insecure_random_choice"].apply(content)
|
|
110
|
+
|
|
111
|
+
content = SAFE_PATTERNS["remove_debug_prints_with_secrets"].apply(content)
|
|
112
|
+
|
|
113
|
+
return content
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def apply_test_fixes(content: str) -> str:
|
|
117
|
+
"""Apply common test-related fixes to content."""
|
|
118
|
+
from . import SAFE_PATTERNS
|
|
119
|
+
|
|
120
|
+
return SAFE_PATTERNS["normalize_assert_statements"].apply(content)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def is_valid_job_id(job_id: str) -> bool:
|
|
124
|
+
"""Check if a job ID is valid."""
|
|
125
|
+
from . import SAFE_PATTERNS
|
|
126
|
+
|
|
127
|
+
return SAFE_PATTERNS["validate_job_id_alphanumeric"].test(job_id)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def remove_coverage_fail_under(addopts: str) -> str:
|
|
131
|
+
"""Remove --cov-fail-under from pytest addopts."""
|
|
132
|
+
from . import SAFE_PATTERNS
|
|
133
|
+
|
|
134
|
+
return SAFE_PATTERNS["remove_coverage_fail_under"].apply(addopts)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def update_coverage_requirement(content: str, new_coverage: float) -> str:
|
|
138
|
+
"""Update coverage requirement to a new value."""
|
|
139
|
+
from . import SAFE_PATTERNS
|
|
140
|
+
|
|
141
|
+
pattern_obj = SAFE_PATTERNS["update_coverage_requirement"]
|
|
142
|
+
|
|
143
|
+
temp_pattern = ValidatedPattern(
|
|
144
|
+
name="temp_coverage_update",
|
|
145
|
+
pattern=pattern_obj.pattern,
|
|
146
|
+
replacement=f"\\1{new_coverage: .0f}",
|
|
147
|
+
description=f"Update coverage to {new_coverage}",
|
|
148
|
+
test_cases=[
|
|
149
|
+
("--cov-fail-under=85", f"--cov-fail-under={new_coverage: .0f}"),
|
|
150
|
+
],
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return re.compile(pattern_obj.pattern).sub(temp_pattern.replacement, content)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def update_repo_revision(content: str, repo_url: str, new_revision: str) -> str:
|
|
157
|
+
"""Update repository revision in content."""
|
|
158
|
+
escaped_url = re.escape(repo_url)
|
|
159
|
+
pattern = rf'("repo": "{escaped_url}".*?"rev": )"([^"]+)"'
|
|
160
|
+
replacement = rf'\1"{new_revision}"'
|
|
161
|
+
|
|
162
|
+
return re.compile(pattern, re.DOTALL).sub(replacement, content)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def sanitize_internal_urls(text: str) -> str:
|
|
166
|
+
"""Sanitize all internal URLs in text."""
|
|
167
|
+
from . import SAFE_PATTERNS
|
|
168
|
+
|
|
169
|
+
url_patterns = [
|
|
170
|
+
"sanitize_localhost_urls",
|
|
171
|
+
"sanitize_127_urls",
|
|
172
|
+
"sanitize_any_localhost_urls",
|
|
173
|
+
"sanitize_ws_localhost_urls",
|
|
174
|
+
"sanitize_ws_127_urls",
|
|
175
|
+
"sanitize_simple_localhost_urls",
|
|
176
|
+
"sanitize_simple_ws_localhost_urls",
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
result = text
|
|
180
|
+
for pattern_name in url_patterns:
|
|
181
|
+
result = SAFE_PATTERNS[pattern_name].apply(result)
|
|
182
|
+
|
|
183
|
+
return result
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def apply_pattern_iteratively(
|
|
187
|
+
text: str, pattern_name: str, max_iterations: int = MAX_ITERATIONS
|
|
188
|
+
) -> str:
|
|
189
|
+
"""Apply a pattern iteratively until no more changes."""
|
|
190
|
+
from . import SAFE_PATTERNS
|
|
191
|
+
|
|
192
|
+
if pattern_name not in SAFE_PATTERNS:
|
|
193
|
+
raise ValueError(f"Unknown pattern: {pattern_name}")
|
|
194
|
+
|
|
195
|
+
return SAFE_PATTERNS[pattern_name].apply_iteratively(text, max_iterations)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_all_pattern_stats() -> dict[str, dict[str, float] | dict[str, str]]:
|
|
199
|
+
"""Get performance statistics for all patterns."""
|
|
200
|
+
from . import SAFE_PATTERNS
|
|
201
|
+
|
|
202
|
+
test_text = "python - m crackerjack - t with pytest - hypothesis - specialist"
|
|
203
|
+
stats: dict[str, dict[str, float] | dict[str, str]] = {}
|
|
204
|
+
|
|
205
|
+
for name, pattern in SAFE_PATTERNS.items():
|
|
206
|
+
try:
|
|
207
|
+
pattern_stats = pattern.get_performance_stats(test_text, iterations=10)
|
|
208
|
+
stats[name] = pattern_stats
|
|
209
|
+
except Exception as e:
|
|
210
|
+
stats[name] = {"error": str(e)}
|
|
211
|
+
|
|
212
|
+
return stats
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def clear_all_caches() -> None:
|
|
216
|
+
"""Clear all pattern caches."""
|
|
217
|
+
CompiledPatternCache.clear_cache()
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_cache_info() -> dict[str, int | list[str]]:
|
|
221
|
+
"""Get cache statistics."""
|
|
222
|
+
return CompiledPatternCache.get_cache_stats()
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def detect_path_traversal_patterns(path_str: str) -> list[str]:
|
|
226
|
+
"""Detect path traversal patterns in a path string."""
|
|
227
|
+
from . import SAFE_PATTERNS
|
|
228
|
+
|
|
229
|
+
detected = []
|
|
230
|
+
traversal_patterns = [
|
|
231
|
+
"detect_directory_traversal_basic",
|
|
232
|
+
"detect_directory_traversal_backslash",
|
|
233
|
+
"detect_url_encoded_traversal",
|
|
234
|
+
"detect_double_url_encoded_traversal",
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
for pattern_name in traversal_patterns:
|
|
238
|
+
pattern = SAFE_PATTERNS[pattern_name]
|
|
239
|
+
if pattern.test(path_str):
|
|
240
|
+
detected.append(pattern_name)
|
|
241
|
+
|
|
242
|
+
return detected
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def detect_null_byte_patterns(path_str: str) -> list[str]:
|
|
246
|
+
"""Detect null byte patterns in a path string."""
|
|
247
|
+
from . import SAFE_PATTERNS
|
|
248
|
+
|
|
249
|
+
detected = []
|
|
250
|
+
null_patterns = [
|
|
251
|
+
"detect_null_bytes_url",
|
|
252
|
+
"detect_null_bytes_literal",
|
|
253
|
+
"detect_utf8_overlong_null",
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
for pattern_name in null_patterns:
|
|
257
|
+
pattern = SAFE_PATTERNS[pattern_name]
|
|
258
|
+
if pattern.test(path_str):
|
|
259
|
+
detected.append(pattern_name)
|
|
260
|
+
|
|
261
|
+
return detected
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def detect_dangerous_directory_patterns(path_str: str) -> list[str]:
|
|
265
|
+
"""Detect dangerous directory access patterns in a path string."""
|
|
266
|
+
from . import SAFE_PATTERNS
|
|
267
|
+
|
|
268
|
+
detected = []
|
|
269
|
+
dangerous_patterns = [
|
|
270
|
+
"detect_sys_directory_pattern",
|
|
271
|
+
"detect_proc_directory_pattern",
|
|
272
|
+
"detect_etc_directory_pattern",
|
|
273
|
+
"detect_boot_directory_pattern",
|
|
274
|
+
"detect_dev_directory_pattern",
|
|
275
|
+
"detect_root_directory_pattern",
|
|
276
|
+
"detect_var_log_directory_pattern",
|
|
277
|
+
"detect_bin_directory_pattern",
|
|
278
|
+
"detect_sbin_directory_pattern",
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
for pattern_name in dangerous_patterns:
|
|
282
|
+
pattern = SAFE_PATTERNS[pattern_name]
|
|
283
|
+
if pattern.test(path_str):
|
|
284
|
+
detected.append(pattern_name)
|
|
285
|
+
|
|
286
|
+
return detected
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def detect_suspicious_path_patterns(path_str: str) -> list[str]:
|
|
290
|
+
"""Detect suspicious path patterns in a path string."""
|
|
291
|
+
from . import SAFE_PATTERNS
|
|
292
|
+
|
|
293
|
+
detected = []
|
|
294
|
+
suspicious_patterns = [
|
|
295
|
+
"detect_parent_directory_in_path",
|
|
296
|
+
"detect_suspicious_temp_traversal",
|
|
297
|
+
"detect_suspicious_var_traversal",
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
for pattern_name in suspicious_patterns:
|
|
301
|
+
pattern = SAFE_PATTERNS[pattern_name]
|
|
302
|
+
if pattern.test(path_str):
|
|
303
|
+
detected.append(pattern_name)
|
|
304
|
+
|
|
305
|
+
return detected
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def validate_path_security(path_str: str) -> dict[str, list[str]]:
|
|
309
|
+
"""Validate path security by checking for various attack patterns."""
|
|
310
|
+
return {
|
|
311
|
+
"traversal_patterns": detect_path_traversal_patterns(path_str),
|
|
312
|
+
"null_bytes": detect_null_byte_patterns(path_str),
|
|
313
|
+
"dangerous_directories": detect_dangerous_directory_patterns(path_str),
|
|
314
|
+
"suspicious_patterns": detect_suspicious_path_patterns(path_str),
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class RegexPatternsService:
|
|
319
|
+
"""Service class that implements RegexPatternsProtocol.
|
|
320
|
+
|
|
321
|
+
Wraps module-level regex pattern functions to provide a protocol-compliant interface.
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
def update_pyproject_version(self, content: str, new_version: str) -> str:
|
|
325
|
+
"""Update version in pyproject.toml content."""
|
|
326
|
+
return update_pyproject_version(content, new_version)
|
|
327
|
+
|
|
328
|
+
def remove_coverage_fail_under(self, content: str) -> str:
|
|
329
|
+
"""Remove --cov-fail-under from pytest addopts."""
|
|
330
|
+
return remove_coverage_fail_under(content)
|
|
331
|
+
|
|
332
|
+
def update_version_in_changelog(self, content: str, new_version: str) -> str:
|
|
333
|
+
"""Update version in changelog content."""
|
|
334
|
+
# Placeholder implementation - can be enhanced later
|
|
335
|
+
return content
|
|
336
|
+
|
|
337
|
+
def mask_tokens_in_text(self, text: str) -> str:
|
|
338
|
+
"""Mask sensitive tokens in text."""
|
|
339
|
+
return sanitize_internal_urls(text)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Input validation patterns."""
|
|
2
|
+
|
|
3
|
+
from .core import ValidatedPattern
|
|
4
|
+
|
|
5
|
+
PATTERNS: dict[str, ValidatedPattern] = {
|
|
6
|
+
"validate_env_var_name_format": ValidatedPattern(
|
|
7
|
+
name="validate_env_var_name_format",
|
|
8
|
+
pattern=r"^[A-Z_][A-Z0-9_]*$",
|
|
9
|
+
replacement="VALID_ENV_VAR_NAME",
|
|
10
|
+
description="Validate environment variable name format - uppercase letters, "
|
|
11
|
+
" numbers, underscores only, must start with letter or underscore",
|
|
12
|
+
test_cases=[
|
|
13
|
+
("VALID_VAR", "VALID_ENV_VAR_NAME"),
|
|
14
|
+
("_VALID_VAR", "VALID_ENV_VAR_NAME"),
|
|
15
|
+
("API_KEY_123", "VALID_ENV_VAR_NAME"),
|
|
16
|
+
("DATABASE_URL", "VALID_ENV_VAR_NAME"),
|
|
17
|
+
("_PRIVATE_VAR", "VALID_ENV_VAR_NAME"),
|
|
18
|
+
],
|
|
19
|
+
),
|
|
20
|
+
"validate_job_id_alphanumeric": ValidatedPattern(
|
|
21
|
+
name="validate_job_id_alphanumeric",
|
|
22
|
+
pattern=r"^[a-zA-Z0-9_-]+$",
|
|
23
|
+
replacement="VALID",
|
|
24
|
+
description="Validate job ID contains only alphanumeric characters, "
|
|
25
|
+
"underscores, and hyphens",
|
|
26
|
+
test_cases=[
|
|
27
|
+
("valid_job-123", "VALID"),
|
|
28
|
+
("another_valid-job_456", "VALID"),
|
|
29
|
+
("job_123", "VALID"),
|
|
30
|
+
],
|
|
31
|
+
),
|
|
32
|
+
"validate_job_id_format": ValidatedPattern(
|
|
33
|
+
name="validate_job_id_format",
|
|
34
|
+
pattern=r"^[a-zA-Z0-9\-_]+$",
|
|
35
|
+
replacement="VALID_JOB_ID",
|
|
36
|
+
description="Validate job ID format - alphanumeric with hyphens and"
|
|
37
|
+
" underscores only",
|
|
38
|
+
test_cases=[
|
|
39
|
+
("valid_job-123", "VALID_JOB_ID"),
|
|
40
|
+
("another-valid_job_456", "VALID_JOB_ID"),
|
|
41
|
+
("job_123", "VALID_JOB_ID"),
|
|
42
|
+
("UPPERCASE_JOB-ID", "VALID_JOB_ID"),
|
|
43
|
+
("hyphen-underscore_combo", "VALID_JOB_ID"),
|
|
44
|
+
],
|
|
45
|
+
),
|
|
46
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Version number extraction and update patterns."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from .core import ValidatedPattern
|
|
6
|
+
|
|
7
|
+
PATTERNS: dict[str, ValidatedPattern] = {
|
|
8
|
+
"extract_version_numbers": ValidatedPattern(
|
|
9
|
+
name="extract_version_numbers",
|
|
10
|
+
pattern=r"version\s+(\d+\.\d+\.\d+)",
|
|
11
|
+
replacement=r"\1",
|
|
12
|
+
description="Extract semantic version numbers from 'version X.Y.Z' patterns",
|
|
13
|
+
flags=re.IGNORECASE,
|
|
14
|
+
test_cases=[
|
|
15
|
+
("version 1.2.3", "1.2.3"),
|
|
16
|
+
("Version 10.0.1", "10.0.1"),
|
|
17
|
+
("current version 0.5.0", "current 0.5.0"),
|
|
18
|
+
("VERSION 2.11.4", "2.11.4"),
|
|
19
|
+
],
|
|
20
|
+
),
|
|
21
|
+
"update_pyproject_version": ValidatedPattern(
|
|
22
|
+
name="update_pyproject_version",
|
|
23
|
+
pattern=r'^(version\s*=\s*["\'])([^"\']+)(["\'])$',
|
|
24
|
+
replacement=r"\g<1>NEW_VERSION\g<3>",
|
|
25
|
+
description="Update version in pyproject.toml files (NEW_VERSION placeholder"
|
|
26
|
+
" replaced dynamically)",
|
|
27
|
+
test_cases=[
|
|
28
|
+
('version = "1.2.3"', 'version = "NEW_VERSION"'),
|
|
29
|
+
("version='0.1.0'", "version='NEW_VERSION'"),
|
|
30
|
+
('version="1.0.0-beta"', 'version="NEW_VERSION"'),
|
|
31
|
+
("version = '2.1.0'", "version = 'NEW_VERSION'"),
|
|
32
|
+
("version='10.20.30'", "version='NEW_VERSION'"),
|
|
33
|
+
('name = "my-package"', 'name = "my-package"'),
|
|
34
|
+
],
|
|
35
|
+
),
|
|
36
|
+
"update_repo_revision": ValidatedPattern(
|
|
37
|
+
name="update_repo_revision",
|
|
38
|
+
pattern=r'("repo": "[^"]+?".*?"rev": )"([^"]+)"',
|
|
39
|
+
replacement=r'\1"NEW_REVISION"',
|
|
40
|
+
description="Update repository revision in config files (NEW_REVISION"
|
|
41
|
+
" placeholder replaced dynamically)",
|
|
42
|
+
flags=re.DOTALL,
|
|
43
|
+
test_cases=[
|
|
44
|
+
(
|
|
45
|
+
'"repo": "https: //github.com/user/repo".*"rev": "old_rev"',
|
|
46
|
+
'"repo": "https: //github.com/user/repo".*"rev": "NEW_REVISION"',
|
|
47
|
+
),
|
|
48
|
+
(
|
|
49
|
+
'"repo": "git@github.com: user/repo.git", "branch": "main", "rev": '
|
|
50
|
+
'"abc123"',
|
|
51
|
+
'"repo": "git@github.com: user/repo.git", "branch": "main", "rev": '
|
|
52
|
+
'"NEW_REVISION"',
|
|
53
|
+
),
|
|
54
|
+
(
|
|
55
|
+
'{"repo": "https: //example.com/repo", "description": "test", "rev": '
|
|
56
|
+
'"456def"}',
|
|
57
|
+
'{"repo": "https: //example.com/repo", "description": "test", "rev": '
|
|
58
|
+
'"NEW_REVISION"}',
|
|
59
|
+
),
|
|
60
|
+
],
|
|
61
|
+
),
|
|
62
|
+
}
|
|
@@ -8,9 +8,18 @@ from dataclasses import dataclass, field
|
|
|
8
8
|
from datetime import datetime, timedelta
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
|
+
if t.TYPE_CHECKING:
|
|
12
|
+
pass
|
|
13
|
+
|
|
11
14
|
logger = logging.getLogger(__name__)
|
|
12
15
|
|
|
13
16
|
|
|
17
|
+
if t.TYPE_CHECKING:
|
|
18
|
+
|
|
19
|
+
class PredictorProtocol(t.Protocol):
|
|
20
|
+
def predict(self, values: list[float], periods: int = 1) -> list[float]: ...
|
|
21
|
+
|
|
22
|
+
|
|
14
23
|
@dataclass
|
|
15
24
|
class TrendAnalysis:
|
|
16
25
|
"""Trend analysis result for a metric."""
|
|
@@ -141,7 +150,7 @@ class PredictiveAnalyticsEngine:
|
|
|
141
150
|
)
|
|
142
151
|
|
|
143
152
|
# Predictors
|
|
144
|
-
self.predictors = {
|
|
153
|
+
self.predictors: dict[str, t.Any] = { # type: ignore[var-annotated]
|
|
145
154
|
"moving_average": MovingAveragePredictor(window_size=10),
|
|
146
155
|
"linear_trend": LinearTrendPredictor(),
|
|
147
156
|
"seasonal": SeasonalPredictor(season_length=24),
|
|
@@ -205,9 +214,11 @@ class PredictiveAnalyticsEngine:
|
|
|
205
214
|
# Generate predictions
|
|
206
215
|
config = self.metric_configs.get(metric_type, {})
|
|
207
216
|
predictor_name = config.get("predictor", "moving_average")
|
|
208
|
-
predictor = self.predictors[predictor_name]
|
|
217
|
+
predictor = self.predictors[t.cast(str, predictor_name)] # type: ignore[index]
|
|
209
218
|
|
|
210
|
-
predicted_values =
|
|
219
|
+
predicted_values = t.cast(t.Any, predictor).predict(
|
|
220
|
+
values, periods=24
|
|
221
|
+
) # 24 periods ahead # type: ignore[union-attr]
|
|
211
222
|
confidence_intervals = self._calculate_confidence_intervals(
|
|
212
223
|
values, predicted_values
|
|
213
224
|
)
|
|
@@ -304,10 +315,10 @@ class PredictiveAnalyticsEngine:
|
|
|
304
315
|
# Select predictor
|
|
305
316
|
if predictor_name is None:
|
|
306
317
|
config = self.metric_configs.get(metric_type, {})
|
|
307
|
-
predictor_name = t.cast(str, config.get("predictor", "moving_average"))
|
|
318
|
+
predictor_name = t.cast(str, config.get("predictor", "moving_average")) # type: ignore[redundant-cast]
|
|
308
319
|
|
|
309
|
-
predictor = self.predictors[predictor_name]
|
|
310
|
-
predicted_values = predictor.predict(values, periods_ahead)
|
|
320
|
+
predictor = self.predictors[t.cast(str, predictor_name)] # type: ignore[index]
|
|
321
|
+
predicted_values = t.cast(t.Any, predictor).predict(values, periods_ahead) # type: ignore[union-attr]
|
|
311
322
|
|
|
312
323
|
# Calculate confidence intervals
|
|
313
324
|
confidence_intervals = self._calculate_confidence_intervals(
|
|
@@ -357,8 +368,10 @@ class PredictiveAnalyticsEngine:
|
|
|
357
368
|
return 0.5
|
|
358
369
|
|
|
359
370
|
# Generate predictions for validation period
|
|
360
|
-
predictor = self.predictors[predictor_name]
|
|
361
|
-
predictions =
|
|
371
|
+
predictor = self.predictors[t.cast(str, predictor_name)] # type: ignore[index]
|
|
372
|
+
predictions = t.cast(t.Any, predictor).predict(
|
|
373
|
+
train_data, periods=len(validation_data)
|
|
374
|
+
) # type: ignore[union-attr]
|
|
362
375
|
|
|
363
376
|
# Calculate accuracy (inverse of mean absolute error)
|
|
364
377
|
mae = statistics.mean(
|