1
0

argparse package was thrown the heck out and replaced with regexp. It has resulted in change of arguments' structure. Configuration class put in action. All these changes are to be tested.

This commit is contained in:
Alexander Andreev 2020-06-04 05:11:29 +04:00
parent f99ce3f6cc
commit f58b675107
6 changed files with 152 additions and 216 deletions

View File

@ -1,13 +1,66 @@
from typing import List
from re import search
from typing import List, Callable
from sys import argv, exit
from piggybank import print_program_version
from piggybank.configuration import Configuration
from piggybank.currencies import CURRENCIES
EPILOGUE = """This program is to assist you to keep track of how much coins
you have across your piggy banks."""
__all__ = ["handle_default_arguments", "complement_array_of_coins"]
USAGE_COMMON: str = "Usage: piggybank-* " \
"[(-h|--help)|(-v|--version)|(-L|--list-currencies)]\n" \
"A set of common flags. Only one could be specified.\n" \
"-h, --help -- print this help;\n" \
"-v, --version -- print program version;\n" \
"-L, --list-currencies -- print supported currencies;\n" \
"--set-default-currency CURRENCY -- set default currency.\n"
def parse_common_arguments(args: str):
r = r"(?P<help>-h|--help)|(?P<version>-v|--version)" \
r"|(?P<list_currencies>-L|--list-currencies)" \
r"|(?=--set-default-currency (?P<default_currency>\w+))"
argd = search(r, args)
if not argd is None:
argd = argd.groupdict()
return {
"help": argd["help"] is None,
"version": argd["transactions"] is None,
"list-currencies": argd["list_currencies"] is None,
"default-currency": argd["default_currency"] }
def handle_default_arguments(args: dict, help_func: Callable) -> None:
cargs = parse_common_arguments(' '.join(argv))
if cargs["help"]:
help_func()
print(USAGE_COMMON)
exit()
elif cargs["version"]:
print_program_version()
exit()
elif cargs["list-currencies"]:
print_supported_currencies()
exit()
elif not cargs["default-currency"] is None:
Configuration()["default-currency"] = cargs["default-currency"]
exit()
def print_supported_currencies() -> None:
"""Print a list of supported currencies."""
print("Supported currencies are:")
for cur in CURRENCIES:
print(f" {cur:^4}{CURRENCIES[cur]['name']:^31}"
f"{CURRENCIES[cur]['description']}")
print("Default currency is", Configuration()["default-currency"])
def complement_array_of_coins(coins: List[int], currency: str,
_reversed: bool = False) -> List[int]:
"""Complements array of coins up to the count of currency's coins."""
offset_array = [0] * (CURRENCIES[currency]["count"] - len(coins))
return offset_array + coins if not _reversed else coins + offset_array
return offset_array + coins if not _reversed else coins + offset_array

View File

