Coverage for silkaj/tui.py: 98%
56 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-04 17:03 +0000
« 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/>.
16import shutil
17import sys
18from collections import OrderedDict
19from typing import Dict, List, Optional, Union
21import rich_click as click
22from texttable import Texttable
24from silkaj import constants
26VERT_TABLE_CHARS = ["─", "│", "│", "═"]
29def endpoint_link(endpoint_host: str) -> str:
30 return f"https://{endpoint_host}/node/summary"
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)
38class Table(Texttable):
39 def __init__(
40 self,
41 style="default",
42 ):
43 super().__init__(max_width=shutil.get_terminal_size().columns)
45 if style == "columns":
46 self.set_deco(self.HEADER | self.VLINES | self.BORDER)
47 self.set_chars(VERT_TABLE_CHARS)
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)
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 = []
73 n = 0
74 while True:
75 row = []
76 empty_cells_number = 0
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
90 return self.fill_rows(rows, keys)
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)