diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/_utils.py b/deltachat-rpc-client/src/deltachat_rpc_client/_utils.py index 47d9b878c..86c23d153 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/_utils.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/_utils.py @@ -44,8 +44,13 @@ class AttrDict(dict): super().__setattr__(attr, val) +def _forever(_event: AttrDict) -> bool: + return False + + def run_client_cli( hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None, + until: Callable[[AttrDict], bool] = _forever, argv: Optional[list] = None, **kwargs, ) -> None: @@ -55,10 +60,11 @@ def run_client_cli( """ from .client import Client - _run_cli(Client, hooks, argv, **kwargs) + _run_cli(Client, until, hooks, argv, **kwargs) def run_bot_cli( + until: Callable[[AttrDict], bool] = _forever, hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None, argv: Optional[list] = None, **kwargs, @@ -69,11 +75,12 @@ def run_bot_cli( """ from .client import Bot - _run_cli(Bot, hooks, argv, **kwargs) + _run_cli(Bot, until, hooks, argv, **kwargs) def _run_cli( client_type: Type["Client"], + until: Callable[[AttrDict], bool] = _forever, hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None, argv: Optional[list] = None, **kwargs, @@ -111,7 +118,7 @@ def _run_cli( kwargs={"email": args.email, "password": args.password}, ) configure_thread.start() - client.run_forever() + client.run_until(until) def extract_addr(text: str) -> str: diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/client.py b/deltachat-rpc-client/src/deltachat_rpc_client/client.py index 5b15914bb..11b3bb2fd 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/client.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/client.py @@ -14,6 +14,7 @@ from typing import ( from ._utils import ( AttrDict, + _forever, parse_system_add_remove, parse_system_image_changed, parse_system_title_changed, @@ -91,19 +92,28 @@ class Client: def run_forever(self) -> None: """Process events forever.""" - self.run_until(lambda _: False) + self.run_until(_forever) def run_until(self, func: Callable[[AttrDict], bool]) -> AttrDict: - """Process events until the given callable evaluates to True. - - The callable should accept an AttrDict object representing the - last processed event. The event is returned when the callable - evaluates to True. - """ + """Start the event processing loop.""" self.logger.debug("Listening to incoming events...") if self.is_configured(): self.account.start_io() self._process_messages() # Process old messages. + return self._process_events(until_func=func) # Loop over incoming events + + def _process_events( + self, + until_func: Callable[[AttrDict], bool], + until_event: EventType = False, + ) -> AttrDict: + """Process events until the given callable evaluates to True, + or until a certain event happens. + + The until_func callable should accept an AttrDict object representing + the last processed event. The event is returned when the callable + evaluates to True. + """ while True: event = self.account.wait_for_event() event["kind"] = EventType(event.kind) @@ -112,10 +122,13 @@ class Client: if event.kind == EventType.INCOMING_MSG: self._process_messages() - stop = func(event) + stop = until_func(event) if stop: return event + if event.kind == until_event: + return event + def _on_event(self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent) -> None: for hook, evfilter in self._hooks.get(filter_type, []): if evfilter.filter(event):