Coverage for silkaj/tui.py: 98%

55 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-20 12:29 +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 endpoint_link(endpoint_host: str) -> str: 

29 return f"https://{endpoint_host}/node/summary" 

30 

31 

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

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

34 sys.exit(constants.SUCCESS_EXIT_STATUS) 

35 

36 

37class Table(Texttable): 

38 def __init__( 

39 self, 

40 style="default", 

41 ): 

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

43 

44 if style == "columns": 

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

46 self.set_chars(VERT_TABLE_CHARS) 

47 

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

49 """ 

50 Fills a table from header and rows list. 

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

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

53 """ 

54 if header: 

55 if len(rows) == 0: 

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

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

58 self.header(header) 

59 for line in rows: 

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

61 self.add_row(line) 

62 

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

64 """ 

65 Given a dict where each value represents a column, 

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

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

68 """ 

69 keys = list(_dict.keys()) 

70 rows = [] 

71 

72 n = 0 

73 while True: 

74 row = [] 

75 empty_cells_number = 0 

76 

77 for key in keys: 

78 try: 

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

80 except IndexError: 

81 row.append("") 

82 empty_cells_number += 1 

83 # break on first empty row 

84 if empty_cells_number == len(keys): 

85 break 

86 rows.append(row) 

87 n += 1 

88 

89 return self.fill_rows(rows, keys) 

90 

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

92 """ 

93 Given a list of dict with same keys, 

94 fills the table with keys as header 

95 """ 

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

97 content = [] 

98 for _dict in dict_list: 

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

100 line = [] 

101 for head in header: 

102 line.append(_dict[head]) 

103 content.append(line) 

104 return self.fill_rows(content, header)