diff options
| author | 2023-12-15 10:15:59 +0800 | |
|---|---|---|
| committer | 2023-12-15 10:15:59 +0800 | |
| commit | 5cf3a4a5ca8adc6db3e95a1cd01502b5167bb88f (patch) | |
| tree | 7ded1b558cc5c7ca0b7ac5973f447ea8c590c581 /src | |
| parent | 4dafb0f0a81255193f2a44df5d203239325e2236 (diff) | |
| parent | f7f775b4c529b1d65e55a12ee6b4e7c6c636f004 (diff) | |
| download | infini-5cf3a4a5ca8adc6db3e95a1cd01502b5167bb88f.tar.gz infini-5cf3a4a5ca8adc6db3e95a1cd01502b5167bb88f.zip | |
Merge pull request #40 from HydroRoll-Team/sourcery/pull-39
🎉 阶段性完成 (Sourcery refactored)
Diffstat (limited to 'src')
| -rw-r--r-- | src/infini/__main__.py | 56 | ||||
| -rw-r--r-- | src/infini/consts/templates.py | 74 | ||||
| -rw-r--r-- | src/infini/event.py | 30 | ||||
| -rw-r--r-- | src/infini/exceptions.py | 12 | ||||
| -rw-r--r-- | src/infini/handler.py | 47 | ||||
| -rw-r--r-- | src/infini/logging.py | 15 | ||||
| -rw-r--r-- | src/infini/matcher.py | 31 | ||||
| -rw-r--r-- | src/infini/utils/cli.py | 23 | ||||
| -rw-r--r-- | src/infini/utils/gui.py | 2 |
9 files changed, 219 insertions, 71 deletions
diff --git a/src/infini/__main__.py b/src/infini/__main__.py new file mode 100644 index 00000000..5c4dc2eb --- /dev/null +++ b/src/infini/__main__.py @@ -0,0 +1,56 @@ +from pathlib import Path +from .utils.cli import parse_args +from .consts import templates +from .logging import logger + +import os +import importlib +import sys + + +def main(): + args = parse_args() + + if args.gui: + logger.critical("选项[--gui]尚未被支持!") + sys.exit(1) + + path = Path(args.path).resolve() if args.path else Path(os.getcwd()).resolve() + + if args.operate == "new": + if path.exists() and not args.force: + logger.error("指定的文件夹已经存在!") + sys.exit(1) + + path.mkdir(parents=True, exist_ok=True) + (path / "handler.py").write_text(templates.RULE, encoding="utf-8") + (path / "event.py").write_text(templates.EVENT, encoding="utf-8") + (path / "tests.py").write_text(templates.TEST, encoding="utf-8") + + logger.success("HydroRoll 规则包模板已创建!") + + if args.operate == "test": + logger.info(f"开始测试规则包: {path.name}...") + sys.path.append(str(path)) + logger.info("初始化规则包中...") + try: + importlib.import_module("event") + importlib.import_module("handler") + except Exception as error: + if args.verbose: + logger.exception(error) + logger.critical(f"初始化规则包时出现异常: {error}") + return + try: + errors = importlib.import_module("tests").test() + except Exception as error: + if args.verbose: + logger.exception(error) + logger.critical(f"测试规则包时出现异常: {error}") + return + sys.path.remove(str(path)) + logger.info(f"测试规则包 {path.name} 出现 {len(errors)} 个异常, 测试完成.") + + +if __name__ == "__main__": + main() diff --git a/src/infini/consts/templates.py b/src/infini/consts/templates.py index e2edc2d6..d25894ae 100644 --- a/src/infini/consts/templates.py +++ b/src/infini/consts/templates.py @@ -1,69 +1,37 @@ -RULE = """from infini import Rule, Result, Dice +RULE = """from infini import Handler, Result +__handlers__ = ["HandlerRule"] -class MyRule(Rule): - \"\"\"自设规则包\"\"\" - name = "MyRule" - priority: int = 0 +class HandlerRule(Handler): + \"\"\"自设业务函数\"\"\" - def __init__(self) -> None: - \"\"\"初始化你的规则包\"\"\" + name = "MyRule" # 规则包名 + priority: int = 0 # 规则包权重 - def check(self, dice: Dice) -> Result: + def process(self, **kwargs) -> Result: \"\"\"声明规则包检定方式\"\"\" - return Result("myevent.event1", True) + return Result("event1", True) """ -EVENT = """from infini import Event +EVENT = """from infini import MessageEvent __events__ = ["MyEvent"] -class MyEvent(Event): +class MyEvent(MessageEvent): name = "event1" output = "检定成功!" """ -DICE = """from infini import Dice - -import random -import re - - -class BaseDice(Dice): - \"\"\"多面骰\"\"\" - - def __init__(self, roll_string: str = "") -> None: - self.roll_string = roll_string - self.parse() - - def parse(self) -> "Dice": - self.dices = [] - split = re.split(r"[dD]", self.roll_string) - - if split[0]: - self.a = int(split[0]) - else: - self.a = 1 - - if split[1]: - self.b = int(split[1]) - else: - self.b = 100 - - self.db = f"{self.a}D{self.b}" - self.dices += [f"D{self.b}"] * self.a - return self - - def roll(self) -> int: - self.results = [] - - for _ in range(self.a): - result = random.randint(1, self.b) - - self.results.append(result) - - self.outcome = sum(self.results) - return self.outcome -""" +TEST = """from infini.matcher import matcher, MatcherEvent + +def test(): + event = MatcherEvent("MyRule") + try: + matcher.run(event) + except Exception as error: + return [error] + finally: + return [] +"""
\ No newline at end of file diff --git a/src/infini/event.py b/src/infini/event.py index 9ce34bd9..0363ac96 100644 --- a/src/infini/event.py +++ b/src/infini/event.py @@ -1,9 +1,10 @@ +from abc import ABCMeta from .typing import Dict -from .logging import logger +from .exceptions import UnknownMessageEvent import re -__all__ = ["Event", "events"] +__all__ = ["MessageEvent", "events"] class Events: @@ -17,8 +18,7 @@ class Events: def process(self, name: str, **kwargs) -> str: if string := self._events.get(name.lower()): return self._format(string, **kwargs) - logger.warning(f"事件[{name.lower()}]不存在,将返回空字符串!") - return "" + raise UnknownMessageEvent(f"事件[{name.lower()}]不存在!") def _format(self, string: str, **kwargs): pattern = r"{(.*?)}" @@ -30,8 +30,8 @@ class Events: return string -class Event: - """事件基类""" +class MessageEvent(metaclass=ABCMeta): + """消息事件基类""" name: str output: str @@ -40,4 +40,20 @@ class Event: events.regist(cls.name, cls.output) -events = Events() +class MatcherEvent: + """Matcher 事件""" + + name: str + string: str + kwargs: dict + + def __init__(self, event_name: str, string: str | None = None, **kwargs): + self.name = event_name + self.string = string or "" + self.kwargs = kwargs + + def __repr__(self) -> str: + return f"<MatcherEvent [{self.name}]>" + + +events = Events()
\ No newline at end of file diff --git a/src/infini/exceptions.py b/src/infini/exceptions.py index 62c88fa1..e7c87b36 100644 --- a/src/infini/exceptions.py +++ b/src/infini/exceptions.py @@ -4,3 +4,15 @@ class HydroError(Exception): class RuleLoadError(HydroError): """规则导入错误""" + + +class EventError(HydroError): + """事件处理时异常""" + + +class UnknownMatcherEvent(EventError): + """未知的给入实现""" + + +class UnknownMessageEvent(EventError): + """未知的给出实现"""
\ No newline at end of file diff --git a/src/infini/handler.py b/src/infini/handler.py new file mode 100644 index 00000000..06d5c5fa --- /dev/null +++ b/src/infini/handler.py @@ -0,0 +1,47 @@ +from abc import ABCMeta, abstractmethod +from .event import MatcherEvent +from .typing import Dict + +__all__ = ["Result", "Handler"] + + +class Result(metaclass=ABCMeta): + """规则包运行结果基类""" + + event: str + status: bool + kwargs: dict = {} + + def __init__(self, event: str, status: bool, **kwargs) -> None: + self.event = event + self.status = status + self.kwargs = kwargs + + +class Handler: + """规则包业务基类""" + + name: str + priority: int = 0 + + def __init_subclass__(cls) -> None: + handlers.regist(cls.name, cls()) + + @abstractmethod + def process(self, event: MatcherEvent) -> Result: + raise NotImplementedError + + +class Handlers: + """规则包业务集合""" + + _handlers: Dict[str, Handler] = {} + + def regist(self, name: str, handler: Handler) -> None: + self._handlers[name.lower()] = handler + + def match(self, name: str) -> Handler | None: + return self._handlers.get(name.lower()) + + +handlers = Handlers() diff --git a/src/infini/logging.py b/src/infini/logging.py index a1458ef4..3c3d2b02 100644 --- a/src/infini/logging.py +++ b/src/infini/logging.py @@ -1,6 +1,6 @@ -"""infini 日志。 +"""Infini 日志。 -infini 使用 [loguru](https://github.com/Delgan/loguru) 来记录日志信息。 +Infini 使用 [loguru](https://github.com/Delgan/loguru) 来记录日志信息。 自定义 logger 请参考 [loguru](https://github.com/Delgan/loguru) 文档。 """ from datetime import datetime @@ -12,7 +12,7 @@ from .settings import DEBUG __all__ = ["logger", "error_or_exception"] logger = multilogger( - name="HydroRoll", payload="Core", level="DEBUG" if DEBUG else "INFO" + name="Infini", payload="Core", level="DEBUG" if DEBUG else "INFO" ) current_path = Path(__file__).resolve().parent LOG_PATH = current_path / "logs" @@ -26,15 +26,8 @@ logger.add( def error_or_exception(message: str, exception: Exception, verbose: bool = True): - # 弃用的方法 - # logger.remove() - # logger.add( - # sys.stderr, - # format="<magenta>{time:YYYY-MM-DD HH:mm:ss.SSS}</magenta> <level>[{level}]</level> > <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>", - # ) - if verbose: logger.exception(exception) logger.critical(message) else: - logger.critical(f"{message} {exception!r}") + logger.critical(f"{message} {exception!r}")
\ No newline at end of file diff --git a/src/infini/matcher.py b/src/infini/matcher.py new file mode 100644 index 00000000..7fc5b88a --- /dev/null +++ b/src/infini/matcher.py @@ -0,0 +1,31 @@ +from .event import MatcherEvent, Events, events +from .handler import Handlers, Handler, handlers +from .exceptions import UnknownMatcherEvent + + +class Matcher: + """事件处理单元""" + + events: Events + handlers: Handlers + + def __init__( + self, _events: Events | None = None, _handlers: Handlers | None = None + ) -> None: + self.events = _events if _events else events + self.handlers = _handlers if _handlers else handlers + + def match(self, name: str) -> Handler: + if handler := self.handlers.match(name): + return handler + else: + raise UnknownMatcherEvent(f"未知的规则包: {name}") + + def run(self, event: MatcherEvent) -> str: + result = self.match(event.name).process(event) + return self.events.process( + result.event, **result.kwargs if result.kwargs else event.kwargs + ) + + +matcher = Matcher() diff --git a/src/infini/utils/cli.py b/src/infini/utils/cli.py new file mode 100644 index 00000000..6a4f9128 --- /dev/null +++ b/src/infini/utils/cli.py @@ -0,0 +1,23 @@ +import argparse +import sys + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(prog="Infini CLI", description="Infini 命令行工具") + + parser.add_argument("--gui", action="store_true", help="启用 GUI 模式") + + subparsers = parser.add_subparsers(title="功能件", dest="operate") + + # 子命令 `new` + new_parser = subparsers.add_parser("new", help="创建一个 Infini 规则包模板") + new_parser.add_argument("path", help="目标位置") + new_parser.add_argument("-v", "--verbose", action="store_true", help="异常追踪") + new_parser.add_argument("-f", "--force", action="store_true", help="强制创建") + + # 子命令 `test` + test_parser = subparsers.add_parser("test", help="测试 Infini 规则包") + test_parser.add_argument("path", help="目标位置") + test_parser.add_argument("-v", "--verbose", action="store_true", help="异常追踪") + + return parser.parse_args(argv if argv else sys.argv[1:]) diff --git a/src/infini/utils/gui.py b/src/infini/utils/gui.py new file mode 100644 index 00000000..d7bc24ae --- /dev/null +++ b/src/infini/utils/gui.py @@ -0,0 +1,2 @@ +"""Infini 核心图形界面""" +# TODO |
