ErisPulse 1.2.9__tar.gz → 2.1.1__tar.gz

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 (97) hide show
  1. erispulse-2.1.1/.github/tools/merge_md.py +141 -0
  2. erispulse-2.1.1/.github/tools/update-api-docs.py +276 -0
  3. erispulse-2.1.1/.github/workflows/auto-tag-release.yml +99 -0
  4. {erispulse-1.2.9 → erispulse-2.1.1}/.github/workflows/pypi-publish.yml +1 -24
  5. {erispulse-1.2.9 → erispulse-2.1.1}/.gitignore +5 -2
  6. erispulse-2.1.1/CODE_OF_CONDUCT.md +54 -0
  7. {erispulse-1.2.9 → erispulse-2.1.1}/LICENSE +4 -3
  8. {erispulse-1.2.9 → erispulse-2.1.1}/PKG-INFO +16 -41
  9. {erispulse-1.2.9 → erispulse-2.1.1}/README.md +7 -38
  10. {erispulse-1.2.9 → erispulse-2.1.1}/devs/test.py +13 -9
  11. erispulse-2.1.1/docs/AI-Module-Generation.md +43 -0
  12. erispulse-2.1.1/docs/AIDocs/ErisPulse-AdapterDev.md +2448 -0
  13. erispulse-2.1.1/docs/AIDocs/ErisPulse-Core.md +1933 -0
  14. erispulse-2.1.1/docs/AIDocs/ErisPulse-Full.md +3112 -0
  15. erispulse-2.1.1/docs/AIDocs/ErisPulse-ModuleDev.md +2496 -0
  16. erispulse-2.1.1/docs/AdapterStandards/APIResponse.md +109 -0
  17. erispulse-2.1.1/docs/AdapterStandards/EventConversion.md +202 -0
  18. erispulse-2.1.1/docs/AdapterStandards/README.md +3 -0
  19. {erispulse-1.2.9 → erispulse-2.1.1}/docs/CHANGELOG.md +64 -5
  20. erispulse-2.1.1/docs/CLI.md +57 -0
  21. erispulse-2.1.1/docs/Development/Adapter.md +193 -0
  22. erispulse-2.1.1/docs/Development/Module.md +128 -0
  23. erispulse-2.1.1/docs/Development/README.md +3 -0
  24. erispulse-2.1.1/docs/PlatformFeatures.md +430 -0
  25. erispulse-2.1.1/docs/UseCore.md +138 -0
  26. erispulse-2.1.1/docs/api/ErisPulse/Core/adapter.md +334 -0
  27. erispulse-2.1.1/docs/api/ErisPulse/Core/env.md +289 -0
  28. erispulse-2.1.1/docs/api/ErisPulse/Core/logger.md +85 -0
  29. erispulse-2.1.1/docs/api/ErisPulse/Core/mods.md +186 -0
  30. erispulse-2.1.1/docs/api/ErisPulse/Core/raiserr.md +107 -0
  31. erispulse-2.1.1/docs/api/ErisPulse/Core/server.md +124 -0
  32. erispulse-2.1.1/docs/api/ErisPulse/Core/util.md +97 -0
  33. erispulse-2.1.1/docs/api/ErisPulse/__init__.md +318 -0
  34. erispulse-2.1.1/docs/api/ErisPulse/__main__.md +192 -0
  35. erispulse-2.1.1/docs/api/README.md +3 -0
  36. {erispulse-1.2.9 → erispulse-2.1.1}/docs/quick-start.md +2 -3
  37. erispulse-2.1.1/examples/example-adapter/LICENSE +21 -0
  38. erispulse-2.1.1/examples/example-adapter/MyAdapter/Core.py +72 -0
  39. erispulse-2.1.1/examples/example-adapter/MyAdapter/__init__.py +1 -0
  40. erispulse-2.1.1/examples/example-adapter/README.md +0 -0
  41. erispulse-2.1.1/examples/example-adapter/pyproject.toml +24 -0
  42. erispulse-2.1.1/examples/example-module/LICENSE +21 -0
  43. erispulse-2.1.1/examples/example-module/MyModule/Core.py +32 -0
  44. erispulse-2.1.1/examples/example-module/MyModule/__init__.py +1 -0
  45. erispulse-2.1.1/examples/example-module/README.md +0 -0
  46. erispulse-2.1.1/examples/example-module/pyproject.toml +23 -0
  47. {erispulse-1.2.9 → erispulse-2.1.1}/pyproject.toml +8 -2
  48. erispulse-2.1.1/scripts/install/install.ps1 +236 -0
  49. erispulse-2.1.1/scripts/install/install.sh +247 -0
  50. erispulse-2.1.1/src/ErisPulse/Core/__init__.py +19 -0
  51. erispulse-2.1.1/src/ErisPulse/Core/adapter.py +548 -0
  52. erispulse-2.1.1/src/ErisPulse/Core/env.py +614 -0
  53. {erispulse-1.2.9/src/ErisPulse → erispulse-2.1.1/src/ErisPulse/Core}/logger.py +51 -113
  54. erispulse-2.1.1/src/ErisPulse/Core/mods.py +226 -0
  55. erispulse-2.1.1/src/ErisPulse/Core/raiserr.py +152 -0
  56. erispulse-2.1.1/src/ErisPulse/Core/server.py +276 -0
  57. erispulse-2.1.1/src/ErisPulse/Core/shellprint.py +165 -0
  58. erispulse-2.1.1/src/ErisPulse/Core/util.py +126 -0
  59. erispulse-2.1.1/src/ErisPulse/__init__.py +748 -0
  60. erispulse-2.1.1/src/ErisPulse/__main__.py +524 -0
  61. erispulse-2.1.1/style_guide/DOCSTRING_SPEC.md +95 -0
  62. erispulse-2.1.1/style_guide/README.md +5 -0
  63. erispulse-1.2.9/.github/ISSUE_TEMPLATE/bug_report.md +0 -36
  64. erispulse-1.2.9/.github/ISSUE_TEMPLATE/feature_request.md +0 -42
  65. erispulse-1.2.9/.github/config/notify.json +0 -10
  66. erispulse-1.2.9/.github/tools/merge_md.py +0 -39
  67. erispulse-1.2.9/.github/tools/update-api-docs.py +0 -76
  68. erispulse-1.2.9/.github/workflows/notifications.yml +0 -80
  69. erispulse-1.2.9/.github/workflows/send-email/action.yml +0 -41
  70. erispulse-1.2.9/.github/workflows/send-email/send_mail.py +0 -64
  71. erispulse-1.2.9/.github/workflows/send-email/send_mail_old.py +0 -29
  72. erispulse-1.2.9/docs/ADAPTERS.md +0 -530
  73. erispulse-1.2.9/docs/AI-Module-Generation.md +0 -125
  74. erispulse-1.2.9/docs/CLI.md +0 -30
  75. erispulse-1.2.9/docs/DEVELOPMENT.md +0 -431
  76. erispulse-1.2.9/docs/ForAIDocs/ErisPulseDevelop.md +0 -2152
  77. erispulse-1.2.9/docs/ORIGIN.md +0 -82
  78. erispulse-1.2.9/docs/REFERENCE.md +0 -964
  79. erispulse-1.2.9/gitc/cd_branch.sh +0 -17
  80. erispulse-1.2.9/gitc/commit.sh +0 -28
  81. erispulse-1.2.9/gitc/create_branch.sh +0 -20
  82. erispulse-1.2.9/gitc/create_pr.sh +0 -28
  83. erispulse-1.2.9/gitc/merge_dev.sh +0 -55
  84. erispulse-1.2.9/gitc/usage.md +0 -29
  85. erispulse-1.2.9/src/ErisPulse/__init__.py +0 -318
  86. erispulse-1.2.9/src/ErisPulse/__main__.py +0 -1317
  87. erispulse-1.2.9/src/ErisPulse/adapter.py +0 -465
  88. erispulse-1.2.9/src/ErisPulse/db.py +0 -769
  89. erispulse-1.2.9/src/ErisPulse/mods.py +0 -345
  90. erispulse-1.2.9/src/ErisPulse/raiserr.py +0 -141
  91. erispulse-1.2.9/src/ErisPulse/util.py +0 -144
  92. {erispulse-1.2.9 → erispulse-2.1.1}/.github/assets/erispulse_logo.png +0 -0
  93. {erispulse-1.2.9 → erispulse-2.1.1}/.python-version +0 -0
  94. {erispulse-1.2.9 → erispulse-2.1.1}/devs/test_adapter.py +0 -0
  95. {erispulse-1.2.9 → erispulse-2.1.1}/devs/test_files/test.docx +0 -0
  96. {erispulse-1.2.9 → erispulse-2.1.1}/devs/test_files/test.jpg +0 -0
  97. {erispulse-1.2.9 → erispulse-2.1.1}/devs/test_files/test.mp4 +0 -0
