ErisPulse 2.8.5__tar.gz → 2.9.0.dev1__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.8.5 → erispulse-2.9.0.dev1}/.gitignore +2 -1
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/PKG-INFO +4 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/pyproject.toml +20 -4
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/create.py +2 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/run.py +9 -4
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/constants.py +11 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/package_manager.py +7 -12
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/__init__.py +8 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/adapter.py +62 -656
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Bases/api_dsl.py +698 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/config_schema.py +215 -17
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Bases/model.py +1167 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/module.py +8 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/send_rules.py +8 -2
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/sql_base.py +175 -13
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/__init__.py +14 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/base.py +76 -7
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/command.py +609 -22
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/command_args.py +539 -0
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/conversation.py +773 -0
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/governance.py +474 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/interaction.py +3 -2
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/message.py +299 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/overrides.py +10 -8
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/throttle.py +180 -0
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/trace.py +134 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/wrapper.py +54 -748
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/__init__.py +19 -1
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/adapter.py +206 -94
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/client.py +24 -19
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/config.py +49 -24
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/constants.py +74 -7
- erispulse-2.9.0.dev1/src/ErisPulse/Core/di.py +226 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/en.py +79 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/ja.py +79 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/ru.py +79 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/zh_cn.py +79 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/zh_tw.py +79 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/lifecycle.py +137 -70
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/logger.py +3 -3
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/master.py +1 -1
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/module.py +231 -187
- erispulse-2.9.0.dev1/src/ErisPulse/Core/ownership.py +517 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/router.py +207 -71
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/scope.py +326 -190
- erispulse-2.9.0.dev1/src/ErisPulse/Core/shadow.py +497 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/mysql.py +23 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/postgres.py +19 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/sqlite.py +11 -2
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/text_match.py +1 -1
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/transcript.py +55 -4
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/module.py +222 -1
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/__init__.py +8 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/diagnostics.py +126 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/exceptions.py +9 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/file_watcher.py +29 -2
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/plugin_reload.py +3 -2
- erispulse-2.9.0.dev1/src/ErisPulse/runtime/proactive_gc.py +292 -0
- erispulse-2.9.0.dev1/src/ErisPulse/runtime/sdk_initializer.py +708 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/tasks.py +8 -2
- erispulse-2.9.0.dev1/src/ErisPulse/runtime/troubleshoot.py +233 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/sdk.py +35 -921
- erispulse-2.8.5/src/ErisPulse/Core/Event/message.py +0 -197
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/LICENSE +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/README.pypi.md +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/config.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/doctor.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/types.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/version.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/en.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/ja.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/ru.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/config_wizard.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/scaffold_text.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/client.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/converter.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/errors.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/i18n_schema.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/kv_builder.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/router.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/send_builder.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/websocket.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/bases/finder.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/adapter.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/plugin_folder.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/strict.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/example_config.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/frame_config.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/memory.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/owner_cleanup.py +0 -0
- {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0-dev.1
|
|
4
4
|
Summary: Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署
|
|
5
5
|
Project-URL: Homepage, https://github.com/ErisPulse/ErisPulse
|
|
6
6
|
Project-URL: Documentation, https://www.erisdev.com#docs
|
|
@@ -24,6 +24,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.11
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.12
|
|
26
26
|
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
27
28
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
28
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
29
30
|
Classifier: Typing :: Typed
|
|
@@ -33,7 +34,7 @@ Requires-Dist: aiosqlite>=0.20.0
|
|
|
33
34
|
Requires-Dist: fastapi>=0.116.1
|
|
34
35
|
Requires-Dist: rich>=13.0.0
|
|
35
36
|
Requires-Dist: tomlkit>=0.15.1
|
|
36
|
-
Requires-Dist: uvicorn>=0.
|
|
37
|
+
Requires-Dist: uvicorn>=0.35.0
|
|
37
38
|
Requires-Dist: websockets>=12.0
|
|
38
39
|
Provides-Extra: mysql
|
|
39
40
|
Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
|
|
@@ -42,9 +43,9 @@ Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
|
|
|
42
43
|
Provides-Extra: test
|
|
43
44
|
Requires-Dist: httpx>=0.24.0; extra == 'test'
|
|
44
45
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
|
|
45
|
-
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
|
|
46
46
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
47
47
|
Requires-Dist: pytest-mock>=3.10.0; extra == 'test'
|
|
48
|
+
Requires-Dist: pytest-timeout>=2.1.0; extra == 'test'
|
|
48
49
|
Requires-Dist: pytest-xdist>=3.0.0; extra == 'test'
|
|
49
50
|
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
|
50
51
|
Description-Content-Type: text/markdown
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ErisPulse"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.9.0-dev.1"
|
|
8
8
|
description = "Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署"
|
|
9
9
|
readme = "README.pypi.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -51,6 +51,7 @@ classifiers = [
|
|
|
51
51
|
"Programming Language :: Python :: 3.11",
|
|
52
52
|
"Programming Language :: Python :: 3.12",
|
|
53
53
|
"Programming Language :: Python :: 3.13",
|
|
54
|
+
"Programming Language :: Python :: 3.14",
|
|
54
55
|
"Programming Language :: Python :: 3 :: Only",
|
|
55
56
|
"Operating System :: OS Independent",
|
|
56
57
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
@@ -66,7 +67,7 @@ dependencies = [
|
|
|
66
67
|
"websockets>=12.0",
|
|
67
68
|
"aiohttp>=3.9.0",
|
|
68
69
|
"fastapi>=0.116.1",
|
|
69
|
-
"uvicorn>=0.
|
|
70
|
+
"uvicorn>=0.35.0",
|
|
70
71
|
# storage 相关(默认 SQLite 后端异步驱动,开箱即用)
|
|
71
72
|
"aiosqlite>=0.20.0",
|
|
72
73
|
]
|
|
@@ -92,12 +93,14 @@ test = [
|
|
|
92
93
|
"pytest-cov>=4.0.0",
|
|
93
94
|
"pytest-asyncio>=0.21.0",
|
|
94
95
|
"pytest-xdist>=3.0.0",
|
|
96
|
+
"pytest-timeout>=2.1.0",
|
|
95
97
|
"pytest-mock>=3.10.0",
|
|
96
|
-
"pytest-benchmark>=4.0.0",
|
|
97
98
|
"httpx>=0.24.0",
|
|
98
99
|
]
|
|
99
100
|
|
|
100
101
|
[dependency-groups]
|
|
102
|
+
# 测试依赖统一维护于 [project.optional-dependencies].test(公开 extras,
|
|
103
|
+
# 生态可 pip install ErisPulse[test]);此处的 test 组已删除以免双处漂移。
|
|
101
104
|
dev = [
|
|
102
105
|
"pyclean>=3.6.0",
|
|
103
106
|
"ruff>=0.1.7",
|
|
@@ -105,6 +108,9 @@ dev = [
|
|
|
105
108
|
"typing_extensions>=4.7.0; python_version < '3.11'",
|
|
106
109
|
]
|
|
107
110
|
|
|
111
|
+
[tool.uv]
|
|
112
|
+
default-groups = ["dev"]
|
|
113
|
+
|
|
108
114
|
[project.scripts]
|
|
109
115
|
ep-init = "ErisPulse.__init__:init_sync"
|
|
110
116
|
epsdk = "ErisPulse.__main__:main"
|
|
@@ -130,7 +136,7 @@ include = [
|
|
|
130
136
|
target-version = "py310"
|
|
131
137
|
line-length = 120
|
|
132
138
|
|
|
133
|
-
include = ["src/**/*.py", "tests/**/*.py"]
|
|
139
|
+
include = ["src/**/*.py", "tests/**/*.py", "scripts/**/*.py", "examples/**/*.py"]
|
|
134
140
|
|
|
135
141
|
extend-exclude = [
|
|
136
142
|
"__pycache__",
|
|
@@ -168,6 +174,7 @@ ignore = [
|
|
|
168
174
|
"RUF003", # ambiguous-unicode-character-comment
|
|
169
175
|
|
|
170
176
|
# 框架/异步代码风格性规则(强行修会破坏 API 或语义)
|
|
177
|
+
"B008", # function-call-in-default-argument —— 依赖注入(Depends)声明的标准形态,DI 框架惯例豁免
|
|
171
178
|
"PLC0415", # import-outside-top-level —— 异步框架中 lazy import 是常用且必要的模式
|
|
172
179
|
"PLR0911", # too-many-return-statements
|
|
173
180
|
"PLR0912", # too-many-branches
|
|
@@ -208,6 +215,13 @@ ignore = [
|
|
|
208
215
|
|
|
209
216
|
[tool.ruff.lint.per-file-ignores]
|
|
210
217
|
"__init__.py" = ["F401", "PLC0415", "I001"] # 导出式 __init__ 经常按需导入
|
|
218
|
+
# 旧版生成/翻译脚本:存量风格债渐进收编(新脚本 check_i18n_locales/check_docs_links/
|
|
219
|
+
# release_check/_common 已全净)。TODO: 逐步修复后移除本段。
|
|
220
|
+
"scripts/tools/translate-docs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "UP008", "A001", "SIM"]
|
|
221
|
+
"scripts/tools/check-translation.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "SIM"]
|
|
222
|
+
"scripts/tools/generate-api-docs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "A001", "SIM", "W29", "E501"]
|
|
223
|
+
"scripts/tools/generate-docs-index.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "RUF015", "SIM"]
|
|
224
|
+
"scripts/tools/generate-type-stubs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "ANN", "A001", "PLW0603", "SIM", "W29"]
|
|
211
225
|
"tests/**/*.py" = [
|
|
212
226
|
# 断言/夹具相关(测试代码天然模式)
|
|
213
227
|
"S101", "PLR2004", "SLF001", "ARG", "ANN", "PTH",
|
|
@@ -282,6 +296,8 @@ python_classes = "Test*"
|
|
|
282
296
|
python_functions = "test_*"
|
|
283
297
|
minversion = "7.0"
|
|
284
298
|
addopts = [
|
|
299
|
+
"--timeout=120",
|
|
300
|
+
"--timeout-method=thread",
|
|
285
301
|
"-v",
|
|
286
302
|
"--strict-markers",
|
|
287
303
|
"--strict-config",
|
|
@@ -219,6 +219,8 @@ class Main(BaseModule):
|
|
|
219
219
|
# 跨命令的用户黑白名单用覆写系统 ACL
|
|
220
220
|
# (ErisPulse.event.overrides.acl 或 overrides.acl.set(name, allow/deny),命令名支持 glob);
|
|
221
221
|
# 模块级可用性 / 事件准入 / 出站限制由作用域 scope 管理(用户可控)
|
|
222
|
+
# 命令支持声明式参数与选项(args= / options=):框架自动解析并按名注入处理器参数,
|
|
223
|
+
# 用户输入错误自动回复本地化提示与用法(类型:str/int/float/bool/literal/duration/rest)
|
|
222
224
|
@command(\"hello\", help=i18n.t(\"module.{name}.command.hello.help\"))
|
|
223
225
|
async def hello_command(event: Event):
|
|
224
226
|
await event.reply(i18n.t(\"module.{name}.command.hello.reply\"))
|
|
@@ -19,7 +19,13 @@ from rich.panel import Panel
|
|
|
19
19
|
from ...runtime.file_watcher import FileSystemEventHandler, PollingObserver
|
|
20
20
|
from ..base import Command
|
|
21
21
|
from ..console import console
|
|
22
|
-
from ..constants import
|
|
22
|
+
from ..constants import (
|
|
23
|
+
ENV_SUPERVISED,
|
|
24
|
+
HARD_RESTART_EXIT_CODE,
|
|
25
|
+
RUN_CRASH_BACKOFF_MAX_SECS,
|
|
26
|
+
RUN_CRASH_BACKOFF_PER_CRASH_SECS,
|
|
27
|
+
RUN_RESTART_PAUSE_SECS,
|
|
28
|
+
)
|
|
23
29
|
from ..i18n import i18n
|
|
24
30
|
from ..utils.package_manager import (
|
|
25
31
|
resolve_target_python,
|
|
@@ -152,7 +158,6 @@ class RunCommand(Command):
|
|
|
152
158
|
self._run_internal(reload_mode)
|
|
153
159
|
|
|
154
160
|
_RESTART_EXIT_CODE = HARD_RESTART_EXIT_CODE
|
|
155
|
-
_MAX_CRASH_BACKOFF = 60.0
|
|
156
161
|
|
|
157
162
|
def _run_internal(self, reload_mode: bool):
|
|
158
163
|
"""
|
|
@@ -213,7 +218,7 @@ class RunCommand(Command):
|
|
|
213
218
|
if process.returncode == self._RESTART_EXIT_CODE:
|
|
214
219
|
console.print(f"[info]{i18n.t('cli.run.restart_request')}[/]")
|
|
215
220
|
crash_count = 0
|
|
216
|
-
time.sleep(
|
|
221
|
+
time.sleep(RUN_RESTART_PAUSE_SECS)
|
|
217
222
|
continue
|
|
218
223
|
|
|
219
224
|
if process.returncode == 0:
|
|
@@ -224,7 +229,7 @@ class RunCommand(Command):
|
|
|
224
229
|
# 非硬重启/非正常退出码:模块/适配器内部错误导致子进程异常终止
|
|
225
230
|
# 不退出主进程,等待后自动重试
|
|
226
231
|
crash_count += 1
|
|
227
|
-
backoff = min(
|
|
232
|
+
backoff = min(RUN_CRASH_BACKOFF_MAX_SECS, RUN_CRASH_BACKOFF_PER_CRASH_SECS * crash_count)
|
|
228
233
|
console.print(
|
|
229
234
|
f"[warning]{i18n.t('cli.run.process_crashed', code=process.returncode)}[/]"
|
|
230
235
|
)
|
|
@@ -43,8 +43,19 @@ ADAPTER_ENTRY_POINT_GROUP: str = "erispulse.adapter"
|
|
|
43
43
|
# PyPI JSON API URL 模板(仅 CLI 做包查询 / 自更新检查时使用)。
|
|
44
44
|
PYPI_PACKAGE_JSON_URL_TEMPLATE: str = "https://pypi.org/pypi/{package}/json"
|
|
45
45
|
|
|
46
|
+
# run 命令子进程监督的退避参数。
|
|
47
|
+
# 使用位置: CLI/commands/run.py -> 监督循环。
|
|
48
|
+
# 修改影响: 每次崩溃的重试间隔 = min(MAX, PER_CRASH x 崩溃次数);
|
|
49
|
+
# RESTART_PAUSE 为硬重启请求后的短暂停顿(让端口等资源释放)。
|
|
50
|
+
RUN_CRASH_BACKOFF_MAX_SECS: float = 60.0
|
|
51
|
+
RUN_CRASH_BACKOFF_PER_CRASH_SECS: float = 3.0
|
|
52
|
+
RUN_RESTART_PAUSE_SECS: float = 0.5
|
|
53
|
+
|
|
46
54
|
__all__ = [
|
|
47
55
|
"ADAPTER_ENTRY_POINT_GROUP",
|
|
56
|
+
"RUN_CRASH_BACKOFF_MAX_SECS",
|
|
57
|
+
"RUN_CRASH_BACKOFF_PER_CRASH_SECS",
|
|
58
|
+
"RUN_RESTART_PAUSE_SECS",
|
|
48
59
|
"ENV_SUPERVISED",
|
|
49
60
|
"HARD_RESTART_EXIT_CODE",
|
|
50
61
|
"MODULE_ENTRY_POINT_GROUP",
|
|
@@ -1711,15 +1711,18 @@ def append_pyproject_dependencies(project_dir: Path, packages: "list[str]") -> b
|
|
|
1711
1711
|
:return: 是否成功(pyproject 不存在 / 解析失败返回 False)
|
|
1712
1712
|
"""
|
|
1713
1713
|
import tomlkit
|
|
1714
|
-
import tomllib
|
|
1715
1714
|
|
|
1716
1715
|
pyproject = Path(project_dir) / "pyproject.toml"
|
|
1717
1716
|
if not pyproject.exists():
|
|
1718
1717
|
return False
|
|
1719
1718
|
try:
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1719
|
+
# tomlkit 解析保留注释与格式(其文档为 dict 子类,get 行为与
|
|
1720
|
+
# tomllib 一致;不用 tomllib——它是 Python 3.11+ 标准库)
|
|
1721
|
+
doc_kit = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
|
|
1722
|
+
proj = doc_kit.get("project")
|
|
1723
|
+
if proj is None:
|
|
1724
|
+
return False
|
|
1725
|
+
deps: list = proj.get("dependencies", [])
|
|
1723
1726
|
added = False
|
|
1724
1727
|
for pkg in packages:
|
|
1725
1728
|
if not any(str(d).split("[;")[0].split("==")[0].split(">=")[0].strip().lower() == pkg.lower() for d in deps):
|
|
@@ -1727,11 +1730,6 @@ def append_pyproject_dependencies(project_dir: Path, packages: "list[str]") -> b
|
|
|
1727
1730
|
added = True
|
|
1728
1731
|
if not added:
|
|
1729
1732
|
return True
|
|
1730
|
-
# tomllib 读的是普通 dict——用 tomlkit 重新解析原文件以保留格式后写回
|
|
1731
|
-
doc_kit = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
|
|
1732
|
-
proj = doc_kit.get("project")
|
|
1733
|
-
if proj is None:
|
|
1734
|
-
return False
|
|
1735
1733
|
proj["dependencies"] = deps
|
|
1736
1734
|
pyproject.write_text(tomlkit.dumps(doc_kit), encoding="utf-8")
|
|
1737
1735
|
return True
|
|
@@ -1848,8 +1846,6 @@ def warn_if_uv_isolated() -> bool:
|
|
|
1848
1846
|
|
|
1849
1847
|
:return: 是否处于隔离场景(True = 已输出警告)
|
|
1850
1848
|
"""
|
|
1851
|
-
import tomllib
|
|
1852
|
-
|
|
1853
1849
|
if "UV" not in os.environ:
|
|
1854
1850
|
return False
|
|
1855
1851
|
if Path("pyproject.toml").exists():
|
|
@@ -1859,7 +1855,6 @@ def warn_if_uv_isolated() -> bool:
|
|
|
1859
1855
|
+ i18n.t("cli.uv.isolated_warning")
|
|
1860
1856
|
+ "[/]"
|
|
1861
1857
|
)
|
|
1862
|
-
_ = tomllib # 保留显式依赖提示位(pyproject 探测未来可深化)
|
|
1863
1858
|
return True
|
|
1864
1859
|
|
|
1865
1860
|
|
|
@@ -44,6 +44,7 @@ from .config_schema import (
|
|
|
44
44
|
BotAccountConfig,
|
|
45
45
|
I18nConfig,
|
|
46
46
|
)
|
|
47
|
+
from .model import BaseModel, ColumnExpr, Condition, Field, Model, QuerySet, relationship
|
|
47
48
|
from .i18n_schema import (
|
|
48
49
|
BaseI18n,
|
|
49
50
|
I18nKey,
|
|
@@ -63,6 +64,7 @@ __all__ = [
|
|
|
63
64
|
"BaseHttpResponse",
|
|
64
65
|
# i18n 键声明 Schema 基类(命名对齐 BaseConfig)
|
|
65
66
|
"BaseI18n",
|
|
67
|
+
"BaseModel",
|
|
66
68
|
"BaseModule",
|
|
67
69
|
"BaseQueryBuilder",
|
|
68
70
|
"BaseStorage",
|
|
@@ -71,7 +73,10 @@ __all__ = [
|
|
|
71
73
|
"ClientConnectionError",
|
|
72
74
|
"ClientError",
|
|
73
75
|
"ClientTimeoutError",
|
|
76
|
+
"Condition",
|
|
77
|
+
"ColumnExpr",
|
|
74
78
|
"ErisPulseError",
|
|
79
|
+
"Field",
|
|
75
80
|
"HTTPStatusError",
|
|
76
81
|
"HttpRequest",
|
|
77
82
|
# i18n 配置 Schema(控制显示语言)
|
|
@@ -82,11 +87,14 @@ __all__ = [
|
|
|
82
87
|
"InteractionCancelled",
|
|
83
88
|
"InteractionError",
|
|
84
89
|
"KVQueryBuilder",
|
|
90
|
+
"Model",
|
|
85
91
|
"ModuleCallError",
|
|
86
92
|
"ModuleCallTimeoutError",
|
|
87
93
|
"ModuleError",
|
|
88
94
|
"ModuleMeta",
|
|
89
95
|
"ModuleNotAvailableError",
|
|
96
|
+
"QuerySet",
|
|
97
|
+
"relationship",
|
|
90
98
|
"RequestDSL",
|
|
91
99
|
"SendBuilder",
|
|
92
100
|
"SendContext",
|