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,361 @@
|
|
|
1
|
+
"""Centralized file I/O operations with consistent error handling."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import aiofiles
|
|
7
|
+
from loguru import logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FileIOService:
|
|
11
|
+
"""Centralized file I/O operations with consistent error handling."""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
async def read_text_file(path: str | Path, encoding: str = "utf-8") -> str:
|
|
15
|
+
"""
|
|
16
|
+
Asynchronously read a text file with consistent error handling.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
path: Path to the file to read
|
|
20
|
+
encoding: Text encoding to use (default: utf-8)
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
File contents as string
|
|
24
|
+
|
|
25
|
+
Raises:
|
|
26
|
+
FileNotFoundError: If the file doesn't exist
|
|
27
|
+
UnicodeDecodeError: If there's an encoding issue
|
|
28
|
+
OSError: For other file system errors
|
|
29
|
+
"""
|
|
30
|
+
try:
|
|
31
|
+
async with aiofiles.open(path, encoding=encoding) as f:
|
|
32
|
+
return await f.read()
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
logger.warning(f"File not found: {path}")
|
|
35
|
+
raise
|
|
36
|
+
except UnicodeDecodeError:
|
|
37
|
+
logger.error(f"Failed to decode file as {encoding}: {path}")
|
|
38
|
+
raise
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.error(f"Error reading file {path}: {e}")
|
|
41
|
+
raise
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
async def write_text_file(
|
|
45
|
+
path: str | Path,
|
|
46
|
+
content: str,
|
|
47
|
+
encoding: str = "utf-8",
|
|
48
|
+
create_dirs: bool = True,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Asynchronously write content to a text file with consistent error handling.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
path: Path to the file to write
|
|
55
|
+
content: Content to write to the file
|
|
56
|
+
encoding: Text encoding to use (default: utf-8)
|
|
57
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
OSError: For file system errors
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
file_path = Path(path)
|
|
64
|
+
|
|
65
|
+
if create_dirs:
|
|
66
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
|
|
68
|
+
async with aiofiles.open(file_path, "w", encoding=encoding) as f:
|
|
69
|
+
await f.write(content)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logger.error(f"Error writing to file {path}: {e}")
|
|
72
|
+
raise
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def read_text_file_sync(path: str | Path, encoding: str = "utf-8") -> str:
|
|
76
|
+
"""
|
|
77
|
+
Synchronously read a text file with consistent error handling.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
path: Path to the file to read
|
|
81
|
+
encoding: Text encoding to use (default: utf-8)
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
File contents as string
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
FileNotFoundError: If the file doesn't exist
|
|
88
|
+
UnicodeDecodeError: If there's an encoding issue
|
|
89
|
+
OSError: For other file system errors
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
with open(path, encoding=encoding) as f:
|
|
93
|
+
return f.read()
|
|
94
|
+
except FileNotFoundError:
|
|
95
|
+
logger.warning(f"File not found: {path}")
|
|
96
|
+
raise
|
|
97
|
+
except UnicodeDecodeError:
|
|
98
|
+
logger.error(f"Failed to decode file as {encoding}: {path}")
|
|
99
|
+
raise
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.error(f"Error reading file {path}: {e}")
|
|
102
|
+
raise
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def write_text_file_sync(
|
|
106
|
+
path: str | Path,
|
|
107
|
+
content: str,
|
|
108
|
+
encoding: str = "utf-8",
|
|
109
|
+
create_dirs: bool = True,
|
|
110
|
+
) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Synchronously write content to a text file with consistent error handling.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
path: Path to the file to write
|
|
116
|
+
content: Content to write to the file
|
|
117
|
+
encoding: Text encoding to use (default: utf-8)
|
|
118
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
OSError: For file system errors
|
|
122
|
+
"""
|
|
123
|
+
try:
|
|
124
|
+
file_path = Path(path)
|
|
125
|
+
|
|
126
|
+
if create_dirs:
|
|
127
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
|
|
129
|
+
with file_path.open("w", encoding=encoding) as f:
|
|
130
|
+
f.write(content)
|
|
131
|
+
except Exception as e:
|
|
132
|
+
logger.error(f"Error writing to file {path}: {e}")
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
async def read_json_file(path: str | Path) -> dict:
|
|
137
|
+
"""
|
|
138
|
+
Asynchronously read and parse a JSON file.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
path: Path to the JSON file to read
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Parsed JSON content as dictionary
|
|
145
|
+
|
|
146
|
+
Raises:
|
|
147
|
+
FileNotFoundError: If the file doesn't exist
|
|
148
|
+
json.JSONDecodeError: If the file contains invalid JSON
|
|
149
|
+
OSError: For other file system errors
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
content = await FileIOService.read_text_file(path)
|
|
153
|
+
return json.loads(content)
|
|
154
|
+
except json.JSONDecodeError as e:
|
|
155
|
+
logger.error(f"Invalid JSON in file {path}: {e}")
|
|
156
|
+
raise
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logger.error(f"Error reading JSON file {path}: {e}")
|
|
159
|
+
raise
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
async def write_json_file(
|
|
163
|
+
path: str | Path, data: dict, create_dirs: bool = True, indent: int = 2
|
|
164
|
+
) -> None:
|
|
165
|
+
"""
|
|
166
|
+
Asynchronously write data to a JSON file.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
path: Path to the JSON file to write
|
|
170
|
+
data: Data to serialize to JSON
|
|
171
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
172
|
+
indent: JSON indentation (default: 2)
|
|
173
|
+
|
|
174
|
+
Raises:
|
|
175
|
+
OSError: For file system errors
|
|
176
|
+
TypeError: If data is not JSON serializable
|
|
177
|
+
"""
|
|
178
|
+
try:
|
|
179
|
+
content = json.dumps(data, indent=indent, ensure_ascii=False)
|
|
180
|
+
await FileIOService.write_text_file(path, content, create_dirs=create_dirs)
|
|
181
|
+
except Exception as e:
|
|
182
|
+
logger.error(f"Error writing JSON file {path}: {e}")
|
|
183
|
+
raise
|
|
184
|
+
|
|
185
|
+
@staticmethod
|
|
186
|
+
def read_json_file_sync(path: str | Path) -> dict:
|
|
187
|
+
"""
|
|
188
|
+
Synchronously read and parse a JSON file.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
path: Path to the JSON file to read
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Parsed JSON content as dictionary
|
|
195
|
+
|
|
196
|
+
Raises:
|
|
197
|
+
FileNotFoundError: If the file doesn't exist
|
|
198
|
+
json.JSONDecodeError: If the file contains invalid JSON
|
|
199
|
+
OSError: For other file system errors
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
with open(path, encoding="utf-8") as f:
|
|
203
|
+
return json.load(f)
|
|
204
|
+
except json.JSONDecodeError as e:
|
|
205
|
+
logger.error(f"Invalid JSON in file {path}: {e}")
|
|
206
|
+
raise
|
|
207
|
+
except Exception as e:
|
|
208
|
+
logger.error(f"Error reading JSON file {path}: {e}")
|
|
209
|
+
raise
|
|
210
|
+
|
|
211
|
+
@staticmethod
|
|
212
|
+
def write_json_file_sync(
|
|
213
|
+
path: str | Path, data: dict, create_dirs: bool = True, indent: int = 2
|
|
214
|
+
) -> None:
|
|
215
|
+
"""
|
|
216
|
+
Synchronously write data to a JSON file.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
path: Path to the JSON file to write
|
|
220
|
+
data: Data to serialize to JSON
|
|
221
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
222
|
+
indent: JSON indentation (default: 2)
|
|
223
|
+
|
|
224
|
+
Raises:
|
|
225
|
+
OSError: For file system errors
|
|
226
|
+
TypeError: If data is not JSON serializable
|
|
227
|
+
"""
|
|
228
|
+
try:
|
|
229
|
+
file_path = Path(path)
|
|
230
|
+
|
|
231
|
+
if create_dirs:
|
|
232
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
233
|
+
|
|
234
|
+
with file_path.open("w", encoding="utf-8") as f:
|
|
235
|
+
json.dump(data, f, indent=indent, ensure_ascii=False)
|
|
236
|
+
except Exception as e:
|
|
237
|
+
logger.error(f"Error writing JSON file {path}: {e}")
|
|
238
|
+
raise
|
|
239
|
+
|
|
240
|
+
@staticmethod
|
|
241
|
+
def read_binary_file_sync(path: str | Path) -> bytes:
|
|
242
|
+
"""
|
|
243
|
+
Synchronously read a binary file with consistent error handling.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
path: Path to the binary file to read
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
File contents as bytes
|
|
250
|
+
|
|
251
|
+
Raises:
|
|
252
|
+
FileNotFoundError: If the file doesn't exist
|
|
253
|
+
OSError: For other file system errors
|
|
254
|
+
"""
|
|
255
|
+
try:
|
|
256
|
+
with open(path, "rb") as f:
|
|
257
|
+
return f.read()
|
|
258
|
+
except Exception as e:
|
|
259
|
+
logger.error(f"Error reading binary file {path}: {e}")
|
|
260
|
+
raise
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
async def read_binary_file(path: str | Path) -> bytes:
|
|
264
|
+
"""
|
|
265
|
+
Asynchronously read a binary file with consistent error handling.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
path: Path to the binary file to read
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
File contents as bytes
|
|
272
|
+
|
|
273
|
+
Raises:
|
|
274
|
+
FileNotFoundError: If the file doesn't exist
|
|
275
|
+
OSError: For other file system errors
|
|
276
|
+
"""
|
|
277
|
+
try:
|
|
278
|
+
async with aiofiles.open(path, "rb") as f:
|
|
279
|
+
return await f.read()
|
|
280
|
+
except Exception as e:
|
|
281
|
+
logger.error(f"Error reading binary file {path}: {e}")
|
|
282
|
+
raise
|
|
283
|
+
|
|
284
|
+
@staticmethod
|
|
285
|
+
def write_binary_file_sync(
|
|
286
|
+
path: str | Path, data: bytes, create_dirs: bool = True
|
|
287
|
+
) -> None:
|
|
288
|
+
"""
|
|
289
|
+
Synchronously write bytes to a binary file with consistent error handling.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
path: Path to the binary file to write
|
|
293
|
+
data: Bytes to write to the file
|
|
294
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
295
|
+
|
|
296
|
+
Raises:
|
|
297
|
+
OSError: For file system errors
|
|
298
|
+
"""
|
|
299
|
+
try:
|
|
300
|
+
file_path = Path(path)
|
|
301
|
+
|
|
302
|
+
if create_dirs:
|
|
303
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
304
|
+
|
|
305
|
+
file_path.write_bytes(data)
|
|
306
|
+
except Exception as e:
|
|
307
|
+
logger.error(f"Error writing to binary file {path}: {e}")
|
|
308
|
+
raise
|
|
309
|
+
|
|
310
|
+
@staticmethod
|
|
311
|
+
async def write_binary_file(
|
|
312
|
+
path: str | Path, data: bytes, create_dirs: bool = True
|
|
313
|
+
) -> None:
|
|
314
|
+
"""
|
|
315
|
+
Asynchronously write bytes to a binary file with consistent error handling.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
path: Path to the binary file to write
|
|
319
|
+
data: Bytes to write to the file
|
|
320
|
+
create_dirs: Whether to create parent directories if they don't exist
|
|
321
|
+
|
|
322
|
+
Raises:
|
|
323
|
+
OSError: For file system errors
|
|
324
|
+
"""
|
|
325
|
+
try:
|
|
326
|
+
file_path = Path(path)
|
|
327
|
+
|
|
328
|
+
if create_dirs:
|
|
329
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
330
|
+
|
|
331
|
+
async with aiofiles.open(file_path, "wb") as f:
|
|
332
|
+
await f.write(data)
|
|
333
|
+
except Exception as e:
|
|
334
|
+
logger.error(f"Error writing to binary file {path}: {e}")
|
|
335
|
+
raise
|
|
336
|
+
|
|
337
|
+
@staticmethod
|
|
338
|
+
def file_exists(path: str | Path) -> bool:
|
|
339
|
+
"""
|
|
340
|
+
Check if a file exists.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
path: Path to check for existence
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
True if file exists, False otherwise
|
|
347
|
+
"""
|
|
348
|
+
return Path(path).is_file()
|
|
349
|
+
|
|
350
|
+
@staticmethod
|
|
351
|
+
def directory_exists(path: str | Path) -> bool:
|
|
352
|
+
"""
|
|
353
|
+
Check if a directory exists.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
path: Path to check for existence
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
True if directory exists, False otherwise
|
|
360
|
+
"""
|
|
361
|
+
return Path(path).is_dir()
|