diff options
author | mathieui <mathieui@mathieui.net> | 2021-04-11 13:10:25 +0200 |
---|---|---|
committer | mathieui <mathieui@mathieui.net> | 2021-04-11 16:33:53 +0200 |
commit | 6d7921da55dd12dba63f6a4473893796ee61a2de (patch) | |
tree | 37a8ba3ab872563c9dc13dc108a3f0216d02b6f2 /poezio/log_loader.py | |
parent | a827743b8677ff9bb4ea63bbb1ac690fdfcb6457 (diff) | |
download | poezio-6d7921da55dd12dba63f6a4473893796ee61a2de.tar.gz poezio-6d7921da55dd12dba63f6a4473893796ee61a2de.tar.bz2 poezio-6d7921da55dd12dba63f6a4473893796ee61a2de.tar.xz poezio-6d7921da55dd12dba63f6a4473893796ee61a2de.zip |
internal: better typing & docstrings for logger/log loader
Diffstat (limited to 'poezio/log_loader.py')
-rw-r--r-- | poezio/log_loader.py | 113 |
1 files changed, 85 insertions, 28 deletions
diff --git a/poezio/log_loader.py b/poezio/log_loader.py index 82cefd2a..835ea3da 100644 --- a/poezio/log_loader.py +++ b/poezio/log_loader.py @@ -1,15 +1,20 @@ +""" +This modules contains a class that loads messages into a ChatTab, either from +MAM or the local logs, and a class that loads MUC history into the local +logs. +""" +from __future__ import annotations import asyncio import logging -import json from datetime import datetime, timedelta, timezone -from typing import List, Dict, Any -from poezio.config import config +from typing import List from poezio import tabs from poezio.logger import ( build_log_message, iterate_messages_reverse, last_message_in_archive, Logger, + LogDict, ) from poezio.mam import ( fetch_history, @@ -27,17 +32,20 @@ from slixmpp import JID log = logging.getLogger(__name__) -def make_line_local(tab: tabs.ChatTab, msg: Dict[str, Any]) -> Message: +def make_line_local(tab: tabs.ChatTab, msg: LogDict) -> Message: + """Create a UI message from a local log read. + + :param tab: Tab in which that message will be displayed + :param msg: Log data + :returns: The UI message + """ if isinstance(tab, tabs.MucTab): jid = JID(tab.jid) - jid.resource = msg['nickname'] + jid.resource = msg.get('nickname') or '' else: jid = JID(tab.jid) msg['time'] = msg['time'].astimezone(tz=timezone.utc) - return make_line(tab, msg['txt'], msg['time'], jid, '') - - -STATUS = {'mam_only', 'local_only'} + return make_line(tab, msg['txt'], msg['time'], jid, '', msg['nickname']) class LogLoader: @@ -52,15 +60,16 @@ class LogLoader: mam_only: bool def __init__(self, logger: Logger, tab: tabs.ChatTab, - mam_only: bool = True): - self.mam_only = mam_only + local_logs: bool = True): + self.mam_only = not local_logs self.logger = logger self.tab = tab - async def tab_open(self): + async def tab_open(self) -> None: """Called on a tab opening or a MUC join""" amount = 2 * self.tab.text_win.height gap = self.tab._text_buffer.find_last_gap_muc() + messages = [] if gap is not None: if self.mam_only: messages = await self.mam_fill_gap(gap) @@ -72,11 +81,20 @@ class LogLoader: else: messages = await self.local_tab_open(amount) + log.debug( + 'Fetched %s messages for %s', + len(messages), self.tab.jid + ) if messages: self.tab._text_buffer.add_history_messages(messages) self.tab.core.refresh_window() async def mam_tab_open(self, nb: int) -> List[BaseMessage]: + """Fetch messages in MAM when opening a new tab. + + :param nb: number of max messages to fetch. + :returns: list of ui messages to add + """ tab = self.tab end = datetime.now() for message in tab._text_buffer.messages: @@ -93,6 +111,11 @@ class LogLoader: tab.query_status = False async def local_tab_open(self, nb: int) -> List[BaseMessage]: + """Fetch messages locally when opening a new tab. + + :param nb: number of max messages to fetch. + :returns: list of ui messages to add + """ await self.wait_mam() results: List[BaseMessage] = [] filepath = self.logger.get_file_path(self.tab.jid) @@ -105,6 +128,11 @@ class LogLoader: return results[::-1] async def mam_fill_gap(self, gap: HistoryGap) -> List[BaseMessage]: + """Fill a message gap in an existing tab using MAM. + + :param gap: Object describing the history gap + :returns: list of ui messages to add + """ tab = self.tab start = gap.last_timestamp_before_leave @@ -121,6 +149,12 @@ class LogLoader: tab.query_status = False async def local_fill_gap(self, gap: HistoryGap) -> List[BaseMessage]: + """Fill a message gap in an existing tab using the local logs. + Mostly useless when not used with the MAMFiller. + + :param gap: Object describing the history gap + :returns: list of ui messages to add + """ await self.wait_mam() start = gap.last_timestamp_before_leave end = gap.first_timestamp_after_join @@ -161,6 +195,11 @@ class LogLoader: tab.core.refresh_window() async def local_scroll_requested(self, nb: int) -> List[BaseMessage]: + """Fetch messages locally on scroll up. + + :param nb: Number of messages to fetch + :returns: list of ui messages to add + """ await self.wait_mam() tab = self.tab last_message_time = None @@ -180,6 +219,11 @@ class LogLoader: return results[::-1] async def mam_scroll_requested(self, nb: int) -> List[BaseMessage]: + """Fetch messages from MAM on scroll up. + + :param nb: Number of messages to fetch + :returns: list of ui messages to add + """ tab = self.tab try: messages = await fetch_history(tab, amount=nb) @@ -205,8 +249,10 @@ class LogLoader: tab.query_status = False async def wait_mam(self) -> None: - if not isinstance(self.tab, tabs.MucTab): - return + """Waitt for the MAM history sync before reading the local logs. + + Does nothing apart from blocking. + """ if self.tab.mam_filler is None: return await self.tab.mam_filler.done.wait() @@ -219,20 +265,24 @@ class MAMFiller: logger: Logger future: asyncio.Future done: asyncio.Event + max_msgs: int = 2000 - def __init__(self, tab: tabs.ChatTab, logger: Logger): + def __init__(self, logger: Logger, tab: tabs.ChatTab): self.tab = tab self.logger = logger - logger.fd_busy(str(tab.jid)) + logger.fd_busy(tab.jid) self.future = asyncio.ensure_future(self.fetch_routine()) self.done = asyncio.Event() - def cancel(self): + def cancel(self) -> None: + """Cancel the routine and signal the end.""" self.future.cancel() self.end() async def fetch_routine(self) -> None: + """Load logs into the local archive, if possible.""" filepath = self.logger.get_file_path(self.tab.jid) + log.debug('Fetching logs for %s', self.tab.jid) try: last_msg = last_message_in_archive(filepath) last_msg_time = None @@ -242,14 +292,20 @@ class MAMFiller: messages = await fetch_history( self.tab, start=last_msg_time, - amount=2000, + amount=self.max_msgs, + ) + log.debug( + 'Fetched %s messages to fill local logs for %s', + len(messages), self.tab.jid, ) except (DiscoInfoException, NoMAMSupportException, MAMQueryException): - log.debug('Failed for %s', self.tab.jid, exc_info=True) + log.debug( + 'Failed fetching logs for %s', + self.tab.jid, exc_info=True + ) return - log.debug('Fetched %s:\n%s', len(messages), messages) - def build_message(msg): + def build_message(msg) -> str: return build_log_message( msg.nickname, msg.txt, @@ -258,16 +314,17 @@ class MAMFiller: ) logs = ''.join(map(build_message, messages)) - log.debug(logs) - self.logger.log_raw(self.tab.jid, logs, force=True) - except Exception as exc: - log.debug('exception: %s', exc, exc_info=True) finally: - log.debug('finishing fill for %s', self.tab.jid) self.end() - def end(self): - self.logger.fd_available(str(self.tab.jid)) + def end(self) -> None: + """End a MAM fill (error or sucess). Remove references and signal on + the Event(). + """ + try: + self.logger.fd_available(self.tab.jid) + except Exception: + log.error('Error when restoring log fd:', exc_info=True) self.tab.mam_filler = None self.done.set() |