@ -1,70 +0,0 @@
from re import match
from sys import argv
from piggybank import print_program_version
from piggybank.currencies import print_supported_currencies
USAGE_PUT = "Usage: piggybank put [-r|--reversed] COINS in FILE of CURRENCY\n" \
"Put a set of coins in a piggybank. Set a currency of a new one.\n\n" \
"-r, --reversed -- use reversed order of COINS (from greater to least);\n" \
"COINS -- array of comma or whitespace separated coins;\n" \
"in FILE -- .pb file name of your piggybank;\n" \
"of CURRENCY -- set a currency for a new piggybank.\n"
USAGE_TAKE = "Take a set of coins from a piggybank.\n" \
"Usage: piggybank take [-r|--reversed] COINS from FILE\n\n" \
"-r, --reversed -- use reversed order of COINS (from greater to least);\n" \
"COINS -- array of comma or whitespace separated coins;\n" \
"from FILE -- .pb file of your piggybank.\n" \
USAGE_SHOW = "Show statistics about a piggybank.\n" \
"Usage: piggybank show FILE [with t,transactions]\n\n" \
"FILE -- .pb file name of your piggybank;\n" \
"with t,transaction -- list all transactions.\n"
HELP = "Usage: piggybank [put | take | show] [-v | --version] " \
"[-h | --help] [-L | --list-currencies]\n\n" \
f"{USAGE_PUT}\n" \
f"{USAGE_TAKE}\n" \
f"{USAGE_SHOW}\n\n" \
"-L,--list-currencies -- list all supported currencies and a default one;" \
"-v,--version -- print version of a program;\n" \
"-h,--help -- print this help.\n"
def put(args):
r = r"^put(?P<reversed> -r| --reversed)? (?P<coins>[\d ,]+) in (?P<file>\S+)(?= of (?P<currency>\w+))?"
def take(args):
r = r"^take(?P<reversed> -r| --reversed)? (?P<coins>[\d ,]+) from (?P<file>\S+)"
def show(args):
r = r"^show (?P<file>\S+)(?= with (?P<transactions>t|transactions))?"
def common(args):
r = r"(?P<version>-v|--version)?(?P<help>-h|--help)?(?P<list_currencies>-L|--list-currencies)?"
argd = match(r, args).groupdict()
if not argd["version"] is None:
print_program_version()
exit()
elif not argd["help"] is None:
print(HELP)
elif not argd["list_currencies"] is None:
print_supported_currencies()
def main():
command = argv[1]
args_str = " ".join(argv[1:])
if command == "put":
put(args_str)
elif command == "take":
take(args_str)
elif command == "show":
show(args_str)
else:
common(args_str)
if __name__ == "__main__":
main()

View File

@ -1,64 +1,53 @@
"""CLI: Put a set of coins into a piggy bank."""
from argparse import ArgumentParser
from os.path import exists
from sys import exit, stderr
from re import match
from sys import argv, exit, stderr
from piggybank import print_program_version
from piggybank.cli import EPILOGUE, complement_array_of_coins
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.configuration import Configuration
from piggybank.cli import complement_array_of_coins, handle_default_arguments
from piggybank.currencies import CURRENCIES, BaseCurrencyError
from piggybank.piggybank import PiggyBank
__all__ = ["main"]
USAGE_PUT = "Usage: piggybank-put [-r|--reversed] COINS in FILE of CURRENCY\n" \
"Put a set of coins in a piggybank. Set a currency of a new one.\n\n" \
"-r, --reversed -- use reversed order of COINS (from greater to least);\n" \
"COINS -- array of comma or whitespace separated coins;\n" \
"in FILE -- .pb file name of your piggybank;\n" \
"of CURRENCY -- set a currency for a new piggybank.\n"
def parse_put_arguments(args):
r = r"^(?P<reversed>-r|--reversed)? (?P<coins>[\d ,]+)" \
r" in (?P<file>\S+)(?= of (?P<currency>\w+))?"
argd = match(r, args)
if not argd is None:
argd = argd.groupdict()
return {
"coins": list(map(str, argd["coins"].split(", "))),
"file": argd["file"],
"currency": Configuration()["default-currency"] \
if argd["currency"] is None else argd["currency"],
"reversed": argd["reversed"] is None }
def main() -> None:
"""An entry point for a put command."""
parser = ArgumentParser(prog="piggybank-put",
description="Add a set of coins to a piggy bank.",
epilog=EPILOGUE)
parser.add_argument("file", type=str,
help="a piggy bank file name. Missing .pb extension"
"will be added")
parser.add_argument("coins", type=int, nargs="+", metavar="COIN",
help="a set of coins to add. A new file will be"
"created if it doesn't exist")
parser.add_argument("-c", "--currency", type=str, default=DEFAULT_CURRENCY,
help="set currency of a piggy bank. Not applicable to"
"an existing one")
parser.add_argument("-v", "--version", action="store_true",
help="show program's version and license and exit")
parser.add_argument("--list-currencies", action="store_true",
help="list all supported currencies and exit")
parser.add_argument("-r", "--reverse", action="store_true",
help="reverse a set of coins so incomplete set"
"fills with zeros from right. E.g. '8 9' will be"
"interpreted as '8 9 0 0 0 0' instead of"
"'0 0 0 0 8 9'")
args = parser.parse_args()
if args.version:
print_program_version()
exit()
if args.list_currencies:
print_supported_currencies()
exit()
handle_default_arguments(' '.join(argv), lambda: print(USAGE_PUT))
args = parse_put_arguments(' '.join(argv))
try:
try:
piggybank = PiggyBank.from_file(args.file)
piggybank = PiggyBank.from_file(args["file"])
except FileNotFoundError:
piggybank = PiggyBank(args.currency)
coins = complement_array_of_coins(args.coins, piggybank.currency,
args.reverse)
piggybank = PiggyBank(args["currency"])
coins = complement_array_of_coins(args["coins"], piggybank.currency,
args["reversed"])
piggybank.transact(coins)
piggybank.save(args.file)
piggybank.save(args["file"])
except BaseCurrencyError:
print(f"{type(err).__name__}:", err, file=stderr)
except ValueError as err:

