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,704 @@
|
|
|
1
|
+
"""Main documentation service for automated API documentation generation."""
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from acb.console import Console
|
|
7
|
+
from acb.depends import Inject, depends
|
|
8
|
+
|
|
9
|
+
from ..models.protocols import (
|
|
10
|
+
APIExtractorProtocol,
|
|
11
|
+
DocumentationGeneratorProtocol,
|
|
12
|
+
DocumentationServiceProtocol,
|
|
13
|
+
)
|
|
14
|
+
from .api_extractor import APIExtractorImpl
|
|
15
|
+
from .documentation_generator import DocumentationGeneratorImpl
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DocumentationServiceImpl(DocumentationServiceProtocol):
|
|
19
|
+
"""Main service for automated documentation generation and maintenance."""
|
|
20
|
+
|
|
21
|
+
@depends.inject
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
console: Inject[Console],
|
|
25
|
+
pkg_path: Path,
|
|
26
|
+
api_extractor: APIExtractorProtocol | None = None,
|
|
27
|
+
doc_generator: DocumentationGeneratorProtocol | None = None,
|
|
28
|
+
) -> None:
|
|
29
|
+
self.console = console
|
|
30
|
+
self.pkg_path = pkg_path
|
|
31
|
+
self.api_extractor = api_extractor or APIExtractorImpl()
|
|
32
|
+
self.doc_generator = doc_generator or DocumentationGeneratorImpl()
|
|
33
|
+
|
|
34
|
+
# Define standard paths
|
|
35
|
+
self.docs_dir = pkg_path / "docs"
|
|
36
|
+
self.generated_docs_dir = self.docs_dir / "generated"
|
|
37
|
+
self.api_docs_dir = self.generated_docs_dir / "api"
|
|
38
|
+
self.guides_dir = self.generated_docs_dir / "guides"
|
|
39
|
+
|
|
40
|
+
# Ensure directories exist
|
|
41
|
+
self._ensure_directories()
|
|
42
|
+
|
|
43
|
+
def _categorize_source_files(
|
|
44
|
+
self, source_paths: list[Path]
|
|
45
|
+
) -> dict[str, list[Path]]:
|
|
46
|
+
"""Categorize source files by type."""
|
|
47
|
+
python_files = [p for p in source_paths if p.suffix == ".py"]
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
"python": python_files,
|
|
51
|
+
"protocol": [p for p in python_files if p.name == "protocols.py"],
|
|
52
|
+
"service": [p for p in python_files if "/services/" in str(p)],
|
|
53
|
+
"manager": [p for p in python_files if "/managers/" in str(p)],
|
|
54
|
+
"cli": [p for p in python_files if "/cli/" in str(p)],
|
|
55
|
+
"mcp": [
|
|
56
|
+
p
|
|
57
|
+
for p in source_paths
|
|
58
|
+
if "/mcp/" in str(p) or p.suffix in (".py", ".md")
|
|
59
|
+
],
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
def _extract_specialized_apis(
|
|
63
|
+
self, categorized_files: dict[str, list[Path]]
|
|
64
|
+
) -> dict[str, t.Any]:
|
|
65
|
+
"""Extract specialized API documentation."""
|
|
66
|
+
api_data = {}
|
|
67
|
+
|
|
68
|
+
# Extract protocol definitions
|
|
69
|
+
if categorized_files["protocol"]:
|
|
70
|
+
for protocol_file in categorized_files["protocol"]:
|
|
71
|
+
protocol_data = self.api_extractor.extract_protocol_definitions(
|
|
72
|
+
protocol_file
|
|
73
|
+
)
|
|
74
|
+
api_data.update(protocol_data)
|
|
75
|
+
|
|
76
|
+
# Extract service interfaces
|
|
77
|
+
if categorized_files["service"]:
|
|
78
|
+
service_data = self.api_extractor.extract_service_interfaces(
|
|
79
|
+
categorized_files["service"]
|
|
80
|
+
)
|
|
81
|
+
api_data.update(service_data)
|
|
82
|
+
|
|
83
|
+
# Extract manager interfaces
|
|
84
|
+
if categorized_files["manager"]:
|
|
85
|
+
manager_data = self.api_extractor.extract_service_interfaces(
|
|
86
|
+
categorized_files["manager"]
|
|
87
|
+
)
|
|
88
|
+
if "services" in manager_data:
|
|
89
|
+
api_data["managers"] = manager_data["services"]
|
|
90
|
+
|
|
91
|
+
# Extract CLI commands
|
|
92
|
+
if categorized_files["cli"]:
|
|
93
|
+
cli_data = self.api_extractor.extract_cli_commands(categorized_files["cli"])
|
|
94
|
+
api_data.update(cli_data)
|
|
95
|
+
|
|
96
|
+
# Extract MCP tools
|
|
97
|
+
if categorized_files["mcp"]:
|
|
98
|
+
mcp_data = self.api_extractor.extract_mcp_tools(categorized_files["mcp"])
|
|
99
|
+
api_data.update(mcp_data)
|
|
100
|
+
|
|
101
|
+
return api_data
|
|
102
|
+
|
|
103
|
+
def extract_api_documentation(self, source_paths: list[Path]) -> dict[str, t.Any]:
|
|
104
|
+
"""Extract API documentation from source code files."""
|
|
105
|
+
self.console.print(
|
|
106
|
+
"[cyan]📖[/cyan] Extracting API documentation from source files..."
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
categorized_files = self._categorize_source_files(source_paths)
|
|
110
|
+
api_data = {}
|
|
111
|
+
|
|
112
|
+
# Extract from Python files
|
|
113
|
+
if categorized_files["python"]:
|
|
114
|
+
python_data = self.api_extractor.extract_from_python_files(
|
|
115
|
+
categorized_files["python"]
|
|
116
|
+
)
|
|
117
|
+
api_data.update(python_data)
|
|
118
|
+
|
|
119
|
+
# Extract specialized APIs
|
|
120
|
+
api_data.update(self._extract_specialized_apis(categorized_files))
|
|
121
|
+
|
|
122
|
+
self.console.print(
|
|
123
|
+
f"[green]✅[/green] Extracted documentation from {len(source_paths)} files"
|
|
124
|
+
)
|
|
125
|
+
return api_data
|
|
126
|
+
|
|
127
|
+
def generate_documentation(
|
|
128
|
+
self, template_name: str, context: dict[str, t.Any]
|
|
129
|
+
) -> str:
|
|
130
|
+
"""Generate documentation using specified template."""
|
|
131
|
+
try:
|
|
132
|
+
return self.doc_generator.render_template(Path(template_name), context)
|
|
133
|
+
except (FileNotFoundError, ValueError):
|
|
134
|
+
# Try built-in templates
|
|
135
|
+
return self.doc_generator.generate_api_reference(context)
|
|
136
|
+
|
|
137
|
+
def validate_documentation(self, doc_paths: list[Path]) -> list[dict[str, str]]:
|
|
138
|
+
"""Validate documentation for issues and inconsistencies."""
|
|
139
|
+
issues = []
|
|
140
|
+
|
|
141
|
+
for doc_path in doc_paths:
|
|
142
|
+
if not doc_path.exists():
|
|
143
|
+
issues.append(
|
|
144
|
+
{
|
|
145
|
+
"type": "missing_file",
|
|
146
|
+
"path": str(doc_path),
|
|
147
|
+
"message": "Documentation file does not exist",
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
content = doc_path.read_text(encoding="utf-8")
|
|
154
|
+
|
|
155
|
+
# Check for broken internal links
|
|
156
|
+
broken_links = self._check_internal_links(content, doc_path)
|
|
157
|
+
issues.extend(broken_links)
|
|
158
|
+
|
|
159
|
+
# Check for empty sections
|
|
160
|
+
empty_sections = self._check_empty_sections(content, doc_path)
|
|
161
|
+
issues.extend(empty_sections)
|
|
162
|
+
|
|
163
|
+
# Check for outdated version references
|
|
164
|
+
outdated_refs = self._check_version_references(content, doc_path)
|
|
165
|
+
issues.extend(outdated_refs)
|
|
166
|
+
|
|
167
|
+
except Exception as e:
|
|
168
|
+
issues.append(
|
|
169
|
+
{
|
|
170
|
+
"type": "read_error",
|
|
171
|
+
"path": str(doc_path),
|
|
172
|
+
"message": f"Could not read file: {e}",
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return issues
|
|
177
|
+
|
|
178
|
+
def update_documentation_index(self) -> bool:
|
|
179
|
+
"""Update the main documentation index with links to all docs."""
|
|
180
|
+
try:
|
|
181
|
+
index_path = self.docs_dir / "INDEX.md"
|
|
182
|
+
|
|
183
|
+
# Collect all documentation files
|
|
184
|
+
api_docs = (
|
|
185
|
+
list[t.Any](self.api_docs_dir.glob("*.md"))
|
|
186
|
+
if self.api_docs_dir.exists()
|
|
187
|
+
else []
|
|
188
|
+
)
|
|
189
|
+
guide_docs = (
|
|
190
|
+
list[t.Any](self.guides_dir.glob("*.md"))
|
|
191
|
+
if self.guides_dir.exists()
|
|
192
|
+
else []
|
|
193
|
+
)
|
|
194
|
+
root_docs = [
|
|
195
|
+
f
|
|
196
|
+
for f in self.docs_dir.glob("*.md")
|
|
197
|
+
if f.name not in ("INDEX.md", "README.md")
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
# Generate index content
|
|
201
|
+
index_content = self._generate_index_content(
|
|
202
|
+
api_docs, guide_docs, root_docs
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Write index file
|
|
206
|
+
index_path.write_text(index_content, encoding="utf-8")
|
|
207
|
+
|
|
208
|
+
self.console.print(
|
|
209
|
+
f"[green]✅[/green] Updated documentation index at {index_path}"
|
|
210
|
+
)
|
|
211
|
+
return True
|
|
212
|
+
|
|
213
|
+
except Exception as e:
|
|
214
|
+
self.console.print(
|
|
215
|
+
f"[red]❌[/red] Failed to update documentation index: {e}"
|
|
216
|
+
)
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
def get_documentation_coverage(self) -> dict[str, t.Any]:
|
|
220
|
+
"""Calculate documentation coverage metrics."""
|
|
221
|
+
# Find all source files
|
|
222
|
+
source_files = self._find_source_files()
|
|
223
|
+
|
|
224
|
+
# Extract API data
|
|
225
|
+
api_data = self.extract_api_documentation(source_files)
|
|
226
|
+
|
|
227
|
+
# Count documented vs undocumented items
|
|
228
|
+
total_items, documented_items = self._count_documentation_items(api_data)
|
|
229
|
+
|
|
230
|
+
# Calculate coverage percentage
|
|
231
|
+
coverage_percentage = (
|
|
232
|
+
(documented_items / total_items * 100) if total_items > 0 else 0.0
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
"total_items": total_items,
|
|
237
|
+
"documented_items": documented_items,
|
|
238
|
+
"coverage_percentage": coverage_percentage,
|
|
239
|
+
"undocumented_items": total_items - documented_items,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
def _find_source_files(self) -> list[Path]:
|
|
243
|
+
"""Find all Python source files excluding hidden directories."""
|
|
244
|
+
source_files = list[t.Any](self.pkg_path.glob("**/*.py"))
|
|
245
|
+
return [
|
|
246
|
+
f for f in source_files if not any(part.startswith(".") for part in f.parts)
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
def _count_documentation_items(self, api_data: dict[str, t.Any]) -> tuple[int, int]:
|
|
250
|
+
"""Count total and documented items in API data."""
|
|
251
|
+
total_items = 0
|
|
252
|
+
documented_items = 0
|
|
253
|
+
|
|
254
|
+
# Count protocols
|
|
255
|
+
protocol_total, protocol_documented = self._count_protocol_items(
|
|
256
|
+
api_data.get("protocols", {})
|
|
257
|
+
)
|
|
258
|
+
total_items += protocol_total
|
|
259
|
+
documented_items += protocol_documented
|
|
260
|
+
|
|
261
|
+
# Count modules (classes and functions)
|
|
262
|
+
module_total, module_documented = self._count_module_items(
|
|
263
|
+
api_data.get("modules", {})
|
|
264
|
+
)
|
|
265
|
+
total_items += module_total
|
|
266
|
+
documented_items += module_documented
|
|
267
|
+
|
|
268
|
+
return total_items, documented_items
|
|
269
|
+
|
|
270
|
+
def _count_protocol_items(self, protocols: dict[str, t.Any]) -> tuple[int, int]:
|
|
271
|
+
"""Count protocol-related documentation items."""
|
|
272
|
+
total_items = 0
|
|
273
|
+
documented_items = 0
|
|
274
|
+
|
|
275
|
+
for protocol_info in protocols.values():
|
|
276
|
+
# Count protocol itself
|
|
277
|
+
total_items += 1
|
|
278
|
+
if protocol_info.get("docstring", {}).get("description"):
|
|
279
|
+
documented_items += 1
|
|
280
|
+
|
|
281
|
+
# Count protocol methods
|
|
282
|
+
method_total, method_documented = self._count_method_items(
|
|
283
|
+
protocol_info.get("methods", [])
|
|
284
|
+
)
|
|
285
|
+
total_items += method_total
|
|
286
|
+
documented_items += method_documented
|
|
287
|
+
|
|
288
|
+
return total_items, documented_items
|
|
289
|
+
|
|
290
|
+
def _count_module_items(self, modules: dict[str, t.Any]) -> tuple[int, int]:
|
|
291
|
+
"""Count module-related documentation items."""
|
|
292
|
+
total_items = 0
|
|
293
|
+
documented_items = 0
|
|
294
|
+
|
|
295
|
+
for module_data in modules.values():
|
|
296
|
+
# Count classes
|
|
297
|
+
class_total, class_documented = self._count_class_items(
|
|
298
|
+
module_data.get("classes", [])
|
|
299
|
+
)
|
|
300
|
+
total_items += class_total
|
|
301
|
+
documented_items += class_documented
|
|
302
|
+
|
|
303
|
+
# Count functions
|
|
304
|
+
func_total, func_documented = self._count_function_items(
|
|
305
|
+
module_data.get("functions", [])
|
|
306
|
+
)
|
|
307
|
+
total_items += func_total
|
|
308
|
+
documented_items += func_documented
|
|
309
|
+
|
|
310
|
+
return total_items, documented_items
|
|
311
|
+
|
|
312
|
+
def _count_class_items(self, classes: list[dict[str, t.Any]]) -> tuple[int, int]:
|
|
313
|
+
"""Count class-related documentation items."""
|
|
314
|
+
total_items = 0
|
|
315
|
+
documented_items = 0
|
|
316
|
+
|
|
317
|
+
for class_info in classes:
|
|
318
|
+
# Count class itself
|
|
319
|
+
total_items += 1
|
|
320
|
+
if class_info.get("docstring", {}).get("description"):
|
|
321
|
+
documented_items += 1
|
|
322
|
+
|
|
323
|
+
# Count class methods
|
|
324
|
+
method_total, method_documented = self._count_method_items(
|
|
325
|
+
class_info.get("methods", [])
|
|
326
|
+
)
|
|
327
|
+
total_items += method_total
|
|
328
|
+
documented_items += method_documented
|
|
329
|
+
|
|
330
|
+
return total_items, documented_items
|
|
331
|
+
|
|
332
|
+
def _count_function_items(
|
|
333
|
+
self, functions: list[dict[str, t.Any]]
|
|
334
|
+
) -> tuple[int, int]:
|
|
335
|
+
"""Count function documentation items."""
|
|
336
|
+
total_items = len(functions)
|
|
337
|
+
documented_items = sum(
|
|
338
|
+
1
|
|
339
|
+
for func_info in functions
|
|
340
|
+
if func_info.get("docstring", {}).get("description")
|
|
341
|
+
)
|
|
342
|
+
return total_items, documented_items
|
|
343
|
+
|
|
344
|
+
def _count_method_items(self, methods: list[dict[str, t.Any]]) -> tuple[int, int]:
|
|
345
|
+
"""Count method documentation items."""
|
|
346
|
+
total_items = len(methods)
|
|
347
|
+
documented_items = sum(
|
|
348
|
+
1 for method in methods if method.get("docstring", {}).get("description")
|
|
349
|
+
)
|
|
350
|
+
return total_items, documented_items
|
|
351
|
+
|
|
352
|
+
def generate_full_api_documentation(self) -> bool:
|
|
353
|
+
"""Generate complete API documentation for the project."""
|
|
354
|
+
try:
|
|
355
|
+
self.console.print(
|
|
356
|
+
"[cyan]📚[/cyan] Generating complete API documentation..."
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# Find all source files
|
|
360
|
+
source_files = list[t.Any](self.pkg_path.glob("**/*.py"))
|
|
361
|
+
source_files = [
|
|
362
|
+
f
|
|
363
|
+
for f in source_files
|
|
364
|
+
if not any(part.startswith(".") for part in f.parts)
|
|
365
|
+
]
|
|
366
|
+
|
|
367
|
+
# Extract API data
|
|
368
|
+
api_data = self.extract_api_documentation(source_files)
|
|
369
|
+
|
|
370
|
+
# Generate API reference
|
|
371
|
+
api_reference = self.doc_generator.generate_api_reference(api_data)
|
|
372
|
+
api_ref_path = self.api_docs_dir / "API_REFERENCE.md"
|
|
373
|
+
api_ref_path.write_text(api_reference, encoding="utf-8")
|
|
374
|
+
|
|
375
|
+
# Generate protocol documentation
|
|
376
|
+
if "protocols" in api_data:
|
|
377
|
+
protocol_docs = self._generate_protocol_documentation(
|
|
378
|
+
api_data["protocols"]
|
|
379
|
+
)
|
|
380
|
+
protocol_path = self.api_docs_dir / "PROTOCOLS.md"
|
|
381
|
+
protocol_path.write_text(protocol_docs, encoding="utf-8")
|
|
382
|
+
|
|
383
|
+
# Generate service documentation
|
|
384
|
+
if "services" in api_data:
|
|
385
|
+
service_docs = self._generate_service_documentation(
|
|
386
|
+
api_data["services"]
|
|
387
|
+
)
|
|
388
|
+
service_path = self.api_docs_dir / "SERVICES.md"
|
|
389
|
+
service_path.write_text(service_docs, encoding="utf-8")
|
|
390
|
+
|
|
391
|
+
# Generate CLI documentation
|
|
392
|
+
if "commands" in api_data:
|
|
393
|
+
cli_docs = self._generate_cli_documentation(api_data["commands"])
|
|
394
|
+
cli_path = self.api_docs_dir / "CLI_REFERENCE.md"
|
|
395
|
+
cli_path.write_text(cli_docs, encoding="utf-8")
|
|
396
|
+
|
|
397
|
+
# Update cross-references
|
|
398
|
+
cross_refs = self.doc_generator.generate_cross_references(api_data)
|
|
399
|
+
if cross_refs:
|
|
400
|
+
cross_ref_path = self.api_docs_dir / "CROSS_REFERENCES.md"
|
|
401
|
+
cross_ref_content = self._format_cross_references(cross_refs)
|
|
402
|
+
cross_ref_path.write_text(cross_ref_content, encoding="utf-8")
|
|
403
|
+
|
|
404
|
+
# Update documentation index
|
|
405
|
+
self.update_documentation_index()
|
|
406
|
+
|
|
407
|
+
self.console.print(
|
|
408
|
+
"[green]🎉[/green] API documentation generation completed!"
|
|
409
|
+
)
|
|
410
|
+
return True
|
|
411
|
+
|
|
412
|
+
except Exception as e:
|
|
413
|
+
self.console.print(
|
|
414
|
+
f"[red]❌[/red] Failed to generate API documentation: {e}"
|
|
415
|
+
)
|
|
416
|
+
return False
|
|
417
|
+
|
|
418
|
+
def _ensure_directories(self) -> None:
|
|
419
|
+
"""Ensure all necessary documentation directories exist."""
|
|
420
|
+
directories = [
|
|
421
|
+
self.docs_dir,
|
|
422
|
+
self.generated_docs_dir,
|
|
423
|
+
self.api_docs_dir,
|
|
424
|
+
self.guides_dir,
|
|
425
|
+
]
|
|
426
|
+
|
|
427
|
+
for directory in directories:
|
|
428
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
429
|
+
|
|
430
|
+
def _check_internal_links(
|
|
431
|
+
self, content: str, doc_path: Path
|
|
432
|
+
) -> list[dict[str, str]]:
|
|
433
|
+
"""Check for broken internal links in documentation."""
|
|
434
|
+
from .regex_patterns import SAFE_PATTERNS
|
|
435
|
+
|
|
436
|
+
issues = []
|
|
437
|
+
|
|
438
|
+
# Find markdown links [text](path)
|
|
439
|
+
link_pattern = SAFE_PATTERNS["extract_markdown_links"]._get_compiled_pattern()
|
|
440
|
+
matches = link_pattern.findall(content)
|
|
441
|
+
|
|
442
|
+
for link_text, link_path in matches:
|
|
443
|
+
if link_path.startswith(("http://", "https://", "mailto:")):
|
|
444
|
+
continue # Skip external links
|
|
445
|
+
|
|
446
|
+
# Resolve relative path
|
|
447
|
+
if link_path.startswith("/"):
|
|
448
|
+
target_path = self.pkg_path / link_path.lstrip("/")
|
|
449
|
+
else:
|
|
450
|
+
target_path = doc_path.parent / link_path
|
|
451
|
+
|
|
452
|
+
if not target_path.exists():
|
|
453
|
+
issues.append(
|
|
454
|
+
{
|
|
455
|
+
"type": "broken_link",
|
|
456
|
+
"path": str(doc_path),
|
|
457
|
+
"message": f"Broken internal link: [{link_text}]({link_path})",
|
|
458
|
+
}
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
return issues
|
|
462
|
+
|
|
463
|
+
def _check_empty_sections(
|
|
464
|
+
self, content: str, doc_path: Path
|
|
465
|
+
) -> list[dict[str, str]]:
|
|
466
|
+
"""Check for empty sections in documentation."""
|
|
467
|
+
import re
|
|
468
|
+
|
|
469
|
+
issues = []
|
|
470
|
+
|
|
471
|
+
# Find headers followed immediately by another header (empty section)
|
|
472
|
+
empty_section_pattern = re.compile( # REGEX OK: markdown section parsing
|
|
473
|
+
r"(#{1,6}\s+[^\n]+)\n\s*(#{1,6}\s+[^\n]+)", re.MULTILINE
|
|
474
|
+
)
|
|
475
|
+
matches = empty_section_pattern.findall(content)
|
|
476
|
+
|
|
477
|
+
for header1, header2 in matches:
|
|
478
|
+
issues.append(
|
|
479
|
+
{
|
|
480
|
+
"type": "empty_section",
|
|
481
|
+
"path": str(doc_path),
|
|
482
|
+
"message": f"Empty section found: {header1.strip()}",
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
return issues
|
|
487
|
+
|
|
488
|
+
def _check_version_references(
|
|
489
|
+
self, content: str, doc_path: Path
|
|
490
|
+
) -> list[dict[str, str]]:
|
|
491
|
+
"""Check for outdated version references."""
|
|
492
|
+
from .regex_patterns import SAFE_PATTERNS
|
|
493
|
+
|
|
494
|
+
issues = []
|
|
495
|
+
|
|
496
|
+
# Look for version patterns
|
|
497
|
+
version_pattern = SAFE_PATTERNS[
|
|
498
|
+
"extract_version_numbers"
|
|
499
|
+
]._get_compiled_pattern()
|
|
500
|
+
matches = version_pattern.findall(content)
|
|
501
|
+
|
|
502
|
+
# This is a placeholder - in a real implementation you'd compare with current version
|
|
503
|
+
for version in matches:
|
|
504
|
+
if version != "1.0.0": # Placeholder version check
|
|
505
|
+
issues.append(
|
|
506
|
+
{
|
|
507
|
+
"type": "outdated_version",
|
|
508
|
+
"path": str(doc_path),
|
|
509
|
+
"message": f"Potentially outdated version reference: {version}",
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
return issues
|
|
514
|
+
|
|
515
|
+
def _generate_index_content(
|
|
516
|
+
self, api_docs: list[Path], guide_docs: list[Path], root_docs: list[Path]
|
|
517
|
+
) -> str:
|
|
518
|
+
"""Generate content for the documentation index."""
|
|
519
|
+
lines = [
|
|
520
|
+
"# Documentation Index\n\n",
|
|
521
|
+
"This is the complete documentation index for the project.\n\n",
|
|
522
|
+
]
|
|
523
|
+
|
|
524
|
+
if api_docs:
|
|
525
|
+
lines.append("## API Documentation\n\n")
|
|
526
|
+
for doc in sorted(api_docs):
|
|
527
|
+
relative_path = doc.relative_to(self.docs_dir)
|
|
528
|
+
lines.append(f"- [{doc.stem}]({relative_path})\n")
|
|
529
|
+
lines.append("\n")
|
|
530
|
+
|
|
531
|
+
if guide_docs:
|
|
532
|
+
lines.append("## User Guides\n\n")
|
|
533
|
+
for doc in sorted(guide_docs):
|
|
534
|
+
relative_path = doc.relative_to(self.docs_dir)
|
|
535
|
+
lines.append(f"- [{doc.stem}]({relative_path})\n")
|
|
536
|
+
lines.append("\n")
|
|
537
|
+
|
|
538
|
+
if root_docs:
|
|
539
|
+
lines.append("## Additional Documentation\n\n")
|
|
540
|
+
for doc in sorted(root_docs):
|
|
541
|
+
lines.append(f"- [{doc.stem}]({doc.name})\n")
|
|
542
|
+
lines.append("\n")
|
|
543
|
+
|
|
544
|
+
return "".join(lines)
|
|
545
|
+
|
|
546
|
+
def _generate_protocol_documentation(self, protocols: dict[str, t.Any]) -> str:
|
|
547
|
+
"""Generate focused protocol documentation."""
|
|
548
|
+
lines = ["# Protocol Reference\n\n"]
|
|
549
|
+
lines.append(
|
|
550
|
+
"This document describes all protocol interfaces used in the codebase.\n\n"
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
for protocol_name, protocol_info in sorted(protocols.items()):
|
|
554
|
+
lines.append(f"## {protocol_name}\n\n")
|
|
555
|
+
|
|
556
|
+
description = protocol_info.get("docstring", {}).get(
|
|
557
|
+
"description", "No description provided."
|
|
558
|
+
)
|
|
559
|
+
lines.append(f"{description}\n\n")
|
|
560
|
+
|
|
561
|
+
if protocol_info.get("runtime_checkable"):
|
|
562
|
+
lines.append("**Runtime Checkable:** Yes\n\n")
|
|
563
|
+
|
|
564
|
+
methods = protocol_info.get("methods", [])
|
|
565
|
+
if methods:
|
|
566
|
+
lines.append("### Required Methods\n\n")
|
|
567
|
+
for method in methods:
|
|
568
|
+
lines.append(f"#### `{method['name']}`\n\n")
|
|
569
|
+
method_desc = method.get("docstring", {}).get(
|
|
570
|
+
"description", "No description provided."
|
|
571
|
+
)
|
|
572
|
+
lines.append(f"{method_desc}\n\n")
|
|
573
|
+
|
|
574
|
+
# Add method signature
|
|
575
|
+
params = method.get("parameters", [])
|
|
576
|
+
param_strings = []
|
|
577
|
+
for param in params:
|
|
578
|
+
param_type = param.get("annotation", "Any")
|
|
579
|
+
param_strings.append(f"{param['name']}: {param_type}")
|
|
580
|
+
|
|
581
|
+
return_type = method.get("return_annotation", "Any")
|
|
582
|
+
signature = f"def {method['name']}({', '.join(param_strings)}) -> {return_type}"
|
|
583
|
+
lines.append(f"```python\n{signature}\n```\n\n")
|
|
584
|
+
|
|
585
|
+
lines.append("---\n\n")
|
|
586
|
+
|
|
587
|
+
return "".join(lines)
|
|
588
|
+
|
|
589
|
+
def _generate_service_documentation(self, services: dict[str, t.Any]) -> str:
|
|
590
|
+
"""Generate focused service documentation."""
|
|
591
|
+
lines = ["# Service Reference\n\n"]
|
|
592
|
+
lines.append(
|
|
593
|
+
"This document describes all service implementations in the codebase.\n\n"
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
for service_name, service_info in sorted(services.items()):
|
|
597
|
+
service_section = self._generate_service_section(service_name, service_info)
|
|
598
|
+
lines.extend(service_section)
|
|
599
|
+
|
|
600
|
+
return "".join(lines)
|
|
601
|
+
|
|
602
|
+
def _generate_service_section(
|
|
603
|
+
self, service_name: str, service_info: dict[str, t.Any]
|
|
604
|
+
) -> list[str]:
|
|
605
|
+
"""Generate documentation section for a single service."""
|
|
606
|
+
lines: list[str] = []
|
|
607
|
+
lines.extend(
|
|
608
|
+
(
|
|
609
|
+
f"## {service_name}\n\n",
|
|
610
|
+
f"**Location:** `{service_info.get('path', 'Unknown')}`\n\n",
|
|
611
|
+
)
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
# Add protocols implemented
|
|
615
|
+
if service_info.get("protocols_implemented"):
|
|
616
|
+
protocol_lines = self._generate_protocols_implemented(
|
|
617
|
+
service_info["protocols_implemented"]
|
|
618
|
+
)
|
|
619
|
+
lines.extend(protocol_lines)
|
|
620
|
+
|
|
621
|
+
# Add class documentation
|
|
622
|
+
class_lines = self._generate_service_classes(service_info.get("classes", []))
|
|
623
|
+
lines.extend(class_lines)
|
|
624
|
+
|
|
625
|
+
return lines
|
|
626
|
+
|
|
627
|
+
def _generate_protocols_implemented(self, protocols: list[str]) -> list[str]:
|
|
628
|
+
"""Generate protocols implemented section."""
|
|
629
|
+
lines = ["**Implements:**\n"]
|
|
630
|
+
for protocol in protocols:
|
|
631
|
+
lines.append(f"- {protocol}\n")
|
|
632
|
+
lines.append("\n")
|
|
633
|
+
return lines
|
|
634
|
+
|
|
635
|
+
def _generate_service_classes(self, classes: list[dict[str, t.Any]]) -> list[str]:
|
|
636
|
+
"""Generate documentation for service classes."""
|
|
637
|
+
lines = []
|
|
638
|
+
|
|
639
|
+
for class_info in classes:
|
|
640
|
+
lines.append(f"### {class_info['name']}\n\n")
|
|
641
|
+
description = class_info.get("docstring", {}).get(
|
|
642
|
+
"description", "No description provided."
|
|
643
|
+
)
|
|
644
|
+
lines.append(f"{description}\n\n")
|
|
645
|
+
|
|
646
|
+
# Add public methods
|
|
647
|
+
public_method_lines = self._generate_public_methods(
|
|
648
|
+
class_info.get("methods", [])
|
|
649
|
+
)
|
|
650
|
+
lines.extend(public_method_lines)
|
|
651
|
+
|
|
652
|
+
return lines
|
|
653
|
+
|
|
654
|
+
def _generate_public_methods(self, methods: list[dict[str, t.Any]]) -> list[str]:
|
|
655
|
+
"""Generate public methods documentation."""
|
|
656
|
+
public_methods = [m for m in methods if m.get("visibility") == "public"]
|
|
657
|
+
|
|
658
|
+
if not public_methods:
|
|
659
|
+
return []
|
|
660
|
+
|
|
661
|
+
lines = ["**Public Methods:**\n"]
|
|
662
|
+
for method in public_methods:
|
|
663
|
+
method_desc = method.get("docstring", {}).get("description", "")
|
|
664
|
+
lines.append(f"- `{method['name']}`: {method_desc}\n")
|
|
665
|
+
lines.append("\n")
|
|
666
|
+
|
|
667
|
+
return lines
|
|
668
|
+
|
|
669
|
+
def _generate_cli_documentation(self, commands: dict[str, t.Any]) -> str:
|
|
670
|
+
"""Generate CLI reference documentation."""
|
|
671
|
+
lines = ["# CLI Reference\n\n"]
|
|
672
|
+
lines.append(
|
|
673
|
+
"This document describes all command-line options and usage patterns.\n\n"
|
|
674
|
+
)
|
|
675
|
+
|
|
676
|
+
for command_name, command_info in sorted(commands.items()):
|
|
677
|
+
lines.append(f"## {command_name}\n\n")
|
|
678
|
+
|
|
679
|
+
options = command_info.get("options", [])
|
|
680
|
+
if options:
|
|
681
|
+
lines.append("### Available Options\n\n")
|
|
682
|
+
for option in options:
|
|
683
|
+
lines.append(
|
|
684
|
+
f"- `--{option['name']}` ({option['type']}): {option.get('description', 'No description')}\n"
|
|
685
|
+
)
|
|
686
|
+
lines.append("\n")
|
|
687
|
+
|
|
688
|
+
return "".join(lines)
|
|
689
|
+
|
|
690
|
+
def _format_cross_references(self, cross_refs: dict[str, list[str]]) -> str:
|
|
691
|
+
"""Format cross-references into markdown."""
|
|
692
|
+
lines = ["# Cross References\n\n"]
|
|
693
|
+
lines.append(
|
|
694
|
+
"This document shows where API components are used throughout the codebase.\n\n"
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
for name, references in sorted(cross_refs.items()):
|
|
698
|
+
if references:
|
|
699
|
+
lines.extend((f"## {name}\n\n", "**Referenced in:**\n"))
|
|
700
|
+
for ref in references:
|
|
701
|
+
lines.append(f"- {ref}\n")
|
|
702
|
+
lines.append("\n")
|
|
703
|
+
|
|
704
|
+
return "".join(lines)
|