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,342 @@
|
|
|
1
|
+
# Python 引入 Rust 扩展 SOP
|
|
2
|
+
|
|
3
|
+
本文档详细说明如何从 Python 代码中引入和使用 Rust 扩展,包括导入方式、使用示例、类型转换和错误处理。
|
|
4
|
+
|
|
5
|
+
## 1. 概述
|
|
6
|
+
|
|
7
|
+
wl_cli 项目使用 PyO3 库将 Rust 代码集成到 Python 中,提供高性能的底层功能。Rust 扩展以动态链接库的形式提供,可直接从 Python 代码中导入使用。
|
|
8
|
+
|
|
9
|
+
## 2. 导入方式
|
|
10
|
+
|
|
11
|
+
### 2.1 直接导入
|
|
12
|
+
|
|
13
|
+
如果 Rust 扩展已经安装在 Python 路径中,可以直接导入:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from wl_cli_native import sum_as_string
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### 2.2 从包中导入
|
|
20
|
+
|
|
21
|
+
在 wl_cli 项目中,Rust 扩展通常通过包结构导入:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from wl_cli.lib.wl_cli_native import sum_as_string
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2.3 延迟导入
|
|
28
|
+
|
|
29
|
+
对于可选依赖或大型扩展,可以使用延迟导入:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
def get_rust_function():
|
|
33
|
+
from wl_cli_native import sum_as_string
|
|
34
|
+
|
|
35
|
+
return sum_as_string
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 3. 使用示例
|
|
39
|
+
|
|
40
|
+
### 3.1 基本函数调用
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from wl_cli_native import sum_as_string
|
|
44
|
+
|
|
45
|
+
# 调用 Rust 函数
|
|
46
|
+
result = sum_as_string(1, 2)
|
|
47
|
+
print(result) # 输出: "3"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3.2 传递复杂数据类型
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from wl_cli_native import process_list
|
|
54
|
+
|
|
55
|
+
# 传递列表给 Rust 函数
|
|
56
|
+
data = [1, 2, 3, 4, 5]
|
|
57
|
+
result = process_list(data)
|
|
58
|
+
print(result) # 输出处理后的结果
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3.3 使用 Rust 类
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from wl_cli_native import RustCalculator
|
|
65
|
+
|
|
66
|
+
# 创建 Rust 类实例
|
|
67
|
+
calc = RustCalculator()
|
|
68
|
+
|
|
69
|
+
# 调用类方法
|
|
70
|
+
result = calc.add(10, 20)
|
|
71
|
+
print(result) # 输出: 30
|
|
72
|
+
|
|
73
|
+
# 访问属性
|
|
74
|
+
calc.multiplier = 2
|
|
75
|
+
result = calc.multiply(5)
|
|
76
|
+
print(result) # 输出: 10
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 4. 类型转换
|
|
80
|
+
|
|
81
|
+
### 4.1 基本类型转换
|
|
82
|
+
|
|
83
|
+
| Python 类型 | Rust 类型 |
|
|
84
|
+
|-------------------|-------------------------|
|
|
85
|
+
| `bool` | `bool` |
|
|
86
|
+
| `int` | `i64` 或 `u64`(根据大小)|
|
|
87
|
+
| `float` | `f64` |
|
|
88
|
+
| `str` | `String` 或 `&str` |
|
|
89
|
+
| `list` | `Vec<T>` |
|
|
90
|
+
| `dict` | `HashMap<K, V>` |
|
|
91
|
+
| `None` | `Option::None` |
|
|
92
|
+
| `Exception` | `Result::Err` |
|
|
93
|
+
|
|
94
|
+
### 4.2 自定义类型转换
|
|
95
|
+
|
|
96
|
+
对于自定义类型,可以使用 PyO3 的 `FromPyObject` 和 `ToPyObject` traits 实现转换:
|
|
97
|
+
|
|
98
|
+
```rust
|
|
99
|
+
use pyo3::prelude::*;
|
|
100
|
+
use pyo3::types::PyDict;
|
|
101
|
+
|
|
102
|
+
#[derive(Debug)]
|
|
103
|
+
struct Person {
|
|
104
|
+
name: String,
|
|
105
|
+
age: u32,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#[pyclass]
|
|
109
|
+
struct PyPerson {
|
|
110
|
+
inner: Person,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
#[pymethods]
|
|
114
|
+
impl PyPerson {
|
|
115
|
+
#[new]
|
|
116
|
+
fn new(name: &str, age: u32) -> Self {
|
|
117
|
+
PyPerson {
|
|
118
|
+
inner: Person { name: name.into(), age },
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
#[getter]
|
|
123
|
+
fn name(&self) -> &str {
|
|
124
|
+
&self.inner.name
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
#[getter]
|
|
128
|
+
fn age(&self) -> u32 {
|
|
129
|
+
self.inner.age
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 5. 错误处理
|
|
135
|
+
|
|
136
|
+
### 5.1 捕获 Rust 异常
|
|
137
|
+
|
|
138
|
+
Rust 函数返回的错误会被转换为 Python 异常,可以使用 try-except 块捕获:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from wl_cli_native import divide
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
result = divide(10, 0)
|
|
145
|
+
except ZeroDivisionError as e:
|
|
146
|
+
print(f"捕获到异常: {e}")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 5.2 常见异常类型
|
|
150
|
+
|
|
151
|
+
| Rust 错误类型 | Python 异常类型 |
|
|
152
|
+
|---------------------|------------------------|
|
|
153
|
+
| `PyZeroDivisionError` | `ZeroDivisionError` |
|
|
154
|
+
| `PyTypeError` | `TypeError` |
|
|
155
|
+
| `PyValueError` | `ValueError` |
|
|
156
|
+
| `PyIOError` | `IOError` |
|
|
157
|
+
| `PyRuntimeError` | `RuntimeError` |
|
|
158
|
+
|
|
159
|
+
## 6. 调试技巧
|
|
160
|
+
|
|
161
|
+
### 6.1 查看导入路径
|
|
162
|
+
|
|
163
|
+
如果遇到导入错误,可以检查 Python 路径:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
import sys
|
|
167
|
+
|
|
168
|
+
print(sys.path)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 6.2 检查扩展是否存在
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from wl_cli.lib import HAS_RUST_EXTENSION
|
|
175
|
+
|
|
176
|
+
# 检查 Rust 扩展是否可用(导入失败时该常量为 False)
|
|
177
|
+
print(f"扩展是否可用: {HAS_RUST_EXTENSION}")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 6.3 启用调试输出
|
|
181
|
+
|
|
182
|
+
在 Rust 代码中,可以使用 `eprintln!` 输出调试信息,这些信息会显示在 Python 运行的控制台中:
|
|
183
|
+
|
|
184
|
+
```rust
|
|
185
|
+
#[pyfunction]
|
|
186
|
+
fn debug_function() -> PyResult<()> {
|
|
187
|
+
eprintln!("Rust 调试信息: 函数被调用");
|
|
188
|
+
Ok(())
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 6.4 使用 Python 调试器
|
|
193
|
+
|
|
194
|
+
可以使用 Python 调试器(如 `pdb` 或 `ipdb`)调试调用 Rust 函数的 Python 代码:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
import pdb
|
|
198
|
+
from wl_cli_native import sum_as_string
|
|
199
|
+
|
|
200
|
+
pdb.set_trace()
|
|
201
|
+
result = sum_as_string(1, 2)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## 7. 性能优化
|
|
205
|
+
|
|
206
|
+
### 7.1 减少类型转换
|
|
207
|
+
|
|
208
|
+
尽量减少 Python 和 Rust 之间的类型转换,特别是对于大型数据结构:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
# 不推荐:多次转换
|
|
212
|
+
total = 0
|
|
213
|
+
for i in range(1000):
|
|
214
|
+
total += int(sum_as_string(i, 0))
|
|
215
|
+
|
|
216
|
+
# 推荐:一次性转换
|
|
217
|
+
results = process_batch(range(1000))
|
|
218
|
+
total = sum(results)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 7.2 使用批量处理
|
|
222
|
+
|
|
223
|
+
对于大量数据,使用批量处理函数减少函数调用开销:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
# 不推荐:多次调用
|
|
227
|
+
data = [1, 2, 3, 4, 5]
|
|
228
|
+
results = []
|
|
229
|
+
for item in data:
|
|
230
|
+
results.append(process_item(item))
|
|
231
|
+
|
|
232
|
+
# 推荐:批量调用
|
|
233
|
+
results = process_batch(data)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 7.3 避免频繁内存分配
|
|
237
|
+
|
|
238
|
+
在 Rust 代码中,尽量重用内存,减少 Python 和 Rust 之间的内存分配:
|
|
239
|
+
|
|
240
|
+
```rust
|
|
241
|
+
#[pyfunction]
|
|
242
|
+
fn process_large_data(data: Vec<u8>) -> PyResult<Vec<u8>> {
|
|
243
|
+
// 在 Rust 中直接处理数据,避免额外内存分配
|
|
244
|
+
let mut result = Vec::with_capacity(data.len());
|
|
245
|
+
// 处理数据...
|
|
246
|
+
Ok(result)
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## 8. 最佳实践
|
|
251
|
+
|
|
252
|
+
1. **明确的类型注解**: 为 Rust 函数添加明确的类型注解,便于 Python 开发者理解
|
|
253
|
+
2. **详细的文档字符串**: 为每个暴露的函数和类型编写详细的文档字符串
|
|
254
|
+
3. **合理的错误信息**: 提供清晰、有用的错误信息,便于调试
|
|
255
|
+
4. **充分的测试**: 编写 Python 集成测试,确保 Rust 扩展正常工作
|
|
256
|
+
5. **版本兼容性**: 确保 Rust 扩展与 Python 版本兼容
|
|
257
|
+
6. **性能测试**: 对关键路径进行性能测试,确保达到预期性能
|
|
258
|
+
|
|
259
|
+
## 9. 示例:完整的使用流程
|
|
260
|
+
|
|
261
|
+
### 9.1 编写 Rust 函数
|
|
262
|
+
|
|
263
|
+
```rust
|
|
264
|
+
// rust/src/lib.rs
|
|
265
|
+
use pyo3::prelude::*;
|
|
266
|
+
|
|
267
|
+
#[pymodule]
|
|
268
|
+
fn wl_cli_native(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
269
|
+
m.add_function(wrap_pyfunction!(calculate_fibonacci, m)?)?;
|
|
270
|
+
Ok(())
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#[pyfunction]
|
|
274
|
+
fn calculate_fibonacci(n: usize) -> PyResult<Vec<u64>> {
|
|
275
|
+
if n == 0 {
|
|
276
|
+
return Ok(Vec::new());
|
|
277
|
+
}
|
|
278
|
+
if n == 1 {
|
|
279
|
+
return Ok(vec![0]);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let mut fib = Vec::with_capacity(n);
|
|
283
|
+
fib.push(0);
|
|
284
|
+
fib.push(1);
|
|
285
|
+
|
|
286
|
+
for i in 2..n {
|
|
287
|
+
let next = fib[i-1] + fib[i-2];
|
|
288
|
+
fib.push(next);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
Ok(fib)
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 9.2 构建 Rust 扩展
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
cd rust
|
|
299
|
+
cargo build --release
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 9.3 在 Python 中使用
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
from wl_cli_native import calculate_fibonacci
|
|
306
|
+
|
|
307
|
+
# 调用 Rust 函数计算斐波那契数列
|
|
308
|
+
fib_sequence = calculate_fibonacci(10)
|
|
309
|
+
print(fib_sequence) # 输出: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## 10. 故障排除
|
|
313
|
+
|
|
314
|
+
### 10.1 导入错误
|
|
315
|
+
|
|
316
|
+
如果遇到 `ImportError: No module named 'wl_cli_native'`:
|
|
317
|
+
|
|
318
|
+
1. 检查 Rust 扩展是否已正确构建
|
|
319
|
+
2. 检查扩展文件是否在 Python 路径中
|
|
320
|
+
3. 检查 Python 版本是否与扩展兼容
|
|
321
|
+
4. 检查操作系统架构是否匹配(32位/64位)
|
|
322
|
+
|
|
323
|
+
### 10.2 类型错误
|
|
324
|
+
|
|
325
|
+
如果遇到 `TypeError: Expected int for parameter 'n'`:
|
|
326
|
+
|
|
327
|
+
1. 检查传递给 Rust 函数的参数类型
|
|
328
|
+
2. 确保参数类型与 Rust 函数签名匹配
|
|
329
|
+
3. 考虑添加类型转换:`calculate_fibonacci(int(n))`
|
|
330
|
+
|
|
331
|
+
### 10.3 运行时错误
|
|
332
|
+
|
|
333
|
+
如果遇到 `RuntimeError: Rust function failed`:
|
|
334
|
+
|
|
335
|
+
1. 检查 Rust 函数中的错误处理
|
|
336
|
+
2. 添加调试输出查看具体错误
|
|
337
|
+
3. 检查输入数据是否符合预期
|
|
338
|
+
4. 考虑添加更详细的错误信息
|
|
339
|
+
|
|
340
|
+
## 11. 结论
|
|
341
|
+
|
|
342
|
+
通过遵循本 SOP,开发者可以轻松地从 Python 代码中引入和使用 Rust 扩展,充分利用 Rust 的高性能和 Python 的易用性。在实际开发中,应根据具体需求选择合适的导入方式和使用模式,并遵循最佳实践确保代码的可维护性和性能。
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Rust-Python 集成标准操作流程 (SOP)
|
|
2
|
+
|
|
3
|
+
本文档详细说明如何将 Rust 代码集成到 Python 项目中,包括文件结构、命名规则、开发流程和最佳实践。
|
|
4
|
+
|
|
5
|
+
## 1. 文件结构
|
|
6
|
+
|
|
7
|
+
Rust 集成部分遵循以下文件结构:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
rust/
|
|
11
|
+
├── src/
|
|
12
|
+
│ ├── lib.rs # 主 Rust 库文件,定义 Python 模块
|
|
13
|
+
│ └── main.rs # 可选的 Rust 可执行文件(用于测试或独立运行)
|
|
14
|
+
├── Cargo.toml # Rust 项目配置文件
|
|
15
|
+
└── rust-analyzer.json # Rust Analyzer 配置文件
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 1.1 目录职责
|
|
19
|
+
|
|
20
|
+
- **rust/src/lib.rs**: 定义 Python 模块,包含所有暴露给 Python 的函数和类型
|
|
21
|
+
- **rust/src/main.rs**: 可选,用于编写独立的 Rust 测试或工具
|
|
22
|
+
- **rust/Cargo.toml**: 配置 Rust 依赖、版本和构建选项
|
|
23
|
+
|
|
24
|
+
## 2. 命名规则
|
|
25
|
+
|
|
26
|
+
### 2.1 Rust 侧命名规则
|
|
27
|
+
|
|
28
|
+
- **模块名**: 使用蛇形命名法,与 Python 模块名保持一致
|
|
29
|
+
- **函数名**: 使用蛇形命名法,与 Python 函数命名习惯一致
|
|
30
|
+
- **类型名**: 使用驼峰命名法,遵循 Rust 传统
|
|
31
|
+
- **常量名**: 使用全大写加下划线,遵循 Rust 传统
|
|
32
|
+
|
|
33
|
+
### 2.2 Python 侧命名规则
|
|
34
|
+
|
|
35
|
+
- **导入名**: 使用与 Rust 模块名相同的名称
|
|
36
|
+
- **函数调用**: 使用与 Rust 函数名相同的名称
|
|
37
|
+
- **类名**: 使用与 Rust 类型名相同的名称
|
|
38
|
+
|
|
39
|
+
## 3. 开发流程
|
|
40
|
+
|
|
41
|
+
### 3.1 编写 Rust 代码
|
|
42
|
+
|
|
43
|
+
1. 在 `rust/src/lib.rs` 中定义 Python 模块
|
|
44
|
+
2. 使用 `#[pymodule]` 宏标记模块入口
|
|
45
|
+
3. 使用 `#[pyfunction]` 宏标记要暴露给 Python 的函数
|
|
46
|
+
4. 使用 `#[pyclass]` 宏标记要暴露给 Python 的类
|
|
47
|
+
|
|
48
|
+
### 3.2 配置 Cargo.toml
|
|
49
|
+
|
|
50
|
+
确保 Cargo.toml 包含以下配置:
|
|
51
|
+
|
|
52
|
+
```toml
|
|
53
|
+
[package]
|
|
54
|
+
name = "wl_cli_native"
|
|
55
|
+
version = "0.2.14"
|
|
56
|
+
edition = "2024"
|
|
57
|
+
|
|
58
|
+
[dependencies]
|
|
59
|
+
pyo3 = { version = "0.27.2", features = ["extension-module"] }
|
|
60
|
+
|
|
61
|
+
[lib]
|
|
62
|
+
name = "wl_cli_native"
|
|
63
|
+
crate-type = ["cdylib"]
|
|
64
|
+
path = "src/lib.rs"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 3.3 构建 Rust 扩展
|
|
68
|
+
|
|
69
|
+
使用以下命令构建 Rust 扩展:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd rust
|
|
73
|
+
cargo build --release
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
构建产物将生成在 `rust/target/release/` 目录中。
|
|
77
|
+
|
|
78
|
+
### 3.4 集成到 Python
|
|
79
|
+
|
|
80
|
+
将构建生成的 `.so`(Linux/macOS)或 `.pyd`(Windows)文件复制到 Python 项目的适当位置,或使用构建工具自动处理。
|
|
81
|
+
|
|
82
|
+
## 4. PyO3 使用指南
|
|
83
|
+
|
|
84
|
+
### 4.1 基本函数暴露
|
|
85
|
+
|
|
86
|
+
```rust
|
|
87
|
+
use pyo3::prelude::*;
|
|
88
|
+
|
|
89
|
+
/// A Python module implemented in Rust.
|
|
90
|
+
#[pymodule]
|
|
91
|
+
fn wl_cli_native(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
92
|
+
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
|
|
93
|
+
Ok(())
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#[pyfunction]
|
|
97
|
+
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
|
|
98
|
+
Ok((a + b).to_string())
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 4.2 类型转换
|
|
103
|
+
|
|
104
|
+
PyO3 自动处理大部分基本类型的转换:
|
|
105
|
+
|
|
106
|
+
| Rust 类型 | Python 类型 |
|
|
107
|
+
|-----------------|-------------------|
|
|
108
|
+
| `bool` | `bool` |
|
|
109
|
+
| `i8`, `i16`, `i32`, `i64`, `isize` | `int` |
|
|
110
|
+
| `u8`, `u16`, `u32`, `u64`, `usize` | `int` |
|
|
111
|
+
| `f32`, `f64` | `float` |
|
|
112
|
+
| `String`, `&str`| `str` |
|
|
113
|
+
| `Vec<T>` | `list` |
|
|
114
|
+
| `HashMap<K, V>` | `dict` |
|
|
115
|
+
| `Option<T>` | `T` 或 `None` |
|
|
116
|
+
| `Result<T, E>` | `T` 或 `Exception`|
|
|
117
|
+
|
|
118
|
+
### 4.3 错误处理
|
|
119
|
+
|
|
120
|
+
使用 `PyResult<T>` 类型处理错误,PyO3 会自动将 Rust 错误转换为 Python 异常:
|
|
121
|
+
|
|
122
|
+
```rust
|
|
123
|
+
#[pyfunction]
|
|
124
|
+
fn divide(a: f64, b: f64) -> PyResult<f64> {
|
|
125
|
+
if b == 0.0 {
|
|
126
|
+
return Err(PyZeroDivisionError::new_err("division by zero"));
|
|
127
|
+
}
|
|
128
|
+
Ok(a / b)
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 5. 测试策略
|
|
133
|
+
|
|
134
|
+
### 5.1 Rust 单元测试
|
|
135
|
+
|
|
136
|
+
在 Rust 代码中编写单元测试,使用 `#[test]` 宏标记:
|
|
137
|
+
|
|
138
|
+
```rust
|
|
139
|
+
#[test]
|
|
140
|
+
fn test_sum_as_string() {
|
|
141
|
+
assert_eq!(sum_as_string(1, 2).unwrap(), "3");
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
运行 Rust 单元测试:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
cd rust
|
|
149
|
+
cargo test
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 5.2 Python 集成测试
|
|
153
|
+
|
|
154
|
+
在 Python 测试文件中测试 Rust 扩展:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
def test_rust_sum():
|
|
158
|
+
from wl_cli_native import sum_as_string
|
|
159
|
+
|
|
160
|
+
assert sum_as_string(1, 2) == "3"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
运行 Python 集成测试:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pytest tests/test_rust_integration.py
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 6. 构建和部署
|
|
170
|
+
|
|
171
|
+
### 6.1 本地开发构建
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
cd rust
|
|
175
|
+
cargo build
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 6.2 发布构建
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
cd rust
|
|
182
|
+
cargo build --release
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 6.3 集成到 Python 包
|
|
186
|
+
|
|
187
|
+
在 Python 项目的构建脚本中,确保包含以下步骤:
|
|
188
|
+
|
|
189
|
+
1. 构建 Rust 扩展
|
|
190
|
+
2. 将构建产物复制到 Python 包目录
|
|
191
|
+
3. 更新 `__init__.py` 以导入 Rust 扩展
|
|
192
|
+
|
|
193
|
+
## 7. 最佳实践
|
|
194
|
+
|
|
195
|
+
1. **最小化暴露**: 只暴露必要的函数和类型给 Python
|
|
196
|
+
2. **清晰的文档**: 为所有暴露的函数和类型编写详细的文档字符串
|
|
197
|
+
3. **类型安全**: 充分利用 Rust 的类型系统确保安全性
|
|
198
|
+
4. **错误处理**: 提供清晰的错误信息,便于 Python 开发者调试
|
|
199
|
+
5. **性能考虑**: 避免不必要的类型转换和内存分配
|
|
200
|
+
6. **测试覆盖**: 确保 Rust 代码和 Python 集成都有充分的测试覆盖
|
|
201
|
+
|
|
202
|
+
## 8. 调试技巧
|
|
203
|
+
|
|
204
|
+
1. **使用 Rust 调试器**: 可以使用 `rust-gdb` 或 `rust-lldb` 调试 Rust 代码
|
|
205
|
+
2. **打印调试信息**: 使用 `println!` 或 `eprintln!` 在 Rust 代码中输出调试信息
|
|
206
|
+
3. **Python 调试器**: 可以使用 `pdb` 或 `ipdb` 调试 Python 代码,包括调用 Rust 函数的部分
|
|
207
|
+
4. **错误信息**: 确保 Rust 错误转换为有意义的 Python 异常
|
|
208
|
+
|
|
209
|
+
## 9. 版本管理
|
|
210
|
+
|
|
211
|
+
Rust 扩展的版本应与 Python 包的版本保持同步。在 `Cargo.toml` 中更新版本号时,确保同时更新 Python 包的版本号。
|
|
212
|
+
|
|
213
|
+
## 10. 依赖管理
|
|
214
|
+
|
|
215
|
+
Rust 依赖应在 `Cargo.toml` 中明确指定,并使用固定版本或版本范围,确保构建的可重复性。
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
遵循本 SOP 可以确保 Rust-Python 集成的一致性、可维护性和可靠性。
|