workflow-loop 0.1.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 (60) hide show
  1. workflow_loop/__init__.py +6 -0
  2. workflow_loop/acceptance_records.py +338 -0
  3. workflow_loop/artifact_paths.py +278 -0
  4. workflow_loop/artifact_validation.py +1738 -0
  5. workflow_loop/bug_record.py +203 -0
  6. workflow_loop/cli.py +3257 -0
  7. workflow_loop/data/Standardized_Repository/acceptance/acceptance.md +119 -0
  8. workflow_loop/data/Standardized_Repository/acceptance/acceptance_plan.md +105 -0
  9. workflow_loop/data/Standardized_Repository/code_design/code_design.md +204 -0
  10. workflow_loop/data/Standardized_Repository/code_design/project_design_init.md +152 -0
  11. workflow_loop/data/Standardized_Repository/code_design/revise_code_design.md +32 -0
  12. workflow_loop/data/Standardized_Repository/code_design/update_code_design.md +94 -0
  13. workflow_loop/data/Standardized_Repository/global/document_writing.md +77 -0
  14. workflow_loop/data/Standardized_Repository/global/workflow_lifecycle.md +91 -0
  15. workflow_loop/data/Standardized_Repository/impl/code_implementation.md +85 -0
  16. workflow_loop/data/Standardized_Repository/impl/impl.md +164 -0
  17. workflow_loop/data/Standardized_Repository/qa/test.md +167 -0
  18. workflow_loop/data/Standardized_Repository/qa/test_code.md +121 -0
  19. workflow_loop/data/Standardized_Repository/qa/test_code_implementation.md +67 -0
  20. workflow_loop/data/Standardized_Repository/qa/test_plan.md +160 -0
  21. workflow_loop/data/Standardized_Repository/reproduce/reproduce.md +60 -0
  22. workflow_loop/data/Standardized_Repository/spec/spec.md +138 -0
  23. workflow_loop/data/Standardized_Repository/spike/spike.md +236 -0
  24. workflow_loop/data/Template_Repository/acceptance/acceptance_plan.md +142 -0
  25. workflow_loop/data/Template_Repository/acceptance/acceptance_result.md +108 -0
  26. workflow_loop/data/Template_Repository/code_design/code_design.md +260 -0
  27. workflow_loop/data/Template_Repository/code_design/project_design_init_evidence.md +39 -0
  28. workflow_loop/data/Template_Repository/impl/impl.md +112 -0
  29. workflow_loop/data/Template_Repository/qa/test.md +102 -0
  30. workflow_loop/data/Template_Repository/qa/test_plan.md +100 -0
  31. workflow_loop/data/Template_Repository/reproduce/reproduce.md +82 -0
  32. workflow_loop/data/Template_Repository/spec/spec.md +222 -0
  33. workflow_loop/data/Template_Repository/spike/spike.md +135 -0
  34. workflow_loop/installer.py +632 -0
  35. workflow_loop/journal.py +78 -0
  36. workflow_loop/path_composer.py +152 -0
  37. workflow_loop/process_runner.py +176 -0
  38. workflow_loop/project.py +397 -0
  39. workflow_loop/role_doc.py +133 -0
  40. workflow_loop/rollback.py +1738 -0
  41. workflow_loop/spike_validation.py +379 -0
  42. workflow_loop/stage_materials.py +169 -0
  43. workflow_loop/stages/__init__.py +45 -0
  44. workflow_loop/stages/base.py +164 -0
  45. workflow_loop/stages/stages.py +1191 -0
  46. workflow_loop/state.py +582 -0
  47. workflow_loop/test_entry.py +123 -0
  48. workflow_loop/test_execution.py +619 -0
  49. workflow_loop/test_mapping.py +568 -0
  50. workflow_loop/test_runner.py +134 -0
  51. workflow_loop/topic.py +114 -0
  52. workflow_loop/topic_relations.py +202 -0
  53. workflow_loop/traceability.py +533 -0
  54. workflow_loop/verification.py +971 -0
  55. workflow_loop-0.1.0.dist-info/METADATA +187 -0
  56. workflow_loop-0.1.0.dist-info/RECORD +60 -0
  57. workflow_loop-0.1.0.dist-info/WHEEL +5 -0
  58. workflow_loop-0.1.0.dist-info/entry_points.txt +2 -0
  59. workflow_loop-0.1.0.dist-info/licenses/LICENSE +21 -0
  60. workflow_loop-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,123 @@
