ErisPulse 2.3.2__tar.gz → 2.3.3.dev0__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.
- erispulse-2.3.3.dev0/.github/tools/update-api-docs.py +557 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/CHANGELOG.md +27 -1
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/PKG-INFO +1 -3
- erispulse-2.3.3.dev0/devs/test_event_wrapper.py +181 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/ErisPulse-AdapterDev.md +2179 -1498
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/ErisPulse-Core.md +2099 -1146
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/ErisPulse-Full.md +2463 -1420
- {erispulse-2.3.2/docs/ai/AIDocs/no-api → erispulse-2.3.3.dev0/docs/ai/AIDocs}/ErisPulse-ModuleDev.md +364 -2
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/no-api/ErisPulse-AdapterDev.md +4 -276
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/no-api/ErisPulse-Core.md +2 -2
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/AIDocs/no-api/ErisPulse-Full.md +366 -276
- {erispulse-2.3.2/docs/ai/AIDocs → erispulse-2.3.3.dev0/docs/ai/AIDocs/no-api}/ErisPulse-ModuleDev.md +364 -2
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Bases/__init__.md +1 -3
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Bases/adapter.md +56 -50
- erispulse-2.3.3.dev0/docs/api/ErisPulse/Core/Bases/module.md +65 -0
- erispulse-2.3.3.dev0/docs/api/ErisPulse/Core/Event/__init__.md +38 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/base.md +33 -26
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/command.md +84 -55
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/exceptions.md +9 -10
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/message.md +44 -34
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/meta.md +43 -33
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/notice.md +51 -39
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/Event/request.md +35 -27
- erispulse-2.3.3.dev0/docs/api/ErisPulse/Core/Event/wrapper.md +511 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/_self_config.md +8 -2
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/adapter.md +103 -98
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/config.md +36 -28
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/exceptions.md +16 -10
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/lifecycle.md +35 -28
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/logger.md +67 -51
- erispulse-2.3.3.dev0/docs/api/ErisPulse/Core/module.md +239 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/router.md +60 -48
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/storage.md +113 -120
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/Core/ux.md +42 -33
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/__init__.md +153 -113
- erispulse-2.3.3.dev0/docs/api/ErisPulse/__main__.md +28 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/utils/__init__.md +1 -3
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/utils/cli.md +69 -51
- erispulse-2.3.3.dev0/docs/api/ErisPulse/utils/console.md +23 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/utils/package_manager.md +100 -78
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/api/ErisPulse/utils/reload_handler.md +27 -21
- erispulse-2.3.3.dev0/docs/api/README.md +164 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/development/adapter.md +3 -274
- erispulse-2.3.3.dev0/docs/development/module.md +701 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/README.md +1 -1
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-module/MyModule/Core.py +47 -36
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/packages.json +5 -5
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/pyproject.toml +1 -3
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/__init__.py +3 -1
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/base.py +5 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/command.py +66 -17
- erispulse-2.3.3.dev0/src/ErisPulse/Core/Event/wrapper.py +592 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/__main__.py +0 -5
- erispulse-2.3.2/.github/tools/update-api-docs.py +0 -609
- erispulse-2.3.2/docs/api/ErisPulse/Core/Bases/module.md +0 -60
- erispulse-2.3.2/docs/api/ErisPulse/Core/Event/__init__.md +0 -36
- erispulse-2.3.2/docs/api/ErisPulse/Core/module.md +0 -229
- erispulse-2.3.2/docs/api/ErisPulse/__main__.md +0 -30
- erispulse-2.3.2/docs/api/ErisPulse/utils/console.md +0 -23
- erispulse-2.3.2/docs/development/module.md +0 -339
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/ISSUE_TEMPLATE/module_submission.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/assets/docs/install_pip.gif +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/assets/erispulse_logo.png +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/scripts/update_packages.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/tools/merge_md.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/workflows/auto-tag-release.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/workflows/auto-update-docs.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/workflows/auto-update-packages.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/workflows/code-quality-check.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.github/workflows/pypi-publish.yml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.gitignore +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/.python-version +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/CODE_OF_CONDUCT.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/CONTRIBUTING.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/LICENSE +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/SECURITY.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_adapter.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_cmd.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_event.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_files/test.docx +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_files/test.jpg +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/devs/test_files/test.mp4 +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/ai/module-generation.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/adapters.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/best-practices.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/cli.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/concepts.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/event-system.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/lazy-loading.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/modules.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/router.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/core/self-config.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/development/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/development/cli.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/email.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/maintain-notes.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/onebot11.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/onebot12.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/telegram.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/platform-features/yunhu.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/quick-start.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/standards/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/standards/api-response.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/standards/event-conversion.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/styleguide/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/docs/styleguide/docstring_spec.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/LICENSE +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/MyAdapter/Converter.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/MyAdapter/Core.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/MyAdapter/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-adapter/pyproject.toml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-cli-module/LICENSE +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-cli-module/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-cli-module/my_cli_module/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-cli-module/my_cli_module/cli.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-cli-module/pyproject.toml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-module/LICENSE +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-module/MyModule/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-module/README.md +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/examples/example-module/pyproject.toml +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/scripts/install/install.ps1 +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/scripts/install/install.sh +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Bases/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Bases/adapter.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Bases/module.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/exceptions.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/_self_config.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/adapter.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/config.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/exceptions.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/lifecycle.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/logger.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/module.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/router.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/storage.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/Core/ux.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/utils/__init__.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/utils/cli.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/utils/console.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/utils/package_manager.py +0 -0
- {erispulse-2.3.2 → erispulse-2.3.3.dev0}/src/ErisPulse/utils/reload_handler.py +0 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ErisPulse API 文档生成器
|
|
3
|
+
|
|
4
|
+
从Python源代码自动生成API文档
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import ast
|
|
9
|
+
import re
|
|
10
|
+
import argparse
|
|
11
|
+
import hashlib
|
|
12
|
+
from typing import List, Dict, Tuple, Optional
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from collections import defaultdict
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def compute_content_hash(content: str) -> str:
|
|
18
|
+
"""
|
|
19
|
+
计算内容的SHA256哈希值(排除最后更新时间)
|
|
20
|
+
|
|
21
|
+
:param content: 内容字符串
|
|
22
|
+
:return: 哈希值
|
|
23
|
+
"""
|
|
24
|
+
# 移除最后更新时间行以避免时间戳影响哈希
|
|
25
|
+
lines = content.split('\n')
|
|
26
|
+
filtered_lines = [line for line in lines if not line.strip().startswith('> 最后更新:')]
|
|
27
|
+
normalized_content = '\n'.join(filtered_lines)
|
|
28
|
+
return hashlib.sha256(normalized_content.encode('utf-8')).hexdigest()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def should_update_file(file_path: str, new_content: str) -> bool:
|
|
32
|
+
"""
|
|
33
|
+
检查文件是否需要更新(基于内容哈希)
|
|
34
|
+
|
|
35
|
+
:param file_path: 文件路径
|
|
36
|
+
:param new_content: 新内容
|
|
37
|
+
:return: 是否需要更新
|
|
38
|
+
"""
|
|
39
|
+
if not os.path.exists(file_path):
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
# 读取现有文件内容并计算哈希
|
|
43
|
+
try:
|
|
44
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
45
|
+
existing_content = f.read()
|
|
46
|
+
existing_hash = compute_content_hash(existing_content)
|
|
47
|
+
new_hash = compute_content_hash(new_content)
|
|
48
|
+
return existing_hash != new_hash
|
|
49
|
+
except Exception:
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def format_timestamp(timestamp: Optional[float] = None) -> str:
|
|
54
|
+
"""
|
|
55
|
+
格式化时间戳为可读字符串
|
|
56
|
+
|
|
57
|
+
:param timestamp: 时间戳,如果为None则使用当前时间
|
|
58
|
+
:return: 格式化后的时间字符串
|
|
59
|
+
"""
|
|
60
|
+
if timestamp is None:
|
|
61
|
+
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
62
|
+
return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def process_docstring_for_markdown(docstring: str) -> Optional[str]:
|
|
66
|
+
"""
|
|
67
|
+
将文档字符串转换为纯Markdown格式
|
|
68
|
+
|
|
69
|
+
:param docstring: 原始文档字符串
|
|
70
|
+
:return: Markdown格式的文档字符串或None(如果包含忽略标签)
|
|
71
|
+
"""
|
|
72
|
+
if not docstring:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
# 检查忽略标签
|
|
76
|
+
if "{!--< ignore >!--}" in docstring:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
lines = docstring.split('\n')
|
|
80
|
+
result = []
|
|
81
|
+
in_code_block = False
|
|
82
|
+
in_tip_block = False
|
|
83
|
+
tip_content = []
|
|
84
|
+
|
|
85
|
+
for line in lines:
|
|
86
|
+
# 处理代码块
|
|
87
|
+
if '```' in line:
|
|
88
|
+
in_code_block = not in_code_block
|
|
89
|
+
result.append(line)
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
if in_code_block:
|
|
93
|
+
result.append(line)
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
# 处理提示块(多行)
|
|
97
|
+
if "{!--< tips >!--}" in line:
|
|
98
|
+
in_tip_block = True
|
|
99
|
+
tip_content = [line.split("{!--< tips >!--}")[-1].strip()]
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
if "{!--< /tips >!--}" in line:
|
|
103
|
+
in_tip_block = False
|
|
104
|
+
before_end = line.split("{!--< /tips >!--}")[0].strip()
|
|
105
|
+
if before_end:
|
|
106
|
+
tip_content.append(before_end)
|
|
107
|
+
|
|
108
|
+
if tip_content:
|
|
109
|
+
result.append("> **提示**")
|
|
110
|
+
for tip_line in tip_content:
|
|
111
|
+
if tip_line:
|
|
112
|
+
result.append(f"> {tip_line}")
|
|
113
|
+
result.append("")
|
|
114
|
+
tip_content = []
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
if in_tip_block:
|
|
118
|
+
tip_content.append(line.strip())
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
# 处理单行提示标签
|
|
122
|
+
if "{!--< tips >!--}" in line:
|
|
123
|
+
content = line.split("{!--< tips >!--}")[-1].strip()
|
|
124
|
+
result.append(f"> **提示**: {content}")
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
# 处理内部使用标签
|
|
128
|
+
if "{!--< internal-use >!--}" in line:
|
|
129
|
+
content = line.split("{!--< internal-use >!--}")[-1].strip()
|
|
130
|
+
result.append(f"> **内部方法** {content}")
|
|
131
|
+
continue
|
|
132
|
+
|
|
133
|
+
# 处理过时标签
|
|
134
|
+
if "{!--< deprecated >!--}" in line:
|
|
135
|
+
content = line.split("{!--< deprecated >!--}")[-1].strip()
|
|
136
|
+
result.append(f"> **已弃用** {content}")
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
# 处理实验性功能标签
|
|
140
|
+
if "{!--< experimental >!--}" in line:
|
|
141
|
+
content = line.split("{!--< experimental >!--}")[-1].strip()
|
|
142
|
+
result.append(f"> **实验性功能** {content}")
|
|
143
|
+
continue
|
|
144
|
+
|
|
145
|
+
# 跳过处理过的标签行
|
|
146
|
+
if "{!--<" in line and ">!--}" in line:
|
|
147
|
+
continue
|
|
148
|
+
|
|
149
|
+
result.append(line)
|
|
150
|
+
|
|
151
|
+
# 处理参数说明
|
|
152
|
+
processed = "\n".join(result)
|
|
153
|
+
|
|
154
|
+
# 转换 :param 格式
|
|
155
|
+
processed = re.sub(
|
|
156
|
+
r":param (\w+):\s*\[([^\]]+)\]\s*(.*)",
|
|
157
|
+
r"- **\1** (`\2`): \3",
|
|
158
|
+
processed
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# 转换 :return 格式(单行)
|
|
162
|
+
processed = re.sub(
|
|
163
|
+
r":return:\s*\[([^\]]+)\]\s*(.*)",
|
|
164
|
+
r"**返回值** (`\1`): \2",
|
|
165
|
+
processed
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# 转换 :raises 格式
|
|
169
|
+
processed = re.sub(
|
|
170
|
+
r":raises (\w+):\s*(.*)",
|
|
171
|
+
r"**异常**: `\1` - \2",
|
|
172
|
+
processed
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# 转换 :example 格式(支持多行,以 >>> 开头的行)
|
|
176
|
+
example_pattern = r":example:\s*\n((?:>>>.*(?:\n|$))+)"
|
|
177
|
+
processed = re.sub(
|
|
178
|
+
example_pattern,
|
|
179
|
+
lambda m: f"\n**示例**:\n```python\n{m.group(1).strip()}\n```\n",
|
|
180
|
+
processed,
|
|
181
|
+
flags=re.DOTALL
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# 清理多余的空行
|
|
185
|
+
processed = re.sub(r"\n{3,}", "\n\n", processed.strip())
|
|
186
|
+
|
|
187
|
+
return processed
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def parse_python_file(file_path: str) -> Tuple[Optional[str], List[Dict], List[Dict]]:
|
|
191
|
+
"""
|
|
192
|
+
解析Python文件,提取模块文档、类和函数信息
|
|
193
|
+
|
|
194
|
+
:param file_path: Python文件路径
|
|
195
|
+
:return: (模块文档, 类列表, 函数列表)
|
|
196
|
+
"""
|
|
197
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
198
|
+
source = f.read()
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
module = ast.parse(source)
|
|
202
|
+
except SyntaxError:
|
|
203
|
+
print(f"语法错误,跳过文件: {file_path}")
|
|
204
|
+
return None, [], []
|
|
205
|
+
|
|
206
|
+
# 提取模块文档
|
|
207
|
+
module_doc = ast.get_docstring(module)
|
|
208
|
+
|
|
209
|
+
classes = []
|
|
210
|
+
functions = []
|
|
211
|
+
|
|
212
|
+
# 遍历AST节点
|
|
213
|
+
for node in module.body:
|
|
214
|
+
# 处理类定义
|
|
215
|
+
if isinstance(node, ast.ClassDef):
|
|
216
|
+
class_doc = ast.get_docstring(node)
|
|
217
|
+
|
|
218
|
+
methods = []
|
|
219
|
+
# 提取类方法
|
|
220
|
+
for item in node.body:
|
|
221
|
+
if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
222
|
+
method_doc = ast.get_docstring(item)
|
|
223
|
+
|
|
224
|
+
if method_doc: # 只有方法有文档才添加
|
|
225
|
+
# 获取函数签名
|
|
226
|
+
args = []
|
|
227
|
+
defaults = dict(zip(
|
|
228
|
+
[arg.arg for arg in item.args.args][-len(item.args.defaults):],
|
|
229
|
+
item.args.defaults
|
|
230
|
+
)) if item.args.defaults else {}
|
|
231
|
+
|
|
232
|
+
for arg in item.args.args:
|
|
233
|
+
if arg.arg == "self" or arg.arg == "cls":
|
|
234
|
+
continue
|
|
235
|
+
arg_str = arg.arg
|
|
236
|
+
if arg.annotation:
|
|
237
|
+
arg_str += f": {ast.unparse(arg.annotation)}"
|
|
238
|
+
if arg.arg in defaults:
|
|
239
|
+
default_val = ast.unparse(defaults[arg.arg])
|
|
240
|
+
arg_str += f" = {default_val}"
|
|
241
|
+
args.append(arg_str)
|
|
242
|
+
|
|
243
|
+
signature = f"{item.name}({', '.join(args)})"
|
|
244
|
+
if isinstance(item, ast.AsyncFunctionDef):
|
|
245
|
+
signature = f"async {signature}"
|
|
246
|
+
|
|
247
|
+
methods.append({
|
|
248
|
+
"name": item.name,
|
|
249
|
+
"signature": signature,
|
|
250
|
+
"doc": method_doc,
|
|
251
|
+
"is_async": isinstance(item, ast.AsyncFunctionDef)
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
# 获取类签名
|
|
255
|
+
bases = [ast.unparse(base) for base in node.bases] if node.bases else []
|
|
256
|
+
class_signature = f"class {node.name}({', '.join(bases)})" if bases else f"class {node.name}"
|
|
257
|
+
|
|
258
|
+
# 只有类有文档或者有方法时才添加类
|
|
259
|
+
if class_doc or methods:
|
|
260
|
+
classes.append({
|
|
261
|
+
"name": node.name,
|
|
262
|
+
"signature": class_signature,
|
|
263
|
+
"doc": class_doc,
|
|
264
|
+
"methods": methods
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
# 处理函数定义
|
|
268
|
+
elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
269
|
+
func_doc = ast.get_docstring(node)
|
|
270
|
+
|
|
271
|
+
if func_doc:
|
|
272
|
+
# 获取函数签名
|
|
273
|
+
args = []
|
|
274
|
+
defaults = dict(zip(
|
|
275
|
+
[arg.arg for arg in node.args.args][-len(node.args.defaults):],
|
|
276
|
+
node.args.defaults
|
|
277
|
+
)) if node.args.defaults else {}
|
|
278
|
+
|
|
279
|
+
for arg in node.args.args:
|
|
280
|
+
arg_str = arg.arg
|
|
281
|
+
if arg.annotation:
|
|
282
|
+
arg_str += f": {ast.unparse(arg.annotation)}"
|
|
283
|
+
if arg.arg in defaults:
|
|
284
|
+
default_val = ast.unparse(defaults[arg.arg])
|
|
285
|
+
arg_str += f" = {default_val}"
|
|
286
|
+
args.append(arg_str)
|
|
287
|
+
|
|
288
|
+
signature = f"{node.name}({', '.join(args)})"
|
|
289
|
+
if isinstance(node, ast.AsyncFunctionDef):
|
|
290
|
+
signature = f"async {signature}"
|
|
291
|
+
|
|
292
|
+
functions.append({
|
|
293
|
+
"name": node.name,
|
|
294
|
+
"signature": signature,
|
|
295
|
+
"doc": func_doc,
|
|
296
|
+
"is_async": isinstance(node, ast.AsyncFunctionDef)
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
return module_doc, classes, functions
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def generate_markdown(module_path: str, module_doc: Optional[str],
|
|
303
|
+
classes: List[Dict], functions: List[Dict]) -> str:
|
|
304
|
+
"""
|
|
305
|
+
生成Markdown格式API文档
|
|
306
|
+
|
|
307
|
+
:param module_path: 模块路径(点分隔)
|
|
308
|
+
:param module_doc: 模块文档
|
|
309
|
+
:param classes: 类信息列表
|
|
310
|
+
:param functions: 函数信息列表
|
|
311
|
+
:return: Markdown格式的文档字符串
|
|
312
|
+
"""
|
|
313
|
+
content = []
|
|
314
|
+
|
|
315
|
+
# 处理模块文档
|
|
316
|
+
processed_module_doc = process_docstring_for_markdown(module_doc) if module_doc else None
|
|
317
|
+
|
|
318
|
+
# 文档头部
|
|
319
|
+
content.append(f"""# `{module_path}` 模块
|
|
320
|
+
|
|
321
|
+
> 最后更新:{format_timestamp()}
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 模块概述
|
|
326
|
+
|
|
327
|
+
""")
|
|
328
|
+
|
|
329
|
+
# 模块文档
|
|
330
|
+
if processed_module_doc:
|
|
331
|
+
content.append(f"{processed_module_doc}\n\n---\n")
|
|
332
|
+
else:
|
|
333
|
+
content.append("该模块暂无概述信息。\n\n---\n")
|
|
334
|
+
|
|
335
|
+
# 函数部分
|
|
336
|
+
if functions:
|
|
337
|
+
content.append("## 函数列表\n\n")
|
|
338
|
+
for func in functions:
|
|
339
|
+
async_marker = "async " if func["is_async"] else ""
|
|
340
|
+
processed_doc = process_docstring_for_markdown(func["doc"])
|
|
341
|
+
|
|
342
|
+
content.append(f"""### `{async_marker}{func['signature']}`
|
|
343
|
+
|
|
344
|
+
{processed_doc}
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
""")
|
|
349
|
+
|
|
350
|
+
# 类部分
|
|
351
|
+
if classes:
|
|
352
|
+
content.append("## 类列表\n\n")
|
|
353
|
+
for cls in classes:
|
|
354
|
+
processed_class_doc = process_docstring_for_markdown(cls["doc"]) if cls["doc"] else None
|
|
355
|
+
class_doc = processed_class_doc if processed_class_doc else f"{cls['name']} 类提供相关功能。"
|
|
356
|
+
|
|
357
|
+
content.append(f"""### `{cls['signature']}`
|
|
358
|
+
|
|
359
|
+
{class_doc}
|
|
360
|
+
|
|
361
|
+
""")
|
|
362
|
+
|
|
363
|
+
# 类方法
|
|
364
|
+
if cls["methods"]:
|
|
365
|
+
content.append("#### 方法列表\n\n")
|
|
366
|
+
for method in cls["methods"]:
|
|
367
|
+
async_marker = "async " if method["is_async"] else ""
|
|
368
|
+
processed_doc = process_docstring_for_markdown(method["doc"])
|
|
369
|
+
|
|
370
|
+
content.append(f"""##### `{async_marker}{method['signature']}`
|
|
371
|
+
|
|
372
|
+
{processed_doc}
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
""")
|
|
377
|
+
|
|
378
|
+
return "\n".join(content)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def generate_index_markdown(modules_info: Dict[str, Dict]) -> str:
|
|
382
|
+
"""
|
|
383
|
+
生成API文档索引页
|
|
384
|
+
|
|
385
|
+
:param modules_info: 模块信息字典
|
|
386
|
+
:return: Markdown格式的索引文档字符串
|
|
387
|
+
"""
|
|
388
|
+
content = []
|
|
389
|
+
|
|
390
|
+
# 统计信息(包括类的方法)
|
|
391
|
+
total_modules = len(modules_info)
|
|
392
|
+
total_classes = sum(len(info.get('classes', [])) for info in modules_info.values())
|
|
393
|
+
total_functions = sum(len(info.get('functions', [])) for info in modules_info.values())
|
|
394
|
+
# 统计所有类的方法
|
|
395
|
+
total_methods = sum(sum(len(cls.get('methods', [])) for cls in info.get('classes', [])) for info in modules_info.values())
|
|
396
|
+
|
|
397
|
+
content.append(f"""# ErisPulse API 文档
|
|
398
|
+
|
|
399
|
+
> 最后更新:{format_timestamp()}
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 概述
|
|
404
|
+
|
|
405
|
+
本文档包含 ErisPulse SDK 的所有 API 参考文档。
|
|
406
|
+
|
|
407
|
+
- **模块总数**: {total_modules}
|
|
408
|
+
- **类总数**: {total_classes}
|
|
409
|
+
- **函数总数**: {total_functions}
|
|
410
|
+
- **方法总数**: {total_methods}
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## 模块列表
|
|
415
|
+
|
|
416
|
+
""")
|
|
417
|
+
|
|
418
|
+
# 按模块路径排序
|
|
419
|
+
sorted_modules = sorted(modules_info.keys())
|
|
420
|
+
|
|
421
|
+
for module_path in sorted_modules:
|
|
422
|
+
info = modules_info[module_path]
|
|
423
|
+
classes = info.get('classes', [])
|
|
424
|
+
functions = info.get('functions', [])
|
|
425
|
+
|
|
426
|
+
# 计算类的方法总数
|
|
427
|
+
methods_count = sum(len(cls.get('methods', [])) for cls in classes)
|
|
428
|
+
|
|
429
|
+
# 计算相对路径
|
|
430
|
+
md_path = module_path.replace('.', '/') + '.md'
|
|
431
|
+
|
|
432
|
+
# 统计标识
|
|
433
|
+
badges = []
|
|
434
|
+
if classes:
|
|
435
|
+
badges.append(f"📦 {len(classes)} 个类")
|
|
436
|
+
if methods_count > 0:
|
|
437
|
+
badges.append(f"🔧 {methods_count} 个方法")
|
|
438
|
+
if functions:
|
|
439
|
+
badges.append(f"⚙️ {len(functions)} 个函数")
|
|
440
|
+
badge_str = ' | '.join(badges) if badges else "📄 模块文档"
|
|
441
|
+
|
|
442
|
+
content.append(f"""### [{module_path}]({md_path})
|
|
443
|
+
|
|
444
|
+
{badge_str}
|
|
445
|
+
|
|
446
|
+
""")
|
|
447
|
+
|
|
448
|
+
return "\n".join(content)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def generate_api_docs(src_dir: str, output_dir: str) -> Dict[str, Dict]:
|
|
452
|
+
"""
|
|
453
|
+
生成API文档
|
|
454
|
+
|
|
455
|
+
:param src_dir: 源代码目录
|
|
456
|
+
:param output_dir: Markdown输出目录
|
|
457
|
+
:return: 模块信息字典
|
|
458
|
+
"""
|
|
459
|
+
# 确保输出目录存在
|
|
460
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
461
|
+
|
|
462
|
+
modules_info = {}
|
|
463
|
+
|
|
464
|
+
# 遍历源代码目录
|
|
465
|
+
for root, _, files in os.walk(src_dir):
|
|
466
|
+
for file in files:
|
|
467
|
+
if file.endswith(".py"):
|
|
468
|
+
file_path = os.path.join(root, file)
|
|
469
|
+
|
|
470
|
+
# 计算模块路径
|
|
471
|
+
rel_path = os.path.relpath(file_path, src_dir)
|
|
472
|
+
module_path = rel_path.replace(".py", "").replace(os.sep, ".")
|
|
473
|
+
|
|
474
|
+
# 解析Python文件
|
|
475
|
+
module_doc, classes, functions = parse_python_file(file_path)
|
|
476
|
+
|
|
477
|
+
# 跳过没有文档的文件
|
|
478
|
+
if not module_doc and not classes and not functions:
|
|
479
|
+
continue
|
|
480
|
+
|
|
481
|
+
# 保存模块信息
|
|
482
|
+
modules_info[module_path] = {
|
|
483
|
+
"classes": classes,
|
|
484
|
+
"functions": functions
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
# 生成Markdown(使用增量更新)
|
|
488
|
+
md_content = generate_markdown(module_path, module_doc, classes, functions)
|
|
489
|
+
md_output_path = os.path.join(output_dir, f"{module_path.replace('.', '/')}.md")
|
|
490
|
+
os.makedirs(os.path.dirname(md_output_path), exist_ok=True)
|
|
491
|
+
|
|
492
|
+
if should_update_file(md_output_path, md_content):
|
|
493
|
+
with open(md_output_path, "w", encoding="utf-8") as f:
|
|
494
|
+
f.write(md_content)
|
|
495
|
+
print(f"已生成Markdown: {md_output_path}")
|
|
496
|
+
else:
|
|
497
|
+
print(f"Markdown未变化,跳过: {md_output_path}")
|
|
498
|
+
|
|
499
|
+
# 生成索引页
|
|
500
|
+
if modules_info:
|
|
501
|
+
index_content = generate_index_markdown(modules_info)
|
|
502
|
+
index_path = os.path.join(output_dir, "README.md")
|
|
503
|
+
|
|
504
|
+
if should_update_file(index_path, index_content):
|
|
505
|
+
with open(index_path, "w", encoding="utf-8") as f:
|
|
506
|
+
f.write(index_content)
|
|
507
|
+
print(f"已生成索引: {index_path}")
|
|
508
|
+
else:
|
|
509
|
+
print(f"索引未变化,跳过: {index_path}")
|
|
510
|
+
|
|
511
|
+
return modules_info
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
if __name__ == "__main__":
|
|
515
|
+
parser = argparse.ArgumentParser(
|
|
516
|
+
description="ErisPulse API文档生成器 v9.0",
|
|
517
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
518
|
+
epilog="""
|
|
519
|
+
示例:
|
|
520
|
+
# 使用默认设置
|
|
521
|
+
python .github/tools/update-api-docs.py
|
|
522
|
+
|
|
523
|
+
# 自定义源目录和输出目录
|
|
524
|
+
python .github/tools/update-api-docs.py --src src --output docs/api
|
|
525
|
+
"""
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
parser.add_argument("--src", default="src", help="源代码目录 (默认: src)")
|
|
529
|
+
parser.add_argument("--output", default="docs/api", help="Markdown输出目录 (默认: docs/api)")
|
|
530
|
+
parser.add_argument("--version", action="version", version="API文档生成器 v9.0")
|
|
531
|
+
|
|
532
|
+
args = parser.parse_args()
|
|
533
|
+
|
|
534
|
+
print(f"""╔══════════════════════════════════════════╗
|
|
535
|
+
║ ErisPulse API 文档生成器 v9.0 ║
|
|
536
|
+
╚══════════════════════════════════════════╝
|
|
537
|
+
|
|
538
|
+
源代码目录: {args.src}
|
|
539
|
+
输出目录: {args.output}
|
|
540
|
+
|
|
541
|
+
正在生成API文档...
|
|
542
|
+
""")
|
|
543
|
+
|
|
544
|
+
modules_info = generate_api_docs(args.src, args.output)
|
|
545
|
+
|
|
546
|
+
total_modules = len(modules_info)
|
|
547
|
+
total_classes = sum(len(info.get('classes', [])) for info in modules_info.values())
|
|
548
|
+
total_functions = sum(len(info.get('functions', [])) for info in modules_info.values())
|
|
549
|
+
total_methods = sum(sum(len(cls.get('methods', [])) for cls in info.get('classes', [])) for info in modules_info.values())
|
|
550
|
+
|
|
551
|
+
print("\n" + "="*50)
|
|
552
|
+
print(f"API文档生成完成!")
|
|
553
|
+
print(f" 模块总数: {total_modules}")
|
|
554
|
+
print(f" 类总数: {total_classes}")
|
|
555
|
+
print(f" 方法总数: {total_methods}")
|
|
556
|
+
print(f" 函数总数: {total_functions}")
|
|
557
|
+
print("="*50)
|
|
@@ -32,6 +32,32 @@
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
---
|
|
35
|
+
## [2.3.3-dev.0] - 2026/01/17
|
|
36
|
+
> 开发版本
|
|
37
|
+
|
|
38
|
+
### 新增
|
|
39
|
+
- @wsu2059q
|
|
40
|
+
- `Event` 模块新增 Event 包装类,提供便捷的事件访问方法:
|
|
41
|
+
- Event 类继承 dict,保持完全的字典兼容性,支持点式访问事件字段
|
|
42
|
+
- 提供核心信息获取方法:`get_id()`, `get_time()`, `get_type()`, `get_platform()`, `get_self_info()`
|
|
43
|
+
- 提供消息事件方法:`get_message()`, `get_text()`, `get_user_id()`, `get_group_id()` 及消息类型判断
|
|
44
|
+
- 提供通知和请求事件方法:`is_notice()`, `is_request()`, `get_operator_id()` 等
|
|
45
|
+
- 提供统一的 `reply()` 方法,支持通过 `method` 参数指定适配器的发送方法(Text、Image、Voice、Video、File 等)
|
|
46
|
+
- 提供 `wait_reply()` 方法,支持等待用户回复,可设置超时、验证函数和回调函数
|
|
47
|
+
- 提供命令信息和原始数据访问方法
|
|
48
|
+
- Event 对象在事件处理流程中自动创建,替换原有的 dict 对象
|
|
49
|
+
- `Event.command` 模块新增命令判断的兜底机制:
|
|
50
|
+
- 优化命令处理流程,当从 `message` 列表中提取的 text 内容没有触发命令时,会自动检查 `alt_message` 字段是否符合触发命令的逻辑
|
|
51
|
+
- 新增 `_process_text_for_command` 方法,用于统一处理文本内容的命令匹配逻辑
|
|
52
|
+
- 改进 `_handle_message` 方法,确保即使适配器的 `message` 列表有问题,只要 `alt_message` 字段正确,命令仍能正常触发
|
|
53
|
+
|
|
54
|
+
### 变更
|
|
55
|
+
- @wsu2059q
|
|
56
|
+
- 更新模块开发文档,新增 Event 包装类的详细使用说明和示例
|
|
57
|
+
- 更新示例模块,演示 Event 包装类的新功能
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
35
61
|
## [2.3.2] - 2025/01/11
|
|
36
62
|
### 新增
|
|
37
63
|
- @wsu2059q
|
|
@@ -660,4 +686,4 @@
|
|
|
660
686
|
### 修复
|
|
661
687
|
- 使用 `send = adapter.<适配器名>.To()` 直接创建发送器, 导致调用旧适配器方法而抛出异常的情况
|
|
662
688
|
|
|
663
|
-
1.x.x 版本更新日志请查看分支日志
|
|
689
|
+
1.x.x 版本更新日志请查看分支日志
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.3.dev0
|
|
4
4
|
Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
|
|
5
5
|
Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
|
|
6
6
|
License: MIT License
|
|
@@ -57,9 +57,7 @@ Requires-Dist: aiohttp
|
|
|
57
57
|
Requires-Dist: colorama
|
|
58
58
|
Requires-Dist: fastapi>=0.116.1
|
|
59
59
|
Requires-Dist: hypercorn>=0.14.0
|
|
60
|
-
Requires-Dist: keyboard
|
|
61
60
|
Requires-Dist: packaging>=25.0
|
|
62
|
-
Requires-Dist: pip
|
|
63
61
|
Requires-Dist: pydantic>=2.10.6
|
|
64
62
|
Requires-Dist: python-multipart>=0.0.20
|
|
65
63
|
Requires-Dist: rich
|