@@ -0,0 +1,141 @@
1
+ import os
2
+
3
+ def merge_md_files(output_file, files_to_merge, title="文档合集"):
4
+ """
5
+ 合并多个Markdown文件
6
+
7
+ :param output_file: 输出文件路径
8
+ :param files_to_merge: 要合并的文件列表,包含文件路径和描述
9
+ :param title: 文档标题
10
+ """
11
+ with open(output_file, 'w', encoding='utf-8') as outfile:
12
+ # 写入头部说明
13
+ outfile.write(f"# ErisPulse {title}\n\n")
14
+ outfile.write("本文件由多个开发文档合并而成,用于辅助 AI 理解 ErisPulse 的相关功能。\n\n")
15
+
16
+ outfile.write("## 各文件对应内容说明\n\n")
17
+ outfile.write("| 文件名 | 作用 |\n")
18
+ outfile.write("|--------|------|\n")
19
+
20
+ # 写入文件说明
21
+ for file_info in files_to_merge:
22
+ outfile.write(f"| {os.path.basename(file_info['path'])} | {file_info.get('description', '')} |\n")
23
+
24
+ outfile.write("\n## 合并内容开始\n\n")
25
+
26
+ # 合并文件内容
27
+ for file_info in files_to_merge:
28
+ file_path = file_info['path']
29
+ if os.path.exists(file_path):
30
+ filename = os.path.basename(file_path)
31
+ with open(file_path, 'r', encoding='utf-8') as infile:
32
+ content = infile.read()
33
+ outfile.write(f"<!-- {filename} -->\n\n")
34
+ outfile.write(content)
35
+ outfile.write(f"\n\n<!--- End of {filename} -->\n\n")
36
+ else:
37
+ print(f"⚠️ 文件不存在,跳过: {file_path}")
38
+
39
+ def merge_api_docs(api_dir, output_file):
40
+ """
41
+ 合并API文档
42
+
43
+ :param api_dir: API文档目录
44
+ :param output_file: 输出文件路径
45
+ """
46
+ with open(output_file, 'a', encoding='utf-8') as outfile:
47
+ outfile.write("<!-- API文档 -->\n\n")
48
+ outfile.write("# API参考\n\n")
49
+
50
+ # 递归遍历API目录
51
+ for root, _, files in os.walk(api_dir):
52
+ for file in files:
53
+ if file.endswith('.md'):
54
+ file_path = os.path.join(root, file)
55
+ rel_path = os.path.relpath(file_path, api_dir)
56
+
57
+ with open(file_path, 'r', encoding='utf-8') as infile:
58
+ content = infile.read()
59
+ outfile.write(f"## {rel_path}\n\n")
60
+ outfile.write(content)
61
+ outfile.write("\n\n")
62
+
63
+ outfile.write("<!--- End of API文档 -->\n")
64
+
65
+ def generate_full_document():
66
+ """生成完整文档"""
67
+ print("⏳ 正在生成完整文档...")
68
+
69
+ # 定义要合并的文件
70
+ files_to_merge = [
71
+ {"path": "docs/quick-start.md", "description": "快速开始指南"},
72
+ {"path": "docs/UseCore.md", "description": "核心功能使用说明"},
73
+ {"path": "docs/PlatformFeatures.md", "description": "平台功能说明"},
74
+ {"path": "docs/Development/Module.md", "description": "模块开发指南"},
75
+ {"path": "docs/Development/Adapter.md", "description": "适配器开发指南"},
76
+ {"path": "docs/AdapterStandards/APIResponse.md", "description": "API响应标准"},
77
+ {"path": "docs/AdapterStandards/EventConversion.md", "description": "事件转换标准"},
78
+ ]
79
+
80
+ output_file = "docs/AIDocs/ErisPulse-Full.md"
81
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
82
+
83
+ merge_md_files(output_file, files_to_merge, "完整开发文档")
84
+ merge_api_docs("docs/api", output_file)
85
+
86
+ print(f"🎉 完整文档生成完成,已保存到: {output_file}")
87
+
88
+ def generate_core_document():
89
+ """生成核心功能文档"""
90
+ print("⏳ 正在生成核心功能文档...")
91
+
92
+ files_to_merge = [
93
+ {"path": "docs/quick-start.md", "description": "快速开始指南"},
94
+ {"path": "docs/UseCore.md", "description": "核心功能使用说明"},
95
+ {"path": "docs/PlatformFeatures.md", "description": "平台功能说明"},
96
+ ]
97
+
98
+ output_file = "docs/AIDocs/ErisPulse-Core.md"
99
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
100
+
101
+ merge_md_files(output_file, files_to_merge, "核心功能文档")
102
+ merge_api_docs("docs/api/ErisPulse/Core", output_file)
103
+
104
+ print(f"🎉 核心功能文档生成完成,已保存到: {output_file}")
105
+
106
+ def generate_dev_documents():
107
+ """生成开发文档(模块和适配器)"""
108
+ print("⏳ 正在生成开发文档...")
109
+
110
+ # 模块开发文档
111
+ module_files = [
112
+ {"path": "docs/UseCore.md", "description": "核心功能使用说明"},
113
+ {"path": "docs/PlatformFeatures.md", "description": "平台支持的发送类型及差异性说明"},
114
+ {"path": "docs/Development/Module.md", "description": "模块开发指南"}
115
+ ]
116
+
117
+ module_output = "docs/AIDocs/ErisPulse-ModuleDev.md"
118
+ merge_md_files(module_output, module_files, "模块开发文档")
119
+ merge_api_docs("docs/api/", module_output)
120
+ print(f"🎉 模块开发文档生成完成,已保存到: {module_output}")
121
+
122
+ # 适配器开发文档
123
+ adapter_files = [
124
+ {"path": "docs/UseCore.md", "description": "核心功能使用说明"},
125
+ {"path": "docs/Development/Adapter.md", "description": "适配器开发指南"},
126
+ {"path": "docs/AdapterStandards/APIResponse.md", "description": "API响应标准"},
127
+ {"path": "docs/AdapterStandards/EventConversion.md", "description": "事件转换标准"},
128
+ ]
129
+
130
+ adapter_output = "docs/AIDocs/ErisPulse-AdapterDev.md"
131
+ merge_md_files(adapter_output, adapter_files, "适配器开发文档")
132
+ merge_api_docs("docs/api", adapter_output)
133
+ print(f"🎉 适配器开发文档生成完成,已保存到: {adapter_output}")
134
+
135
+ if __name__ == "__main__":
136
+ # 生成所有文档
137
+ generate_full_document()
138
+ generate_core_document()
139
+ generate_dev_documents()
140
+
141
+ print("✅ 所有文档生成完成")
@@ -0,0 +1,276 @@
1
+ import os
2
+ import ast
3
+ import re
4
+ import argparse
5
+ from typing import List, Dict, Tuple, Optional, Set
6
+ from datetime import datetime
7
+
8
+ def process_docstring(docstring: str) -> Optional[str]:
9
+ """
10
+ 处理文档字符串中的特殊标签
11
+
12
+ :param docstring: 原始文档字符串
13
+ :return: 处理后的文档字符串或None(如果包含忽略标签)
14
+ """
15
+ if not docstring:
16
+ return None
17
+
18
+ # 检查忽略标签
19
+ if "{!--< ignore >!--}" in docstring:
20
+ return None
21
+
22
+ # 替换 {!--< internal-use >!--}
23
+ docstring = re.sub(
24
+ r"{!--< internal-use >!--}(.*)",
25
+ lambda m: f"⚠️ **内部方法**:{m.group(1).strip()}\n\n",
26
+ docstring
27
+ )
28
+
29
+ # 替换过时标签
30
+ docstring = re.sub(
31
+ r"\{!--< deprecated >!--\}(.*)",
32
+ lambda m: f"⚠️ **已弃用**:{m.group(1).strip()}\n\n",
33
+ docstring
34
+ )
35
+
36
+ # 替换实验性标签
37
+ docstring = re.sub(
38
+ r"\{!--< experimental >!--\}(.*)",
39
+ lambda m: f"🔬 **实验性功能**:{m.group(1).strip()}\n\n",
40
+ docstring
41
+ )
42
+
43
+ # 处理提示标签(多行)
44
+ docstring = re.sub(
45
+ r"\{!--< tips >!--\}(.*?)\{!--< /tips >!--\}",
46
+ lambda m: f"💡 **提示**:\n\n{m.group(1).strip()}\n\n",
47
+ docstring,
48
+ flags=re.DOTALL
49
+ )
50
+
51
+ # 处理单行提示标签
52
+ docstring = re.sub(
53
+ r"\{!--< tips >!--\}([^\n]*)",
54
+ lambda m: f"💡 **提示**:{m.group(1).strip()}\n\n",
55
+ docstring
56
+ )
57
+
58
+ # 参数说明
59
+ docstring = re.sub(
60
+ r":param (\w+):\s*\[([^\]]+)\]\s*(.*)",
61
+ lambda m: f"- `{m.group(1)}` ({m.group(2)}): {m.group(3).strip()}",
62
+ docstring
63
+ )
64
+
65
+ # 返回值说明
66
+ docstring = re.sub(
67
+ r":return:\s*\[([^\]]+)\]\s*(.*)",
68
+ lambda m: f"**返回**: \n\n- 类型: `{m.group(1)}`\n- 描述: {m.group(2).strip()}",
69
+ docstring
70
+ )
71
+
72
+ # 异常说明
73
+ docstring = re.sub(
74
+ r":raises (\w+):\s*(.*)",
75
+ lambda m: f"⚠️ **可能抛出**: `{m.group(1)}` - {m.group(2).strip()}",
76
+ docstring
77
+ )
78
+
79
+ # 统一换行符为两个换行
80
+ docstring = re.sub(r"\n{2,}", "\n\n", docstring.strip())
81
+
82
+ return docstring.strip()
83
+
84
+ def parse_python_file(file_path: str) -> Tuple[Optional[str], List[Dict], List[Dict]]:
85
+ """
86
+ 解析Python文件,提取模块文档、类和函数信息
87
+
88
+ :param file_path: Python文件路径
89
+ :return: (模块文档, 类列表, 函数列表)
90
+ """
91
+ with open(file_path, "r", encoding="utf-8") as f:
92
+ source = f.read()
93
+
94
+ try:
95
+ module = ast.parse(source)
96
+ except SyntaxError:
97
+ print(f"⚠️ 语法错误,跳过文件: {file_path}")
98
+ return None, [], []
99
+
100
+ # 提取模块文档
101
+ module_doc = ast.get_docstring(module)
102
+ processed_module_doc = process_docstring(module_doc) if module_doc else None
103
+
104
+ classes = []
105
+ functions = []
106
+
107
+ # 遍历AST节点
108
+ for node in module.body:
109
+ # 处理类定义
110
+ if isinstance(node, ast.ClassDef):
111
+ class_doc = ast.get_docstring(node)
112
+ processed_class_doc = process_docstring(class_doc) if class_doc else None
113
+
114
+ if processed_class_doc is None:
115
+ continue
116
+
117
+ methods = []
118
+ # 提取类方法
119
+ for item in node.body:
120
+ if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)):
121
+ method_doc = ast.get_docstring(item)
122
+ processed_method_doc = process_docstring(method_doc) if method_doc else None
123
+
124
+ if processed_method_doc:
125
+ methods.append({
126
+ "name": item.name,
127
+ "doc": processed_method_doc,
128
+ "is_async": isinstance(item, ast.AsyncFunctionDef)
129
+ })
130
+
131
+ classes.append({
132
+ "name": node.name,
133
+ "doc": processed_class_doc,
134
+ "methods": methods
135
+ })
136
+
137
+ # 处理函数定义
138
+ elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
139
+ func_doc = ast.get_docstring(node)
140
+ processed_func_doc = process_docstring(func_doc) if func_doc else None
141
+
142
+ if processed_func_doc:
143
+ functions.append({
144
+ "name": node.name,
145
+ "doc": processed_func_doc,
146
+ "is_async": isinstance(node, ast.AsyncFunctionDef)
147
+ })
148
+
149
+ return processed_module_doc, classes, functions
150
+
151
+ def generate_markdown(module_path: str, module_doc: Optional[str],
152
+ classes: List[Dict], functions: List[Dict]) -> str:
153
+ """
154
+ 生成Markdown格式API文档
155
+
156
+ :param module_path: 模块路径(点分隔)
157
+ :param module_doc: 模块文档
158
+ :param classes: 类信息列表
159
+ :param functions: 函数信息列表
160
+ :return: Markdown格式的文档字符串
161
+ """
162
+ content = []
163
+
164
+ # 文档头部
165
+ content.append(f"""# 📦 `{module_path}` 模块
166
+
167
+ *自动生成于 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
168
+
169
+ ---
170
+ """)
171
+
172
+ # 模块文档
173
+ if module_doc:
174
+ content.append(f"## 模块概述\n\n{module_doc}\n\n---\n")
175
+
176
+ # 函数部分
177
+ if functions:
178
+ content.append("## 🛠️ 函数\n")
179
+ for func in functions:
180
+ async_marker = "🔹 `async` " if func["is_async"] else ""
181
+ content.append(f"""### {async_marker}`{func['name']}`
182
+
183
+ {func['doc']}
184
+
185
+ ---
186
+ """)
187
+
188
+ # 类部分
189
+ if classes:
190
+ content.append("## 🏛️ 类\n")
191
+ for cls in classes:
192
+ content.append(f"""### `{cls['name']}`
193
+
194
+ {cls['doc']}
195
+
196
+ """)
197
+
198
+ # 类方法
199
+ if cls["methods"]:
200
+ content.append("#### 🧰 方法\n")
201
+ for method in cls["methods"]:
202
+ async_marker = "🔹 `async` " if method["is_async"] else ""
203
+ content.append(f"""##### {async_marker}`{method['name']}`
204
+
205
+ {method['doc']}
206
+
207
+ ---
208
+ """)
209
+
210
+ # 文档尾部
211
+ content.append(f"\n*文档最后更新于 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*")
212
+
213
+ return "\n".join(content)
214
+
215
+ def generate_api_docs(src_dir: str, output_dir: str):
216
+ """
217
+ 生成API文档
218
+
219
+ :param src_dir: 源代码目录
220
+ :param output_dir: 输出目录
221
+ """
222
+ # 确保输出目录存在
223
+ os.makedirs(output_dir, exist_ok=True)
224
+
225
+ # 遍历源代码目录
226
+ for root, _, files in os.walk(src_dir):
227
+ for file in files:
228
+ if file.endswith(".py"):
229
+ file_path = os.path.join(root, file)
230
+
231
+ # 计算模块路径
232
+ rel_path = os.path.relpath(file_path, src_dir)
233
+ module_path = rel_path.replace(".py", "").replace(os.sep, ".")
234
+
235
+ # 解析Python文件
236
+ module_doc, classes, functions = parse_python_file(file_path)
237
+
238
+ # 跳过没有文档的文件
239
+ if not module_doc and not classes and not functions:
240
+ print(f"⏭️ 跳过无文档文件: {file_path}")
241
+ continue
242
+
243
+ # 生成Markdown内容
244
+ md_content = generate_markdown(module_path, module_doc, classes, functions)
245
+
246
+ # 写入文件
247
+ output_path = os.path.join(output_dir, f"{module_path.replace('.', '/')}.md")
248
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
249
+
250
+ with open(output_path, "w", encoding="utf-8") as f:
251
+ f.write(md_content)
252
+
253
+ print(f"✅ 已生成: {output_path}")
254
+
255
+ if __name__ == "__main__":
256
+ parser = argparse.ArgumentParser(description="API文档生成器")
257
+ parser.add_argument("--src", default="src", help="源代码目录 (默认: src)")
258
+ parser.add_argument("--output", default="docs/api", help="输出目录 (默认: docs/api)")
259
+ parser.add_argument("--version", action="version", version="API文档生成器 2.0")
260
+
261
+ args = parser.parse_args()
262
+
263
+ print(f"""📁 源代码目录: {args.src}
264
+ 📂 输出目录: {args.output}
265
+ ⏳ 正在生成API文档...""")
266
+
267
+ generate_api_docs(args.src, args.output)
268
+
269
+ print("""🎉 API文档生成完成!
270
+
271
+ 生成文档包含以下改进:
272
+ ✨ 更美观的排版和格式
273
+ 📅 自动添加生成时间戳
274
+ 🔖 使用emoji图标提高可读性
275
+ 📝 优化了参数和返回值的显示方式
276
+ """)
@@ -0,0 +1,99 @@
1
+ name: 🎀 艾莉丝的版本标签魔法 ~
2
+
3
+ permissions:
4
+ contents: write
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+
10
+ jobs:
11
+ auto-tag-and-release:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: 检出代码
15
+ uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+ token: ${{ secrets.GITHUB_TOKEN }}
19
+
20
+ - name: 读取版本卷轴
21
+ id: info
22
+ shell: bash
23
+ run: |
24
+ version=$(grep '^version' pyproject.toml | head -1 | sed 's/version = "//;s/"//')
25
+ echo "version=$version" >> $GITHUB_OUTPUT
26
+ echo "发现新版本: $version"
27
+
28
+ if [[ $version =~ dev|alpha|beta|a|b ]]; then
29
+ echo "is_dev=true" >> $GITHUB_OUTPUT
30
+ else
31
+ echo "is_dev=false" >> $GITHUB_OUTPUT
32
+ fi
33
+
34
+ commit_msg=$(git log -1 --pretty=%B)
35
+ commit_short=$(git rev-parse --short HEAD)
36
+ echo "commit_short=$commit_short" >> $GITHUB_OUTPUT
37
+ echo "commit_msg<<EOF" >> $GITHUB_OUTPUT
38
+ echo "$commit_msg" >> $GITHUB_OUTPUT
39
+ echo "EOF" >> $GITHUB_OUTPUT
40
+
41
+ - name: 获取变更文件列表
42
+ id: changed_files
43
+ shell: bash
44
+ run: |
45
+ before="${{ github.event.before }}"
46
+ after="${{ github.sha }}"
47
+
48
+ if [[ "$before" == "0000000000000000000000000000000000000000" ]]; then
49
+ before="HEAD~1"
50
+ fi
51
+
52
+ echo "before=$before" >> $GITHUB_OUTPUT
53
+ echo "after=$after" >> $GITHUB_OUTPUT
54
+
55
+ files=$(git diff --name-only $before..$after | head -n 50 | xargs)
56
+ file_count=$(git diff --name-only $before..$after | wc -l)
57
+
58
+ if [ "$file_count" -gt 50 ]; then
59
+ files="$files ..."
60
+ fi
61
+
62
+ echo "files=$files" >> $GITHUB_OUTPUT
63
+
64
+ - name: 施展版本魔法
65
+ env:
66
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67
+ shell: bash
68
+ run: |
69
+ version="${{ steps.info.outputs.version }}"
70
+ commit_short="${{ steps.info.outputs.commit_short }}"
71
+ commit_msg="${{ steps.info.outputs.commit_msg }}"
72
+ is_dev="${{ steps.info.outputs.is_dev }}"
73
+ tag_name="v$version"
74
+
75
+ if [ -f "docs/CHANGELOG.md" ]; then
76
+ changelog=$(sed -n "/^## \[$version\]/,/^## /p" docs/CHANGELOG.md | sed '1d;$d')
77
+ fi
78
+ if [ -z "$changelog" ]; then
79
+ changelog="### ✨ 魔法更新\n\n- $commit_msg ($commit_short)"
80
+ fi
81
+
82
+ if ! git rev-parse "$tag_name" >/dev/null 2>&1; then
83
+ echo "🎀 施加新的魔法印记..."
84
+ git tag "$tag_name"
85
+ git push origin "$tag_name"
86
+ fi
87
+
88
+ if gh release view "$tag_name" &>/dev/null; then
89
+ gh release edit "$tag_name" \
90
+ --notes "$changelog" \
91
+ --prerelease=$is_dev
92
+ echo "🌟 已更新魔法版本 $tag_name"
93
+ else
94
+ gh release create "$tag_name" \
95
+ --notes "$changelog" \
96
+ --title "✨ 艾莉丝的魔法更新 $tag_name" \
97
+ --prerelease=$is_dev
98
+ echo "✨ 已发布新的魔法版本 $tag_name"
99
+ fi
@@ -2,7 +2,7 @@ name: 🎀 艾莉丝的PyPI包裹快递服务 ~
2
2
 
