"""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