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.
Files changed (320) hide show
  1. py_wlcli-0.8.0.dist-info/METADATA +139 -0
  2. py_wlcli-0.8.0.dist-info/RECORD +320 -0
  3. py_wlcli-0.8.0.dist-info/WHEEL +4 -0
  4. py_wlcli-0.8.0.dist-info/entry_points.txt +2 -0
  5. py_wlcli-0.8.0.dist-info/licenses/LICENSE +21 -0
  6. wl_cli/__init__.py +27 -0
  7. wl_cli/__main__.py +130 -0
  8. wl_cli/capabilities.py +79 -0
  9. wl_cli/cc/__init__.py +5 -0
  10. wl_cli/cc/checks.py +1019 -0
  11. wl_cli/cc/cli.py +370 -0
  12. wl_cli/cc/mutate.py +1350 -0
  13. wl_cli/cli_click.py +156 -0
  14. wl_cli/commands/__init__.py +84 -0
  15. wl_cli/commands/base.py +80 -0
  16. wl_cli/commands/buildcommands/__init__.py +1 -0
  17. wl_cli/commands/buildcommands/build.py +71 -0
  18. wl_cli/commands/buildcommands/build_utils.py +47 -0
  19. wl_cli/commands/buildcommands/builders/__init__.py +18 -0
  20. wl_cli/commands/buildcommands/builders/cleanup.py +35 -0
  21. wl_cli/commands/buildcommands/builders/coordinator.py +122 -0
  22. wl_cli/commands/buildcommands/builders/environment.py +81 -0
  23. wl_cli/commands/buildcommands/builders/rust_builder.py +39 -0
  24. wl_cli/commands/buildcommands/builders/stubs.py +58 -0
  25. wl_cli/commands/buildcommands/dist.py +326 -0
  26. wl_cli/commands/buildcommands/test.py +89 -0
  27. wl_cli/commands/clean/__init__.py +1 -0
  28. wl_cli/commands/clean/build.py +151 -0
  29. wl_cli/commands/clean/clean.py +294 -0
  30. wl_cli/commands/clean/clean_utils.py +77 -0
  31. wl_cli/commands/clean/core.py +236 -0
  32. wl_cli/commands/clean/dead_code/__init__.py +0 -0
  33. wl_cli/commands/clean/dead_code/dead_code_command.py +70 -0
  34. wl_cli/commands/clean/dead_code/detector.py +161 -0
  35. wl_cli/commands/clean/dead_code/fixer.py +176 -0
  36. wl_cli/commands/clean/dead_code/reporter.py +295 -0
  37. wl_cli/commands/clean/dead_code/utils.py +0 -0
  38. wl_cli/commands/clean/lfs.py +215 -0
  39. wl_cli/commands/clean/python.py +81 -0
  40. wl_cli/commands/clean/rust.py +91 -0
  41. wl_cli/commands/clean/utils/__init__.py +34 -0
  42. wl_cli/commands/clean/venv.py +91 -0
  43. wl_cli/commands/cleanup.py +73 -0
  44. wl_cli/commands/click_base.py +79 -0
  45. wl_cli/commands/config/__init__.py +1 -0
  46. wl_cli/commands/config/config.py +291 -0
  47. wl_cli/commands/debug/__init__.py +6 -0
  48. wl_cli/commands/debug/debug.py +309 -0
  49. wl_cli/commands/debug/debug_cache.py +86 -0
  50. wl_cli/commands/debug/debug_subagent.py +156 -0
  51. wl_cli/commands/debug/output_formatter.py +165 -0
  52. wl_cli/commands/debug/source_hasher.py +92 -0
  53. wl_cli/commands/format/__init__.py +13 -0
  54. wl_cli/commands/format/format_cache_adapter.py +125 -0
  55. wl_cli/commands/format/format_command.py +197 -0
  56. wl_cli/commands/format/format_coordinator.py +191 -0
  57. wl_cli/commands/format/format_executor.py +470 -0
  58. wl_cli/commands/format/format_outcome.py +44 -0
  59. wl_cli/commands/format/format_path_handler.py +1016 -0
  60. wl_cli/commands/format/format_progress.py +62 -0
  61. wl_cli/commands/format/format_reporter.py +31 -0
  62. wl_cli/commands/format/python_formatter.py +506 -0
  63. wl_cli/commands/format/rust_formatter.py +106 -0
  64. wl_cli/commands/gate/__init__.py +1 -0
  65. wl_cli/commands/gate/gate_command.py +862 -0
  66. wl_cli/commands/gate/preflight.py +445 -0
  67. wl_cli/commands/git/__init__.py +1 -0
  68. wl_cli/commands/git/config.py +169 -0
  69. wl_cli/commands/git/git_facts.py +60 -0
  70. wl_cli/commands/git/git_flow.py +86 -0
  71. wl_cli/commands/git/hook.py +112 -0
  72. wl_cli/commands/git/policy.py +216 -0
  73. wl_cli/commands/git/push_update.py +82 -0
  74. wl_cli/commands/initenv/__init__.py +1 -0
  75. wl_cli/commands/initenv/common/__init__.py +23 -0
  76. wl_cli/commands/initenv/common/check_git_bash.py +78 -0
  77. wl_cli/commands/initenv/common/error_handler.py +68 -0
  78. wl_cli/commands/initenv/common/exceptions.py +52 -0
  79. wl_cli/commands/initenv/components/__init__.py +4 -0
  80. wl_cli/commands/initenv/components/cargo_sync.py +240 -0
  81. wl_cli/commands/initenv/components/config_manager.py +106 -0
  82. wl_cli/commands/initenv/components/directory_utils.py +71 -0
  83. wl_cli/commands/initenv/components/git/__init__.py +9 -0
  84. wl_cli/commands/initenv/components/git/branch_creator.py +143 -0
  85. wl_cli/commands/initenv/components/git/git_flow_interface.py +24 -0
  86. wl_cli/commands/initenv/components/git/git_flow_manager.py +159 -0
  87. wl_cli/commands/initenv/components/git/git_lfs_manager.py +272 -0
  88. wl_cli/commands/initenv/components/git/git_utility.py +254 -0
  89. wl_cli/commands/initenv/components/git/gitignore_manager.py +53 -0
  90. wl_cli/commands/initenv/components/git_initializer.py +212 -0
  91. wl_cli/commands/initenv/components/i18n_manager.py +104 -0
  92. wl_cli/commands/initenv/components/log_manager.py +241 -0
  93. wl_cli/commands/initenv/components/project_structure/__init__.py +23 -0
  94. wl_cli/commands/initenv/components/project_structure/config_generator.py +360 -0
  95. wl_cli/commands/initenv/components/project_structure/directory_creator.py +184 -0
  96. wl_cli/commands/initenv/components/project_structure/hook_source.py +110 -0
  97. wl_cli/commands/initenv/components/project_structure/hooks_manager.py +995 -0
  98. wl_cli/commands/initenv/components/project_structure/readme_handler.py +56 -0
  99. wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +30 -0
  100. wl_cli/commands/initenv/components/project_structure/setup_handler.py +103 -0
  101. wl_cli/commands/initenv/components/project_structure/sop_generator.py +73 -0
  102. wl_cli/commands/initenv/components/project_structure/template_copier.py +104 -0
  103. wl_cli/commands/initenv/components/project_structure/template_manager.py +195 -0
  104. wl_cli/commands/initenv/components/pyproject_generator.py +194 -0
  105. wl_cli/commands/initenv/components/rust_initializer.py +145 -0
  106. wl_cli/commands/initenv/components/symlink_cleaner.py +99 -0
  107. wl_cli/commands/initenv/components/symlink_manager.py +52 -0
  108. wl_cli/commands/initenv/components/venv_manager.py +118 -0
  109. wl_cli/commands/initenv/initenv.py +169 -0
  110. wl_cli/commands/initenv/services/__init__.py +11 -0
  111. wl_cli/commands/initenv/services/environment_initializer.py +288 -0
  112. wl_cli/commands/initenv/services/git_lfs_initializer.py +26 -0
  113. wl_cli/commands/initenv/services/project_structure_initializer.py +52 -0
  114. wl_cli/commands/lfs/README.md +221 -0
  115. wl_cli/commands/lfs/__init__.py +5 -0
  116. wl_cli/commands/lfs/cli.py +106 -0
  117. wl_cli/commands/lfs/config.py +164 -0
  118. wl_cli/commands/lfs/hook.py +61 -0
  119. wl_cli/commands/lfs/initializer.py +531 -0
  120. wl_cli/commands/lfs/manager.py +95 -0
  121. wl_cli/commands/lfs/policy.py +165 -0
  122. wl_cli/commands/lfs/watcher.py +294 -0
  123. wl_cli/commands/lint/__init__.py +1 -0
  124. wl_cli/commands/lint/lint_command.py +297 -0
  125. wl_cli/commands/lint/lint_executor.py +409 -0
  126. wl_cli/commands/lint/lint_reporter.py +579 -0
  127. wl_cli/commands/lint/lint_run.py +258 -0
  128. wl_cli/commands/lint/mypy_config.py +90 -0
  129. wl_cli/commands/registry.py +103 -0
  130. wl_cli/commands/self/__init__.py +7 -0
  131. wl_cli/commands/self/common/__init__.py +8 -0
  132. wl_cli/commands/self/common/capabilities.py +30 -0
  133. wl_cli/commands/self/common/config.py +27 -0
  134. wl_cli/commands/self/common/version_cache.py +85 -0
  135. wl_cli/commands/self/handlers/__init__.py +19 -0
  136. wl_cli/commands/self/handlers/base_handler.py +28 -0
  137. wl_cli/commands/self/handlers/install_handler.py +85 -0
  138. wl_cli/commands/self/handlers/status_handler.py +66 -0
  139. wl_cli/commands/self/handlers/uninstall_handler.py +58 -0
  140. wl_cli/commands/self/handlers/update_handler.py +102 -0
  141. wl_cli/commands/self/handlers/version_handler.py +16 -0
  142. wl_cli/commands/self/self_command.py +237 -0
  143. wl_cli/commands/self/services/__init__.py +15 -0
  144. wl_cli/commands/self/services/installation_manager.py +187 -0
  145. wl_cli/commands/self/services/local_installer.py +165 -0
  146. wl_cli/commands/self/services/pypi_updater.py +278 -0
  147. wl_cli/commands/self/services/windows_update.py +174 -0
  148. wl_cli/commands/testcommands/__init__.py +8 -0
  149. wl_cli/commands/testcommands/base_dependency_analyzer.py +198 -0
  150. wl_cli/commands/testcommands/batch_processor.py +278 -0
  151. wl_cli/commands/testcommands/cache_manager.py +1156 -0
  152. wl_cli/commands/testcommands/coverage_analyzer.py +955 -0
  153. wl_cli/commands/testcommands/coverage_cache_manager.py +183 -0
  154. wl_cli/commands/testcommands/progress_manager.py +79 -0
  155. wl_cli/commands/testcommands/python_env_detector.py +207 -0
  156. wl_cli/commands/testcommands/report_generator.py +101 -0
  157. wl_cli/commands/testcommands/single_test_executor.py +250 -0
  158. wl_cli/commands/testcommands/speed_checker.py +118 -0
  159. wl_cli/commands/testcommands/test_command_builder.py +165 -0
  160. wl_cli/commands/testcommands/test_commands.py +786 -0
  161. wl_cli/commands/testcommands/test_reporter.py +181 -0
  162. wl_cli/commands/testcommands/test_result_handler.py +96 -0
  163. wl_cli/commands/testcommands/test_runner.py +1343 -0
  164. wl_cli/commands/testcommands/test_utils.py +197 -0
  165. wl_cli/commands/testcommands/utils/__init__.py +17 -0
  166. wl_cli/commands/testcommands/utils/coverage_parser.py +98 -0
  167. wl_cli/commands/testcommands/utils/env_info.py +36 -0
  168. wl_cli/commands/testcommands/utils/junit_parser.py +75 -0
  169. wl_cli/commands/testcommands/utils/markdown_utils.py +20 -0
  170. wl_cli/commands/testcommands/utils/project_root.py +61 -0
  171. wl_cli/commands/update/__init__.py +9 -0
  172. wl_cli/commands/update/services/__init__.py +21 -0
  173. wl_cli/commands/update/services/backup_manager.py +207 -0
  174. wl_cli/commands/update/services/component_manager.py +83 -0
  175. wl_cli/commands/update/services/conflict_resolver.py +189 -0
  176. wl_cli/commands/update/services/vendors_updater.py +85 -0
  177. wl_cli/commands/update/services/version_tracker.py +127 -0
  178. wl_cli/commands/update/update_command.py +270 -0
  179. wl_cli/commands/update/utils/__init__.py +3 -0
  180. wl_cli/commands/version/__init__.py +9 -0
  181. wl_cli/commands/version/version_command.py +155 -0
  182. wl_cli/commands/workflow.py +477 -0
  183. wl_cli/env/__init__.py +5 -0
  184. wl_cli/env/cli.py +167 -0
  185. wl_cli/env_status.py +157 -0
  186. wl_cli/envelope.py +91 -0
  187. wl_cli/exceptions.py +85 -0
  188. wl_cli/lib/__init__.py +3 -0
  189. wl_cli/lib/rust_utils.py +35 -0
  190. wl_cli/mcp/__init__.py +6 -0
  191. wl_cli/mcp/capabilities.py +19 -0
  192. wl_cli/mcp/cli.py +22 -0
  193. wl_cli/mcp/gitlab.py +553 -0
  194. wl_cli/mcp/k8s.py +344 -0
  195. wl_cli/mcp/protocol.py +159 -0
  196. wl_cli/platform.py +139 -0
  197. wl_cli/quality/__init__.py +18 -0
  198. wl_cli/utils/__init__.py +7 -0
  199. wl_cli/utils/cache.py +491 -0
  200. wl_cli/utils/cache_ledger.py +355 -0
  201. wl_cli/utils/cache_store.py +546 -0
  202. wl_cli/utils/config/__init__.py +27 -0
  203. wl_cli/utils/config/config_loader.py +163 -0
  204. wl_cli/utils/config/core.py +862 -0
  205. wl_cli/utils/config/defaults.py +142 -0
  206. wl_cli/utils/config/env_exporter.py +86 -0
  207. wl_cli/utils/config/env_parser.py +108 -0
  208. wl_cli/utils/config/validation.py +280 -0
  209. wl_cli/utils/error_handler.py +165 -0
  210. wl_cli/utils/file_copier.py +56 -0
  211. wl_cli/utils/file_operations.py +506 -0
  212. wl_cli/utils/language_utils.py +122 -0
  213. wl_cli/utils/lazy_import.py +240 -0
  214. wl_cli/utils/log_levels.py +35 -0
  215. wl_cli/utils/log_rotators.py +74 -0
  216. wl_cli/utils/logging.py +458 -0
  217. wl_cli/utils/output_context.py +142 -0
  218. wl_cli/utils/performance/__init__.py +1 -0
  219. wl_cli/utils/performance/decorators.py +111 -0
  220. wl_cli/utils/performance/exporter.py +38 -0
  221. wl_cli/utils/performance/models.py +16 -0
  222. wl_cli/utils/performance/monitor.py +161 -0
  223. wl_cli/utils/performance_monitor.py +32 -0
  224. wl_cli/utils/platform_adapter.py +131 -0
  225. wl_cli/utils/pre_commit.py +266 -0
  226. wl_cli/utils/pre_commit_config.py +72 -0
  227. wl_cli/utils/root.py +521 -0
  228. wl_cli/utils/root_fallback.py +256 -0
  229. wl_cli/utils/run_evidence.py +236 -0
  230. wl_cli/utils/structured_logger.py +18 -0
  231. wl_cli/utils/structured_logging/__init__.py +19 -0
  232. wl_cli/utils/structured_logging/config.py +337 -0
  233. wl_cli/utils/structured_logging/core.py +177 -0
  234. wl_cli/utils/structured_logging/env.py +56 -0
  235. wl_cli/utils/structured_logging/filtering.py +75 -0
  236. wl_cli/utils/structured_logging/filters.py +55 -0
  237. wl_cli/utils/structured_logging/formatters.py +251 -0
  238. wl_cli/utils/structured_logging/handlers.py +308 -0
  239. wl_cli/utils/structured_logging/logger.py +354 -0
  240. wl_cli/utils/subprocess.py +71 -0
  241. wl_cli/utils/subprocess_utils.py +260 -0
  242. wl_cli/utils/test_utils/__init__.py +5 -0
  243. wl_cli/utils/test_utils/test_filter.py +36 -0
  244. wl_cli/utils/uv_run.py +79 -0
  245. wl_cli/utils/uv_tool.py +117 -0
  246. wl_cli/utils/uv_tree.py +71 -0
  247. wl_cli/utils/uv_workspace.py +174 -0
  248. wl_cli/utils/version/__init__.py +15 -0
  249. wl_cli/utils/version/pypi_version_checker.py +95 -0
  250. wl_cli/utils/version/version_comparator.py +133 -0
  251. wl_cli/utils/version/version_detectors.py +312 -0
  252. wl_cli/utils/version/version_service.py +131 -0
  253. wl_cli/utils/version/version_updater.py +198 -0
  254. wl_cli/utils/wl_dir_updater.py +1440 -0
  255. wl_cli/utils/workspace_detector/__init__.py +28 -0
  256. wl_cli/utils/workspace_detector/core.py +161 -0
  257. wl_cli/utils/workspace_detector/detection_strategies.py +107 -0
  258. wl_cli/utils/workspace_detector/exceptions.py +5 -0
  259. wl_cli/utils/workspace_detector/types.py +17 -0
  260. wl_cli/utils/workspace_detector/venv_resolver.py +84 -0
  261. wl_cli/vendors/config/.codespellrc +2 -0
  262. wl_cli/vendors/config/dependencies.toml +10 -0
  263. wl_cli/vendors/config/mypy.ini +62 -0
  264. wl_cli/vendors/config/pyproject_defaults.toml +28 -0
  265. wl_cli/vendors/config/template_config.toml +24 -0
  266. wl_cli/vendors/config/tool_configs.toml +76 -0
  267. wl_cli/vendors/git/.gitignore +122 -0
  268. wl_cli/vendors/git/.pre-commit-config.yaml +37 -0
  269. wl_cli/vendors/hooks/applypatch-msg.sample +15 -0
  270. wl_cli/vendors/hooks/commit-msg.sample +24 -0
  271. wl_cli/vendors/hooks/fsmonitor-watchman.sample +174 -0
  272. wl_cli/vendors/hooks/post-update.sample +8 -0
  273. wl_cli/vendors/hooks/pre-applypatch.sample +14 -0
  274. wl_cli/vendors/hooks/pre-commit +45 -0
  275. wl_cli/vendors/hooks/pre-commit.legacy +31 -0
  276. wl_cli/vendors/hooks/pre-commit.sample +49 -0
  277. wl_cli/vendors/hooks/pre-merge-commit.sample +13 -0
  278. wl_cli/vendors/hooks/pre-push.sample +60 -0
  279. wl_cli/vendors/hooks/pre-rebase.sample +169 -0
  280. wl_cli/vendors/hooks/pre-receive.sample +24 -0
  281. wl_cli/vendors/hooks/prepare-commit-msg.sample +42 -0
  282. wl_cli/vendors/hooks/push-to-checkout.sample +78 -0
  283. wl_cli/vendors/hooks/sendemail-validate.sample +77 -0
  284. wl_cli/vendors/hooks/unix/applypatch-msg.sample +15 -0
  285. wl_cli/vendors/hooks/unix/check_lockfile.py +58 -0
  286. wl_cli/vendors/hooks/unix/check_lockfile.sh +36 -0
  287. wl_cli/vendors/hooks/unix/commit-msg.sample +24 -0
  288. wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +174 -0
  289. wl_cli/vendors/hooks/unix/post-update.sample +8 -0
  290. wl_cli/vendors/hooks/unix/pre-applypatch.sample +14 -0
  291. wl_cli/vendors/hooks/unix/pre-commit +190 -0
  292. wl_cli/vendors/hooks/unix/pre-commit.legacy +31 -0
  293. wl_cli/vendors/hooks/unix/pre-commit.py +81 -0
  294. wl_cli/vendors/hooks/unix/pre-commit.sample +49 -0
  295. wl_cli/vendors/hooks/unix/pre-merge-commit.sample +13 -0
  296. wl_cli/vendors/hooks/unix/pre-push +417 -0
  297. wl_cli/vendors/hooks/unix/pre-push.sample +53 -0
  298. wl_cli/vendors/hooks/unix/pre-rebase.sample +169 -0
  299. wl_cli/vendors/hooks/unix/pre-receive.sample +24 -0
  300. wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +42 -0
  301. wl_cli/vendors/hooks/update.sample +128 -0
  302. wl_cli/vendors/hooks/win/work.bat +63 -0
  303. wl_cli/vendors/project/.gitignore +90 -0
  304. wl_cli/vendors/project/.python-version +1 -0
  305. wl_cli/vendors/project/LICENSE +21 -0
  306. wl_cli/vendors/project/README.md +0 -0
  307. wl_cli/vendors/project/pyproject.toml +27 -0
  308. wl_cli/vendors/project/pyproject_no_workspace.toml +16 -0
  309. wl_cli/vendors/project/pyproject_workspace.toml +14 -0
  310. wl_cli/vendors/readme/README.md +120 -0
  311. wl_cli/vendors/rust/Cargo.toml +14 -0
  312. wl_cli/vendors/rust/lib/__init__.py +3 -0
  313. wl_cli/vendors/rust/lib/rust_utils.py +31 -0
  314. wl_cli/vendors/rust/src/lib.rs +13 -0
  315. wl_cli/vendors/rust/src/main.rs +3 -0
  316. wl_cli/vendors/rust/tests/test_rust_fallback.py +40 -0
  317. wl_cli/vendors/sop_doc/git-dev-sop.md +220 -0
  318. wl_cli/vendors/sop_doc/industrial-standard-sop.md +145 -0
  319. wl_cli/vendors/sop_doc/python-sop.md +342 -0
  320. wl_cli/vendors/sop_doc/rust-readme.md +219 -0
