Coverage for src/extratools_core/printtools.py: 0%

33 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-05 19:38 -0700

1from collections.abc import Callable, Iterable 

2from io import StringIO 

3from itertools import zip_longest 

4from typing import cast 

5 

6from toolz import sliding_window 

7 

8from .typing import Comparable 

9 

10 

11def sorted_to_str[T]( 

12 seq: Iterable[T], 

13 *, 

14 key: Callable[[T], Comparable] | None = None, 

15) -> str: 

16 def default_key(v: T) -> Comparable: 

17 return cast("Comparable", v) 

18 

19 local_key: Callable[[T], Comparable] = default_key if key is None else key 

20 

21 s = StringIO() 

22 

23 first: bool = True 

24 for prev, curr in sliding_window(2, seq): 

25 if first: 

26 s.write(repr(prev)) 

27 first = False 

28 

29 s.write(" == " if local_key(prev) == local_key(curr) else " < ") 

30 s.write(repr(curr)) 

31 

32 return s.getvalue() 

33 

34 

35def alignment_to_str[T]( 

36 *seqs: Iterable[T | None], 

37 default: str = "", 

38 separator: str = " | ", 

39) -> str: 

40 strs: list[StringIO] = [] 

41 

42 for i, col in enumerate(zip_longest(*seqs, fillvalue=default)): 

43 if i == 0: 

44 strs = [StringIO() for _ in col] 

45 else: 

46 for s in strs: 

47 s.write(separator) 

48 

49 vals: list[str] = [ 

50 default if v is None else repr(v) 

51 for v in col 

52 ] 

53 max_len: int = max( 

54 len(val) 

55 for val in vals 

56 ) 

57 pads: list[str] = [ 

58 (max_len - len(val)) * ' ' 

59 for val in vals 

60 ] 

61 

62 for s, pad, val in zip(strs, pads, vals, strict=True): 

63 s.write(val) 

64 s.write(pad) 

65 

66 return '\n'.join([s.getvalue() for s in strs])