Browse Source

Performed some refactoring on an existing code base before further work.

master
Alexander "Arav" Andreev 2 years ago
committed by Alexander Arav Andreev
parent
commit
d9dbf0fb8d
  1. 2
      .gitignore
  2. 13
      piggybank/cli/__init__.py
  3. 15
      piggybank/cli/put.py
  4. 8
      piggybank/cli/show.py
  5. 21
      piggybank/cli/take.py
  6. 20
      piggybank/currencies.py
  7. 12
      piggybank/piggybank.py
  8. 9
      piggybank/transaction.py
  9. 34
      piggybank/util.py

2
.gitignore

@ -1,6 +1,6 @@
.vscode/
build/
dist/
piggybank.egg-info/
*.egg-info/
__pycache__
*.pb

13
piggybank/cli/__init__.py

@ -1,2 +1,13 @@
from typing import List
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."""
you have across your piggy banks."""
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

15
piggybank/cli/put.py

@ -5,12 +5,10 @@ from os.path import exists
from sys import exit, stderr
from piggybank import print_program_version
from piggybank.cli import EPILOGUE
from piggybank.cli import EPILOGUE, complement_array_of_coins
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.piggybank import PiggyBank
from piggybank.util import add_common_arguments_to_parser, \
complement_array_of_coins
__all__ = ["main"]
@ -31,7 +29,16 @@ def main() -> None:
help="set currency of a piggy bank. Not applicable to"
"an existing one")
add_common_arguments_to_parser(parser)
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()

8
piggybank/cli/show.py

@ -1,4 +1,4 @@
"""CLI: Take a set of coins from a piggy bank."""
"""CLI: Show summarised information on a piggybank."""
from argparse import ArgumentParser
from os.path import exists
@ -9,7 +9,6 @@ from piggybank.cli import EPILOGUE
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.piggybank import PiggyBank
from piggybank.util import add_common_arguments_to_parser
__all__ = ["main"]
@ -88,7 +87,10 @@ def main():
help="merge multiple files to show how much do you"
"have across them. They all should be of same currency")
add_common_arguments_to_parser(parser, include_reverse_flag=False)
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()

21
piggybank/cli/take.py

@ -4,13 +4,11 @@ from argparse import ArgumentParser
from sys import exit, stderr
from piggybank import print_program_version
from piggybank.cli import EPILOGUE
from piggybank.cli import EPILOGUE, complement_array_of_coins
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY, \
BaseCurrencyError, print_supported_currencies
from piggybank.piggybank import PiggyBank
from piggybank.transaction import TYPE_OUTCOME
from piggybank.util import add_common_arguments_to_parser, \
complement_array_of_coins
__all__ = ["main"]
@ -18,16 +16,25 @@ __all__ = ["main"]
def main():
"""An entry point for a take command."""
parser = ArgumentParser(prog="piggybank-take",
description="Take a set of coins from a coin box.",
description="Take a set of coins from a piggy bank.",
epilog=EPILOGUE)
parser.add_argument("file", type=str,
help="a coin box file name. Missing .cb extension will"
"be added")
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")
add_common_arguments_to_parser(parser)
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()

20
piggybank/currencies.py

@ -1,20 +1,22 @@
"""Here is a dictionary of supported currencies defined. Which could be easily
extended with new ones.
Each dictionary entry has an ISO code of a currency as its key. Or it can
slightly differ from an ISO to represent a modified version of a currency. An
example is SRUB entry for shortened version of RUB where coins of 1 and 5 kopek
value were removed. And value is an another dictionary consists of following
fields:
Each entry is a dictionary that has an ISO code of a currency as its key. Or it
can be slightly differ from an ISO code to represent a modified version of a
currency.
Each entry consists of following fields:
name -- a full name of a currency;
description -- usually a country where this currency is used is being
mentioned. Plus additional information;
count -- a number of coins in a currency;
names -- an array of names for each coins' face values;
multipliers -- an array of multipliers for each face value in a decimal
format. Decimal is used to avoid problems of rounding float numbers.
So first two digits are used to store a fraction part. You can simply
divide this number by 100 to get a regular floating-point number.
multipliers -- an array of multipliers for each face value in a decimal*
format.
* - Decimal is used to avoid problems of rounding float numbers. So first two
digits to the right are used to store a fraction part. You can simply divide
this number by 100 to get a regular floating-point number.
"""
from typing import Dict, List, TypedDict

12
piggybank/piggybank.py

@ -1,4 +1,4 @@
"""Implementation of the piggy bank itself."""
"""PiggyBank implementation."""
from __future__ import annotations
from os.path import exists
@ -14,8 +14,7 @@ __all__ = ["PiggyBank"]
class PiggyBank:
"""This class stores transactions and do file I/O on piggy bank
.pb files."""
"""This class stores array of transactions and perform some actions on it."""
def __init__(self, currency: str = DEFAULT_CURRENCY) -> None:
if currency.upper() in CURRENCIES:
self._currency = currency.upper()
@ -28,7 +27,7 @@ class PiggyBank:
"""Make a transaction."""
if len(coins) != CURRENCIES[self.currency]["count"]:
raise ValueError("Length of passed coins list doesn't match the "
f"currency's coins count ({len(coins)} "
f"currency's coins count. ({len(coins)} "
f"!= {CURRENCIES[self.currency]['count']})")
self._transactions.append(Transaction(coins, direction))
@ -41,7 +40,7 @@ class PiggyBank:
@property
def count(self) -> List[int]:
"""Returns a list of counts for each face value."""
"""Returns a list of counts for each face value in total."""
count = [0] * CURRENCIES[self.currency]["count"]
for tr in self.transactions:
count = [x + y if tr.direction == TYPE_INCOME
@ -123,6 +122,3 @@ class PiggyBank:
new = PiggyBank(self.currency)
new._transactions = self.transactions + piggybank._transactions
return new
def __repr__(self) -> str:
return f"PiggyBank(currency={self.currency!r})"

9
piggybank/transaction.py

@ -1,4 +1,4 @@
"""Implementation of Transaction class."""
"""Transaction class implementation."""
from __future__ import annotations
from time import strftime, strptime, gmtime
@ -12,8 +12,9 @@ TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
class Transaction:
"""Represents a single transaction.
Consists of array of coins' list, direction and timestamp."""
"""Transaction consists of a timestamp, a direction
and an array of coins. It doesn't depend on a currency. Only coins count is
stored."""
def __init__(self, coins, direction: str = TYPE_INCOME,
timestamp: Optional[str] = None) -> None:
self.coins = coins
@ -29,7 +30,7 @@ class Transaction:
strptime(timestamp, TIME_FORMAT)
except ValueError:
raise ValueError(f"Timestamp {timestamp} has wrong format. "
f"The right one is {TIME_FORMAT}")
f"The right one is '{TIME_FORMAT}''")
self.timestamp = timestamp
@staticmethod

34
piggybank/util.py

@ -1,34 +0,0 @@
"""Utility functions."""
from argparse import ArgumentParser
from typing import List
from piggybank import __version__, __copyright__, __license__
from piggybank.currencies import CURRENCIES, DEFAULT_CURRENCY
__all__ = ["add_common_arguments_to_parser", "complement_array_of_coins"]
def add_common_arguments_to_parser(parser: ArgumentParser,
include_reverse_flag: bool = True) -> None:
"""Extends ArgumentParser with a common set of arguments that are shared
amongst all parsers in CLI module."""
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")
if include_reverse_flag:
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'")
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
Loading…
Cancel
Save