Coverage for silkaj/tui.py: 98%

53 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-22 12:04 +0000

1# Copyright 2016-2025 Maël Azimi <m.a@moul.re> 

2# 

3# Silkaj is free software: you can redistribute it and/or modify 

4# it under the terms of the GNU Affero General Public License as published by 

5# the Free Software Foundation, either version 3 of the License, or 

6# (at your option) any later version. 

7# 

8# Silkaj is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU Affero General Public License for more details. 

12# 

13# You should have received a copy of the GNU Affero General Public License 

14# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. 

15 

16import shutil 

17import sys 

18from typing import Optional 

19 

20import rich_click as click 

21from texttable import Texttable 

22 

23from silkaj import constants 

24 

25VERT_TABLE_CHARS = ["─", "│", "│", "═"] 

26 

27 

28def send_doc_confirmation(document_name: str) -> None: 

29 if not click.confirm(f"Do you confirm sending this {document_name}?"): 

30 sys.exit(constants.SUCCESS_EXIT_STATUS) 

31 

32 

33class Table(Texttable): 

34 def __init__( 

35 self, 

36 style="default", 

37 ): 

38 super().__init__(max_width=shutil.get_terminal_size().columns) 

39 

40 if style == "columns": 

41 self.set_deco(self.HEADER | self.VLINES | self.BORDER) 

42 self.set_chars(VERT_TABLE_CHARS) 

43 

44 def fill_rows(self, rows: list[list], header: Optional[list] = None) -> None: 

45 """ 

46 Fills a table from header and rows list. 

47 `rows` is a list of lists representing each row content. 

48 each element of `rows` and header must be of same length. 

49 """ 

50 if header: 

51 if len(rows) == 0: 

52 rows.append([""] * len(header)) 

53 assert len(header) == len(rows[0]) 

54 self.header(header) 

55 for line in rows: 

56 assert len(line) == len(rows[0]) 

57 self.add_row(line) 

58 

59 def fill_from_dict(self, _dict: dict) -> None: 

60 """ 

61 Given a dict where each value represents a column, 

62 fill a table where labels are dict keys and columns are dict values 

63 This function stops on the first line with only empty cells 

64 """ 

65 keys = list(_dict.keys()) 

66 rows = [] 

67 

68 n = 0 

69 while True: 

70 row = [] 

71 empty_cells_number = 0 

72 

73 for key in keys: 

74 try: 

75 row.append(_dict[key][n]) 

76 except IndexError: 

77 row.append("") 

78 empty_cells_number += 1 

79 # break on first empty row 

80 if empty_cells_number == len(keys): 

81 break 

82 rows.append(row) 

83 n += 1 

84 

85 return self.fill_rows(rows, keys) 

86 

87 def fill_from_dict_list(self, dict_list: list[dict]) -> None: 

88 """ 

89 Given a list of dict with same keys, 

90 fills the table with keys as header 

91 """ 

92 header = list(dict_list[0].keys()) 

93 content = [] 

94 for _dict in dict_list: 

95 assert list(_dict.keys()) == header 

96 line = [] 

97 for head in header: 

98 line.append(_dict[head]) 

99 content.append(line) 

100 return self.fill_rows(content, header)