diff --git a/kotonebot/backend/bot.py b/kotonebot/backend/bot.py index f5c9e09..fd146a1 100644 --- a/kotonebot/backend/bot.py +++ b/kotonebot/backend/bot.py @@ -12,6 +12,7 @@ from kotonebot.client import Device from kotonebot.client.host.protocol import Instance from kotonebot.backend.context import init_context, vars from kotonebot.backend.context import task_registry, action_registry, Task, Action +from kotonebot.errors import StopCurrentTask log_stream = io.StringIO() stream_handler = logging.StreamHandler(log_stream) @@ -19,10 +20,11 @@ stream_handler.setFormatter(logging.Formatter('[%(asctime)s] [%(levelname)s] [%( logging.getLogger('kotonebot').addHandler(stream_handler) logger = logging.getLogger(__name__) +TaskStatusValue = Literal['pending', 'running', 'finished', 'error', 'cancelled', 'stopped'] @dataclass class TaskStatus: task: Task - status: Literal['pending', 'running', 'finished', 'error', 'cancelled'] + status: TaskStatusValue @dataclass class RunStatus: @@ -73,7 +75,7 @@ class Event(Generic[Params, Return]): class KotoneBotEvents: def __init__(self): self.task_status_changed = Event[ - [Task, Literal['pending', 'running', 'finished', 'error', 'cancelled']], None + [Task, TaskStatusValue], None ]() self.task_error = Event[ [Task, Exception], None @@ -186,6 +188,9 @@ class KotoneBot: try: task.func() self.events.task_status_changed.trigger(task, 'finished') + except StopCurrentTask: + logger.info(f'Task skipped/stopped: {task.name}') + self.events.task_status_changed.trigger(task, 'stopped') # 用户中止 except KeyboardInterrupt as e: logger.exception('Keyboard interrupt detected.') @@ -205,8 +210,8 @@ class KotoneBot: for task1 in tasks[tasks.index(task)+1:]: self.events.task_status_changed.trigger(task1, 'cancelled') break - logger.info(f'Task finished: {task.name}') - logger.info('All tasks finished.') + logger.info(f'Task ended: {task.name}') + logger.info('All tasks ended.') self.events.finished.trigger() def run_all(self) -> None: @@ -228,7 +233,7 @@ class KotoneBot: self.events.finished -= _on_finished self.events.task_status_changed -= _on_task_status_changed - def _on_task_status_changed(task: Task, status: Literal['pending', 'running', 'finished', 'error', 'cancelled']): + def _on_task_status_changed(task: Task, status: TaskStatusValue): def _find(task: Task) -> TaskStatus: for task_status in run_status.tasks: if task_status.task == task: diff --git a/kotonebot/errors.py b/kotonebot/errors.py index d13e62c..924b52a 100644 --- a/kotonebot/errors.py +++ b/kotonebot/errors.py @@ -31,7 +31,10 @@ class UnscalableResolutionError(KotonebotError): self.screen_size = screen_size super().__init__(f'Cannot scale to target resolution {target_resolution}. ' f'Screen size: {screen_size}') - + class ContextNotInitializedError(KotonebotError): def __init__(self, msg: str = 'Context not initialized'): - super().__init__(msg) \ No newline at end of file + super().__init__(msg) + +class StopCurrentTask(KotonebotError): + pass \ No newline at end of file