3
3
  # 艾莉丝今天也要努力发包呢!
4
4
  on:
5
- workflow_dispatch: {} # 手动触发
5
+ workflow_dispatch: {}
6
6
 
7
7
  permissions:
8
8
  contents: read
@@ -89,26 +89,3 @@ jobs:
89
89
  run: |
90
90
  emails=$(cat .github/config/notify.json | jq -c '.emails')
91
91
  echo "emails=$emails" >> $GITHUB_OUTPUT
92
-
93
- - name: 发送邮件通知
94
- uses: ./.github/workflows/send-email
95
- with:
96
- subject: "[艾莉丝快报] 新版本 ${{ steps.version.outputs.CURRENT_TAG }} 已发布至 PyPI!✨"
97
- content: |
98
- 🎀 您好主人~
99
-
100
- 我是艾莉丝,负责为您播报最新消息!
101
- 今天我们的项目又更新啦~快去看看吧!
102
-
103
- 🔖 版本号:${{ steps.version.outputs.CURRENT_TAG }}
104
- 📦 包地址:
105
- https://pypi.org/project/erispulse/${{ steps.version.outputs.CURRENT_TAG }}
106
-
107
- 📝 更新内容:
108
- ${{ steps.version.outputs.CURRENT_TAG }}
109
-
110
- 祝您每天都有好心情~ 💖
111
- —— 艾莉丝
112
- recipients: ${{ steps.get_emails.outputs.emails }}
113
- resend_api_key: ${{ secrets.RESEND_API_KEY }}
114
- feishu_smtp_password: ${{ secrets.FEISHU_SMTP_PASSWORD }}
@@ -1,5 +1,7 @@
1
1
  # dev gnore ignore file for Python projects
