109 lines
4.2 KiB
Python
109 lines
4.2 KiB
Python
"""CLI: Show summarised information on a piggybank."""
|
|
|
|
from re import match
|
|
from sys import argv, exit, stderr
|
|
|
|
from piggybank.cli import handle_default_arguments
|
|
from piggybank.currencies import CURRENCIES, BaseCurrencyError
|
|
from piggybank.piggybank import PiggyBank
|
|
from piggybank.transaction import sum_transactions, multiply_transactions
|
|
|
|
__all__ = ["main"]
|
|
|
|
|
|
USAGE_SHOW: str = "Usage: piggybank-show FILE [with t,transactions]\n\n" \
|
|
"Show statistics about a piggybank.\n" \
|
|
"FILE -- .pb file name of your piggybank;\n" \
|
|
"with (t|transaction) -- also list all transactions.\n"
|
|
|
|
DEFAULT_COIN_CENTERING: int = 10
|
|
|
|
|
|
def parse_show_arguments(args):
|
|
r = r"^(?P<file>\S+)(?= with (?P<transactions>t|transactions))?"
|
|
argd = match(r, args)
|
|
if not argd is None:
|
|
argd = argd.groupdict()
|
|
return {
|
|
"file": argd["file"],
|
|
"transactions": not argd["transactions"] is None }
|
|
return None
|
|
|
|
|
|
def print_summary(piggybank: PiggyBank,
|
|
centering: int = DEFAULT_COIN_CENTERING) -> None:
|
|
"""Print summarised information on a piggy bank.
|
|
Prints a table with totals of how much coins of which face value are in a
|
|
piggy bank; A total sum converted to its currency for each face value and
|
|
overall total sum in a currency of a piggy bank."""
|
|
def print_separator(left="┣", lmiddle="╋", rmiddle="╋", right="┫"):
|
|
line = rmiddle.join('━' * centering
|
|
for _ in
|
|
range(CURRENCIES[piggybank.currency]['count']))
|
|
print(f"{left}{'━'*27}{lmiddle}{line}{right}")
|
|
|
|
cc = sum_transactions(piggybank.transactions)
|
|
cs = multiply_transactions(piggybank.transactions, piggybank.currency)
|
|
ct = sum(cc)
|
|
|
|
nline = "┃".join([f'{l:^{centering}}'
|
|
for l in CURRENCIES[piggybank.currency]["names"]])
|
|
nline_len = len(nline)
|
|
|
|
print_separator(left="┏", lmiddle="┳", rmiddle="━", right="┓")
|
|
print(f"┃{'currency':^27}┃"
|
|
f"{CURRENCIES[piggybank.currency]['name']:^{nline_len}}┃")
|
|
print_separator(rmiddle="┳")
|
|
print(f"┃{'face values':^27}┃{nline}┃")
|
|
print_separator()
|
|
print(f"┃{'amount':^27}┃{'┃'.join([f'{c:^{centering}}' for c in cc])}┃")
|
|
print_separator()
|
|
print(f"┃{'sum':^27}┃"
|
|
f"{'┃'.join(['{:^{}.2f}'.format(c / 100, centering) for c in cs])}┃")
|
|
print_separator(rmiddle="┻")
|
|
print(f"┃{'total':^27}┃{'{:^{}.2f}'.format(ct / 100, nline_len)}┃")
|
|
print_separator(left="┗", lmiddle="┻", rmiddle="━", right="┛")
|
|
|
|
|
|
def print_transactions(piggybank, centering=DEFAULT_COIN_CENTERING):
|
|
"""Print a list of all transactions stored in a piggy bank."""
|
|
def print_separator(left="┏", middle="┳", right="┓"):
|
|
line = middle.join('━' * centering
|
|
for _ in
|
|
range(CURRENCIES[piggybank.currency]['count']))
|
|
print(f"{left}━━━━━━━━━━━━━━━━━━━━━{middle}━━━━━{middle}{line}{right}")
|
|
|
|
nline = "┃".join([f'{l:^{centering}}'
|
|
for l in CURRENCIES[piggybank.currency]["names"]])
|
|
|
|
print_separator()
|
|
print(f"┃{'Timestamp':^21}┃ I/O ┃{nline}┃")
|
|
print_separator("┣", "╋", "┫")
|
|
for tr in piggybank.transactions:
|
|
coin_line = "┃".join([f'{c:^{centering}}' for c in tr.coins])
|
|
ts = tr.timestamp.replace("T", " ")
|
|
print(f"┃ {ts} ┃{tr.direction:^5}┃{coin_line}┃")
|
|
print_separator("┗", "┻", "┛")
|
|
|
|
|
|
def main() -> None:
|
|
handle_default_arguments(' '.join(argv[1:]), lambda: print(USAGE_SHOW))
|
|
args = parse_show_arguments(' '.join(argv[1:]))
|
|
|
|
if args is None:
|
|
print(USAGE_SHOW)
|
|
exit()
|
|
|
|
try:
|
|
piggybank = PiggyBank.from_file(args["file"])
|
|
print_summary(piggybank)
|
|
if args["transactions"]:
|
|
print_transactions(piggybank)
|
|
except BaseCurrencyError as err:
|
|
print(f"{type(err).__name__}:", err, file=stderr)
|
|
except FileNotFoundError as err:
|
|
print(f"{type(err).__name__}:", f"{err} doesn't exist.", file=stderr)
|
|
except Exception as err:
|
|
print(f"Something went exceptionally wrong. Error:",
|
|
f"{type(err).__name__}:", err, file=stderr)
|