py-wlcli 0.8.0__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.
- py_wlcli-0.8.0.dist-info/METADATA +139 -0
- py_wlcli-0.8.0.dist-info/RECORD +320 -0
- py_wlcli-0.8.0.dist-info/WHEEL +4 -0
- py_wlcli-0.8.0.dist-info/entry_points.txt +2 -0
- py_wlcli-0.8.0.dist-info/licenses/LICENSE +21 -0
- wl_cli/__init__.py +27 -0
- wl_cli/__main__.py +130 -0
- wl_cli/capabilities.py +79 -0
- wl_cli/cc/__init__.py +5 -0
- wl_cli/cc/checks.py +1019 -0
- wl_cli/cc/cli.py +370 -0
- wl_cli/cc/mutate.py +1350 -0
- wl_cli/cli_click.py +156 -0
- wl_cli/commands/__init__.py +84 -0
- wl_cli/commands/base.py +80 -0
- wl_cli/commands/buildcommands/__init__.py +1 -0
- wl_cli/commands/buildcommands/build.py +71 -0
- wl_cli/commands/buildcommands/build_utils.py +47 -0
- wl_cli/commands/buildcommands/builders/__init__.py +18 -0
- wl_cli/commands/buildcommands/builders/cleanup.py +35 -0
- wl_cli/commands/buildcommands/builders/coordinator.py +122 -0
- wl_cli/commands/buildcommands/builders/environment.py +81 -0
- wl_cli/commands/buildcommands/builders/rust_builder.py +39 -0
- wl_cli/commands/buildcommands/builders/stubs.py +58 -0
- wl_cli/commands/buildcommands/dist.py +326 -0
- wl_cli/commands/buildcommands/test.py +89 -0
- wl_cli/commands/clean/__init__.py +1 -0
- wl_cli/commands/clean/build.py +151 -0
- wl_cli/commands/clean/clean.py +294 -0
- wl_cli/commands/clean/clean_utils.py +77 -0
- wl_cli/commands/clean/core.py +236 -0
- wl_cli/commands/clean/dead_code/__init__.py +0 -0
- wl_cli/commands/clean/dead_code/dead_code_command.py +70 -0
- wl_cli/commands/clean/dead_code/detector.py +161 -0
- wl_cli/commands/clean/dead_code/fixer.py +176 -0
- wl_cli/commands/clean/dead_code/reporter.py +295 -0
- wl_cli/commands/clean/dead_code/utils.py +0 -0
- wl_cli/commands/clean/lfs.py +215 -0
- wl_cli/commands/clean/python.py +81 -0
- wl_cli/commands/clean/rust.py +91 -0
- wl_cli/commands/clean/utils/__init__.py +34 -0
- wl_cli/commands/clean/venv.py +91 -0
- wl_cli/commands/cleanup.py +73 -0
- wl_cli/commands/click_base.py +79 -0
- wl_cli/commands/config/__init__.py +1 -0
- wl_cli/commands/config/config.py +291 -0
- wl_cli/commands/debug/__init__.py +6 -0
- wl_cli/commands/debug/debug.py +309 -0
- wl_cli/commands/debug/debug_cache.py +86 -0
- wl_cli/commands/debug/debug_subagent.py +156 -0
- wl_cli/commands/debug/output_formatter.py +165 -0
- wl_cli/commands/debug/source_hasher.py +92 -0
- wl_cli/commands/format/__init__.py +13 -0
- wl_cli/commands/format/format_cache_adapter.py +125 -0
- wl_cli/commands/format/format_command.py +197 -0
- wl_cli/commands/format/format_coordinator.py +191 -0
- wl_cli/commands/format/format_executor.py +470 -0
- wl_cli/commands/format/format_outcome.py +44 -0
- wl_cli/commands/format/format_path_handler.py +1016 -0
- wl_cli/commands/format/format_progress.py +62 -0
- wl_cli/commands/format/format_reporter.py +31 -0
- wl_cli/commands/format/python_formatter.py +506 -0
- wl_cli/commands/format/rust_formatter.py +106 -0
- wl_cli/commands/gate/__init__.py +1 -0
- wl_cli/commands/gate/gate_command.py +862 -0
- wl_cli/commands/gate/preflight.py +445 -0
- wl_cli/commands/git/__init__.py +1 -0
- wl_cli/commands/git/config.py +169 -0
- wl_cli/commands/git/git_facts.py +60 -0
- wl_cli/commands/git/git_flow.py +86 -0
- wl_cli/commands/git/hook.py +112 -0
- wl_cli/commands/git/policy.py +216 -0
- wl_cli/commands/git/push_update.py +82 -0
- wl_cli/commands/initenv/__init__.py +1 -0
- wl_cli/commands/initenv/common/__init__.py +23 -0
- wl_cli/commands/initenv/common/check_git_bash.py +78 -0
- wl_cli/commands/initenv/common/error_handler.py +68 -0
- wl_cli/commands/initenv/common/exceptions.py +52 -0
- wl_cli/commands/initenv/components/__init__.py +4 -0
- wl_cli/commands/initenv/components/cargo_sync.py +240 -0
- wl_cli/commands/initenv/components/config_manager.py +106 -0
- wl_cli/commands/initenv/components/directory_utils.py +71 -0
- wl_cli/commands/initenv/components/git/__init__.py +9 -0
- wl_cli/commands/initenv/components/git/branch_creator.py +143 -0
- wl_cli/commands/initenv/components/git/git_flow_interface.py +24 -0
- wl_cli/commands/initenv/components/git/git_flow_manager.py +159 -0
- wl_cli/commands/initenv/components/git/git_lfs_manager.py +272 -0
- wl_cli/commands/initenv/components/git/git_utility.py +254 -0
- wl_cli/commands/initenv/components/git/gitignore_manager.py +53 -0
- wl_cli/commands/initenv/components/git_initializer.py +212 -0
- wl_cli/commands/initenv/components/i18n_manager.py +104 -0
- wl_cli/commands/initenv/components/log_manager.py +241 -0
- wl_cli/commands/initenv/components/project_structure/__init__.py +23 -0
- wl_cli/commands/initenv/components/project_structure/config_generator.py +360 -0
- wl_cli/commands/initenv/components/project_structure/directory_creator.py +184 -0
- wl_cli/commands/initenv/components/project_structure/hook_source.py +110 -0
- wl_cli/commands/initenv/components/project_structure/hooks_manager.py +995 -0
- wl_cli/commands/initenv/components/project_structure/readme_handler.py +56 -0
- wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +30 -0
- wl_cli/commands/initenv/components/project_structure/setup_handler.py +103 -0
- wl_cli/commands/initenv/components/project_structure/sop_generator.py +73 -0
- wl_cli/commands/initenv/components/project_structure/template_copier.py +104 -0
- wl_cli/commands/initenv/components/project_structure/template_manager.py +195 -0
- wl_cli/commands/initenv/components/pyproject_generator.py +194 -0
- wl_cli/commands/initenv/components/rust_initializer.py +145 -0
- wl_cli/commands/initenv/components/symlink_cleaner.py +99 -0
- wl_cli/commands/initenv/components/symlink_manager.py +52 -0
- wl_cli/commands/initenv/components/venv_manager.py +118 -0
- wl_cli/commands/initenv/initenv.py +169 -0
- wl_cli/commands/initenv/services/__init__.py +11 -0
- wl_cli/commands/initenv/services/environment_initializer.py +288 -0
- wl_cli/commands/initenv/services/git_lfs_initializer.py +26 -0
- wl_cli/commands/initenv/services/project_structure_initializer.py +52 -0
- wl_cli/commands/lfs/README.md +221 -0
- wl_cli/commands/lfs/__init__.py +5 -0
- wl_cli/commands/lfs/cli.py +106 -0
- wl_cli/commands/lfs/config.py +164 -0
- wl_cli/commands/lfs/hook.py +61 -0
- wl_cli/commands/lfs/initializer.py +531 -0
- wl_cli/commands/lfs/manager.py +95 -0
- wl_cli/commands/lfs/policy.py +165 -0
- wl_cli/commands/lfs/watcher.py +294 -0
- wl_cli/commands/lint/__init__.py +1 -0
- wl_cli/commands/lint/lint_command.py +297 -0
- wl_cli/commands/lint/lint_executor.py +409 -0
- wl_cli/commands/lint/lint_reporter.py +579 -0
- wl_cli/commands/lint/lint_run.py +258 -0
- wl_cli/commands/lint/mypy_config.py +90 -0
- wl_cli/commands/registry.py +103 -0
- wl_cli/commands/self/__init__.py +7 -0
- wl_cli/commands/self/common/__init__.py +8 -0
- wl_cli/commands/self/common/capabilities.py +30 -0
- wl_cli/commands/self/common/config.py +27 -0
- wl_cli/commands/self/common/version_cache.py +85 -0
- wl_cli/commands/self/handlers/__init__.py +19 -0
- wl_cli/commands/self/handlers/base_handler.py +28 -0
- wl_cli/commands/self/handlers/install_handler.py +85 -0
- wl_cli/commands/self/handlers/status_handler.py +66 -0
- wl_cli/commands/self/handlers/uninstall_handler.py +58 -0
- wl_cli/commands/self/handlers/update_handler.py +102 -0
- wl_cli/commands/self/handlers/version_handler.py +16 -0
- wl_cli/commands/self/self_command.py +237 -0
- wl_cli/commands/self/services/__init__.py +15 -0
- wl_cli/commands/self/services/installation_manager.py +187 -0
- wl_cli/commands/self/services/local_installer.py +165 -0
- wl_cli/commands/self/services/pypi_updater.py +278 -0
- wl_cli/commands/self/services/windows_update.py +174 -0
- wl_cli/commands/testcommands/__init__.py +8 -0
- wl_cli/commands/testcommands/base_dependency_analyzer.py +198 -0
- wl_cli/commands/testcommands/batch_processor.py +278 -0
- wl_cli/commands/testcommands/cache_manager.py +1156 -0
- wl_cli/commands/testcommands/coverage_analyzer.py +955 -0
- wl_cli/commands/testcommands/coverage_cache_manager.py +183 -0
- wl_cli/commands/testcommands/progress_manager.py +79 -0
- wl_cli/commands/testcommands/python_env_detector.py +207 -0
- wl_cli/commands/testcommands/report_generator.py +101 -0
- wl_cli/commands/testcommands/single_test_executor.py +250 -0
- wl_cli/commands/testcommands/speed_checker.py +118 -0
- wl_cli/commands/testcommands/test_command_builder.py +165 -0
- wl_cli/commands/testcommands/test_commands.py +786 -0
- wl_cli/commands/testcommands/test_reporter.py +181 -0
- wl_cli/commands/testcommands/test_result_handler.py +96 -0
- wl_cli/commands/testcommands/test_runner.py +1343 -0
- wl_cli/commands/testcommands/test_utils.py +197 -0
- wl_cli/commands/testcommands/utils/__init__.py +17 -0
- wl_cli/commands/testcommands/utils/coverage_parser.py +98 -0
- wl_cli/commands/testcommands/utils/env_info.py +36 -0
- wl_cli/commands/testcommands/utils/junit_parser.py +75 -0
- wl_cli/commands/testcommands/utils/markdown_utils.py +20 -0
- wl_cli/commands/testcommands/utils/project_root.py +61 -0
- wl_cli/commands/update/__init__.py +9 -0
- wl_cli/commands/update/services/__init__.py +21 -0
- wl_cli/commands/update/services/backup_manager.py +207 -0
- wl_cli/commands/update/services/component_manager.py +83 -0
- wl_cli/commands/update/services/conflict_resolver.py +189 -0
- wl_cli/commands/update/services/vendors_updater.py +85 -0
- wl_cli/commands/update/services/version_tracker.py +127 -0
- wl_cli/commands/update/update_command.py +270 -0
- wl_cli/commands/update/utils/__init__.py +3 -0
- wl_cli/commands/version/__init__.py +9 -0
- wl_cli/commands/version/version_command.py +155 -0
- wl_cli/commands/workflow.py +477 -0
- wl_cli/env/__init__.py +5 -0
- wl_cli/env/cli.py +167 -0
- wl_cli/env_status.py +157 -0
- wl_cli/envelope.py +91 -0
- wl_cli/exceptions.py +85 -0
- wl_cli/lib/__init__.py +3 -0
- wl_cli/lib/rust_utils.py +35 -0
- wl_cli/mcp/__init__.py +6 -0
- wl_cli/mcp/capabilities.py +19 -0
- wl_cli/mcp/cli.py +22 -0
- wl_cli/mcp/gitlab.py +553 -0
- wl_cli/mcp/k8s.py +344 -0
- wl_cli/mcp/protocol.py +159 -0
- wl_cli/platform.py +139 -0
- wl_cli/quality/__init__.py +18 -0
- wl_cli/utils/__init__.py +7 -0
- wl_cli/utils/cache.py +491 -0
- wl_cli/utils/cache_ledger.py +355 -0
- wl_cli/utils/cache_store.py +546 -0
- wl_cli/utils/config/__init__.py +27 -0
- wl_cli/utils/config/config_loader.py +163 -0
- wl_cli/utils/config/core.py +862 -0
- wl_cli/utils/config/defaults.py +142 -0
- wl_cli/utils/config/env_exporter.py +86 -0
- wl_cli/utils/config/env_parser.py +108 -0
- wl_cli/utils/config/validation.py +280 -0
- wl_cli/utils/error_handler.py +165 -0
- wl_cli/utils/file_copier.py +56 -0
- wl_cli/utils/file_operations.py +506 -0
- wl_cli/utils/language_utils.py +122 -0
- wl_cli/utils/lazy_import.py +240 -0
- wl_cli/utils/log_levels.py +35 -0
- wl_cli/utils/log_rotators.py +74 -0
- wl_cli/utils/logging.py +458 -0
- wl_cli/utils/output_context.py +142 -0
- wl_cli/utils/performance/__init__.py +1 -0
- wl_cli/utils/performance/decorators.py +111 -0
- wl_cli/utils/performance/exporter.py +38 -0
- wl_cli/utils/performance/models.py +16 -0
- wl_cli/utils/performance/monitor.py +161 -0
- wl_cli/utils/performance_monitor.py +32 -0
- wl_cli/utils/platform_adapter.py +131 -0
- wl_cli/utils/pre_commit.py +266 -0
- wl_cli/utils/pre_commit_config.py +72 -0
- wl_cli/utils/root.py +521 -0
- wl_cli/utils/root_fallback.py +256 -0
- wl_cli/utils/run_evidence.py +236 -0
- wl_cli/utils/structured_logger.py +18 -0
- wl_cli/utils/structured_logging/__init__.py +19 -0
- wl_cli/utils/structured_logging/config.py +337 -0
- wl_cli/utils/structured_logging/core.py +177 -0
- wl_cli/utils/structured_logging/env.py +56 -0
- wl_cli/utils/structured_logging/filtering.py +75 -0
- wl_cli/utils/structured_logging/filters.py +55 -0
- wl_cli/utils/structured_logging/formatters.py +251 -0
- wl_cli/utils/structured_logging/handlers.py +308 -0
- wl_cli/utils/structured_logging/logger.py +354 -0
- wl_cli/utils/subprocess.py +71 -0
- wl_cli/utils/subprocess_utils.py +260 -0
- wl_cli/utils/test_utils/__init__.py +5 -0
- wl_cli/utils/test_utils/test_filter.py +36 -0
- wl_cli/utils/uv_run.py +79 -0
- wl_cli/utils/uv_tool.py +117 -0
- wl_cli/utils/uv_tree.py +71 -0
- wl_cli/utils/uv_workspace.py +174 -0
- wl_cli/utils/version/__init__.py +15 -0
- wl_cli/utils/version/pypi_version_checker.py +95 -0
- wl_cli/utils/version/version_comparator.py +133 -0
- wl_cli/utils/version/version_detectors.py +312 -0
- wl_cli/utils/version/version_service.py +131 -0
- wl_cli/utils/version/version_updater.py +198 -0
- wl_cli/utils/wl_dir_updater.py +1440 -0
- wl_cli/utils/workspace_detector/__init__.py +28 -0
- wl_cli/utils/workspace_detector/core.py +161 -0
- wl_cli/utils/workspace_detector/detection_strategies.py +107 -0
- wl_cli/utils/workspace_detector/exceptions.py +5 -0
- wl_cli/utils/workspace_detector/types.py +17 -0
- wl_cli/utils/workspace_detector/venv_resolver.py +84 -0
- wl_cli/vendors/config/.codespellrc +2 -0
- wl_cli/vendors/config/dependencies.toml +10 -0
- wl_cli/vendors/config/mypy.ini +62 -0
- wl_cli/vendors/config/pyproject_defaults.toml +28 -0
- wl_cli/vendors/config/template_config.toml +24 -0
- wl_cli/vendors/config/tool_configs.toml +76 -0
- wl_cli/vendors/git/.gitignore +122 -0
- wl_cli/vendors/git/.pre-commit-config.yaml +37 -0
- wl_cli/vendors/hooks/applypatch-msg.sample +15 -0
- wl_cli/vendors/hooks/commit-msg.sample +24 -0
- wl_cli/vendors/hooks/fsmonitor-watchman.sample +174 -0
- wl_cli/vendors/hooks/post-update.sample +8 -0
- wl_cli/vendors/hooks/pre-applypatch.sample +14 -0
- wl_cli/vendors/hooks/pre-commit +45 -0
- wl_cli/vendors/hooks/pre-commit.legacy +31 -0
- wl_cli/vendors/hooks/pre-commit.sample +49 -0
- wl_cli/vendors/hooks/pre-merge-commit.sample +13 -0
- wl_cli/vendors/hooks/pre-push.sample +60 -0
- wl_cli/vendors/hooks/pre-rebase.sample +169 -0
- wl_cli/vendors/hooks/pre-receive.sample +24 -0
- wl_cli/vendors/hooks/prepare-commit-msg.sample +42 -0
- wl_cli/vendors/hooks/push-to-checkout.sample +78 -0
- wl_cli/vendors/hooks/sendemail-validate.sample +77 -0
- wl_cli/vendors/hooks/unix/applypatch-msg.sample +15 -0
- wl_cli/vendors/hooks/unix/check_lockfile.py +58 -0
- wl_cli/vendors/hooks/unix/check_lockfile.sh +36 -0
- wl_cli/vendors/hooks/unix/commit-msg.sample +24 -0
- wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +174 -0
- wl_cli/vendors/hooks/unix/post-update.sample +8 -0
- wl_cli/vendors/hooks/unix/pre-applypatch.sample +14 -0
- wl_cli/vendors/hooks/unix/pre-commit +190 -0
- wl_cli/vendors/hooks/unix/pre-commit.legacy +31 -0
- wl_cli/vendors/hooks/unix/pre-commit.py +81 -0
- wl_cli/vendors/hooks/unix/pre-commit.sample +49 -0
- wl_cli/vendors/hooks/unix/pre-merge-commit.sample +13 -0
- wl_cli/vendors/hooks/unix/pre-push +417 -0
- wl_cli/vendors/hooks/unix/pre-push.sample +53 -0
- wl_cli/vendors/hooks/unix/pre-rebase.sample +169 -0
- wl_cli/vendors/hooks/unix/pre-receive.sample +24 -0
- wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +42 -0
- wl_cli/vendors/hooks/update.sample +128 -0
- wl_cli/vendors/hooks/win/work.bat +63 -0
- wl_cli/vendors/project/.gitignore +90 -0
- wl_cli/vendors/project/.python-version +1 -0
- wl_cli/vendors/project/LICENSE +21 -0
- wl_cli/vendors/project/README.md +0 -0
- wl_cli/vendors/project/pyproject.toml +27 -0
- wl_cli/vendors/project/pyproject_no_workspace.toml +16 -0
- wl_cli/vendors/project/pyproject_workspace.toml +14 -0
- wl_cli/vendors/readme/README.md +120 -0
- wl_cli/vendors/rust/Cargo.toml +14 -0
- wl_cli/vendors/rust/lib/__init__.py +3 -0
- wl_cli/vendors/rust/lib/rust_utils.py +31 -0
- wl_cli/vendors/rust/src/lib.rs +13 -0
- wl_cli/vendors/rust/src/main.rs +3 -0
- wl_cli/vendors/rust/tests/test_rust_fallback.py +40 -0
- wl_cli/vendors/sop_doc/git-dev-sop.md +220 -0
- wl_cli/vendors/sop_doc/industrial-standard-sop.md +145 -0
- wl_cli/vendors/sop_doc/python-sop.md +342 -0
- wl_cli/vendors/sop_doc/rust-readme.md +219 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Unified error handling utilities for WL Commands."""
|
|
2
|
+
|
|
3
|
+
import traceback
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any, TypeVar, cast
|
|
6
|
+
|
|
7
|
+
from ..exceptions import CommandError
|
|
8
|
+
from .logging import log_error
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ErrorHandler:
|
|
14
|
+
"""Unified error handler for WL Commands."""
|
|
15
|
+
|
|
16
|
+
# Error message format constants
|
|
17
|
+
ERROR_FORMAT = "{error_type}: {error_message}"
|
|
18
|
+
ERROR_WITH_CONTEXT_FORMAT = "Error in {context}: {error_type} - {error_message}"
|
|
19
|
+
COMMAND_ERROR_FORMAT = "Command execution failed: {error_message}"
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def handle_error(
|
|
23
|
+
error: Exception, context: str | None = None, show_traceback: bool = False
|
|
24
|
+
) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Handle an error with consistent formatting and logging.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
error: The exception to handle
|
|
30
|
+
context: Optional context information about where the error occurred
|
|
31
|
+
show_traceback: Whether to show full traceback for debugging
|
|
32
|
+
"""
|
|
33
|
+
error_type = type(error).__name__
|
|
34
|
+
error_message = str(error)
|
|
35
|
+
|
|
36
|
+
if context:
|
|
37
|
+
formatted_error = ErrorHandler.ERROR_WITH_CONTEXT_FORMAT.format(
|
|
38
|
+
context=context, error_type=error_type, error_message=error_message
|
|
39
|
+
)
|
|
40
|
+
else:
|
|
41
|
+
formatted_error = ErrorHandler.ERROR_FORMAT.format(
|
|
42
|
+
error_type=error_type, error_message=error_message
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Log the error with appropriate context
|
|
46
|
+
log_error(formatted_error, **ErrorHandler._get_error_context(error))
|
|
47
|
+
|
|
48
|
+
# Show traceback if requested
|
|
49
|
+
if show_traceback:
|
|
50
|
+
traceback.print_exc()
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def _get_error_context(error: Exception) -> dict[str, Any]:
|
|
54
|
+
"""
|
|
55
|
+
Extract context information from the error object.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
error: The exception to extract context from
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Dict with context information
|
|
62
|
+
"""
|
|
63
|
+
context = {}
|
|
64
|
+
# Extract additional context from specific exception types
|
|
65
|
+
if hasattr(error, "path"):
|
|
66
|
+
context["path"] = error.path
|
|
67
|
+
if hasattr(error, "command"):
|
|
68
|
+
context["command"] = error.command
|
|
69
|
+
if hasattr(error, "url"):
|
|
70
|
+
context["url"] = error.url
|
|
71
|
+
if hasattr(error, "field"):
|
|
72
|
+
context["field"] = error.field
|
|
73
|
+
if hasattr(error, "error_code"):
|
|
74
|
+
context["error_code"] = error.error_code
|
|
75
|
+
return context
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def wrap_command_execution(func: Callable[..., T], *args: Any, **kwargs: Any) -> T:
|
|
79
|
+
"""
|
|
80
|
+
Wrap command execution with error handling.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
func: The function to execute
|
|
84
|
+
*args: Positional arguments to pass to the function
|
|
85
|
+
**kwargs: Keyword arguments to pass to the function
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
The result of the function execution
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
CommandError: If the function raises an exception
|
|
92
|
+
"""
|
|
93
|
+
try:
|
|
94
|
+
return func(*args, **kwargs)
|
|
95
|
+
except CommandError:
|
|
96
|
+
# Re-raise CommandError as is
|
|
97
|
+
raise
|
|
98
|
+
except Exception as e:
|
|
99
|
+
# Wrap other exceptions in CommandError with standardized format
|
|
100
|
+
error_message = ErrorHandler.COMMAND_ERROR_FORMAT.format(
|
|
101
|
+
error_message=str(e)
|
|
102
|
+
)
|
|
103
|
+
raise CommandError(error_message) from e
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def global_exception_handler(func: Callable[..., T]) -> Callable[..., T]:
|
|
107
|
+
"""
|
|
108
|
+
Global exception handler decorator for command functions.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
func: The function to decorate
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
The decorated function with global exception handling
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def wrapper(*args: Any, **kwargs: Any) -> T:
|
|
118
|
+
try:
|
|
119
|
+
return func(*args, **kwargs)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
# Handle all exceptions globally
|
|
122
|
+
ErrorHandler.handle_error(e, context=func.__name__)
|
|
123
|
+
# For CLI commands, we should return an error code
|
|
124
|
+
if func.__name__ == "main" or "cli" in func.__name__:
|
|
125
|
+
return cast("T", 1)
|
|
126
|
+
raise
|
|
127
|
+
|
|
128
|
+
return wrapper
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def exception_to_dict(error: Exception) -> dict[str, Any]:
|
|
132
|
+
"""
|
|
133
|
+
Convert an exception to a dictionary for structured logging.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
error: The exception to convert
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Dict with exception information
|
|
140
|
+
"""
|
|
141
|
+
return {
|
|
142
|
+
"error_type": type(error).__name__,
|
|
143
|
+
"error_message": str(error),
|
|
144
|
+
"error_code": getattr(error, "error_code", None),
|
|
145
|
+
**ErrorHandler._get_error_context(error),
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class ErrorContext:
|
|
150
|
+
"""Context manager for error handling."""
|
|
151
|
+
|
|
152
|
+
def __init__(self, context: str, show_traceback: bool = False):
|
|
153
|
+
self.context = context
|
|
154
|
+
self.show_traceback = show_traceback
|
|
155
|
+
|
|
156
|
+
def __enter__(self):
|
|
157
|
+
return self
|
|
158
|
+
|
|
159
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
160
|
+
if exc_type is not None:
|
|
161
|
+
ErrorHandler.handle_error(
|
|
162
|
+
exc_val, self.context, show_traceback=self.show_traceback
|
|
163
|
+
)
|
|
164
|
+
return True # Suppress the exception
|
|
165
|
+
return False
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class CopyResult:
|
|
9
|
+
success: bool
|
|
10
|
+
message: str = ""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FileCopier:
|
|
14
|
+
def copy_file(
|
|
15
|
+
self,
|
|
16
|
+
src: Path,
|
|
17
|
+
dest: Path,
|
|
18
|
+
template: bool = False,
|
|
19
|
+
context: dict[str, Any] | None = None,
|
|
20
|
+
overwrite: bool = False,
|
|
21
|
+
) -> CopyResult:
|
|
22
|
+
try:
|
|
23
|
+
if not src.exists():
|
|
24
|
+
return CopyResult(False, f"Source file not found: {src}")
|
|
25
|
+
|
|
26
|
+
if dest.exists() and not overwrite:
|
|
27
|
+
return CopyResult(False, f"Destination already exists: {dest}")
|
|
28
|
+
|
|
29
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
|
|
31
|
+
if template and context:
|
|
32
|
+
try:
|
|
33
|
+
content = src.read_text(encoding="utf-8")
|
|
34
|
+
content = content.format(**context)
|
|
35
|
+
dest.write_text(content, encoding="utf-8")
|
|
36
|
+
except KeyError as e:
|
|
37
|
+
return CopyResult(False, f"Missing template key: {e}")
|
|
38
|
+
else:
|
|
39
|
+
shutil.copy2(src, dest)
|
|
40
|
+
|
|
41
|
+
return CopyResult(True)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
return CopyResult(False, str(e))
|
|
44
|
+
|
|
45
|
+
def copy_directory(self, src: Path, dest: Path) -> CopyResult:
|
|
46
|
+
try:
|
|
47
|
+
if not src.exists():
|
|
48
|
+
return CopyResult(False, f"Source directory not found: {src}")
|
|
49
|
+
|
|
50
|
+
if dest.exists():
|
|
51
|
+
shutil.rmtree(dest)
|
|
52
|
+
|
|
53
|
+
shutil.copytree(src, dest)
|
|
54
|
+
return CopyResult(True)
|
|
55
|
+
except Exception as e:
|
|
56
|
+
return CopyResult(False, str(e))
|