2
- env.py
2
+ main.py
3
+ venvs
4
+ config.toml
3
5
  adapters
4
6
  uv.lock
5
7
  snapshots/
@@ -207,4 +209,5 @@ pyvenv.cfg
207
209
 
208
210
  # erispulse
209
211
  my_bot
210
- modules
212
+ modules
213
+ config.toml
@@ -0,0 +1,54 @@
1
+ # 贡献者公约行为准则
2
+
3
+ ## 我们的承诺
4
+
5
+ 为了促进一个开放和欢迎的环境,我们作为贡献者和维护者承诺,让每个人在我们的项目和社区中的参与都成为一个
6
+ 无骚扰的体验,无论年龄、身体大小、残疾、种族、性别认同和表现、经验水平、国籍、个人外貌、种族、宗教
7
+ 或性别认同和取向如何。
8
+
9
+ ## 我们的标准
10
+
11
+ 有助于创造积极环境的行为示例包括:
12
+
13
+ * 使用热情和包容的语言
14
+ * 尊重不同的观点和经验
15
+ * 优雅地接受建设性的批评
16
+ * 专注于社区的最佳利益
17
+ * 对其他社区成员表现出同情
18
+
19
+ 参与者不可接受行为的示例包括:
20
+
21
+ * 使用性暗示的语言或图像,以及不受欢迎的性关注或挑逗
22
+ * 钓鱼、侮辱/贬损的评论和个人或政治攻击
23
+ * 公共或私人骚扰
24
+ * 在未获得明确许可的情况下发布他人的私人信息,如地址或电子邮件地址
25
+ * 其他在专业环境中被合理视为不当的行为
26
+
27
+ ## 我们的责任
28
+
29
+ 项目维护者负责澄清可接受行为的标准,并被期望对任何不可接受行为采取适当和公正的纠正措施。
30
+
31
+ 项目维护者有权和责任删除、编辑或拒绝与本行为准则不符的评论、提交、代码、维基编辑、问题和其他贡献,
32
+ 或因其他他们认为不当、威胁、冒犯或有害的行为而暂时或永久禁止任何贡献者。
33
+
34
+ ## 适用范围
35
+
36
+ 本行为准则适用于项目空间内和公共空间中,个人代表项目或其社区时的行为。代表项目或社区的示例包括使用
37
+ 官方项目电子邮件地址、通过官方社交媒体账户发布信息,或在在线或离线活动中担任任命代表。项目的代表性
38
+ 可能由项目维护者进一步定义和澄清。
39
+
40
+ ## 执行
41
+
42
+ 虐待、骚扰或其他不可接受行为的实例可以通过联系 erispulse@163.com 报告。
43
+ 所有投诉将被审查和调查,并将根据情况作出必要和适当的回应。项目团队有责任对事件举报者保持保密。
44
+ 具体的执行政策可能会单独发布。
45
+
46
+ 不善意遵循或执行行为准则的项目维护者可能会面临其他项目领导成员决定的临时或永久后果。
47
+
48
+ ## 归属
49
+
50
+ 本行为准则改编自 [贡献者公约][homepage],版本 1.4, 可在
51
+ [https://contributor-covenant.org/version/1/4][version] 获取。
52
+
53
+ [homepage]: https://contributor-covenant.org
54
+ [version]: https://www.contributor-covenant.org/version/1/4
@@ -2,8 +2,7 @@ MIT License
2
2
 
3
3
  Copyright (c) 2025 ErisPulse
4
4
 
5
- Portions of this software are based on https://github.com/FramerOrg/Framer
6
- (Copyright (c) 2025 runoneall).
5
+ Portions of this software are based on https://github.com/runoneall/sdkFrame.
7
6
 
8
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
9
8
  of this software and associated documentation files (the "Software"), to deal
@@ -25,4 +24,6 @@ SOFTWARE.
25
24
 
26
25
  The documentation portion of this project references content from https://codeberg.org/ybr/yhwiki,
27
26
  licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
28
- International License (CC BY-NC-ND 4.0).
27
+ International License (CC BY-NC-ND 4.0).
28
+
29
+ Note: This license file has been updated to correct the upstream project reference.