home · contact · privacy
In testing log, fix loss of log tests, include comments and empty lines, add insert...
authorChristian Heller <c.heller@plomlompom.de>
Fri, 5 Dec 2025 19:22:37 +0000 (20:22 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 5 Dec 2025 19:22:37 +0000 (20:22 +0100)
src/ircplom/testing.py

index 2ec70801dc99d86ab6d90c567ad43244fccced35..28bc9490245e523ea39044ea1adc16045b95b56e 100644 (file)
@@ -195,6 +195,7 @@ class _Playbook:
     redraw_affected: Optional[Callable] = None
     _lines_t: list[tuple[str, str]]
     _colwidths: dict[str, int]
+    _idx_: int = 0
 
     def __init__(self, path: Path, get_client: Callable, verbose: bool
                  ) -> None:
@@ -205,10 +206,9 @@ class _Playbook:
 
         def lines_t_from_file(path: Path, prefix='') -> list[tuple[str, str]]:
             with path.open('r', encoding='utf8') as f:
-                return [(f'{prefix}{idx + 1}', line.rstrip('\n'))
-                        for idx, line in enumerate(f.readlines())
-                        if line.rstrip()
-                        and not line.startswith(_MARK_COMMENT)]
+                return [(f'{prefix}{idx + 1}',
+                         line.rstrip('\n') if line.rstrip() else _MARK_COMMENT)
+                        for idx, line in enumerate(f.readlines())]
 
         def insert(idx_str: str,
                    insert_args: tuple[str, ...],
@@ -253,7 +253,7 @@ class _Playbook:
                         else:
                             to_join += [_SEP_1.join(str(n + bumped_offset)
                                                     for n in cmd_arg)
-                                        or ',']
+                                        or _SEP_1]
                     candidate[1] = _SEP_0.join(to_join)
 
             try:
@@ -297,6 +297,8 @@ class _Playbook:
             fragment: list[tuple[str, str]] = []
             fragments_cutoff = -1
             for idx, line_t in enumerate(self._lines_t[:] + [('', '')]):
+                if line_t[1].startswith(_MARK_COMMENT):
+                    continue
                 if line_t[1].startswith(_MARK_FRAGMENT):
                     assert _SEP_0 in line_t[1], (idx, line_t)
                     if anchor:
@@ -315,12 +317,11 @@ class _Playbook:
                 if replacement_happened or idx == fragments_cutoff:
                     new_lines_t += [line_t]
                     continue
-                cmd_name, remains = line_t[1].split(_SEP_0, maxsplit=1)
+                cmd_name, args = self._cmdname_and_args_from(line_t[1])
                 if cmd_name == _MARK_INSERT:
-                    new_lines_t += insert(
-                            line_t[0],
-                            self._args_for_cmd(cmd_name, remains),
-                            fragments)
+                    new_lines_t += [('', f'# <{line_t[1]}>')]
+                    new_lines_t += insert(line_t[0], args, fragments)
+                    new_lines_t += [('', f'# </${_MARK_INSERT}>')]
                     replacement_happened = True
                 else:
                     new_lines_t += [line_t]
@@ -332,7 +333,15 @@ class _Playbook:
         # NB: To start playback past fragments section, could move ._idx there;
         # but .ensure_has_started can easier test unchangedness if by .idx==0.
         self._lines_t = self._lines_t[fragments_cutoff + 1:]
-        self._idx = 0
+
+    @property
+    def _idx(self) -> int:
+        return self._idx_
+
+    @_idx.setter
+    def _idx(self, val: int) -> None:
+        self._line_log_and_parse(*self._current_line)
+        self._idx_ = val
 
     @staticmethod
     def _args_for_cmd(cmd_name: str, remains: str) -> tuple[str, ...]:
@@ -342,6 +351,8 @@ class _Playbook:
 
     @classmethod
     def _cmdname_and_args_from(cls, line: str) -> tuple[str, tuple[str, ...]]:
+        if line.startswith(_MARK_COMMENT):
+            return '', tuple()
         cmd_name, remains = line.split(_SEP_0, maxsplit=1)
         return cmd_name, cls._args_for_cmd(cmd_name, remains)
 
@@ -349,44 +360,46 @@ class _Playbook:
     def _current_line(self) -> tuple[str, str]:
         return self._lines_t[self._idx]
 
-    def _line_log_and_parse(self, idx_info: str, line: str
-                            ) -> tuple[str, tuple[str, ...]]:
+    def _line_log_and_parse(self, idx_info: str, line: str) -> None:
         col_titles = ('line number(s)', 'command', 'arguments')
 
         def args_verbose(args: tuple[str, ...]) -> str:
             return ' '.join(f'[{arg}]' for arg in args)
 
+        def log_by_mode(to_print: str) -> None:
+            (print if self._verbose else self._print_on_fail.append)(to_print)
+
         def print_padded(to_pad: tuple[str, ...], unpadded_end: str) -> None:
             to_log = []
             for idx, colname in enumerate(col_titles[:len(to_pad)]):
                 text = to_pad[idx]
                 to_log += [text + ' ' * (self._colwidths[colname] - len(text))]
             to_log += [unpadded_end]
-            if self._verbose:
-                print(*to_log)
-            else:
-                self._print_on_fail += [' '.join(to_log)]
+            log_by_mode(' '.join(to_log))
 
         if not hasattr(self, '_colwidths'):
             self._colwidths: dict[str, int] = {}
             for idx_str, line_ in self._lines_t:
                 cmd_name, args = self._cmdname_and_args_from(line_)
-                for idx, value in enumerate((idx_str,
-                                             cmd_name,
-                                             args_verbose(args[:-1]))):
-                    title = col_titles[idx]
-                    to_cmp = [len(value), self._colwidths.get(title, 0)]
-                    if idx < len(col_titles) - 1:
-                        to_cmp += [len(title)]
-                    self._colwidths[title] = max(to_cmp)
+                if cmd_name:
+                    for idx, value in enumerate((idx_str,
+                                                 cmd_name,
+                                                 args_verbose(args[:-1]))):
+                        title = col_titles[idx]
+                        to_cmp = [len(value), self._colwidths.get(title, 0)]
+                        if idx < len(col_titles) - 1:
+                            to_cmp += [len(title)]
+                        self._colwidths[title] = max(to_cmp)
             print_padded(to_pad=col_titles[:-1],
                          unpadded_end=col_titles[-1])
 
         cmd_name, args = self._cmdname_and_args_from(line)
-        items = (idx_info, cmd_name) + args
-        print_padded(to_pad=items[:2] + (args_verbose(items[2:-1]),),
-                     unpadded_end=items[-1])
-        return cmd_name, args
+        if cmd_name:
+            items = (idx_info, cmd_name) + args
+            print_padded(to_pad=items[:2] + (args_verbose(items[2:-1]),),
+                         unpadded_end=items[-1])
+        else:
+            log_by_mode('    ' + line)
 
     def ensure_has_started(self) -> None:
         'Check if still at beginning, and if so, play till at next log line.'
@@ -422,7 +435,7 @@ class _Playbook:
             if self._idx >= len(self._lines_t):
                 self._lines_t += [('', '> /quit'),
                                   ('', 'log 0 <..')]
-            cmd_name, args = self._line_log_and_parse(*self._current_line)
+            cmd_name, args = self._cmdname_and_args_from(self._current_line[1])
             if cmd_name == _MARK_PROMPT:
                 assert self.put_keypress is not None
                 if args[0] == 'raise_sigwinch':