View File

@ -1,20 +1,36 @@
"""CLI: Show summarised information on a piggybank."""
from argparse import ArgumentParser
from os.path import exists
from sys import exit, stderr
from re import match
from sys import argv, exit, stderr
from piggybank import print_program_version, PIGGYBANK_FILE_EXTENSION
from piggybank.cli import EPILOGUE
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.configuration import Configuration
from piggybank.cli import handle_default_arguments
from piggybank.currencies import CURRENCIES, \
BaseCurrencyError
from piggybank.piggybank import PiggyBank
__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": argd["transactions"] is None }
def print_summary(piggybank: PiggyBank,
centering: int = DEFAULT_COIN_CENTERING) -> None:
"""Print summarised information on a piggy bank.
@ -69,48 +85,15 @@ def print_transactions(piggybank, centering=DEFAULT_COIN_CENTERING):
print_separator("", "", "")
def main():
"""An entry point for a show command."""
parser = ArgumentParser(prog="piggybank-show",
description="Show information on a piggy bank.",
epilog=EPILOGUE)
def main() -> None:
handle_default_arguments(' '.join(argv), lambda: print(USAGE_SHOW))
parser.add_argument("file", type=str,
help="a piggy bank file name. Missing .pb extension"
"will be added")
parser.add_argument("-t", "--transactions", action="store_true",
help="print a list of transactions as well")
parser.add_argument("-m", "--merge", action="append",
type=str, metavar="FILE",
help="merge multiple files to show how much do you"
"have across them. They all should be of same currency")
parser.add_argument("-v", "--version", action="store_true",
help="show program's version and license and exit")
parser.add_argument("--list-currencies", action="store_true",
help="list all supported currencies and exit")
args = parser.parse_args()
if args.version:
print_program_version()
exit()
if args.list_currencies:
print_supported_currencies()
exit()
args = parse_show_arguments(' '.join(argv))
try:
piggybank = PiggyBank.from_file(args.file)
if args.merge:
for _file in args.merge:
merge_piggybank = PiggyBank.from_file(_file)
piggybank += merge_piggybank
print(_file)
piggybank = PiggyBank.from_file(args["file"])
print_summary(piggybank)
if args.transactions:
if args["transactions"]:
print_transactions(piggybank)
except BaseCurrencyError as err:
print(f"{type(err).__name__}:", err, file=stderr)

View File

@ -1,57 +1,51 @@
"""CLI: Take a set of coins from a coin box."""
from argparse import ArgumentParser
from sys import exit, stderr
from re import match, search
from sys import argv, exit, stderr
from piggybank import print_program_version
from piggybank.cli import EPILOGUE, complement_array_of_coins
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.configuration import Configuration
from piggybank.cli import complement_array_of_coins, handle_default_arguments
from piggybank.currencies import CURRENCIES, BaseCurrencyError
from piggybank.piggybank import PiggyBank
from piggybank.transaction import TYPE_OUTCOME
__all__ = ["main"]
USAGE_TAKE: str = "Usage: piggybank-take [-r|--reversed] COINS from FILE\n\n" \
"Take a set of coins from a piggybank.\n" \
"-r, --reversed -- use reversed order of COINS (from greater to least);\n" \
"COINS -- array of comma or whitespace separated coins;\n" \
"from FILE -- .pb filename.\n"
def parse_take_arguments(args):
r = r"^(?P<reversed>-r|--reversed)?(?P<coins>[\d ,]+) from (?P<file>\S+)"
argd = match(r, args)
if not argd is None:
argd = argd.groupdict()
return {
"coins": list(map(str, argd["coins"].split(", "))),
"file": argd["file"],
"reversed": argd["reversed"] is None }
def main():
"""An entry point for a take command."""
parser = ArgumentParser(prog="piggybank-take",
description="Take a set of coins from a piggy bank.",
epilog=EPILOGUE)
parser.add_argument("file", type=str,
help="a piggy bank file name. Missing .pb extension"
"will be added")
parser.add_argument("coins", type=int, nargs="+", metavar="COIN",
help="add a set of coins. A new file will be created"
"if it doesn't exist")
handle_default_arguments(' '.join(argv), lambda: print(USAGE_TAKE))
parser.add_argument("-v", "--version", action="store_true",
help="show program's version and license and exit")
parser.add_argument("--list-currencies", action="store_true",
help="list all supported currencies and exit")
args = parse_take_arguments(' '.join(argv))
parser.add_argument("-r", "--reverse", action="store_true",
help="reverse a set of coins so incomplete set"
"fills with zeros from right. E.g. '8 9' will be"
"interpreted as '8 9 0 0 0 0' instead of"
"'0 0 0 0 8 9'")
args = parser.parse_args()
if args.version:
print_program_version()
exit()
if args.list_currencies:
print_supported_currencies()
if args["coins"] is None or args["file"] is None:
print(USAGE_TAKE)
exit()
try:
piggybank = PiggyBank.from_file(args.file)
coins = complement_array_of_coins(args.coins, piggybank.currency,
args.reverse)
piggybank = PiggyBank.from_file(args["file"])
coins = complement_array_of_coins(args["coins"], piggybank.currency,
args["reversed"])
piggybank.transact(coins, TYPE_OUTCOME)
piggybank.save(args.file)
piggybank.save(args["file"])
except BaseCurrencyError as err:
print(f"{type(err).__name__}:", err, file=stderr)
except ValueError as err:

View File

@ -21,9 +21,8 @@ this number by 100 to get a regular floating-point number.
from typing import Dict, List, TypedDict
__all__ = ["CURRENCIES", "DEFAULT_CURRENCY", "BaseCurrencyError",
"CurrencyIsNotSupportedError", "CurrenciesCoinCountMismatchError",
"CurrencyMismatchError", "print_supported_currencies"]
__all__ = ["CURRENCIES", "BaseCurrencyError", "CurrencyIsNotSupportedError",
"CurrenciesCoinCountMismatchError", "CurrencyMismatchError"]
class BaseCurrencyError(Exception):
@ -53,9 +52,6 @@ class CurrenciesCoinCountMismatchError(BaseCurrencyError):
pass
DEFAULT_CURRENCY: str = "SRUB"
class Currency(TypedDict):
name: str
description: str
@ -116,12 +112,3 @@ CURRENCIES: Dict[str, Currency] = {
"multipliers": [1, 2, 5, 10, 20, 25, 50, 1_00, 2_00]
}
}
def print_supported_currencies() -> None:
"""Print a list of supported currencies."""
print("Supported currencies are:")
for cur in CURRENCIES:
print(f" {cur:^4}{CURRENCIES[cur]['name']:^31}"
f"{CURRENCIES[cur]['description']}")
print("Default currency is", DEFAULT_CURRENCY)