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
wl_cli/cli_click.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Command line interface entry point based on Click."""
|
|
3
|
+
|
|
4
|
+
import importlib
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from . import __version__
|
|
10
|
+
from .commands.registry import COMMAND_TABLE
|
|
11
|
+
from .utils.logging import log_error
|
|
12
|
+
from .utils.wl_dir_updater import check_and_update_wl_dir
|
|
13
|
+
|
|
14
|
+
#: Command prefixes that own their stdout stream (JSON / JSON-RPC).
|
|
15
|
+
#: The startup ``.wl`` self-sync logs INFO lines on stdout, which would corrupt
|
|
16
|
+
#: those payloads, so the dispatcher skips the sync for these commands (#220).
|
|
17
|
+
#: The ``cc`` write commands are listed individually: ``cc init --json`` and
|
|
18
|
+
#: friends emit one envelope line just like ``cc check`` (#223).
|
|
19
|
+
_SYNC_SKIP_PREFIXES: tuple[tuple[str, ...], ...] = (
|
|
20
|
+
("env", "check"),
|
|
21
|
+
("cc", "check"),
|
|
22
|
+
("cc", "init"),
|
|
23
|
+
("cc", "repair"),
|
|
24
|
+
("cc", "upgrade"),
|
|
25
|
+
("cc", "plugins"),
|
|
26
|
+
("cc", "mcp"),
|
|
27
|
+
("cc", "settings"),
|
|
28
|
+
("cc", "statusline"),
|
|
29
|
+
("cc", "hooks"),
|
|
30
|
+
("cc", "stamps"),
|
|
31
|
+
("self", "capabilities"),
|
|
32
|
+
("mcp", "serve"),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
#: Raw argv of the current :func:`main` invocation. Click resolves and consumes
|
|
36
|
+
#: the subcommand tokens before the group callback runs (``ctx.args`` is empty),
|
|
37
|
+
#: so ``main`` records them here for :func:`should_skip_wl_sync`. Direct ``wl``
|
|
38
|
+
#: invocations (tests) leave this empty, which means "run the sync".
|
|
39
|
+
_INVOCATION_ARGV: list[str] = []
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def should_skip_wl_sync(argv: list[str]) -> bool:
|
|
43
|
+
"""Return True when the startup ``.wl`` self-sync must be skipped.
|
|
44
|
+
|
|
45
|
+
Read-only commands that emit machine-readable output on stdout
|
|
46
|
+
(``wl env check --json``, ``wl self capabilities``, ``wl mcp serve``)
|
|
47
|
+
cannot tolerate the sync's INFO logging on the same stream. This is a
|
|
48
|
+
pure argv predicate: no command business logic belongs here.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
argv: Raw argv handed to ``wl``, without the program name.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
True if ``argv`` starts with one of the read-only command prefixes.
|
|
55
|
+
"""
|
|
56
|
+
return any(tuple(argv[: len(prefix)]) == prefix for prefix in _SYNC_SKIP_PREFIXES)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@click.group(
|
|
60
|
+
invoke_without_command=True,
|
|
61
|
+
context_settings={"help_option_names": ["-h", "--help"]},
|
|
62
|
+
)
|
|
63
|
+
@click.option("--version", "-v", is_flag=True, help="Show version information")
|
|
64
|
+
def wl(version):
|
|
65
|
+
"""WL Commands - A command-line tool for project management."""
|
|
66
|
+
ctx = click.get_current_context()
|
|
67
|
+
|
|
68
|
+
if version:
|
|
69
|
+
click.echo(f"wl {__version__}")
|
|
70
|
+
ctx.exit(0)
|
|
71
|
+
|
|
72
|
+
if not should_skip_wl_sync(_INVOCATION_ARGV):
|
|
73
|
+
check_and_update_wl_dir()
|
|
74
|
+
|
|
75
|
+
if ctx.invoked_subcommand is None:
|
|
76
|
+
click.echo(ctx.get_help())
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _register_click_command(
|
|
80
|
+
name: str, click_func, aliases: list[str] | None = None
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Register a Click command function with the wl group.
|
|
83
|
+
|
|
84
|
+
Aliases register the *same* Click object under a second name (Click keeps
|
|
85
|
+
the object's own ``name`` untouched), so an alias accepts exactly the
|
|
86
|
+
canonical command's options, arguments and subcommands. A zero-option
|
|
87
|
+
wrapper shell would reject every parameter an alias was given (#194).
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
name: Command name
|
|
91
|
+
click_func: Click command function
|
|
92
|
+
aliases: List of command aliases
|
|
93
|
+
"""
|
|
94
|
+
wl.add_command(click_func, name=name)
|
|
95
|
+
for alias in aliases or ():
|
|
96
|
+
wl.add_command(click_func, name=alias)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def setup_commands():
|
|
100
|
+
"""Register every command on the ``wl`` group from COMMAND_TABLE.
|
|
101
|
+
|
|
102
|
+
Each module in the table is imported exactly once; the symbol named by the
|
|
103
|
+
spec is fetched and, when the spec asks for it, instantiated. The command is
|
|
104
|
+
then registered under its canonical name plus any live aliases.
|
|
105
|
+
"""
|
|
106
|
+
try:
|
|
107
|
+
if not hasattr(wl, "_commands_setup") or not wl._commands_setup:
|
|
108
|
+
for name, spec in COMMAND_TABLE.items():
|
|
109
|
+
module = importlib.import_module(f"{spec.package}.{spec.module_path}")
|
|
110
|
+
click_func = getattr(module, spec.symbol)
|
|
111
|
+
if spec.instantiate:
|
|
112
|
+
click_func = click_func()
|
|
113
|
+
_register_click_command(name, click_func, aliases=list(spec.aliases))
|
|
114
|
+
|
|
115
|
+
wl._commands_setup = True
|
|
116
|
+
except Exception as e:
|
|
117
|
+
log_error(f"Error setting up commands: {e}")
|
|
118
|
+
raise
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main(argv: list[str] | None = None) -> int:
|
|
122
|
+
"""Main entry point for the CLI.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
argv: Command line arguments
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
int: Exit code, 0 for success, 1 for failure
|
|
129
|
+
"""
|
|
130
|
+
global _INVOCATION_ARGV
|
|
131
|
+
|
|
132
|
+
if argv is None:
|
|
133
|
+
argv = sys.argv[1:]
|
|
134
|
+
|
|
135
|
+
if argv and (argv[0] == "--version" or argv[0] == "-v"):
|
|
136
|
+
click.echo(f"wl {__version__}")
|
|
137
|
+
raise SystemExit(0)
|
|
138
|
+
|
|
139
|
+
_INVOCATION_ARGV = list(argv)
|
|
140
|
+
try:
|
|
141
|
+
setup_commands()
|
|
142
|
+
wl.main(args=argv, standalone_mode=True)
|
|
143
|
+
return 0
|
|
144
|
+
except click.ClickException as e:
|
|
145
|
+
log_error(str(e))
|
|
146
|
+
return 1
|
|
147
|
+
except Exception as e:
|
|
148
|
+
log_error(str(e))
|
|
149
|
+
return 1
|
|
150
|
+
finally:
|
|
151
|
+
# Never leak one invocation's argv into a later in-process invocation.
|
|
152
|
+
_INVOCATION_ARGV = []
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
if __name__ == "__main__":
|
|
156
|
+
sys.exit(main())
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Command registration and management module."""
|
|
2
|
+
|
|
3
|
+
import functools
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ..exceptions import ErrorCode
|
|
8
|
+
from .base import CommandBase
|
|
9
|
+
from .registry import get_command, list_commands
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Command(CommandBase):
|
|
13
|
+
"""
|
|
14
|
+
Base class for all commands.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, **dependencies: Any) -> None:
|
|
18
|
+
super().__init__(**dependencies)
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def name(self) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Get the command name.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
str: The command name
|
|
27
|
+
"""
|
|
28
|
+
raise NotImplementedError("Command subclasses must implement name property")
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def help(self) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Get the command help text.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
str: The command help text
|
|
37
|
+
"""
|
|
38
|
+
raise NotImplementedError("Command subclasses must implement help property")
|
|
39
|
+
|
|
40
|
+
def execute(self, *_: Any, **kwargs: Any) -> Any:
|
|
41
|
+
"""
|
|
42
|
+
Execute the command.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
*args: Positional arguments
|
|
46
|
+
**kwargs: Keyword arguments
|
|
47
|
+
"""
|
|
48
|
+
raise NotImplementedError("Command subclasses must implement execute method")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def validate_command_args(**validators: Callable[[Any], bool]) -> Callable:
|
|
52
|
+
"""
|
|
53
|
+
Decorator to validate command arguments.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
**validators: A dictionary of argument names and validation functions
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Callable: The decorator function
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def decorator(func: Callable) -> Callable:
|
|
63
|
+
@functools.wraps(func)
|
|
64
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
65
|
+
for arg_name, validator in validators.items():
|
|
66
|
+
if arg_name in kwargs:
|
|
67
|
+
if not validator(kwargs[arg_name]):
|
|
68
|
+
raise ValueError(f"Invalid value for {arg_name}")
|
|
69
|
+
|
|
70
|
+
return func(*args, **kwargs)
|
|
71
|
+
|
|
72
|
+
return wrapper
|
|
73
|
+
|
|
74
|
+
return decorator
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
"Command",
|
|
79
|
+
"CommandBase",
|
|
80
|
+
"ErrorCode",
|
|
81
|
+
"get_command",
|
|
82
|
+
"list_commands",
|
|
83
|
+
"validate_command_args",
|
|
84
|
+
]
|
wl_cli/commands/base.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Unified command base class for WL Commands."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CommandBase(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Abstract base class for all commands, providing lifecycle and logging utilities.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, **dependencies: Any) -> None:
|
|
13
|
+
"""Initialize the command with dependencies.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
**dependencies: Dependencies for the command
|
|
17
|
+
"""
|
|
18
|
+
self._dependencies = dependencies
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def name(self) -> str:
|
|
23
|
+
"""Get the command name."""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def help(self) -> str:
|
|
29
|
+
"""Get the command help text."""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def execute(self, *_: Any, **kwargs: Any) -> Any:
|
|
34
|
+
"""Execute the command."""
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
def before_execute(self, *args: Any, **kwargs: Any) -> None:
|
|
38
|
+
"""Lifecycle hook called before execution."""
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
def after_execute(self, result: Any = None) -> None:
|
|
42
|
+
"""Lifecycle hook called after execution."""
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def run(self, *args: Any, **kwargs: Any) -> Any:
|
|
46
|
+
"""Run with lifecycle and error handling around execute."""
|
|
47
|
+
try:
|
|
48
|
+
# Validate arguments and use the validated kwargs
|
|
49
|
+
validated_kwargs = self.validate_args(**kwargs)
|
|
50
|
+
self.before_execute(*args, **validated_kwargs)
|
|
51
|
+
result = self.execute(*args, **validated_kwargs)
|
|
52
|
+
self.after_execute(result)
|
|
53
|
+
return result
|
|
54
|
+
except Exception as error:
|
|
55
|
+
self.handle_error(error)
|
|
56
|
+
raise
|
|
57
|
+
|
|
58
|
+
def validate_args(self, **kwargs: Any) -> dict[str, Any]:
|
|
59
|
+
"""Validate command arguments."""
|
|
60
|
+
return kwargs
|
|
61
|
+
|
|
62
|
+
def handle_error(self, error: Exception) -> None:
|
|
63
|
+
"""Default error handler; override for custom behavior."""
|
|
64
|
+
raise error
|
|
65
|
+
|
|
66
|
+
def log_info(self, en_msg: str, zh_msg: str | None = None) -> None:
|
|
67
|
+
"""Log messages in English and optionally Chinese."""
|
|
68
|
+
try:
|
|
69
|
+
from wl_cli.utils.logging import log_info
|
|
70
|
+
|
|
71
|
+
log_info(en_msg, lang="en")
|
|
72
|
+
if zh_msg is not None:
|
|
73
|
+
log_info(zh_msg, lang="zh")
|
|
74
|
+
except Exception:
|
|
75
|
+
# Logging utility may not be available in certain contexts; ignore
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# Backward compatibility alias
|
|
80
|
+
BaseCommand = CommandBase
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Build commands package (registered lazily via COMMAND_TABLE)."""
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Build command for WL Commands."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from .. import Command
|
|
8
|
+
from .build_utils import build_project, build_project_full
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BuildCommand(Command):
|
|
12
|
+
"""Command to build the project"""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def name(self) -> str:
|
|
16
|
+
"""Return command name"""
|
|
17
|
+
return "build"
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def help(self) -> str:
|
|
21
|
+
"""Get command help text"""
|
|
22
|
+
return "Build the project"
|
|
23
|
+
|
|
24
|
+
def execute(self, *_: Any, **kwargs: Any) -> None:
|
|
25
|
+
"""Execute the build command."""
|
|
26
|
+
unknown_args = kwargs.get("unknown_args", [])
|
|
27
|
+
if unknown_args and unknown_args[0] == "dist":
|
|
28
|
+
build_project_full()
|
|
29
|
+
else:
|
|
30
|
+
build_project()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BuildCommandImpl:
|
|
34
|
+
"""Implementation of the build command."""
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def name(self) -> str:
|
|
38
|
+
return "build"
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def help(self) -> str:
|
|
42
|
+
return "Build the project"
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def aliases(self) -> list[str]:
|
|
46
|
+
return []
|
|
47
|
+
|
|
48
|
+
def execute(self, dist: bool = False) -> None:
|
|
49
|
+
"""Execute the build command.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
dist: If True, perform full compilation (build_project_full).
|
|
53
|
+
If False, perform regular build (build_project).
|
|
54
|
+
"""
|
|
55
|
+
if dist:
|
|
56
|
+
build_project_full()
|
|
57
|
+
else:
|
|
58
|
+
build_project()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@click.command()
|
|
62
|
+
@click.option(
|
|
63
|
+
"-d",
|
|
64
|
+
"--dist",
|
|
65
|
+
is_flag=True,
|
|
66
|
+
help="Perform full compilation including all outputs",
|
|
67
|
+
)
|
|
68
|
+
def build_command(dist: bool) -> None:
|
|
69
|
+
"""Build command Click wrapper."""
|
|
70
|
+
cmd = BuildCommandImpl()
|
|
71
|
+
cmd.execute(dist=dist)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Build utilities for WL Commands.
|
|
2
|
+
|
|
3
|
+
This module serves as the entry point for the modularized build functionality.
|
|
4
|
+
主要功能委托给专门的模块以获得更好的组织结构。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .builders.cleanup import CleanupManager
|
|
8
|
+
from .builders.coordinator import BuildCoordinator
|
|
9
|
+
from .builders.environment import EnvironmentDetector
|
|
10
|
+
from .builders.rust_builder import RustBuilder
|
|
11
|
+
from .builders.stubs import StubsManager
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Backward compatibility: re-export all the main functions
|
|
15
|
+
def is_rust_enabled() -> bool:
|
|
16
|
+
"""Check if Rust is enabled for this project."""
|
|
17
|
+
return EnvironmentDetector.is_rust_enabled()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_project_full() -> None:
|
|
21
|
+
"""Perform a full project build."""
|
|
22
|
+
coordinator = BuildCoordinator()
|
|
23
|
+
coordinator.build_project_full()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_project() -> None:
|
|
27
|
+
"""Build the project based on the current platform."""
|
|
28
|
+
try:
|
|
29
|
+
coordinator = BuildCoordinator()
|
|
30
|
+
coordinator.build_project()
|
|
31
|
+
except Exception as e:
|
|
32
|
+
from wl_cli.exceptions import CommandError
|
|
33
|
+
|
|
34
|
+
raise CommandError(f"Build failed: {e}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Re-export classes for advanced usage
|
|
38
|
+
__all__ = [
|
|
39
|
+
"is_rust_enabled",
|
|
40
|
+
"build_project_full",
|
|
41
|
+
"build_project",
|
|
42
|
+
"EnvironmentDetector",
|
|
43
|
+
"StubsManager",
|
|
44
|
+
"RustBuilder",
|
|
45
|
+
"CleanupManager",
|
|
46
|
+
"BuildCoordinator",
|
|
47
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Build command modules for specialized functionality.
|
|
2
|
+
|
|
3
|
+
This package contains modularized build utilities for better code organization.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .cleanup import CleanupManager
|
|
7
|
+
from .coordinator import BuildCoordinator
|
|
8
|
+
from .environment import EnvironmentDetector
|
|
9
|
+
from .rust_builder import RustBuilder
|
|
10
|
+
from .stubs import StubsManager
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"EnvironmentDetector",
|
|
14
|
+
"StubsManager",
|
|
15
|
+
"RustBuilder",
|
|
16
|
+
"CleanupManager",
|
|
17
|
+
"BuildCoordinator",
|
|
18
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Build cleanup utilities."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from ....utils.logging import log_error, log_info
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CleanupManager:
|
|
10
|
+
"""Handle post-build cleanup operations."""
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def cleanup_after_build(is_workspace: bool) -> None:
|
|
14
|
+
"""Clean up temporary files and directories after build."""
|
|
15
|
+
try:
|
|
16
|
+
root = Path.cwd()
|
|
17
|
+
typings_path = root / "typings"
|
|
18
|
+
if typings_path.exists():
|
|
19
|
+
shutil.rmtree(typings_path, ignore_errors=True)
|
|
20
|
+
log_info("✓ typings directory removed")
|
|
21
|
+
|
|
22
|
+
src_path = root / "src"
|
|
23
|
+
if src_path.exists():
|
|
24
|
+
removed = 0
|
|
25
|
+
for p in src_path.rglob("*.pyi"):
|
|
26
|
+
try:
|
|
27
|
+
p.unlink()
|
|
28
|
+
removed += 1
|
|
29
|
+
except Exception:
|
|
30
|
+
pass
|
|
31
|
+
if removed:
|
|
32
|
+
log_info(f"✓ Removed {removed} .pyi files from src")
|
|
33
|
+
|
|
34
|
+
except Exception as e:
|
|
35
|
+
log_error(f"Failed to cleanup stubs: {e}")
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Build coordination logic for different platforms and scenarios."""
|
|
2
|
+
|
|
3
|
+
from ....exceptions import CommandError
|
|
4
|
+
from ....utils.logging import (
|
|
5
|
+
log_error_pair,
|
|
6
|
+
log_info,
|
|
7
|
+
log_info_pair,
|
|
8
|
+
)
|
|
9
|
+
from ....utils.subprocess import run_command
|
|
10
|
+
from .cleanup import CleanupManager
|
|
11
|
+
from .environment import EnvironmentDetector
|
|
12
|
+
from .rust_builder import RustBuilder
|
|
13
|
+
from .stubs import StubsManager
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BuildCoordinator:
|
|
17
|
+
"""Coordinate build operations across different platforms and scenarios."""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.environment_detector = EnvironmentDetector()
|
|
21
|
+
self.stubs_manager = StubsManager()
|
|
22
|
+
self.rust_builder = RustBuilder()
|
|
23
|
+
self.cleanup_manager = CleanupManager()
|
|
24
|
+
|
|
25
|
+
def build_project_full(self) -> None:
|
|
26
|
+
"""Perform a full project build."""
|
|
27
|
+
rust_enabled = self.environment_detector.is_rust_enabled()
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
if rust_enabled:
|
|
31
|
+
log_info_pair(
|
|
32
|
+
"Using maturin build for full compilation...",
|
|
33
|
+
"使用 maturin build 进行完整编译...",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
python_executable, is_workspace = (
|
|
37
|
+
self.environment_detector.resolve_python_executable()
|
|
38
|
+
)
|
|
39
|
+
self.stubs_manager.generate_and_copy_stubs()
|
|
40
|
+
self.rust_builder.build_full(python_executable)
|
|
41
|
+
self.cleanup_manager.cleanup_after_build(is_workspace)
|
|
42
|
+
else:
|
|
43
|
+
log_info_pair(
|
|
44
|
+
"Pure Python project, using uv build to generate distribution packages...",
|
|
45
|
+
"纯 Python 项目,使用 uv build 生成分发包...",
|
|
46
|
+
)
|
|
47
|
+
run_command(
|
|
48
|
+
["uv", "build"],
|
|
49
|
+
capture_output=False,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
log_info_pair(
|
|
53
|
+
"✓ Full build completed successfully",
|
|
54
|
+
"✓ 完整构建成功完成",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# List files in dist directory for verification
|
|
58
|
+
from pathlib import Path
|
|
59
|
+
|
|
60
|
+
dist_dir = Path("dist")
|
|
61
|
+
if dist_dir.exists():
|
|
62
|
+
dist_files = list(dist_dir.iterdir())
|
|
63
|
+
if dist_files:
|
|
64
|
+
log_info_pair(
|
|
65
|
+
"Generated distribution packages in dist directory:",
|
|
66
|
+
"在 dist 目录中生成的分发包:",
|
|
67
|
+
)
|
|
68
|
+
for f in dist_files:
|
|
69
|
+
log_info(f" - {f.name}")
|
|
70
|
+
else:
|
|
71
|
+
log_info_pair(
|
|
72
|
+
"No distribution packages generated in dist directory",
|
|
73
|
+
"在 dist 目录中没有生成分发包",
|
|
74
|
+
)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
log_error_pair(
|
|
77
|
+
f"Full build failed: {e}",
|
|
78
|
+
f"完整构建失败: {e}",
|
|
79
|
+
)
|
|
80
|
+
raise CommandError(f"Full build failed: {e}")
|
|
81
|
+
|
|
82
|
+
def build(self) -> None:
|
|
83
|
+
"""Build the project in place, on any platform.
|
|
84
|
+
|
|
85
|
+
The former ``build_windows`` and ``build_unix`` bodies were
|
|
86
|
+
byte-identical, so the platform branch collapsed away.
|
|
87
|
+
"""
|
|
88
|
+
rust_enabled = self.environment_detector.is_rust_enabled()
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
if rust_enabled:
|
|
92
|
+
self.rust_builder.build_incremental()
|
|
93
|
+
else:
|
|
94
|
+
log_info_pair(
|
|
95
|
+
"Pure Python project, using uv pip install -e . for installation...",
|
|
96
|
+
"纯 Python 项目,使用 uv pip install -e . 进行安装...",
|
|
97
|
+
)
|
|
98
|
+
run_command(
|
|
99
|
+
["uv", "pip", "install", "--link-mode=copy", "-e", "."],
|
|
100
|
+
capture_output=False,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
log_info_pair(
|
|
104
|
+
"✓ Build completed successfully",
|
|
105
|
+
"✓ 构建成功完成",
|
|
106
|
+
)
|
|
107
|
+
except CommandError as e:
|
|
108
|
+
log_error_pair(
|
|
109
|
+
f"Build failed: {e}",
|
|
110
|
+
f"构建失败: {e}",
|
|
111
|
+
)
|
|
112
|
+
raise
|
|
113
|
+
except Exception as e:
|
|
114
|
+
log_error_pair(
|
|
115
|
+
f"Unexpected error during build: {e}",
|
|
116
|
+
f"构建过程中出现意外错误: {e}",
|
|
117
|
+
)
|
|
118
|
+
raise CommandError(f"Build failed: {e}")
|
|
119
|
+
|
|
120
|
+
def build_project(self) -> None:
|
|
121
|
+
"""Build the project."""
|
|
122
|
+
self.build()
|