Coverage for silkaj/tui.py: 98%

56 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-04 17:03 +0000

1# Copyright 2016-2024 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 collections import OrderedDict 

19from typing import Dict, List, Optional, Union 

20 

21import rich_click as click 

22from texttable import Texttable 

23 

24from silkaj import constants 

25 

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

27 

28 

29def endpoint_link(endpoint_host: str) -> str: 

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

31 

32 

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

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

35 sys.exit(constants.SUCCESS_EXIT_STATUS) 

36 

37 

38class Table(Texttable): 

39 def __init__( 

40 self, 

41 style="default", 

42 ): 

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

44 

45 if style == "columns": 

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

47 self.set_chars(VERT_TABLE_CHARS) 

48 

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

50 """ 

51 Fills a table from header and rows list. 

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

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

54 """ 

55 if header: 

56 if len(rows) == 0: 

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

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

59 self.header(header) 

60 for line in rows: 

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

62 self.add_row(line) 

63 

64 def fill_from_dict(self, _dict: Union[Dict, OrderedDict]) -> None: 

65 """ 

66 Given a dict where each value represents a column, 

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

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

69 """ 

70 keys = list(_dict.keys()) 

71 rows = [] 

72 

73 n = 0 

74 while True: 

75 row = [] 

76 empty_cells_number = 0 

77 

78 for key in keys: 

79 try: 

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

81 except IndexError: 

82 row.append("") 

83 empty_cells_number += 1 

84 # break on first empty row 

85 if empty_cells_number == len(keys): 

86 break 

87 rows.append(row) 

88 n += 1 

89 

90 return self.fill_rows(rows, keys) 

91 

92 def fill_from_dict_list(self, dict_list: List[Dict]) -> None: 

93 """ 

94 Given a list of dict with same keys, 

95 fills the table with keys as header 

96 """ 

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

98 content = [] 

99 for _dict in dict_list: 

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

101 line = [] 

102 for head in header: 

103 line.append(_dict[head]) 

104 content.append(line) 

105 return self.fill_rows(content, header)