@@ -0,0 +1,181 @@
1
+ from __future__ import annotations
2
+
3
+ from ...utils.logging import log_info_pair
4
+ from .utils import (
5
+ coverage_totals,
6
+ file_entries,
7
+ fmt_pct,
8
+ get_env_info,
9
+ parse_junit,
10
+ read_json,
11
+ read_xml,
12
+ write_md,
13
+ )
14
+
15
+ # Re-export private functions for backward compatibility (used in tests)
16
+ _coverage_totals = coverage_totals
17
+ _file_entries = file_entries
18
+ _fmt_pct = fmt_pct
19
+ _get_env_info = get_env_info
20
+ _parse_junit = parse_junit
21
+ _read_json = read_json
22
+ _read_xml = read_xml
23
+ _write_md = write_md
24
+
25
+
26
+ def generate_reports(
27
+ coverage_json_path: str,
28
+ junit_xml_path: str,
29
+ out_cov: str,
30
+ out_err: str,
31
+ project_root: str,
32
+ ) -> str:
33
+ _log_inputs(coverage_json_path, junit_xml_path, out_cov, out_err)
34
+ cov = _read_json(coverage_json_path)
35
+ junit = _read_xml(junit_xml_path)
36
+ env_info = _get_env_info()
37
+
38
+ line_pct, branch_pct, num_lines, num_branches, num_files = _coverage_totals(cov)
39
+ files = _file_entries(cov, project_root)
40
+ top_files = sorted(files, key=lambda x: x[1] or 0.0, reverse=True)[:10]
41
+ low_files = sorted(files, key=lambda x: x[1] or 0.0)[:10]
42
+
43
+ cov_lines = _build_coverage_lines(
44
+ env_info,
45
+ line_pct,
46
+ branch_pct,
47
+ num_lines,
48
+ num_branches,
49
+ num_files,
50
+ top_files,
51
+ low_files,
52
+ )
53
+ _write_md(out_cov, cov_lines)
54
+ _log_written(out_cov)
55
+
56
+ tests, failures, errors, skipped, warnings, time_spent, cases = _parse_junit(junit)
57
+ err_lines = _build_error_lines(
58
+ env_info, tests, failures, errors, skipped, warnings, time_spent, cases
59
+ )
60
+ _write_md(out_err, err_lines)
61
+ _log_written(out_err)
62
+
63
+ summary = f"总行覆盖率 {fmt_pct(line_pct)} | 分支覆盖率 {fmt_pct(branch_pct)} | 文件数 {num_files} | 失败用例 {failures + errors}"
64
+ return summary
65
+
66
+
67
+ def _log_inputs(
68
+ coverage_json_path: str, junit_xml_path: str, out_cov: str, out_err: str
69
+ ) -> None:
70
+ try:
71
+ log_info_pair(
72
+ f"Generating coverage report to: {out_cov}",
73
+ f"生成覆盖率报告到: {out_cov}",
74
+ )
75
+ log_info_pair(
76
+ f"Generating error report to: {out_err}",
77
+ f"生成错误报告到: {out_err}",
78
+ )
79
+ log_info_pair(
80
+ f"Coverage JSON source: {coverage_json_path}",
81
+ f"覆盖率JSON来源: {coverage_json_path}",
82
+ )
83
+ log_info_pair(
84
+ f"JUnit XML source: {junit_xml_path}",
85
+ f"JUnit XML来源: {junit_xml_path}",
86
+ )
87
+ except Exception:
88
+ pass
89
+
90
+
91
+ def _log_written(path: str) -> None:
92
+ try:
93
+ log_info_pair(
94
+ f"Coverage Markdown written: {path}",
95
+ f"覆盖率Markdown已写入: {path}",
96
+ )
97
+ except Exception:
98
+ pass
99
+
100
+
101
+ def _build_coverage_lines(
102
+ env_info,
103
+ line_pct,
104
+ branch_pct,
105
+ num_lines,
106
+ num_branches,
107
+ num_files,
108
+ top_files,
109
+ low_files,
110
+ ) -> list[str]:
111
+ cov_lines: list[str] = []
112
+ cov_lines.append("# WL 测试覆盖率报告")
113
+ cov_lines.append("")
114
+ cov_lines.append("## 测试环境")
115
+ cov_lines.extend([f"- {x}" for x in env_info])
116
+ cov_lines.append("")
117
+ cov_lines.append("## 总览")
118
+ cov_lines.append(f"- 行覆盖率: {fmt_pct(line_pct)}")
119
+ cov_lines.append(f"- 分支覆盖率: {fmt_pct(branch_pct)}")
120
+ cov_lines.append(f"- 语句数: {num_lines if num_lines else 'N/A'}")
121
+ cov_lines.append(f"- 分支数: {num_branches if num_branches else 'N/A'}")
122
+ cov_lines.append(f"- 文件数: {num_files}")
123
+ cov_lines.append("")
124
+ cov_lines.append("## Top 文件")
125
+ for rel, lp, bp in top_files:
126
+ cov_lines.append(f"- `{rel}` | 行 {fmt_pct(lp)} | 分支 {fmt_pct(bp)}")
127
+ cov_lines.append("")
128
+ cov_lines.append("## 低覆盖率文件")
129
+ for rel, lp, bp in low_files:
130
+ cov_lines.append(f"- `{rel}` | 行 {fmt_pct(lp)} | 分支 {fmt_pct(bp)}")
131
+ return cov_lines
132
+
133
+
134
+ def _build_error_lines(
135
+ env_info, tests, failures, errors, skipped, warnings, time_spent, cases
136
+ ) -> list[str]:
137
+ err_lines: list[str] = []
138
+ err_lines.append("# WL 测试错误报告")
139
+ err_lines.append("")
140
+ err_lines.append("## 测试环境")
141
+ err_lines.extend([f"- {x}" for x in env_info])
142
+ err_lines.append("")
143
+ err_lines.append("## 测试统计")
144
+ err_lines.append(f"- 总用例: {tests}")
145
+ err_lines.append(f"- 失败: {failures}")
146
+ err_lines.append(f"- 错误: {errors}")
147
+ err_lines.append(f"- 跳过: {skipped}")
148
+ err_lines.append(f"- 警告: {warnings}")
149
+ err_lines.append(f"- 总时长: {time_spent:.2f}s")
150
+ err_lines.append("")
151
+
152
+ failure_cases = [c for c in cases if c.get("kind") == "failure"]
153
+ error_cases = [c for c in cases if c.get("kind") == "error"]
154
+ warning_cases = [c for c in cases if c.get("kind") == "warning"]
155
+
156
+ if failure_cases:
157
+ err_lines.append("## 失败明细")
158
+ _append_case_lines(err_lines, failure_cases)
159
+
160
+ if error_cases:
161
+ err_lines.append("## 错误明细")
162
+ _append_case_lines(err_lines, error_cases)
163
+
164
+ if warning_cases:
165
+ err_lines.append("## 警告明细")
166
+ _append_case_lines(err_lines, warning_cases)
167
+
168
+ return err_lines
169
+
170
+
171
+ def _append_case_lines(err_lines: list[str], cases: list) -> None:
172
+ for c in cases:
173
+ loc = c.get("file") or c.get("classname") or ""
174
+ err_lines.append(
175
+ f"- 用例: `{c.get('name', '')}` @ `{loc}` [{c.get('kind', '')}]"
176
+ )
177
+ err_lines.append("")
178
+ err_lines.append("```")
179
+ err_lines.append(c.get("text", ""))
180
+ err_lines.append("```")
181
+ err_lines.append("")
@@ -0,0 +1,96 @@
1
+ """
2
+ Test result handling utilities for test command.
3
+ """
4
+
5
+ import sys
6
+
7
+
8
+ class TestResultHandler:
9
+ """Handle test results and exit codes."""
10
+
11
+ def handle_test_result(self, result, report_mode: bool) -> int:
12
+ """
13
+ Handle the test result based on return code.
14
+
15
+ Reports the outcome to the user and returns the exit code to hand back
16
+ to the caller. Exiting is deliberately left to the caller so that
17
+ post-run work (report generation, per-file cache attribution) still
18
+ happens on a failing suite.
19
+
20
+ Args:
21
+ result: The subprocess result object
22
+ report_mode: Whether we're in report mode
23
+
24
+ Returns:
25
+ The exit code to exit with (pytest's return code, unchanged)
26
+ """
27
+ if result.returncode == 0:
28
+ # Tests passed
29
+ if not report_mode:
30
+ print("All tests passed successfully!")
31
+ else:
32
+ # Tests failed
33
+ if not report_mode:
34
+ self._print_test_failure_info(result)
35
+ return int(result.returncode)
36
+
37
+ def _print_test_failure_info(self, result) -> None:
38
+ """
39
+ Print test failure information, filtering out progress bars.
40
+
41
+ Args:
42
+ result: The subprocess result object
43
+ """
44
+ # In concise mode, only show the short test summary info
45
+ # Skip the long progress bar to reduce token consumption
46
+ if hasattr(result, "stdout") and result.stdout:
47
+ output = self._filter_test_output(result.stdout, result)
48
+ # Only print if there's something left to print
49
+ if output.strip():
50
+ print(output)
51
+ if hasattr(result, "stderr") and result.stderr:
52
+ # stderr usually doesn't contain the summary
53
+ # Only output if it's not empty and not already in stdout
54
+ stderr = result.stderr.strip()
55
+ if stderr:
56
+ print(stderr, file=sys.stderr)
57
+ print(f"Tests failed with return code {result.returncode}")
58
+
59
+ def _filter_test_output(self, output: str, result) -> str:
60
+ """
61
+ Filter test output to remove progress bars and keep only useful information.
62
+
63
+ Args:
64
+ output: The test output to filter
65
+ result: The subprocess result object
66
+
67
+ Returns:
68
+ Filtered test output
69
+ """
70
+ # Find the short test summary info section
71
+ marker = "short test summary info"
72
+ if marker in output:
73
+ # Extract everything from the marker onwards
74
+ return output[output.index(marker) :]
75
+ else:
76
+ # If no marker found, filter out progress bar lines manually
77
+ # Filter lines that look like:
78
+ # - progress percentage: "... [XX%]"
79
+ # - progress dots: "filename.py ........." with many dots
80
+ lines = output.splitlines()
81
+ filtered_lines = []
82
+ for line in lines:
83
+ # Skip collection progress lines with percentage
84
+ # Matches both "[ 100%]" and "[100%]"
85
+ if "[" in line and "%]" in line:
86
+ continue
87
+ # Skip lines like "filename.py ........." that contain many dots
88
+ # These are the per-file progress dots from pytest
89
+ if "." in line and line.count(".") > 7:
90
+ continue
91
+ filtered_lines.append(line)
92
+ filtered_output = "\n".join(filtered_lines)
93
+ # If after filtering output is empty and there's stderr, don't print anything here
94
+ if not filtered_output.strip() and hasattr(result, "stderr"):
95
+ return ""
96
+ return filtered_output