1
0
PiggyBank/piggybank/piggybank.py

108 lines
4.1 KiB
Python
Raw Normal View History

"""PiggyBank implementation."""
from __future__ import annotations
from os.path import exists
from typing import List
from piggybank import PIGGYBANK_FILE_EXTENSION
from piggybank.currencies import CURRENCIES, \
CurrencyIsNotSupportedError, CurrenciesCoinCountMismatchError, \
CurrencyMismatchError
from piggybank.transaction import Transaction, sum_transactions, TYPE_INCOME
__all__ = ["PiggyBank"]
class PiggyBank:
"""This class stores array of transactions and perform some actions on it."""
def __init__(self, currency: str = None) -> None:
if not currency is None:
self.currency = currency
self._transactions = []
self._last_transaction = None
def transact(self, coins: List[int], direction: str = TYPE_INCOME) -> None:
"""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"!= {CURRENCIES[self._currency]['count']})")
self._last_transaction = Transaction(coins, direction)
self._transactions.append(self._last_transaction)
for coin_count in sum_transactions(self._transactions):
if coin_count < 0:
del self._transactions[-1]
self._last_transaction = None
raise ValueError(
"You can't take out more than you have.")
@property
def currency(self) -> str:
"""Returns a currency of a PiggyBank."""
return self._currency
@currency.setter
def currency(self, currency: str = None) -> None:
"""Sets a currency of a PiggyBank with check for support. And if count
of coins doesn't match the old currency it won't set a new one."""
currency = currency.upper()
if not currency in CURRENCIES:
raise CurrencyIsNotSupportedError
if not self._currency is None and \
CURRENCIES[currency]["count"] \
!= CURRENCIES[self._currency]["count"]:
raise CurrenciesCoinCountMismatchError
self._currency = currency
@property
def transactions(self) -> List[Transaction]:
"""Returns a list of transactions."""
return self._transactions
@staticmethod
def from_file(filename: str) -> PiggyBank:
"""Returns a PiggyBank object loaded from a file."""
piggybank = PiggyBank()
piggybank.load(filename)
return piggybank
def save(self, filename: str) -> None:
"""Appends last successful transaction to a file. File will be created
if not exist yet."""
if self._last_transaction is None:
raise ValueError("No successful transaction found.")
if not filename.endswith(PIGGYBANK_FILE_EXTENSION):
filename += PIGGYBANK_FILE_EXTENSION
if not exists(filename):
with open(filename, 'w') as pbf:
pbf.write(f"{self.currency}\n{self._last_transaction}\n")
else:
with open(filename, 'a') as pbf:
pbf.write(f"{self._last_transaction}\n")
def load(self, filename: str) -> None:
"""Loads a PiggyBank from a file."""
if not filename.endswith(PIGGYBANK_FILE_EXTENSION):
filename += PIGGYBANK_FILE_EXTENSION
if not exists(filename):
raise FileNotFoundError(filename)
with open(filename, 'r') as pbf:
currency = pbf.readline()[:-1]
if currency not in CURRENCIES:
raise CurrencyIsNotSupportedError
else:
self._currency = currency
for line in pbf:
self._transactions.append(Transaction.from_string(line))
def __eq__(self, piggybank: PiggyBank) -> str:
"""Compares only currency."""
return self._currency == piggybank.currency
def __add__(self, piggybank: PiggyBank) -> PiggyBank:
if self != piggybank:
raise CurrencyMismatchError
new = PiggyBank(self._currency)
new._transactions = self._transactions + piggybank._transactions
return new