1
+ """项目全量测试入口选择器。
2
+
3
+ `project.json` 的 `test_entry` 保存操作系统到命令参数数组的映射:
4
+ `default`(默认)、`windows`、`linux`、`darwin`(macOS)。当前操作系统优先使用
5
+ 同名配置,没有时才使用 `default`。参数数组直接交给进程执行器,不经过 Shell;
6
+ 需要管道、重定向或多条命令时,必须调用项目自己的统一入口脚本。
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ import sys
13
+
14
+ # 允许的平台键
15
+ PLATFORM_KEYS = ("windows", "linux", "darwin", "default")
16
+ # 参数中不允许出现的 Shell 元字符:这些能力属于项目脚本,不属于参数数组
17
+ _SHELL_META_CHARS = set("|&;<>\n`$()")
18
+ _SCRIPT_SUFFIXES = {
19
+ ".sh",
20
+ ".bash",
21
+ ".zsh",
22
+ ".ps1",
23
+ ".cmd",
24
+ ".bat",
25
+ ".py",
26
+ ".js",
27
+ ".mjs",
28
+ ".cjs",
29
+ }
30
+
31
+
32
+ def current_platform_key() -> str:
33
+ """返回当前操作系统对应的平台键。"""
34
+ if sys.platform.startswith("win"):
35
+ return "windows"
36
+ if sys.platform == "darwin":
37
+ return "darwin"
38
+ return "linux"
39
+
40
+
41
+ def validate_entry_config(config) -> list[str]:
42
+ """校验入口配置;返回错误列表(为空表示配置合法)。
43
+
44
+ 只接受 平台键 → 非空字符串数组 的映射。空映射合法(表示尚未配置)。
45
+ """
46
+ errors: list[str] = []
47
+ if not isinstance(config, dict):
48
+ return [f"测试入口必须是平台到参数数组的映射,不能是 {type(config).__name__}"]
49
+ for key, argv in config.items():
50
+ if key not in PLATFORM_KEYS:
51
+ errors.append(f"未知平台键: {key}(只接受 {'/'.join(PLATFORM_KEYS)})")
52
+ continue
53
+ if not isinstance(argv, list) or not argv:
54
+ errors.append(f"平台 {key} 的入口必须是非空参数数组")
55
+ continue
56
+ for argument in argv:
57
+ if not isinstance(argument, str):
58
+ errors.append(f"平台 {key} 的参数必须是字符串: {argument!r}")
59
+ continue
60
+ if not argument:
61
+ errors.append(f"平台 {key} 包含空参数")
62
+ continue
63
+ bad_chars = sorted(set(argument) & _SHELL_META_CHARS)
64
+ if bad_chars:
65
+ errors.append(
66
+ f"平台 {key} 的参数 {argument!r} 包含 Shell 运算符 {bad_chars};"
67
+ "需要管道、重定向或多条命令时,请放入项目统一入口脚本"
68
+ )
69
+ return errors
70
+
71
+
72
+ def normalized_entry_config(raw) -> dict[str, list[str]]:
73
+ """把外部输入规范化为合法配置;不合法时抛 ValueError。"""
74
+ errors = validate_entry_config(raw)
75
+ if errors:
76
+ raise ValueError(";".join(errors))
77
+ return {key: list(argv) for key, argv in raw.items()}
78
+
79
+
80
+ def select_entry(
81
+ config: dict[str, list[str]],
82
+ platform_key: str | None = None,
83
+ ) -> list[str] | None:
84
+ """按当前操作系统选择入口参数数组;同名配置优先,缺少时用 default。
85
+
86
+ 返回 None 表示当前平台没有可用入口(配置缺失)。
87
+ """
88
+ if not isinstance(config, dict):
89
+ return None
90
+ key = platform_key or current_platform_key()
91
+ argv = config.get(key) or config.get("default")
92
+ if not argv:
93
+ return None
94
+ return list(argv)
95
+
96
+
97
+ def describe_config(config: dict[str, list[str]]) -> str:
98
+ """给用户看的入口配置说明。"""
99
+ if not config:
100
+ return "(尚未配置项目全量测试入口)"
101
+ parts = []
102
+ for key in PLATFORM_KEYS:
103
+ if key in config:
104
+ parts.append(f"{key}: {config[key]}")
105
+ return ";".join(parts)
106
+
107
+
108
+ def referenced_project_scripts(config: dict[str, list[str]]) -> list[str]:
109
+ """列出入口参数中明确引用的项目脚本相对路径。"""
110
+ scripts: set[str] = set()
111
+ for argv in config.values():
112
+ for argument in argv:
113
+ normalized = argument.replace("\\", "/")
114
+ if (
115
+ not normalized
116
+ or os.path.isabs(argument)
117
+ or normalized.startswith("-")
118
+ or ".." in normalized.split("/")
119
+ ):
120
+ continue
121
+ if os.path.splitext(normalized)[1].lower() in _SCRIPT_SUFFIXES:
122
+ scripts.add(normalized)
123
+ return sorted(scripts)