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,230 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from .base import (
|
|
4
|
+
AgentContext,
|
|
5
|
+
FixResult,
|
|
6
|
+
Issue,
|
|
7
|
+
IssueType,
|
|
8
|
+
SubAgent,
|
|
9
|
+
agent_registry,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FormattingAgent(SubAgent):
|
|
14
|
+
def __init__(self, context: AgentContext) -> None:
|
|
15
|
+
super().__init__(context)
|
|
16
|
+
|
|
17
|
+
def get_supported_types(self) -> set[IssueType]:
|
|
18
|
+
return {IssueType.FORMATTING, IssueType.IMPORT_ERROR}
|
|
19
|
+
|
|
20
|
+
async def can_handle(self, issue: Issue) -> float:
|
|
21
|
+
if issue.type not in self.get_supported_types():
|
|
22
|
+
return 0.0
|
|
23
|
+
|
|
24
|
+
message_lower = issue.message.lower()
|
|
25
|
+
|
|
26
|
+
if any(
|
|
27
|
+
keyword in message_lower
|
|
28
|
+
for keyword in (
|
|
29
|
+
"would reformat",
|
|
30
|
+
"trailing whitespace",
|
|
31
|
+
"missing newline",
|
|
32
|
+
"import sorting",
|
|
33
|
+
"unused import",
|
|
34
|
+
"ruff",
|
|
35
|
+
"format",
|
|
36
|
+
)
|
|
37
|
+
):
|
|
38
|
+
return 1.0
|
|
39
|
+
|
|
40
|
+
if any(
|
|
41
|
+
keyword in message_lower
|
|
42
|
+
for keyword in (
|
|
43
|
+
"whitespace",
|
|
44
|
+
"indent",
|
|
45
|
+
"spacing",
|
|
46
|
+
"line length",
|
|
47
|
+
"import",
|
|
48
|
+
"style",
|
|
49
|
+
"format",
|
|
50
|
+
)
|
|
51
|
+
):
|
|
52
|
+
return 0.8
|
|
53
|
+
|
|
54
|
+
if issue.type == IssueType.FORMATTING:
|
|
55
|
+
return 0.6
|
|
56
|
+
|
|
57
|
+
return 0.0
|
|
58
|
+
|
|
59
|
+
async def analyze_and_fix(self, issue: Issue) -> FixResult:
|
|
60
|
+
self.log(f"Analyzing formatting issue: {issue.message}")
|
|
61
|
+
|
|
62
|
+
fixes_applied: list[str] = []
|
|
63
|
+
files_modified: list[str] = []
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
ruff_fixes = await self._apply_ruff_fixes()
|
|
67
|
+
fixes_applied.extend(ruff_fixes)
|
|
68
|
+
|
|
69
|
+
whitespace_fixes = await self._apply_whitespace_fixes()
|
|
70
|
+
fixes_applied.extend(whitespace_fixes)
|
|
71
|
+
|
|
72
|
+
import_fixes = await self._apply_import_fixes()
|
|
73
|
+
fixes_applied.extend(import_fixes)
|
|
74
|
+
|
|
75
|
+
if issue.file_path:
|
|
76
|
+
file_fixes = await self._fix_specific_file(issue.file_path, issue)
|
|
77
|
+
fixes_applied.extend(file_fixes)
|
|
78
|
+
if file_fixes:
|
|
79
|
+
files_modified.append(issue.file_path)
|
|
80
|
+
|
|
81
|
+
success = len(fixes_applied) > 0
|
|
82
|
+
confidence = 0.9 if success else 0.3
|
|
83
|
+
|
|
84
|
+
return FixResult(
|
|
85
|
+
success=success,
|
|
86
|
+
confidence=confidence,
|
|
87
|
+
fixes_applied=fixes_applied,
|
|
88
|
+
files_modified=files_modified,
|
|
89
|
+
recommendations=[
|
|
90
|
+
"Run ruff format regularly for consistent styling",
|
|
91
|
+
"Configure pre-commit hooks for automatic formatting",
|
|
92
|
+
]
|
|
93
|
+
if not success
|
|
94
|
+
else [],
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
except Exception as e:
|
|
98
|
+
self.log(f"Error fixing formatting issue: {e}", "ERROR")
|
|
99
|
+
return FixResult(
|
|
100
|
+
success=False,
|
|
101
|
+
confidence=0.0,
|
|
102
|
+
remaining_issues=[f"Failed to apply formatting fixes: {e}"],
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
async def _apply_ruff_fixes(self) -> list[str]:
|
|
106
|
+
fixes: list[str] = []
|
|
107
|
+
|
|
108
|
+
returncode, _, stderr = await self.run_command(
|
|
109
|
+
["uv", "run", "ruff", "format", "."],
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if returncode == 0:
|
|
113
|
+
fixes.append("Applied ruff code formatting")
|
|
114
|
+
self.log("Successfully applied ruff formatting")
|
|
115
|
+
else:
|
|
116
|
+
self.log(f"Ruff format failed: {stderr}", "WARN")
|
|
117
|
+
|
|
118
|
+
returncode, _, stderr = await self.run_command(
|
|
119
|
+
["uv", "run", "ruff", "check", ".", "--fix"],
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if returncode == 0:
|
|
123
|
+
fixes.append("Applied ruff linting fixes")
|
|
124
|
+
self.log("Successfully applied ruff linting fixes")
|
|
125
|
+
else:
|
|
126
|
+
self.log(f"Ruff check --fix had issues: {stderr}", "WARN")
|
|
127
|
+
|
|
128
|
+
return fixes
|
|
129
|
+
|
|
130
|
+
async def _apply_whitespace_fixes(self) -> list[str]:
|
|
131
|
+
fixes: list[str] = []
|
|
132
|
+
|
|
133
|
+
returncode, _, _ = await self.run_command(
|
|
134
|
+
[
|
|
135
|
+
"uv",
|
|
136
|
+
"run",
|
|
137
|
+
"python",
|
|
138
|
+
"-m",
|
|
139
|
+
"crackerjack.tools.trailing_whitespace",
|
|
140
|
+
],
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if returncode == 0:
|
|
144
|
+
fixes.append("Fixed trailing whitespace")
|
|
145
|
+
self.log("Fixed trailing whitespace")
|
|
146
|
+
|
|
147
|
+
returncode, _, _ = await self.run_command(
|
|
148
|
+
[
|
|
149
|
+
"uv",
|
|
150
|
+
"run",
|
|
151
|
+
"python",
|
|
152
|
+
"-m",
|
|
153
|
+
"crackerjack.tools.end_of_file_fixer",
|
|
154
|
+
],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if returncode == 0:
|
|
158
|
+
fixes.append("Fixed end-of-file formatting")
|
|
159
|
+
self.log("Fixed end-of-file formatting")
|
|
160
|
+
|
|
161
|
+
return fixes
|
|
162
|
+
|
|
163
|
+
async def _apply_import_fixes(self) -> list[str]:
|
|
164
|
+
fixes: list[str] = []
|
|
165
|
+
|
|
166
|
+
returncode, _, _ = await self.run_command(
|
|
167
|
+
[
|
|
168
|
+
"uv",
|
|
169
|
+
"run",
|
|
170
|
+
"ruff",
|
|
171
|
+
"check",
|
|
172
|
+
".",
|
|
173
|
+
"--select",
|
|
174
|
+
"I, F401",
|
|
175
|
+
"--fix",
|
|
176
|
+
],
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if returncode == 0:
|
|
180
|
+
fixes.append("Organized imports and removed unused imports")
|
|
181
|
+
self.log("Fixed import organization")
|
|
182
|
+
|
|
183
|
+
return fixes
|
|
184
|
+
|
|
185
|
+
async def _fix_specific_file(self, file_path: str, issue: Issue) -> list[str]:
|
|
186
|
+
fixes: list[str] = []
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
path = Path(file_path)
|
|
190
|
+
content = self._validate_and_get_file_content(path)
|
|
191
|
+
if not content:
|
|
192
|
+
return fixes
|
|
193
|
+
|
|
194
|
+
original_content = content
|
|
195
|
+
cleaned_content = self._apply_content_formatting(content)
|
|
196
|
+
|
|
197
|
+
if cleaned_content != original_content:
|
|
198
|
+
if self.context.write_file_content(path, cleaned_content):
|
|
199
|
+
fixes.append(f"Fixed formatting in {file_path}")
|
|
200
|
+
self.log(f"Applied file-specific fixes to {file_path}")
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
self.log(f"Error fixing file {file_path}: {e}", "ERROR")
|
|
204
|
+
|
|
205
|
+
return fixes
|
|
206
|
+
|
|
207
|
+
def _validate_and_get_file_content(self, path: Path) -> str | None:
|
|
208
|
+
if not path.exists() or not path.is_file():
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
content = self.context.get_file_content(path)
|
|
212
|
+
return content or None
|
|
213
|
+
|
|
214
|
+
def _apply_content_formatting(self, content: str) -> str:
|
|
215
|
+
from crackerjack.services.regex_patterns import apply_formatting_fixes
|
|
216
|
+
|
|
217
|
+
content = apply_formatting_fixes(content)
|
|
218
|
+
|
|
219
|
+
if content and not content.endswith("\n"):
|
|
220
|
+
content += "\n"
|
|
221
|
+
|
|
222
|
+
return self._convert_tabs_to_spaces(content)
|
|
223
|
+
|
|
224
|
+
def _convert_tabs_to_spaces(self, content: str) -> str:
|
|
225
|
+
lines = content.split("\n")
|
|
226
|
+
fixed_lines = [line.expandtabs(4) for line in lines]
|
|
227
|
+
return "\n".join(fixed_lines)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
agent_registry.register(FormattingAgent)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Package for helper modules used by crackerjack agents.
|
|
2
|
+
|
|
3
|
+
This package contains supporting modules for various agent types:
|
|
4
|
+
- performance: Performance analysis and optimization helpers
|
|
5
|
+
- refactoring: Code refactoring utilities
|
|
6
|
+
- test_creation: Test generation helpers
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# This file makes the directory a proper Python package
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Performance optimization helpers for the PerformanceAgent.
|
|
2
|
+
|
|
3
|
+
This module provides specialized helpers for detecting and fixing performance
|
|
4
|
+
anti-patterns while maintaining the AgentContext pattern.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .performance_ast_analyzer import PerformanceASTAnalyzer
|
|
8
|
+
from .performance_pattern_detector import (
|
|
9
|
+
ListOpAnalyzer,
|
|
10
|
+
NestedLoopAnalyzer,
|
|
11
|
+
PerformancePatternDetector,
|
|
12
|
+
)
|
|
13
|
+
from .performance_recommender import OptimizationResult, PerformanceRecommender
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"PerformancePatternDetector",
|
|
17
|
+
"PerformanceASTAnalyzer",
|
|
18
|
+
"PerformanceRecommender",
|
|
19
|
+
"OptimizationResult",
|
|
20
|
+
"NestedLoopAnalyzer",
|
|
21
|
+
"ListOpAnalyzer",
|
|
22
|
+
]
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"""AST analysis for performance complexity detection."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import typing as t
|
|
5
|
+
|
|
6
|
+
from ...base import AgentContext
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PerformanceASTAnalyzer:
|
|
10
|
+
"""Analyzes Python AST for performance-related complexity issues."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, context: AgentContext) -> None:
|
|
13
|
+
"""Initialize analyzer with agent context.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
context: AgentContext for logging and operations
|
|
17
|
+
"""
|
|
18
|
+
self.context = context
|
|
19
|
+
|
|
20
|
+
def extract_performance_critical_functions(
|
|
21
|
+
self, content: str
|
|
22
|
+
) -> list[dict[str, t.Any]]:
|
|
23
|
+
"""Extract functions likely to have performance issues.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
content: File content
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
List of performance-critical functions
|
|
30
|
+
"""
|
|
31
|
+
functions: list[dict[str, t.Any]] = []
|
|
32
|
+
lines = content.split("\n")
|
|
33
|
+
current_function = None
|
|
34
|
+
|
|
35
|
+
for i, line in enumerate(lines):
|
|
36
|
+
stripped = line.strip()
|
|
37
|
+
|
|
38
|
+
if self._is_empty_or_comment_line(stripped):
|
|
39
|
+
if current_function:
|
|
40
|
+
current_function["body"] += line + "\n"
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
indent = len(line) - len(line.lstrip())
|
|
44
|
+
|
|
45
|
+
if self._is_function_definition(stripped):
|
|
46
|
+
current_function = self._handle_function_definition(
|
|
47
|
+
current_function, functions, stripped, indent, i
|
|
48
|
+
)
|
|
49
|
+
elif current_function:
|
|
50
|
+
current_function = self._handle_function_body_line(
|
|
51
|
+
current_function, functions, line, stripped, indent, i
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
self._handle_last_function(current_function, functions, len(lines))
|
|
55
|
+
return functions
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _is_empty_or_comment_line(stripped: str) -> bool:
|
|
59
|
+
"""Check if line is empty or comment.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
stripped: Stripped line
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
True if empty or comment
|
|
66
|
+
"""
|
|
67
|
+
return not stripped or stripped.startswith("#")
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def _is_function_definition(stripped: str) -> bool:
|
|
71
|
+
"""Check if line is function definition.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
stripped: Stripped line
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
True if function definition
|
|
78
|
+
"""
|
|
79
|
+
return stripped.startswith("def ") and "(" in stripped
|
|
80
|
+
|
|
81
|
+
def _handle_function_definition(
|
|
82
|
+
self,
|
|
83
|
+
current_function: dict[str, t.Any] | None,
|
|
84
|
+
functions: list[dict[str, t.Any]],
|
|
85
|
+
stripped: str,
|
|
86
|
+
indent: int,
|
|
87
|
+
line_number: int,
|
|
88
|
+
) -> dict[str, t.Any]:
|
|
89
|
+
"""Handle function definition line.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
current_function: Current function being parsed
|
|
93
|
+
functions: List of functions
|
|
94
|
+
stripped: Stripped line
|
|
95
|
+
indent: Indentation level
|
|
96
|
+
line_number: Line number
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
New function dict
|
|
100
|
+
"""
|
|
101
|
+
if current_function and self._is_performance_critical(current_function):
|
|
102
|
+
self._finalize_function(current_function, functions, line_number)
|
|
103
|
+
|
|
104
|
+
func_name = stripped.split("(")[0].replace("def ", "").strip()
|
|
105
|
+
return {
|
|
106
|
+
"name": func_name,
|
|
107
|
+
"signature": stripped,
|
|
108
|
+
"start_line": line_number + 1,
|
|
109
|
+
"body": "",
|
|
110
|
+
"indent_level": indent,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
def _handle_function_body_line(
|
|
114
|
+
self,
|
|
115
|
+
current_function: dict[str, t.Any],
|
|
116
|
+
functions: list[dict[str, t.Any]],
|
|
117
|
+
line: str,
|
|
118
|
+
stripped: str,
|
|
119
|
+
indent: int,
|
|
120
|
+
line_number: int,
|
|
121
|
+
) -> dict[str, t.Any] | None:
|
|
122
|
+
"""Handle line within function body.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
current_function: Current function
|
|
126
|
+
functions: Functions list
|
|
127
|
+
line: Full line
|
|
128
|
+
stripped: Stripped line
|
|
129
|
+
indent: Indent level
|
|
130
|
+
line_number: Line number
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Updated current function or None
|
|
134
|
+
"""
|
|
135
|
+
if self._is_still_in_function(current_function, indent, stripped):
|
|
136
|
+
current_function["body"] += line + "\n"
|
|
137
|
+
return current_function
|
|
138
|
+
else:
|
|
139
|
+
if self._is_performance_critical(current_function):
|
|
140
|
+
self._finalize_function(current_function, functions, line_number)
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def _is_still_in_function(
|
|
145
|
+
current_function: dict[str, t.Any], indent: int, stripped: str
|
|
146
|
+
) -> bool:
|
|
147
|
+
"""Check if still inside function.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
current_function: Current function
|
|
151
|
+
indent: Indent level
|
|
152
|
+
stripped: Stripped line
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
True if still inside
|
|
156
|
+
"""
|
|
157
|
+
return indent > current_function["indent_level"] or (
|
|
158
|
+
indent == current_function["indent_level"]
|
|
159
|
+
and stripped.startswith(('"', "'", "@"))
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
def _finalize_function(
|
|
163
|
+
self,
|
|
164
|
+
function: dict[str, t.Any],
|
|
165
|
+
functions: list[dict[str, t.Any]],
|
|
166
|
+
end_line: int,
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Finalize function and add to results.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
function: Function to finalize
|
|
172
|
+
functions: Functions list
|
|
173
|
+
end_line: End line number
|
|
174
|
+
"""
|
|
175
|
+
function["end_line"] = end_line
|
|
176
|
+
function["body_sample"] = function["body"][:300]
|
|
177
|
+
function["estimated_complexity"] = self._estimate_complexity(function["body"])
|
|
178
|
+
functions.append(function)
|
|
179
|
+
|
|
180
|
+
def _handle_last_function(
|
|
181
|
+
self,
|
|
182
|
+
current_function: dict[str, t.Any] | None,
|
|
183
|
+
functions: list[dict[str, t.Any]],
|
|
184
|
+
total_lines: int,
|
|
185
|
+
) -> None:
|
|
186
|
+
"""Handle last function in file.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
current_function: Last function
|
|
190
|
+
functions: Functions list
|
|
191
|
+
total_lines: Total lines
|
|
192
|
+
"""
|
|
193
|
+
if current_function and self._is_performance_critical(current_function):
|
|
194
|
+
self._finalize_function(current_function, functions, total_lines)
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def _is_performance_critical(function_info: dict[str, t.Any]) -> bool:
|
|
198
|
+
"""Determine if function is performance-critical.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
function_info: Function info
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
True if performance-critical
|
|
205
|
+
"""
|
|
206
|
+
body = function_info.get("body", "")
|
|
207
|
+
name = function_info.get("name", "")
|
|
208
|
+
|
|
209
|
+
performance_indicators = [
|
|
210
|
+
"for " in body
|
|
211
|
+
and len([line for line in body.split("\n") if "for " in line]) > 1,
|
|
212
|
+
"while " in body,
|
|
213
|
+
body.count("for ") > 0 and len(body) > 200,
|
|
214
|
+
any(pattern in body for pattern in (".append(", "+=", ".extend(", "len(")),
|
|
215
|
+
any(
|
|
216
|
+
pattern in name
|
|
217
|
+
for pattern in (
|
|
218
|
+
"process",
|
|
219
|
+
"analyze",
|
|
220
|
+
"compute",
|
|
221
|
+
"calculate",
|
|
222
|
+
"optimize",
|
|
223
|
+
)
|
|
224
|
+
),
|
|
225
|
+
"range(" in body and ("1000" in body or "len(" in body),
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
return any(performance_indicators)
|
|
229
|
+
|
|
230
|
+
@staticmethod
|
|
231
|
+
def _estimate_complexity(body: str) -> int:
|
|
232
|
+
"""Estimate computational complexity of function.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
body: Function body
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
Complexity score
|
|
239
|
+
"""
|
|
240
|
+
complexity = 1
|
|
241
|
+
|
|
242
|
+
nested_for_loops = 0
|
|
243
|
+
for_depth = 0
|
|
244
|
+
lines = body.split("\n")
|
|
245
|
+
|
|
246
|
+
for line in lines:
|
|
247
|
+
stripped = line.strip()
|
|
248
|
+
if "for " in stripped:
|
|
249
|
+
for_depth += 1
|
|
250
|
+
nested_for_loops = max(nested_for_loops, for_depth)
|
|
251
|
+
elif (
|
|
252
|
+
stripped
|
|
253
|
+
and not stripped.startswith("#")
|
|
254
|
+
and len(line) - len(line.lstrip()) == 0
|
|
255
|
+
):
|
|
256
|
+
for_depth = 0
|
|
257
|
+
|
|
258
|
+
complexity = max(complexity, nested_for_loops)
|
|
259
|
+
|
|
260
|
+
if ".sort(" in body or "sorted(" in body:
|
|
261
|
+
complexity += 1
|
|
262
|
+
if body.count("len(") > 5:
|
|
263
|
+
complexity += 1
|
|
264
|
+
if ".index(" in body or ".find(" in body:
|
|
265
|
+
complexity += 1
|
|
266
|
+
|
|
267
|
+
return complexity
|
|
268
|
+
|
|
269
|
+
def analyze_performance_patterns(
|
|
270
|
+
self, semantic_insight: t.Any, current_func: dict[str, t.Any]
|
|
271
|
+
) -> dict[str, t.Any]:
|
|
272
|
+
"""Analyze semantic patterns for performance insights.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
semantic_insight: Semantic insight from analysis
|
|
276
|
+
current_func: Current function
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
Analysis dict
|
|
280
|
+
"""
|
|
281
|
+
analysis: dict[str, t.Any] = {
|
|
282
|
+
"issues_found": False,
|
|
283
|
+
"optimization_suggestion": "Consider reviewing similar implementations for consistency",
|
|
284
|
+
"pattern_insights": [],
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if semantic_insight.high_confidence_matches > 0:
|
|
288
|
+
analysis["issues_found"] = True
|
|
289
|
+
analysis["pattern_insights"].append(
|
|
290
|
+
f"Found {semantic_insight.high_confidence_matches} highly similar implementations"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
performance_concerns = []
|
|
294
|
+
for pattern in semantic_insight.related_patterns:
|
|
295
|
+
content = pattern.get("content", "").lower()
|
|
296
|
+
if any(
|
|
297
|
+
concern in content for concern in ("for", "while", "+=", "append")
|
|
298
|
+
):
|
|
299
|
+
performance_concerns.append(pattern["file_path"])
|
|
300
|
+
|
|
301
|
+
if performance_concerns:
|
|
302
|
+
analysis["optimization_suggestion"] = (
|
|
303
|
+
f"Performance review needed: {len(performance_concerns)} similar functions "
|
|
304
|
+
f"may benefit from the same optimization approach"
|
|
305
|
+
)
|
|
306
|
+
analysis["pattern_insights"].append(
|
|
307
|
+
f"Similar performance patterns found in: {', '.join(list(set(performance_concerns))[:3])}"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return analysis
|
|
311
|
+
|
|
312
|
+
def analyze_code_metrics(self, tree: ast.AST) -> dict[str, t.Any]:
|
|
313
|
+
"""Analyze code metrics from AST.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
tree: AST tree
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Metrics dict
|
|
320
|
+
"""
|
|
321
|
+
metrics: dict[str, t.Any] = {
|
|
322
|
+
"total_functions": 0,
|
|
323
|
+
"total_classes": 0,
|
|
324
|
+
"average_function_length": 0,
|
|
325
|
+
"max_nesting_depth": 0,
|
|
326
|
+
"high_complexity_functions": [],
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
class MetricsCollector(ast.NodeVisitor):
|
|
330
|
+
def __init__(self) -> None:
|
|
331
|
+
self.function_count = 0
|
|
332
|
+
self.class_count = 0
|
|
333
|
+
self.function_lengths: list[int] = []
|
|
334
|
+
self.max_depth = 0
|
|
335
|
+
|
|
336
|
+
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
|
337
|
+
self.function_count += 1
|
|
338
|
+
length = (node.end_lineno or node.lineno) - node.lineno
|
|
339
|
+
self.function_lengths.append(length)
|
|
340
|
+
self.generic_visit(node)
|
|
341
|
+
|
|
342
|
+
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
|
343
|
+
self.class_count += 1
|
|
344
|
+
self.generic_visit(node)
|
|
345
|
+
|
|
346
|
+
collector = MetricsCollector()
|
|
347
|
+
collector.visit(tree)
|
|
348
|
+
|
|
349
|
+
metrics["total_functions"] = collector.function_count
|
|
350
|
+
metrics["total_classes"] = collector.class_count
|
|
351
|
+
|
|
352
|
+
if collector.function_lengths:
|
|
353
|
+
metrics["average_function_length"] = sum(collector.function_lengths) / len(
|
|
354
|
+
collector.function_lengths
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return metrics
|