Skip to content
Snippets Groups Projects
Commit e0e07070 authored by matograine's avatar matograine Committed by Moul
Browse files

[enh] #203: Create Table class and methods texttable based

- create related tests
parent e8d622eb
No related branches found
No related tags found
1 merge request!199#203: Harmonize tables style using Texttable
......@@ -13,15 +13,21 @@
# You should have received a copy of the GNU Affero General Public License
# along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
import shutil
import sys
from collections import OrderedDict
from typing import List, Optional
import click
from texttable import Texttable
from silkaj import constants
from silkaj import crypto_tools as ct
from silkaj import wot_tools
HORIZ_TABLE_CHARS = ["", "", "", ""]
VERT_TABLE_CHARS = ["", "", "", ""]
def display_amount(
tx: List, message: str, amount: float, ud_value: float, currency_symbol: str
......@@ -66,3 +72,74 @@ def gen_pubkey_checksum(
def send_doc_confirmation(document_name: str) -> None:
if not click.confirm(f"Do you confirm sending this {document_name}?"):
sys.exit(constants.SUCCESS_EXIT_STATUS)
class Table(Texttable):
def __init__(
self,
style="default",
):
Texttable.__init__(self, max_width=shutil.get_terminal_size()[0])
if style == "columns":
self.set_deco(self.HEADER | self.VLINES | self.BORDER)
self.set_chars(VERT_TABLE_CHARS)
def fill_rows(self, rows: list, headers=None):
"""
Fills a table from headers and rows list.
`rows` is a list of lists representing each row content.
each element of `rows` and headers must be of same length.
"""
if headers:
if len(rows) == 0:
rows.append([""] * len(headers))
assert len(headers) == len(rows[0])
self.header(headers)
for line in rows:
assert len(line) == len(rows[0])
self.add_row(line)
return self
def fill_from_dict(self, _dict: OrderedDict):
"""
Given an OrderedDict where each value represents a column,
fill a table where labels are dict keys and columns are dict values.
This function stops on the first line with only empty cells.
"""
labels = list(_dict.keys())
content = []
n = 0
while True:
line = []
empty_cells_number = 0
for label in labels:
try:
line.append(_dict[label][n])
except IndexError:
line.append("")
empty_cells_number += 1
# break on first empty line
if empty_cells_number == len(labels):
break
content.append(line)
n += 1
return self.fill_rows(content, labels)
def fill_from_dict_list(self, dict_list: list):
"""
Given a list of dict with same keys,
fills the table with keys as headers.
"""
headers = list(dict_list[0].keys())
content = []
for _dict in dict_list:
assert list(_dict.keys()) == headers
line = []
for head in headers:
line.append(_dict[head])
content.append(line)
return self.fill_rows(content, headers)
......@@ -13,13 +13,16 @@
# You should have received a copy of the GNU Affero General Public License
# along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
import shutil
from collections import OrderedDict
import pytest
from texttable import Texttable
from patched.test_constants import mock_ud_value
from patched.wot import patched_is_member
from silkaj import wot_tools
from silkaj import tui, wot_tools
from silkaj.constants import G1_SYMBOL, SHORT_PUBKEY_SIZE
from silkaj.tui import display_amount, display_pubkey, gen_pubkey_checksum
# display_amount()
......@@ -35,7 +38,7 @@ def test_display_amount(message, amount, currency_symbol):
]
]
tx = []
display_amount(tx, message, amount, mock_ud_value, currency_symbol)
tui.display_amount(tx, message, amount, mock_ud_value, currency_symbol)
assert tx == expected
......@@ -50,11 +53,11 @@ def test_display_amount(message, amount, currency_symbol):
def test_display_pubkey(message, pubkey, uid, monkeypatch):
monkeypatch.setattr(wot_tools, "is_member", patched_is_member)
expected = [[f"{message} (pubkey:checksum)", gen_pubkey_checksum(pubkey)]]
expected = [[f"{message} (pubkey:checksum)", tui.gen_pubkey_checksum(pubkey)]]
if uid:
expected.append([f"{message} (id)", uid])
tx = []
display_pubkey(tx, message, pubkey)
tui.display_pubkey(tx, message, pubkey)
assert tx == expected
......@@ -66,10 +69,138 @@ def test_display_pubkey(message, pubkey, uid, monkeypatch):
],
)
def test_gen_pubkey_checksum(pubkey, checksum):
assert pubkey + ":" + checksum == gen_pubkey_checksum(pubkey)
assert pubkey[:SHORT_PUBKEY_SIZE] + "…:" + checksum == gen_pubkey_checksum(
assert f"{pubkey}:{checksum}" == tui.gen_pubkey_checksum(pubkey)
assert f"{pubkey[:SHORT_PUBKEY_SIZE]}…:{checksum}" == tui.gen_pubkey_checksum(
pubkey, short=True
)
assert pubkey[:14] + "…:" + checksum == gen_pubkey_checksum(
assert f"{pubkey[:14]}…:{checksum}" == tui.gen_pubkey_checksum(
pubkey, short=True, length=14
)
def test_create_table():
expected = Texttable(max_width=shutil.get_terminal_size()[0])
expected.add_rows([["one", "two"], ["three", "four"]])
expected.set_chars(tui.VERT_TABLE_CHARS)
test_table = tui.Table().add_rows([["one", "two"], ["three", "four"]])
assert expected.draw() == test_table.draw()
expected.set_deco(expected.HEADER | expected.VLINES | expected.BORDER)
test_table = tui.Table("columns").add_rows([["one", "two"], ["three", "four"]])
assert expected.draw() == test_table.draw()
@pytest.mark.parametrize(
"rows, headers, expected",
[
(
[
["three", "o'clock"],
["four", "o'clock"],
["rock", "rock around the clock"],
],
["one", "two"],
"│───────│───────────────────────│\n\
│ one │ two │\n\
│═══════│═══════════════════════│\n\
│ three │ o'clock │\n\
│───────│───────────────────────│\n\
│ four │ o'clock │\n\
│───────│───────────────────────│\n\
│ rock │ rock around the clock │\n\
│───────│───────────────────────│",
),
(
[
["three", "o'clock"],
["four", "o'clock"],
["rock", "rock around the clock"],
],
None,
"│───────│───────────────────────│\n\
│ three │ o'clock │\n\
│───────│───────────────────────│\n\
│ four │ o'clock │\n\
│───────│───────────────────────│\n\
│ rock │ rock around the clock │\n\
│───────│───────────────────────│",
),
(
[
["three", "o'clock"],
["four", "o'clock"],
["rock"],
],
["one", "two"],
False,
),
],
)
def test_fill_rows(rows, headers, expected):
table = tui.Table()
if not expected:
with pytest.raises(AssertionError) as pytest_error:
table.fill_rows(rows, headers)
assert pytest_error.type == AssertionError # is it useful ?
else:
table.fill_rows(rows, headers)
assert table.draw() == expected
@pytest.mark.parametrize(
"dict_, expected",
[
(
OrderedDict(
[
("one", ["three", "four", "rock"]),
("two", ["o'clock", "o'clock", "rock around the clock"]),
]
),
"│───────│───────────────────────│\n\
│ one │ two │\n\
│═══════│═══════════════════════│\n\
│ three │ o'clock │\n\
│───────│───────────────────────│\n\
│ four │ o'clock │\n\
│───────│───────────────────────│\n\
│ rock │ rock around the clock │\n\
│───────│───────────────────────│",
),
],
)
def test_fill_from_dict(dict_, expected):
table = tui.Table()
table.fill_from_dict(dict_)
assert table.draw() == expected
@pytest.mark.parametrize(
"dict_list, expected",
[
(
(
[
{"one": "three", "two": "o'clock"},
{"one": "four", "two": "o'clock"},
{"one": "rock", "two": "rock around the clock"},
]
),
"│───────│───────────────────────│\n\
│ one │ two │\n\
│═══════│═══════════════════════│\n\
│ three │ o'clock │\n\
│───────│───────────────────────│\n\
│ four │ o'clock │\n\
│───────│───────────────────────│\n\
│ rock │ rock around the clock │\n\
│───────│───────────────────────│",
),
],
)
def test_fill_from_dict_list(dict_list, expected):
table = tui.Table()
table.fill_from_dict_list(dict_list)
assert table.draw() == expected
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment