-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin_registry.py
More file actions
66 lines (55 loc) · 2.29 KB
/
Copy pathplugin_registry.py
File metadata and controls
66 lines (55 loc) · 2.29 KB
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""v0.3 后处理插件框架。插件只接收已解析 Transaction,不进入读卡核心。"""
from __future__ import annotations
import importlib.util
import os
import traceback
import paths
_loaded = None
_errors = []
_runtime_errors = []
def plugin_dir():
d = paths.data_path("plugins")
os.makedirs(d, exist_ok=True)
return d
def discover(force=False):
global _loaded, _errors, _runtime_errors
if _loaded is not None and not force:
return _loaded
_loaded = []; _errors = []
if force:
_runtime_errors = []
for name in sorted(os.listdir(plugin_dir())):
if not name.endswith(".py") or name.startswith("_"):
continue
path = os.path.join(plugin_dir(), name)
try:
spec = importlib.util.spec_from_file_location(f"neko_plugin_{name[:-3]}", path)
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
hook = getattr(module, "postprocess", None)
if callable(hook):
_loaded.append({"name": getattr(module, "PLUGIN_NAME", name[:-3]),
"version": getattr(module, "PLUGIN_VERSION", "0"),
"path": path, "hook": hook})
except Exception:
_errors.append({"name": name, "error": traceback.format_exc(limit=3)})
return _loaded
def apply(transactions, context=None):
global _runtime_errors
result = list(transactions); errors = []
for plugin in discover():
try:
value = plugin["hook"](result, context or {})
if value is not None:
candidate = list(value)
if not all(callable(getattr(tx, "to_dict", None)) for tx in candidate):
raise TypeError("postprocess 必须返回 Transaction 序列")
result = candidate
except Exception as exc:
errors.append({"plugin": plugin["name"], "error": str(exc)})
_runtime_errors = list(errors)
return result, errors
def status():
return {"directory": plugin_dir(),
"plugins": [{k: p[k] for k in ("name", "version", "path")} for p in discover()],
"errors": list(_errors) + [{"name": e["plugin"], "error": e["error"]}
for e in _runtime_errors]}